Skip to content

Commit

Permalink
Implement z-layers (#98)
Browse files Browse the repository at this point in the history
  • Loading branch information
JoshKarpel authored Jan 29, 2024
1 parent 3e40303 commit 414db6c
Show file tree
Hide file tree
Showing 16 changed files with 398 additions and 112 deletions.
10 changes: 2 additions & 8 deletions counterweight/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from counterweight._context_vars import current_event_queue
from counterweight._utils import drain_queue
from counterweight.border_healing import heal_borders
from counterweight.cell_paint import CellPaint
from counterweight.components import Component, component
from counterweight.controls import AnyControl, Bell, Quit, Screenshot, Suspend, ToggleBorderHealing, _Control
from counterweight.elements import AnyElement, Div
Expand All @@ -43,15 +42,10 @@
stop_mouse_tracking,
stop_output_control,
)
from counterweight.paint import Paint, paint_layout, svg
from counterweight.paint import BLANK, Paint, paint_layout, svg
from counterweight.shadow import ShadowNode, update_shadow
from counterweight.styles import Span, Style
from counterweight.styles.styles import CellStyle, Color, Flex

BLANK = CellPaint(
char=" ",
style=CellStyle(background=Color.from_name("black")),
)
from counterweight.styles.styles import Flex

logger = get_logger()

Expand Down
13 changes: 6 additions & 7 deletions counterweight/border_healing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

from functools import lru_cache

from counterweight.cell_paint import CellPaint
from counterweight.geometry import Position
from counterweight.paint import Paint
from counterweight.paint import P, Paint
from counterweight.styles.styles import JoinedBorderKind, JoinedBorderParts


Expand Down Expand Up @@ -40,15 +39,15 @@ def dither(position: Position) -> tuple[Position, Position, Position, Position]:

def heal_borders(paint: Paint) -> Paint:
overlay: Paint = {}
for p, cell_paint in paint.items():
char = cell_paint.char
for pos, p in paint.items():
char = p.char
for kind in JOINED_BORDER_KINDS:
if char not in kind: # the center character must be a joined border part
continue

left, right, above, below = map(paint.get, dither(p))
left, right, above, below = map(paint.get, dither(pos))

# TODO: cell styles must match too (i.e., colors)
# TODO: cell styles and z-levels must match too (i.e., colors)

if replaced_char := get_replacement_char(
kind,
Expand All @@ -58,6 +57,6 @@ def heal_borders(paint: Paint) -> Paint:
above=above.char if above else None,
below=below.char if below else None,
):
overlay[p] = CellPaint(char=replaced_char, style=cell_paint.style)
overlay[pos] = P(char=replaced_char, style=p.style, z=p.z)

return overlay
47 changes: 0 additions & 47 deletions counterweight/cell_paint.py

This file was deleted.

8 changes: 7 additions & 1 deletion counterweight/elements.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from __future__ import annotations

from dataclasses import dataclass, field
from functools import cached_property
from typing import Callable, Literal, Sequence, Union

from pydantic import Field

from counterweight.cell_paint import CellPaint
from counterweight.controls import AnyControl
from counterweight.events import KeyPressed, MouseDown, MouseUp
from counterweight.styles import CellStyle, Style
Expand Down Expand Up @@ -73,3 +73,9 @@ def cells(self) -> tuple[CellPaint, ...]:

Div.model_rebuild()
Text.model_rebuild()


@dataclass(slots=True)
class CellPaint:
char: str
style: CellStyle = field(default=CellStyle())
5 changes: 5 additions & 0 deletions counterweight/geometry.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from __future__ import annotations

from collections.abc import Iterator
from dataclasses import dataclass, field
from functools import lru_cache
from itertools import product
from typing import NamedTuple


Expand Down Expand Up @@ -36,6 +38,9 @@ def x_range(self) -> range:
def y_range(self) -> range:
return range(self.y, self.y + self.height)

def xy_range(self) -> Iterator[tuple[int, int]]:
return product(self.x_range(), self.y_range())

@property
def left(self) -> int:
return self.x
Expand Down
43 changes: 41 additions & 2 deletions counterweight/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

from collections.abc import Iterator
from dataclasses import dataclass, field
from typing import Iterable, Literal

from more_itertools import take
from structlog import get_logger

from counterweight._utils import halve_integer, partition_int
from counterweight.cell_paint import wrap_cells
from counterweight.components import Component
from counterweight.elements import AnyElement
from counterweight.elements import AnyElement, CellPaint
from counterweight.geometry import Edge, Rect
from counterweight.styles.styles import BorderEdge

Expand Down Expand Up @@ -63,6 +63,11 @@ class LayoutBox:
children: list[LayoutBox] = field(default_factory=list)
dims: LayoutBoxDimensions = field(default_factory=LayoutBoxDimensions)

def walk_from_top(self) -> Iterator[LayoutBox]:
yield self
for child in self.children:
yield from child.walk_from_top()

def walk_from_bottom(self) -> Iterator[LayoutBox]:
for child in self.children:
yield from child.walk_from_bottom()
Expand Down Expand Up @@ -432,3 +437,37 @@ def build_layout_tree_from_concrete_element_tree(element: AnyElement, parent: La
)

return box


def wrap_cells(
cells: Iterable[CellPaint],
wrap: Literal["none", "paragraphs"],
width: int,
) -> list[list[CellPaint]]:
if width <= 0:
return []

if wrap == "none":
lines: list[list[CellPaint]] = []
current_line: list[CellPaint] = []
for cell in cells:
if cell.char == "\n":
lines.append(current_line)
current_line = []
else:
current_line.append(cell)
lines.append(current_line)
return lines

raise NotImplementedError("non-none wrapping not yet implemented")

# wrapper = TextWrapper(width=width)
#
# paragraphs = text.split("\n\n") # double newline = paragraph break
#
# lines = []
# for paragraph in paragraphs:
# lines.extend(wrapper.wrap(paragraph))
# lines.append("") # empty line between paragraphs
#
# return lines[:-1] # remove last empty line
6 changes: 5 additions & 1 deletion counterweight/output.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
from typing import TextIO
from __future__ import annotations

from typing import TYPE_CHECKING, TextIO

from structlog import get_logger

from counterweight.geometry import Position
from counterweight.paint import Paint
from counterweight.styles.styles import CellStyle

if TYPE_CHECKING:
pass
# https://www.xfree86.org/current/ctlseqs.html
# https://invisible-island.net/xterm/ctlseqs/ctlseqs.pdf

Expand Down
Loading

0 comments on commit 414db6c

Please sign in to comment.