Implement rendering to TreeView

This commit is contained in:
Joscha 2019-05-11 20:39:57 +00:00
parent 4dbdb8d976
commit 01a97c4147

View file

@ -3,6 +3,7 @@ from typing import Any, List, Optional, Set
from .element import Element, ElementSupply, Id, RenderedElement from .element import Element, ElementSupply, Id, RenderedElement
from .exceptions import TreeException from .exceptions import TreeException
from .markup import AttributedText
from .tree_list import TreeList from .tree_list import TreeList
__all__ = ["TreeDisplay"] __all__ = ["TreeDisplay"]
@ -148,8 +149,8 @@ class TreeDisplay:
- make sure the anchor is visible - make sure the anchor is visible
""" """
self._width = width self.width = width
self._height = height self.height = height
#self._root_id: Optional[Id] = None # TODO add root stuff #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. 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: def render_display_lines(self) -> None:
""" """
@ -278,116 +356,6 @@ class TreeDisplay:
self.fold(element_id) self.fold(element_id)
return True 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: # Terminology:
# #
# root # root