Skip to content

Commit 269439c

Browse files
authored
Merge pull request #6 from Miras3210/gui
Merge GUI features to main
2 parents 3a44fe9 + d133706 commit 269439c

File tree

6 files changed

+366
-106
lines changed

6 files changed

+366
-106
lines changed

src/gui/__init__.py

Lines changed: 26 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
from typing import Protocol
2-
31
import js # type: ignore[import]
42

3+
from gui.components.description import Description
4+
from gui.components.image_preview import ImagePreview
5+
from gui.components.terminal_gui import TerminalGui
56
from gui.element import Element
67

78
_base_style = """
@@ -13,35 +14,10 @@
1314
display: flex;
1415
flex-direction: column;
1516
overflow: hidden;
16-
font-family: monospace, serif;
17-
}
18-
19-
.image {
20-
background-color: #adadad;
21-
height: 50%;
22-
display: flex;
23-
flex-direction: column;
24-
justify-content: center;
25-
align-items: center;
26-
}
27-
28-
.separator {
29-
background-color: rgb(119, 119, 119);
30-
width: 100%;
31-
height: 1%;
32-
cursor: pointer;
33-
}
34-
35-
.terminal {
36-
font-size: 1.5em;
37-
padding: 20px;
38-
background-color: black;
39-
color: white;
40-
flex-grow: 1;
41-
overflow-y: scroll;
17+
font-family: monospace;
4218
}
4319
44-
.document-panel {
20+
#description {
4521
position:fixed;
4622
top: 0;
4723
right: 0;
@@ -56,32 +32,31 @@
5632
align-items: center;
5733
}
5834
59-
.document-panel.open {
35+
#description.open {
6036
width: 40%;
6137
height: 100%;
6238
overflow-y: auto;
6339
overflow-x: hidden;
6440
}
6541
66-
.expand-btn {
67-
background-color: rgb(119, 119, 119);
68-
cursor: pointer;
69-
width: 100%;
70-
text-align: center;
71-
user-select: none;
42+
#terminal::selection,
43+
#terminal-input::selection,
44+
#terminal-input-field::selection,
45+
.user-input::selection {
46+
background-color: white;
47+
color: black;
7248
}
7349
74-
.documents {
75-
text-align: left;
76-
padding: 10%;
50+
.terminal-output::selection {
51+
color: black;
52+
background-color: var(--terminal-output-color, white);
7753
}
78-
"""
79-
8054
81-
class _MouseEvent(Protocol):
82-
button: int
83-
clientX: int # noqa: N815
84-
clientY: int # noqa: N815
55+
.terminal-output {
56+
color: var(--terminal-output-color, white);
57+
background-color: black;
58+
}
59+
"""
8560

8661

8762
def init_gui() -> Element:
@@ -93,58 +68,12 @@ def init_gui() -> Element:
9368
base_style.text = _base_style
9469
js.document.head.appendChild(base_style.html_element)
9570

96-
image = Element("div", parent=body, id="image")
97-
image.text = "[Placeholder Image]"
98-
image.class_name = "image"
99-
100-
is_dragging = False
101-
102-
def move_separator_to_mouse(event: _MouseEvent) -> None:
103-
if not is_dragging:
104-
return
105-
mouse_y = event.clientY
106-
image["style"].height = str(mouse_y) + "px"
107-
108-
def attach_separator_to_mouse(event: _MouseEvent) -> None:
109-
if event.button != 0:
110-
return
111-
nonlocal is_dragging
112-
is_dragging = True
113-
body["style"].userSelect = "none"
114-
115-
def release_separator(_event: _MouseEvent) -> None:
116-
nonlocal is_dragging
117-
is_dragging = False
118-
body["style"].userSelect = "auto"
119-
120-
def on_body_mousemove(event: _MouseEvent) -> None:
121-
if is_dragging:
122-
move_separator_to_mouse(event)
123-
124-
body.on("mouseup", release_separator)
125-
body.on("mousemove", on_body_mousemove)
126-
127-
separator = Element("div", parent=body, id="separator")
128-
separator.class_name = "separator"
129-
130-
separator.on("mousedown", attach_separator_to_mouse)
131-
separator.on("mouseup", release_separator)
132-
133-
terminal = Element("div", parent=body, id="terminal")
134-
terminal.class_name = "terminal"
135-
terminal.text = "Image editor v2.1 $ ping\npong!\nImage editor v2.1 $"
136-
137-
document_panel = Element("div", parent=body, id="DocumentPanel")
138-
document_panel.class_name = "document-panel"
139-
140-
expand_btn = Element("div", parent=document_panel, id="ExpandBtn")
141-
expand_btn.class_name = "expand-btn"
142-
expand_btn.text = "☰"
143-
144-
expand_btn.on("click", lambda _: document_panel["classList"].toggle("open"))
71+
image_preview = ImagePreview(parent=body)
72+
TerminalGui(parent=body)
73+
description = Description(parent=body)
14574

146-
documents = Element("div", parent=document_panel, id="Documents")
147-
documents.class_name = "documents"
148-
documents.text = "How to use the app:"
75+
body.on("click", lambda _: description["classList"].remove("open"))
76+
body.on("mouseup", image_preview.on_separator_mouse_up)
77+
body.on("mousemove", image_preview.on_separator_mouse_move)
14978

15079
return body

src/gui/components/__init__.py

Whitespace-only changes.

src/gui/components/description.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from typing import Any
2+
3+
from gui.element import Button, Element, HTMLElement
4+
5+
6+
class Description(Element):
7+
"""The description element for displaying useful information to the user."""
8+
9+
def __init__(self, parent: HTMLElement | Element | None = None) -> None:
10+
super().__init__("div", parent=parent, id="description")
11+
self.class_name = "description"
12+
13+
expand_btn = Button(
14+
parent=self,
15+
id="expand-btn",
16+
style="""
17+
background-color: rgb(119, 119, 119);
18+
width: 100%;
19+
text-align: center;
20+
user-select: none;
21+
""",
22+
)
23+
expand_btn.class_name = "expand-btn"
24+
expand_btn.text = "☰"
25+
expand_btn.on_click(self._on_expand_btn_click)
26+
27+
description_content = Element(
28+
"div",
29+
parent=self,
30+
id="description-content",
31+
style="""
32+
text-align: left;
33+
padding: 10%;
34+
""",
35+
)
36+
description_content.class_name = "description-content"
37+
description_content.text = "How to use the app:"
38+
39+
self.on("click", lambda event: event.stopPropagation())
40+
41+
def _on_expand_btn_click(self, event: Any) -> None: # noqa: ANN401
42+
self["classList"].toggle("open")
43+
event.stopPropagation()
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
from typing import Any
2+
3+
from gui.element import Element, HTMLElement
4+
5+
6+
class ImagePreview(Element):
7+
"""A component for displaying an image preview with a draggable separator."""
8+
9+
is_dragging = False
10+
11+
def __init__(self, parent: HTMLElement | Element | None = None) -> None:
12+
super().__init__(
13+
tag_name="div",
14+
parent=parent,
15+
id="image-preview",
16+
style="""
17+
background-color: #adadad;
18+
height: 50%;
19+
display: flex;
20+
flex-direction: column;
21+
justify-content: center;
22+
align-items: center;
23+
flex-shrink: 0;
24+
""",
25+
)
26+
self.class_name = "image-preview"
27+
self.text = "[Placeholder Image]"
28+
separator = Element(
29+
"div",
30+
parent=parent,
31+
id="separator",
32+
style="""
33+
background-color: rgb(119, 119, 119);
34+
width: 100%;
35+
height: 1%;
36+
cursor: pointer;
37+
flex-shrink: 0;
38+
""",
39+
)
40+
separator.class_name = "separator"
41+
42+
separator.on("mousemove", self.on_separator_mouse_move)
43+
separator.on("mousedown", self.on_separator_mouse_down)
44+
separator.on("mouseup", self.on_separator_mouse_up)
45+
46+
def on_separator_mouse_move(self, event: Any) -> None: # noqa: ANN401
47+
"""Handle mouse movement over the separator to adjust the height of the image preview."""
48+
if not self.is_dragging:
49+
return
50+
mouse_y = event.clientY
51+
self["style"].height = str(mouse_y) + "px"
52+
53+
def on_separator_mouse_down(self, event: Any) -> None: # noqa: ANN401
54+
"""Handle mouse down on the separator to start dragging."""
55+
if event.button != 0:
56+
return
57+
self.is_dragging = True
58+
59+
def on_separator_mouse_up(self, _event: Any) -> None: # noqa: ANN401
60+
"""Handle mouse up on the separator to stop dragging."""
61+
self.is_dragging = False

0 commit comments

Comments
 (0)