aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJJ2022-12-29 02:07:29 +0000
committerJJ2022-12-29 02:20:51 +0000
commit595853ad76bbebf74a9a737870d5a89fb9f21f55 (patch)
treebb0f0dc491696519c3a5eae9a89087b7b626a004
parentddf614b732649875f20b54af3ef622c5c39127ff (diff)
Rework layout generator
-rw-r--r--src/main/model/html/HtmlParser.java22
-rw-r--r--src/main/model/html/TextNode.java1
-rw-r--r--src/main/model/layout/BlockLayout.java23
-rw-r--r--src/main/model/layout/DocumentLayout.java9
-rw-r--r--src/main/model/layout/InlineLayout.java50
-rw-r--r--src/main/model/layout/Layout.java25
-rw-r--r--src/main/model/layout/TextLayout.java21
-rw-r--r--src/main/ui/BrowserCanvas.java21
-rw-r--r--src/main/ui/BrowserWindow.java5
9 files changed, 79 insertions, 98 deletions
diff --git a/src/main/model/html/HtmlParser.java b/src/main/model/html/HtmlParser.java
index a3abe0f..6e015ae 100644
--- a/src/main/model/html/HtmlParser.java
+++ b/src/main/model/html/HtmlParser.java
@@ -60,8 +60,6 @@ public class HtmlParser {
public ArrayList<Node> parseHtml(String input) {
for (char c : input.toCharArray()) {
- // System.out.print(state);
- // System.out.println(" " + c + " " + currentText);
switch (state) {
case HTML -> caseHtml(c);
case UNKNOWN_TAG -> caseUnknownTag(c);
@@ -85,7 +83,7 @@ public class HtmlParser {
addNewTextNode();
}
}
- case ' ', '\n' -> {
+ case ' ', '\t', '\n' -> {
if (previousChar != ' ') {
currentText += ' ';
}
@@ -125,7 +123,7 @@ public class HtmlParser {
private void caseOpeningTag(char c) {
switch (c) {
case '>' -> addNewElementNode();
- case ' ', '\n' -> state = ParserState.KEY;
+ case ' ', '\t', '\n' -> state = ParserState.KEY;
default -> currentTag += c;
}
}
@@ -142,7 +140,7 @@ public class HtmlParser {
}
currentTag = "";
}
- case ' ', '\n' -> {}
+ case ' ', '\t', '\n' -> {}
default -> currentTag += c;
}
}
@@ -151,7 +149,7 @@ public class HtmlParser {
switch (c) {
case '>' -> addNewElementNode();
case '=' -> state = ParserState.VALUE;
- case ' ', '\n' -> {}
+ case ' ', '\t', '\n' -> {}
default -> currentKey += c;
}
}
@@ -160,7 +158,7 @@ public class HtmlParser {
switch (c) {
case '\'' -> state = ParserState.SINGLE_QUOTES;
case '\"' -> state = ParserState.DOUBLE_QUOTES;
- case ' ', '\n' -> {
+ case ' ', '\t', '\n' -> {
state = ParserState.KEY;
currentAttributes.add(new Pair<>(currentKey, currentValue));
currentKey = "";
@@ -237,10 +235,12 @@ public class HtmlParser {
// Helper function to check method length boxes.
private void addNewTextNode() {
- if (unfinished.size() != 0) {
- unfinished.getLast().children.add(new TextNode(currentText));
- } else {
- result.add(new TextNode(currentText));
+ if (!currentText.equals(" ")) { // fixme
+ if (unfinished.size() != 0) {
+ unfinished.getLast().children.add(new TextNode(currentText));
+ } else {
+ result.add(new TextNode(currentText));
+ }
}
currentText = "";
previousChar = '\0';
diff --git a/src/main/model/html/TextNode.java b/src/main/model/html/TextNode.java
index 29f2791..cebf854 100644
--- a/src/main/model/html/TextNode.java
+++ b/src/main/model/html/TextNode.java
@@ -4,6 +4,7 @@ package model.html;
* This TextNode class represents raw text, with no nested tags.
*/
public record TextNode(String text) implements Node {
+
// We implement this method for easy debugging.
public String data() {
return text();
diff --git a/src/main/model/layout/BlockLayout.java b/src/main/model/layout/BlockLayout.java
index 9264035..89bbbe4 100644
--- a/src/main/model/layout/BlockLayout.java
+++ b/src/main/model/layout/BlockLayout.java
@@ -1,31 +1,24 @@
package model.layout;
-import model.html.Node;
-
-import java.awt.*;
+import model.html.ElementNode;
public class BlockLayout extends Layout {
- public BlockLayout(Node node, Layout parent) {
+ public BlockLayout(ElementNode node, Layout parent) {
super(node, parent);
}
// recursively construct the layout tree
public void layout() {
- this.location = (Point) this.parent.location.clone();
- this.previousSibling.ifPresent(
- sibling -> this.location.y = sibling.location.y + sibling.dimension.height);
-// this.previousSibling.ifPresent(
-// sibling -> System.out.println("bluh" + sibling.associatedNode.data()));
-
-// this.dimension = (Dimension) this.parent.dimension.clone();
+ this.location.x = this.parent.location.x;
+ this.location.y = this.previousSibling
+ .map(sibling -> sibling.location.y + sibling.dimension.height)
+ .orElseGet(() -> this.parent.location.y);
for (Layout child : this.children) {
child.layout();
- this.dimension.height += child.dimension.height;
+ this.dimension.height = Math.max(this.dimension.height, (child.location.y + child.dimension.height) - this.location.y);
+ this.dimension.width = Math.max(this.dimension.width, (child.location.x + child.dimension.width) - this.location.x);
}
-// System.out.println(this.associatedNode.data() + this.location);
-// System.out.println(System.identityHashCode(this.location));
-// System.out.println(this.associatedNode.data() + this.dimension);
}
}
diff --git a/src/main/model/layout/DocumentLayout.java b/src/main/model/layout/DocumentLayout.java
index df2a1b9..b09ed10 100644
--- a/src/main/model/layout/DocumentLayout.java
+++ b/src/main/model/layout/DocumentLayout.java
@@ -1,7 +1,5 @@
package model.layout;
-import java.awt.*;
-
public class DocumentLayout extends Layout {
/*
@@ -15,12 +13,13 @@ public class DocumentLayout extends Layout {
// recursively construct the layout tree
public void layout() {
- this.location = new Point(10, 20);
- this.dimension = new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ this.location.x = DEFAULT_X;
+ this.location.y = DEFAULT_Y;
for (Layout child : this.children) {
child.layout();
- this.dimension.height += child.dimension.height;
+ this.dimension.height = Math.max(this.dimension.height, (child.location.y + child.dimension.height) - this.location.y);
+ this.dimension.width = Math.max(this.dimension.width, (child.location.x + child.dimension.width) - this.location.x);
}
}
}
diff --git a/src/main/model/layout/InlineLayout.java b/src/main/model/layout/InlineLayout.java
index 845a717..2940ef8 100644
--- a/src/main/model/layout/InlineLayout.java
+++ b/src/main/model/layout/InlineLayout.java
@@ -1,58 +1,26 @@
package model.layout;
import model.html.ElementNode;
-import model.html.Node;
-
-import java.awt.*;
public class InlineLayout extends Layout {
- private Point cursor;
-
- public InlineLayout(Node node, Layout parent) {
+ public InlineLayout(ElementNode node, Layout parent) {
super(node, parent);
- cursor = new Point();
}
// recursively construct the layout tree
public void layout() {
- this.location = (Point) this.parent.location.clone(); // java moment
- this.previousSibling.ifPresent(
- sibling -> this.location.y = sibling.location.y + sibling.dimension.height);
-
- this.dimension.width = this.parent.dimension.width;
- this.setCursor(this.location.x, this.location.y);
-
- Node node = this.associatedNode;
- switch (node) {
- case ElementNode e -> {
- if (e.tag.equals("a")) {
- this.location.x += this.parent.dimension.width;
- }
- }
- default -> {
- if (node.data().length() > 5) {
- this.dimension.height = 20;
-// this.dimension.width = this.dimension.width + node.data().length();
- }
- }
- }
+ this.location.x = this.previousSibling
+ .map(sibling -> sibling.location.x + sibling.dimension.width)
+ .orElseGet(() -> this.parent.location.x);
+ this.location.y = this.previousSibling
+ .map(sibling -> sibling.location.y)
+ .orElseGet(() -> this.parent.location.y);
for (Layout child : this.children) {
child.layout();
- this.dimension.height += child.dimension.height; // fixme
+ this.dimension.height = Math.max(this.dimension.height, (child.location.y + child.dimension.height) - this.location.y);
+ this.dimension.width = Math.max(this.dimension.width, (child.location.x + child.dimension.width) - this.location.x);
}
-
- // todo: recurse to calculate cursor
-// this.height = cursor.location.y - this.location.y;
-// System.out.println(this.associatedNode.data() + this.location);
- }
-
- public void setCursor(Point cursor) {
- this.cursor = cursor;
- }
-
- public void setCursor(double x, double y) {
- this.cursor.setLocation(x, y);
}
}
diff --git a/src/main/model/layout/Layout.java b/src/main/model/layout/Layout.java
index d9c3954..c7ea74a 100644
--- a/src/main/model/layout/Layout.java
+++ b/src/main/model/layout/Layout.java
@@ -1,7 +1,6 @@
package model.layout;
-import model.html.ElementNode;
-import model.html.Node;
+import model.html.*;
import java.awt.*;
import java.util.*;
@@ -11,8 +10,8 @@ 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 Point location;
- public Dimension dimension;
+ public final Point location;
+ public final Dimension dimension;
public final Node associatedNode;
public final Layout parent;
@@ -20,17 +19,24 @@ public abstract class Layout {
public Optional<Layout> nextSibling;
public ArrayList<Layout> 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<String> BLOCK_ELEMENTS = new HashSet<>(
- Arrays.asList("address", "article", "aside", "blockquote",
+ 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<String> HIDDEN_ELEMENTS = new HashSet<>(
+ Arrays.asList("head", "meta", "link", "title"));
+
// the big function
public abstract void layout();
@@ -55,15 +61,16 @@ public abstract class Layout {
switch (node) {
case ElementNode e -> {
if (BLOCK_ELEMENTS.contains(e.tag)) {
- layout = new BlockLayout(node, parent);
+ layout = new BlockLayout(e, parent);
} else {
- layout = new InlineLayout(node, parent);
+ layout = new InlineLayout(e, parent);
}
layout.children = constructTree(e.children, layout);
}
- default -> {
- layout = new InlineLayout(node, parent);
+ case TextNode t -> {
+ layout = new TextLayout(t, parent);
}
+ default -> throw new IllegalStateException("Unexpected value: " + node);
}
if (result.size() > 0) {
diff --git a/src/main/model/layout/TextLayout.java b/src/main/model/layout/TextLayout.java
new file mode 100644
index 0000000..67a07a4
--- /dev/null
+++ b/src/main/model/layout/TextLayout.java
@@ -0,0 +1,21 @@
+package model.layout;
+
+import model.html.TextNode;
+
+public class TextLayout extends Layout {
+
+ public TextLayout(TextNode node, Layout parent) {
+ super(node, parent);
+ }
+
+ // recursively construct the layout tree
+ public void layout() {
+ this.location.x = this.previousSibling
+ .map(sibling -> sibling.location.x + sibling.dimension.width)
+ .orElseGet(() -> this.parent.location.x);
+ this.location.y = this.parent.location.y;
+
+ this.dimension.height = TEXT_HEIGHT_CONSTANT;
+ this.dimension.width = this.associatedNode.data().length() * TEXT_WIDTH_CONSTANT;
+ }
+}
diff --git a/src/main/ui/BrowserCanvas.java b/src/main/ui/BrowserCanvas.java
index ea20e81..cde894f 100644
--- a/src/main/ui/BrowserCanvas.java
+++ b/src/main/ui/BrowserCanvas.java
@@ -13,33 +13,26 @@ public class BrowserCanvas extends JPanel {
public BrowserCanvas(ArrayList<Node> html) {
super();
this.currentLayout = Layout.constructTree(html);
- printTree(this.currentLayout.children);
- }
-
- private void printTree(ArrayList<Layout> tree) {
- for (Layout node : tree) {
-// System.out.println(System.identityHashCode(node.location));
- printTree((node).children);
- }
+ this.setBackground(Color.BLACK);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Point location = new Point(10, 20); // we need a mutable reference
+ g.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
+ g.setColor(Color.WHITE);
+ g.drawString("X", location.x, location.y);
renderHtml(this.currentLayout.children, g, location);
}
private void renderHtml(ArrayList<Layout> tree, Graphics g, Point location) {
for (Layout layout : tree) {
-// System.out.println(layout.location);
+ g.setColor(new Color((int)(Math.random() * 0x1000000)));
g.drawRect(layout.location.x, layout.location.y, layout.dimension.width, layout.dimension.height);
+ g.setColor(Color.WHITE);
if (layout.associatedNode instanceof TextNode) {
- if (layout.associatedNode.data().length() > 5) {
-// System.out.println(location);
- g.drawString(layout.associatedNode.data(), layout.location.x, layout.location.y);
- g.drawString("X", 10, 20);
- }
+ g.drawString(layout.associatedNode.data(), layout.location.x, layout.location.y + layout.dimension.height - 5);
} else {
renderHtml(layout.children, g, location);
}
diff --git a/src/main/ui/BrowserWindow.java b/src/main/ui/BrowserWindow.java
index abf164f..28d0b13 100644
--- a/src/main/ui/BrowserWindow.java
+++ b/src/main/ui/BrowserWindow.java
@@ -10,8 +10,8 @@ import java.util.*;
// Broad JFrame usage taken from here: https://docs.oracle.com/javase/tutorial/uiswing/components/frame.html
public class BrowserWindow extends JFrame {
- public static final int WIDTH = 1200;
- public static final int HEIGHT = 800;
+ public static final int WIDTH = 1500;
+ public static final int HEIGHT = 500;
private BrowserCanvas canvas;
private final BrowserBar browserBar;
@@ -34,7 +34,6 @@ public class BrowserWindow extends JFrame {
public void render(String uri) {
state.currentTab = uri;
remove(canvas);
-// System.out.println(state.currentTab);
try {
String file = Files.readString(Path.of(state.currentTab));
HtmlParser parser = new HtmlParser();