diff --git a/enable/base.py b/enable/base.py index 0b47ce592..7b79de65a 100644 --- a/enable/base.py +++ b/enable/base.py @@ -138,18 +138,21 @@ def intersect_coordinates ( coordinates1, coordinates2 ): return ( xl, yb, xr, yt ) return empty_rectangle -def intersect_bounds ( bounds1, bounds2 ): +def intersect_bounds( bounds1, bounds2 ): "Compute the intersection of two bounds rectangles" if (bounds1 is empty_rectangle) or (bounds2 is empty_rectangle): return empty_rectangle - - intersection = intersect_coordinates( - bounds_to_coordinates( bounds1 ), - bounds_to_coordinates( bounds2 ) ) - if intersection is empty_rectangle: + x1, y1, w1, h1 = bounds1 + x2, y2, w2, h2 = bounds2 + + x = max(x1, x2) + y = max(y1, y2) + w = min(w1 - x2 + x1, w2 - x1 + x2, w1, w2) + h = min(h1 - y2 + y1, h2 - y1 + y2, h1, h2) + if w <= 0 or h <= 0: return empty_rectangle - xl, yb, xr, yt = intersection - return ( xl, yb, xr - xl, yt - yb ) + else: + return (x,y,w,h) def union_coordinates ( coordinates1, coordinates2 ): "Compute the union of two coordinate based rectangles" diff --git a/enable/component.py b/enable/component.py index 9f210f713..66b560a38 100644 --- a/enable/component.py +++ b/enable/component.py @@ -5,7 +5,7 @@ # Enthought library imports from traits.api \ import Any, Bool, Delegate, Enum, Float, Instance, Int, List, \ - Property, Str, Trait + Property, Str, Trait, cached_property from kiva.constants import FILL, STROKE # Local relative imports @@ -188,7 +188,9 @@ class Component(CoordinateBox, Interactor): # will not change the padding or bounds. # This returns a tuple because modifying the returned value has no effect. # To modify outer_position element-wise, use set_outer_position(). - outer_position = Property + outer_position = Property(depends_on=["position", "border_visible", + "inset_border", "border_width", + "padding_left", "padding_bottom"]) # The number of horizontal and vertical pixels in the padding outer box. # Setting these bounds will modify the bounds of the component, but @@ -196,7 +198,10 @@ class Component(CoordinateBox, Interactor): # the padding. # This returns a tuple because modifying the returned value has no effect. # To modify outer_bounds element-wise, use set_outer_bounds(). - outer_bounds = Property + outer_bounds = Property(depends_on=["bounds", "border_visible", + "inset_border", "border_width", + "padding_left", "padding_right", + "padding_top", "padding_bottom"]) outer_x = Property outer_x2 = Property @@ -416,7 +421,7 @@ def draw(self, gc, view_bounds=None, mode="default"): an aesthetic cost. """ if self.layout_needed: - self.do_layout() + self.do_layout(force=True) self._draw(gc, view_bounds, mode) return @@ -543,14 +548,15 @@ def invalidate_draw(self, damaged_regions=None, self_relative=False): Call this method whenever a component's internal state changes such that it must be redrawn on the next draw() call.""" - self.draw_valid = False if damaged_regions is None: damaged_regions = self._default_damaged_regions() + self.draw_valid = False + if self_relative: - damaged_regions = [[region[0] + self.x, region[1] + self.y, - region[2], region[3]] for region in damaged_regions] + damaged_regions = [[x + self.x, y + self.y, + w, h] for x,y,w,h in damaged_regions] for view in self.viewports: view.invalidate_draw(damaged_regions=damaged_regions, self_relative=True, view_relative=True) @@ -633,7 +639,7 @@ def do_layout(self, size=None, force=False): even if *force* is False. """ - if self.layout_needed or force: + if force or self.layout_needed: if size is not None: self.bounds = size self._do_layout() @@ -712,7 +718,7 @@ def _draw(self, gc, view_bounds=None, mode="default"): return if self.layout_needed: - self.do_layout() + self.do_layout(force=True) self.drawn_outer_position = list(self.outer_position[:]) self.drawn_outer_bounds = list(self.outer_bounds[:]) @@ -786,7 +792,7 @@ def _dispatch_draw(self, layer, gc, view_bounds, mode): if layer == "selection" and not self.use_selection: return if self.layout_needed: - self.do_layout() + self.do_layout(force=True) handler = getattr(self, "_draw_" + layer, None) if handler: @@ -1178,6 +1184,7 @@ def _get_vpadding(self): # Outer position setters and getters #------------------------------------------------------------------------ + @cached_property def _get_outer_position(self): border = self._get_visible_border() pos = self.position @@ -1218,6 +1225,7 @@ def _set_outer_y2(self, val): # Outer bounds setters and getters #------------------------------------------------------------------------ + @cached_property def _get_outer_bounds(self): bounds = self.bounds return (bounds[0] + self.hpadding, bounds[1] + self.vpadding) diff --git a/enable/container.py b/enable/container.py index b5f6d5e7f..9a9692ef2 100644 --- a/enable/container.py +++ b/enable/container.py @@ -302,7 +302,7 @@ def _dispatch_draw(self, layer, gc, view_bounds, mode): return if self.layout_needed: - self.do_layout() + self.do_layout(force=True) # Give the container a chance to draw first for the layers that are # considered "under" or "at" the main layer level