Implement rendering to TreeView
This commit is contained in:
parent
4dbdb8d976
commit
01a97c4147
1 changed files with 81 additions and 113 deletions
|
|
@ -3,6 +3,7 @@ from typing import Any, List, Optional, Set
|
|||
|
||||
from .element import Element, ElementSupply, Id, RenderedElement
|
||||
from .exceptions import TreeException
|
||||
from .markup import AttributedText
|
||||
from .tree_list import TreeList
|
||||
|
||||
__all__ = ["TreeDisplay"]
|
||||
|
|
@ -148,8 +149,8 @@ class TreeDisplay:
|
|||
- make sure the anchor is visible
|
||||
"""
|
||||
|
||||
self._width = width
|
||||
self._height = height
|
||||
self.width = width
|
||||
self.height = height
|
||||
|
||||
#self._root_id: Optional[Id] = None # TODO add root stuff
|
||||
|
||||
|
|
@ -187,7 +188,84 @@ class TreeDisplay:
|
|||
anchor offset, cursor, width or height are manually changed.
|
||||
"""
|
||||
|
||||
pass # TODO
|
||||
if self.anchor_id is None:
|
||||
# As described in the class docstring, we have no starting point
|
||||
# for rendering, so we don't even attempt it.
|
||||
self._rendered = None
|
||||
return
|
||||
|
||||
anchor_tree = self._render_tree(self.anchor_id)
|
||||
|
||||
self._rendered = TreeList(anchor_tree, self.anchor_id)
|
||||
self._rendered.offset_by(self.anchor_offset)
|
||||
|
||||
self._fill_screen_upwards()
|
||||
self._fill_screen_downwards()
|
||||
|
||||
def _render_tree(self,
|
||||
tree_id: Id,
|
||||
depth: int = 0
|
||||
) -> List[RenderedElement]:
|
||||
|
||||
elements: List[RenderedElement] = []
|
||||
|
||||
highlighted = tree_id == self.cursor_id
|
||||
folded = tree_id in self._folded
|
||||
|
||||
tree = self._supply.get(tree_id)
|
||||
rendered = tree.render(width=self.width, depth=depth,
|
||||
highlighted=highlighted, folded=folded)
|
||||
|
||||
elements.append(rendered)
|
||||
|
||||
if not folded:
|
||||
for child_id in self._supply.get_children_ids(tree_id):
|
||||
subelements = self._render_tree(child_id, depth=depth+1)
|
||||
elements.extend(subelements)
|
||||
|
||||
return elements
|
||||
|
||||
def _fill_screen_upwards(self) -> None:
|
||||
if self._rendered is None:
|
||||
raise TreeException((
|
||||
"Can't fill screen upwards without a TreeList. This exception"
|
||||
" should never occur."
|
||||
))
|
||||
|
||||
while True:
|
||||
if self._rendered.upper_offset <= 0:
|
||||
break
|
||||
|
||||
above_tree_id = self._supply.get_previous_id(
|
||||
self._rendered.upper_tree_id)
|
||||
|
||||
if above_tree_id is None:
|
||||
break # We've hit the top of the supply
|
||||
|
||||
self._rendered.add_above(self._render_tree(above_tree_id))
|
||||
|
||||
def _fill_screen_downwards(self) -> None:
|
||||
"""
|
||||
Eerily similar to _fill_screen_upwards()...
|
||||
"""
|
||||
|
||||
if self._rendered is None:
|
||||
raise TreeException((
|
||||
"Can't fill screen downwards without a TreeList. This exception"
|
||||
" should never occur."
|
||||
))
|
||||
|
||||
while True:
|
||||
if self._rendered.lower_offset <= 0:
|
||||
break
|
||||
|
||||
below_tree_id = self._supply.get_previous_id(
|
||||
self._rendered.upper_tree_id)
|
||||
|
||||
if below_tree_id is None:
|
||||
break # We've hit the bottom of the supply
|
||||
|
||||
self._rendered.add_below(self._render_tree(below_tree_id))
|
||||
|
||||
def render_display_lines(self) -> None:
|
||||
"""
|
||||
|
|
@ -278,116 +356,6 @@ class TreeDisplay:
|
|||
self.fold(element_id)
|
||||
return True
|
||||
|
||||
# OTHER STUFF
|
||||
|
||||
def resize(self, width: int, height: int) -> None:
|
||||
# TODO maybe empty _rendered/invalidate caches etc.?
|
||||
self._width = width
|
||||
self._height = height
|
||||
|
||||
def render(self) -> None:
|
||||
# Steps:
|
||||
#
|
||||
# 1. Find and render anchor's branch to TreeList
|
||||
# 2. Render above and below the branch until the screen is full (with
|
||||
# the specified anchor offset)
|
||||
# 2.1. Keep the TreeList for later things like scrolling
|
||||
# 3. Cut out the visible lines and messages
|
||||
# 4. Cut out the visible parts horizontally (self._horizontal_offset)
|
||||
# 4.1. Keep the result for later reference (mouse clicks)
|
||||
# 5. Convert the result to plain text and draw it in the curses window
|
||||
#
|
||||
# Not happy with these steps yet. Scrolling, checking if the cursor is
|
||||
# in view, switching anchors etc. still feel weird.
|
||||
#
|
||||
# TODO Add the above into the TreeDisplay model.
|
||||
|
||||
if self._anchor_id is None:
|
||||
self._rendered = None
|
||||
return
|
||||
|
||||
if self._root_id is None:
|
||||
ancestor_id = self._supply.get_furthest_ancestor_id(
|
||||
self._anchor_id)
|
||||
else:
|
||||
ancestor_id = self._root_id
|
||||
|
||||
ancestor_tree = self._render_tree(self._supply.get_tree(ancestor_id))
|
||||
|
||||
self._rendered = TreeList(ancestor_tree, self._anchor_id)
|
||||
self._rendered.offset_by(self._anchor_offset)
|
||||
|
||||
if self._root_id is None:
|
||||
self._fill_screen_upwards()
|
||||
self._fill_screen_downwards()
|
||||
|
||||
self._pad.set_lines(self._rendered.to_lines())
|
||||
# The vertical offset (anchor offset) is already being dealt with in
|
||||
# the TreeView, since it is more useful to apply it there (each line's
|
||||
# offset/index is also the anchor offset it would have if it was the
|
||||
# anchor.
|
||||
self._pad.stamp(self._horizontal_offset, 0, self._width, self._height)
|
||||
|
||||
def _render_tree(self,
|
||||
tree: Element,
|
||||
depth: int = 0
|
||||
) -> List[RenderedElement]:
|
||||
elements: List[RenderedElement] = []
|
||||
|
||||
highlighted = tree.id == self._cursor_id
|
||||
folded = tree.id in self._folded
|
||||
|
||||
elements.append(tree.render(depth=depth, highlighted=highlighted,
|
||||
folded=folded))
|
||||
|
||||
if not folded:
|
||||
for child in tree.children:
|
||||
elements.extend(self._render_tree(child, depth=depth+1))
|
||||
|
||||
return elements
|
||||
|
||||
def _fill_screen_upwards(self) -> None:
|
||||
if self._rendered is None:
|
||||
return # TODO think of sensible thing to do here
|
||||
|
||||
while True:
|
||||
if self._rendered.upper_offset <= 0:
|
||||
break
|
||||
|
||||
above_tree_id = self._supply.get_previous_id(
|
||||
self._rendered.upper_tree_id)
|
||||
|
||||
if above_tree_id is None:
|
||||
break
|
||||
|
||||
above_tree = self._supply.get_tree(above_tree_id)
|
||||
self._rendered.add_above(self._render_tree(above_tree))
|
||||
|
||||
def _fill_screen_downwards(self) -> None:
|
||||
"""
|
||||
Eerily similar to _fill_screen_upwards()...
|
||||
"""
|
||||
|
||||
if self._rendered is None:
|
||||
return # TODO think of sensible thing to do here
|
||||
|
||||
while True:
|
||||
if self._rendered.lower_offset >= self._height - 1:
|
||||
break
|
||||
|
||||
below_tree_id = self._supply.get_next_id(
|
||||
self._rendered.lower_tree_id)
|
||||
|
||||
if below_tree_id is None:
|
||||
break
|
||||
|
||||
below_tree = self._supply.get_tree(below_tree_id)
|
||||
self._rendered.add_below(self._render_tree(below_tree))
|
||||
|
||||
def draw_to(self, window: Any) -> None:
|
||||
# TODO color styles of the text itself
|
||||
pass
|
||||
|
||||
# Terminology:
|
||||
#
|
||||
# root
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue