package model.layout; import model.html.*; import java.awt.*; import java.util.*; // Generic Layout class public abstract class Layout { // fuck encapsulation all my homies hate encapsulation // but seriously, what a garbage idea: get a better language // (please read the above comment in the voice of https://www.youtube.com/watch?v=EdWSg6YwUeo) public final Point location; public final Dimension dimension; public final Node associatedNode; public final Layout parent; public Optional previousSibling; public Optional nextSibling; public ArrayList children; public static final int DEFAULT_X = 10; public static final int DEFAULT_Y = 20; public static final int DEFAULT_WIDTH = 1000; public static final int DEFAULT_HEIGHT = 800; public static final int TEXT_WIDTH_CONSTANT = 7; public static final int TEXT_HEIGHT_CONSTANT = 20; // https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements public static final Set BLOCK_ELEMENTS = new HashSet<>( Arrays.asList("address", "article", "aside", "blockquote", "body", "details", "dialog", "dd", "div", "dl", "dt", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "header", "hgroup", "hr", "li", "main", "nav", "ol", "p", "pre", "section", "table", "ul")); public static final Set HIDDEN_ELEMENTS = new HashSet<>( Arrays.asList("head", "meta", "link", "title")); // the big function public abstract void layout(); public Layout(Node node, Layout parent) { this.associatedNode = node; this.location = new Point(); this.dimension = new Dimension(); this.parent = parent; this.previousSibling = Optional.empty(); this.nextSibling = Optional.empty(); this.children = new ArrayList<>(); } // eh, probably the best place to put this // parent MAY BE nil: a handy call to Optional.ofNullable allows this public static ArrayList constructTree(ArrayList html, Layout parent) { var result = new ArrayDeque(); for (Node node : html) { Layout layout; switch (node) { case ElementNode e -> { if (BLOCK_ELEMENTS.contains(e.tag)) { layout = new BlockLayout(e, parent); } else { layout = new InlineLayout(e, parent); } layout.children = constructTree(e.children, layout); } case TextNode t -> { layout = new TextLayout(t, parent); } default -> throw new IllegalStateException("Unexpected value: " + node); } if (result.size() > 0) { layout.previousSibling = Optional.of(result.getLast()); result.getLast().nextSibling = Optional.of(layout); } result.add(layout); } return new ArrayList<>(result); // haha } public static DocumentLayout constructTree(ArrayList html) { var result = new DocumentLayout(); result.children = constructTree(html, result); result.layout(); return result; } }