Partially move matrix recalculation to GtkView

This commit is contained in:
Arjan Molenaar 2020-10-24 21:45:03 +02:00
parent 1a1435a4ef
commit 7594c1da87
4 changed files with 46 additions and 37 deletions

View File

@ -415,8 +415,7 @@ class Canvas:
# full update (only called for items that requested a full update)
contexts = self._pre_update_items(dirty_items)
# recalculate matrices
dirty_matrix_items = self.update_matrices(self._dirty_matrix_items)
dirty_matrix_items = set(self._dirty_matrix_items)
self._dirty_matrix_items.clear()
# solve all constraints
@ -431,6 +430,7 @@ class Canvas:
if len(dirty_items) != len(self._dirty_items):
dirty_items = list(reversed(sort(self._dirty_items)))
# keep it here, since we need up to date matrices for the solver
for d in dirty_matrix_items:
d.matrix_i2c.set(*self.get_matrix_i2c(d))
@ -454,27 +454,6 @@ class Canvas:
self._update_views(dirty_items, dirty_matrix_items)
def update_matrices(self, items):
"""Recalculate matrices of the items. Items' children matrices are
recalculated, too.
Return items, which matrices were recalculated.
"""
changed = set()
for item in items:
parent = self._tree.get_parent(item)
if parent is not None and parent in items:
# item's matrix will be updated thanks to parent's matrix
# update
continue
changed.add(item)
changed_children = self.update_matrices(set(self.get_children(item)))
changed.update(changed_children)
return changed
def register_view(self, view):
"""Register a view on this canvas.

View File

@ -1,11 +1,14 @@
"""This module contains everything to display a Canvas on a screen."""
from typing import Optional, Set
import cairo
from gi.repository import Gdk, GLib, GObject, Gtk
from gaphas.canvas import Context, instant_cairo_context
from gaphas.canvas import Canvas, Context, instant_cairo_context
from gaphas.decorators import AsyncIO
from gaphas.geometry import Rectangle, distance_point_point_fast
from gaphas.item import Item
from gaphas.matrix import Matrix
from gaphas.position import Position
from gaphas.tool import DefaultTool
@ -71,11 +74,11 @@ class GtkView(Gtk.DrawingArea, Gtk.Scrollable, View):
),
}
def __init__(self, canvas=None):
def __init__(self, canvas: Optional[Canvas] = None):
Gtk.DrawingArea.__init__(self)
self._dirty_items = set()
self._dirty_matrix_items = set()
self._dirty_items: Set[Item] = set()
self._dirty_matrix_items: Set[Item] = set()
View.__init__(self, canvas)
@ -92,8 +95,8 @@ class GtkView(Gtk.DrawingArea, Gtk.Scrollable, View):
self._back_buffer = None
self._back_buffer_needs_resizing = True
self._hadjustment = None
self._vadjustment = None
self._hadjustment: Optional[Gtk.Adjustment] = None
self._vadjustment: Optional[Gtk.Adjustment] = None
self._hadjustment_handler_id = None
self._vadjustment_handler_id = None
self._hscroll_policy = None
@ -158,7 +161,7 @@ class GtkView(Gtk.DrawingArea, Gtk.Scrollable, View):
super()._set_bounding_box_painter(painter)
self.emit("painter-changed")
def _set_canvas(self, canvas):
def _set_canvas(self, canvas: Optional[Canvas]):
"""
Use view.canvas = my_canvas to set the canvas to be rendered
in the view.
@ -351,6 +354,7 @@ class GtkView(Gtk.DrawingArea, Gtk.Scrollable, View):
# Remove removed items:
if removed_items:
selection = self._selection
self._dirty_matrix_items.difference_update(removed_items)
self._dirty_items.difference_update(removed_items)
for item in removed_items:
@ -369,14 +373,15 @@ class GtkView(Gtk.DrawingArea, Gtk.Scrollable, View):
@AsyncIO(single=True)
def update(self):
"""Update view status according to the items updated by the canvas."""
if not self.get_window():
canvas = self.canvas
if not self.get_window() or not canvas:
return
dirty_items = self._dirty_items
dirty_matrix_items = self._dirty_matrix_items
try:
dirty_matrix_items = self.update_matrices(self._dirty_matrix_items)
self.update_qtree(dirty_matrix_items, dirty_items)
self.update_bounding_box(dirty_items)
self.update_adjustments()
@ -385,6 +390,33 @@ class GtkView(Gtk.DrawingArea, Gtk.Scrollable, View):
dirty_items.clear()
dirty_matrix_items.clear()
def update_matrices(self, items):
"""Recalculate matrices of the items. Items' children matrices are
recalculated, too.
Return items, which matrices were recalculated.
"""
canvas = self._canvas
if not canvas:
return
changed = set()
for item in items:
parent = canvas.get_parent(item)
if parent is not None and parent in items:
# item's matrix will be updated thanks to parent's matrix update
continue
changed.add(item)
changed_children = self.update_matrices(set(canvas.get_children(item)))
changed.update(changed_children)
for d in changed:
d.matrix_i2c.set(*canvas.get_matrix_i2c(d))
return changed
def update_qtree(self, dirty_matrix_items, dirty_items):
for i in dirty_matrix_items:
if i not in self._qtree:

View File

@ -1,6 +1,6 @@
from typing import Tuple
from typing import Optional, Tuple
from gaphas.canvas import Context
from gaphas.canvas import Canvas, Context
from gaphas.geometry import Rectangle
from gaphas.item import Item
from gaphas.matrix import Matrix
@ -18,7 +18,7 @@ class View:
self._qtree: Quadtree[Item, Tuple[float, float, float, float]] = Quadtree()
self._canvas = None
self._canvas: Optional[Canvas] = None
if canvas:
self._set_canvas(canvas)

View File

@ -18,8 +18,6 @@ def test_update_matrices():
i.matrix.translate(5.0, 0.0)
ii.matrix.translate(0.0, 8.0)
c.update_matrices([i])
assert c.get_matrix_i2c(i) == Matrix(1, 0, 0, 1, 5, 0)
assert c.get_matrix_i2c(ii) == Matrix(1, 0, 0, 1, 5, 8)