summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Koslowski <koslowski@kit.edu>2016-08-01 17:25:50 +0200
committerSebastian Koslowski <koslowski@kit.edu>2016-08-03 21:46:12 +0200
commita59464a7a90715065b600416a3575a734cba51f2 (patch)
tree1a3724fccfd24ba9a38672788556c3a63fd45444
parent52dadbf46f16b682348a6969a782ff64a129d9f8 (diff)
grc: gtk3: speed up what_is_selected()
-rw-r--r--grc/gui/Block.py8
-rw-r--r--grc/gui/Connection.py11
-rw-r--r--grc/gui/Element.py85
-rw-r--r--grc/gui/Port.py9
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)