diff options
author | Sebastian Koslowski <koslowski@kit.edu> | 2016-08-01 17:25:50 +0200 |
---|---|---|
committer | Sebastian Koslowski <koslowski@kit.edu> | 2016-08-03 21:46:12 +0200 |
commit | a59464a7a90715065b600416a3575a734cba51f2 (patch) | |
tree | 1a3724fccfd24ba9a38672788556c3a63fd45444 | |
parent | 52dadbf46f16b682348a6969a782ff64a129d9f8 (diff) |
grc: gtk3: speed up what_is_selected()
-rw-r--r-- | grc/gui/Block.py | 8 | ||||
-rw-r--r-- | grc/gui/Connection.py | 11 | ||||
-rw-r--r-- | grc/gui/Element.py | 85 | ||||
-rw-r--r-- | grc/gui/Port.py | 9 |
4 files changed, 56 insertions, 57 deletions
diff --git a/grc/gui/Block.py b/grc/gui/Block.py index 65039943d3..813f0ebf81 100644 --- a/grc/gui/Block.py +++ b/grc/gui/Block.py @@ -55,6 +55,7 @@ class Block(CoreBlock, Element): self._surface_layout_offsets = 0, 0 self._comment_layout = None + self._area = [] self._border_color = (Colors.MISSING_BLOCK_BORDER_COLOR if self.is_dummy_block else Colors.BORDER_COLOR) self._bg_color = Colors.BLOCK_ENABLED_COLOR @@ -108,9 +109,10 @@ class Block(CoreBlock, Element): def create_shapes(self): """Update the block, parameters, and ports when a change occurs.""" if self.is_horizontal(): - self.area = [0, 0, self.width, self.height] + self._area = (0, 0, self.width, self.height) elif self.is_vertical(): - self.area = [0, 0, self.height, self.width] + self._area = (0, 0, self.height, self.width) + self.bounds_from_area(self._area) bussified = self.current_bus_structure['source'], self.current_bus_structure['sink'] for ports, has_busses in zip((self.active_sources, self.active_sinks), bussified): @@ -251,7 +253,7 @@ class Block(CoreBlock, Element): port.draw(widget, cr, border_color) cr.restore() - cr.rectangle(*self.area) + cr.rectangle(*self._area) cr.set_source_rgb(*self._bg_color) cr.fill_preserve() cr.set_source_rgb(*border_color) diff --git a/grc/gui/Connection.py b/grc/gui/Connection.py index 949840401e..69c035e1f0 100644 --- a/grc/gui/Connection.py +++ b/grc/gui/Connection.py @@ -41,6 +41,7 @@ class Connection(CoreConnection, Element): super(self.__class__, self).__init__(*args, **kwargs) Element.__init__(self) + self._line = [] self._color = self._color2 = self._arrow_color = None self._sink_rot = self._source_rot = None @@ -65,7 +66,6 @@ class Connection(CoreConnection, Element): def create_shapes(self): """Pre-calculate relative coordinates.""" - Element.create_shapes(self) self._sink_rot = None self._source_rot = None self._sink_coor = None @@ -135,7 +135,7 @@ class Connection(CoreConnection, Element): points, alt = alt, points # create 3-line connector i1, i2 = points - self.line = [p0, p1, i1, i2, p2, p3] + self._line = [p0, p1, i1, i2, p2, p3] else: # 2 possible points to create a right-angled connector point, alt = [(x1, y2), (x2, y1)] @@ -149,9 +149,10 @@ class Connection(CoreConnection, Element): if Utils.get_angle_from_coordinates(point, p1) == source_dir: point, alt = alt, point # create right-angled connector - self.line = [p0, p1, point, p2, p3] + self._line = [p0, p1, point, p2, p3] + self.bounds_from_line(self._line) - def draw(self, widget, cr, border_color=None, bg_color=None): + def draw(self, widget, cr): """ Draw the connection. """ @@ -174,7 +175,7 @@ class Connection(CoreConnection, Element): color for color in (self._color, self._color2, self._arrow_color)) cr.translate(*self.coordinate) - for point in self.line: + for point in self._line: cr.line_to(*point) cr.set_source_rgb(*color1) cr.stroke_preserve() diff --git a/grc/gui/Element.py b/grc/gui/Element.py index 30bc640127..73be7b8c92 100644 --- a/grc/gui/Element.py +++ b/grc/gui/Element.py @@ -1,5 +1,5 @@ """ -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +Copyright 2007, 2008, 2009, 2016 Free Software Foundation, Inc. This file is part of GNU Radio GNU Radio Companion is free software; you can redistribute it and/or @@ -45,8 +45,8 @@ class Element(object): self.rotation = 0 self.highlighted = False - self.area = [] - self.line = [] + self._bounding_rects = [] + self._bounding_points = [] def is_horizontal(self, rotation=None): """ @@ -115,6 +115,30 @@ class Element(object): dx, dy = delta_coor self.coordinate = (x + dx, y + dy) + def bounds_from_area(self, area): + x1, y1, w, h = area + x2 = x1 + w + y2 = y1 + h + self._bounding_rects = [(x1, y1, x2, y2)] + self._bounding_points = [(x1, y1), (x2, y1), (x1, y2), (x2, y2)] + + def bounds_from_line(self, line): + self._bounding_rects = rects = [] + self._bounding_points = list(line) + last_point = line[0] + for x2, y2 in line[1:]: + (x1, y1), last_point = last_point, (x2, y2) + if x1 == x2: + x1, x2 = x1 - LINE_SELECT_SENSITIVITY, x2 + LINE_SELECT_SENSITIVITY + if y2 < y1: + y1, y2 = y2, y1 + elif y1 == y2: + y1, y2 = y1 - LINE_SELECT_SENSITIVITY, y2 + LINE_SELECT_SENSITIVITY + if x2 < x1: + x1, x2 = x2, x1 + + rects.append((x1, y1, x2, y2)) + def what_is_selected(self, coor, coor_m=None): """ One coordinate specified: @@ -131,53 +155,22 @@ class Element(object): Returns: self if one of the areas/lines encompasses coor, else None. """ - # function to test if p is between a and b (inclusive) - def in_between(p, a, b): - # return min(a, b) <= p <= max(a, b) - return a <= p <= b or b <= p <= a - # relative coordinate x, y = [a - b for a, b in zip(coor, self.coordinate)] - if coor_m: - x_m, y_m = [a - b for a, b in zip(coor_m, self.coordinate)] - # handle rectangular areas - if self.area: - x1, y1, w, h = self.area - if ( - in_between(x1, x, x_m) and in_between(y1, y, y_m) or - in_between(x1 + w, x, x_m) and in_between(y1, y, y_m) or - in_between(x1, x, x_m) and in_between(y1 + h, y, y_m) or - in_between(x1 + w, x, x_m) and in_between(y1 + h, y, y_m) - ): + + if not coor_m: + for x1, y1, x2, y2 in self._bounding_rects: + if x1 <= x <= x2 and y1 <= y <= y2: return self - # handle horizontal or vertical lines - elif self.line: - last_point = self.line[0] - for x2, y2 in self.line[1:]: - (x1, y1), last_point = last_point, (x2, y2) - if ( - in_between(x1, x, x_m) and in_between(y1, y, y_m) or - in_between(x2, x, x_m) and in_between(y2, y, y_m) - ): - return self - return None else: - # handle rectangular areas - if self.area: - x1, y1, w, h = self.area - if in_between(x, x1, x1+w) and in_between(y, y1, y1+h): + x_m, y_m = [a - b for a, b in zip(coor_m, self.coordinate)] + if y_m < y: + y, y_m = y_m, y + if x_m < x: + x, x_m = x_m, x + + for x1, y1 in self._bounding_points: + if x <= x1 <= x_m and y <= y1 <= y_m: return self - # handle horizontal or vertical lines - elif self.line: - last_point = self.line[0] - for x2, y2 in self.line[1:]: - (x1, y1), last_point = last_point, (x2, y2) - if x1 == x2: - x1, x2 = x1 - LINE_SELECT_SENSITIVITY, x2 + LINE_SELECT_SENSITIVITY - if y1 == y2: - y1, y2 = y1 - LINE_SELECT_SENSITIVITY, y2 + LINE_SELECT_SENSITIVITY - if in_between(x, x1, x2) and in_between(y, y1, y2): - return self - return None def mouse_over(self): pass diff --git a/grc/gui/Port.py b/grc/gui/Port.py index 5e7d9cab68..0880856b00 100644 --- a/grc/gui/Port.py +++ b/grc/gui/Port.py @@ -42,6 +42,8 @@ class Port(_Port, Element): self._connector_coordinate = (0, 0) self._hovering = False self.force_show_label = False + + self._area = [] self._bg_color = 0, 0, 0 self._line_width_factor = 1.0 self._label_layout_offsets = 0, 0 @@ -79,9 +81,10 @@ class Port(_Port, Element): def create_shapes(self): """Create new areas and labels for the port.""" if self.is_horizontal(): - self.area = [0, 0, self.width, self.height] + self._area = (0, 0, self.width, self.height) elif self.is_vertical(): - self.area = [0, 0, self.height, self.width] + self._area = (0, 0, self.height, self.width) + self.bounds_from_area(self._area) self._connector_coordinate = { 0: (self.width, self.height / 2), @@ -121,7 +124,7 @@ class Port(_Port, Element): cr.set_line_width(self._line_width_factor * cr.get_line_width()) cr.translate(*self.coordinate) - cr.rectangle(*self.area) + cr.rectangle(*self._area) cr.set_source_rgb(*self._bg_color) cr.fill_preserve() cr.set_source_rgb(*border_color) |