Skip to content

Commit

Permalink
Add initial support for input radio and checkbox
Browse files Browse the repository at this point in the history
  • Loading branch information
aaralh committed Dec 3, 2023
1 parent cd1c9f8 commit 37a5f79
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 23 deletions.
11 changes: 10 additions & 1 deletion browser/Browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,20 @@ def handle_canvas_click(self, e):
self.search_bar.insert(END, url)
return self.load(url)
elif elt.name == "input":
if elt.attributes.get("type", "") == "submit":
type = elt.attributes.get("type", "input")
if type == "submit":
while elt:
if elt.name == "form" and "action" in elt.attributes:
return self.submit_form(elt)
elt = elt.parentNode
elif type == "radio" or type == "checkbox":
current_value = elt.attributes.get("value", "off")
if current_value == "off":
elt.attributes["value"] = "on"
elif current_value == "on" and type != "radio":
elt.attributes["value"] = "off"
self.redraw()
return
else:
if not elt.attributes.get("value"):
elt.attributes["value"] = ""
Expand Down
30 changes: 30 additions & 0 deletions browser/elements/elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,36 @@ class BorderProperties:
color: ValidColor
width: int

class DrawOval:
def __init__(self, x1, y1, x2, y2, color: ValidColor, border: BorderProperties = BorderProperties(transform_color(""), 0)):
self.top = y1
self.left = x1
self.bottom = y2
self.right = x2
self.color = color
self.used_resources = None
self.border = border

def execute(self, scroll: int, canvas: Canvas, supported_emojis: List[str]):
# TODO: Do proper implementation for rgb and rgba colors.
if self.color.type == "rgba_color":
if not self.used_resources:
image = Image.new('RGBA', (int(self.right-self.left), int(self.bottom-self.top)), self.color.color)
tk_image = ImageTk.PhotoImage(image)
self.used_resources = tk_image
canvas.create_image((self.left, self.top - scroll), image=self.used_resources, anchor='nw')
if not self.color.type == "rgba_color":
outline = self.border.color.color
if self.border.color.type == "rgba_color":
outline = "#" + rgba_to_hex(outline)[:-2]
canvas.create_oval(
self.left, self.top - scroll,
self.right, self.bottom - scroll,
width=self.border.width,
fill=self.color.color,
outline=outline
)

class DrawRect:
def __init__(self, x1, y1, x2, y2, color: ValidColor, border: BorderProperties = BorderProperties(transform_color(""), 0)):
self.top = y1
Expand Down
6 changes: 5 additions & 1 deletion browser/layouts/InlineLayout.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,11 @@ def input(self, element: Union[HTMLInputElement, HTMLButtonElement]):
if style == "normal": style = "roman"
size = int(float(element.style["font-size"][:-2]) * .75)
font = get_font(size, font_weight_to_string(weight), style)
w = INPUT_WIDTH_PX
type = element.attributes.get("type")
if type == "radio" or type == "checkbox":
w = 10
else:
w = INPUT_WIDTH_PX
if self.cursor_x + w > self.x + self.width:
self.new_line()
line = self.children[-1]
Expand Down
66 changes: 45 additions & 21 deletions browser/layouts/InputLayout.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import List
from browser.elements.elements import DrawRect, DrawText
from tkinter import W
from typing import List, Literal
from browser.elements.elements import DrawOval, DrawRect, DrawText
from browser.layouts.Layout import Layout
from browser.layouts.utils import font_weight_to_string, get_font
from browser.styling.color.utils import transform_color
Expand All @@ -16,6 +17,7 @@ def __init__(self, node: Node, parent: Layout, previous: Layout):
super().__init__()
self.children = []
self.previous = previous
self.type: Literal["input", "radio", "checkbox"] = self.node.attributes.get("type", "input")

def layout(self):
super().layout()
Expand All @@ -25,7 +27,12 @@ def layout(self):
size = int(float(self.node.style["font-size"][:-2]) * .75)
self.font = get_font(size, font_weight_to_string(weight), style)

self.width = INPUT_WIDTH_PX
if self.type == "radio" or self.type == "checkbox":
self.width = 10
self.height = 10
else:
self.width = INPUT_WIDTH_PX
self.height = self.font.metrics("linespace")

if self.node.attributes.get("type", "") == "submit":
text = self.node.attributes.get("value", None)
Expand All @@ -46,14 +53,13 @@ def layout(self):
if self.width < min_width:
self.width = min_width"""

self.height = self.font.metrics("linespace")


def paint(self, display_list: list):
if self.node.attributes.get("type") == "hidden": return
if self.node.attributes.get("type") == "hidden": return

bgcolor = self.node.style.get("background-color",
"transparent")

if bgcolor == "unset":
try:
if isinstance(self.node.parentNode, Element):
Expand All @@ -64,18 +70,35 @@ def paint(self, display_list: list):

if bgcolor != "transparent":
x2, y2 = self.x + self.width, self.y + self.height
if self.border:
rect = DrawRect(self.x, self.y, x2, y2, transform_color(bgcolor), self.border)
if self.type == "radio":
display_list.append(
DrawOval(self.x, self.y, x2, y2, transform_color(bgcolor), self.border)
)

text = self.node.attributes.get("value", None)
if text == "on":
display_list.append(
DrawOval(self.x + 2, self.y + 2, x2 - 2, y2 - 2, transform_color("black"), self.border)
)
elif self.type == "checkbox":
display_list.append(
DrawRect(self.x, self.y, x2, y2, transform_color(bgcolor), self.border)
)
text = self.node.attributes.get("value", None)
if text == "on":
display_list.append(
DrawRect(self.x + 2, self.y + 2, x2 - 2, y2 - 2, transform_color("black"), self.border)
)
else:
rect = DrawRect(self.x, self.y, x2, y2, transform_color(bgcolor))
display_list.append(rect)
display_list.append(DrawRect(self.x, self.y, x2, y2, transform_color(bgcolor), self.border))

if self.node.name == "input":
text = self.node.attributes.get("value", None)
if not text:
text = self.node.attributes.get('alt', " ")
if len(text) == 0:
text = self.node.attributes.get("placeholder", "")
if self.type == "input":
text = self.node.attributes.get("value", None)
if not text:
text = self.node.attributes.get('alt', " ")
if len(text) == 0:
text = self.node.attributes.get("placeholder", "")
elif self.node.name == "button":
visible_children: List[Node] = list(filter(lambda child: child.style.get("display") != "none", self.node.children))
if len(visible_children) == 0: return
Expand All @@ -87,9 +110,10 @@ def paint(self, display_list: list):
text = child.children[0].data
except:
text = ""

color = self.node.style["color"]

display_list.append(
DrawText(self.x, self.y, text, self.font, color)
)
if self.type == "input" or self.type == "button":
display_list.append(
DrawText(self.x, self.y, text, self.font, color)
)

0 comments on commit 37a5f79

Please sign in to comment.