summaryrefslogtreecommitdiff
path: root/grc/gui/Connection.py
diff options
context:
space:
mode:
Diffstat (limited to 'grc/gui/Connection.py')
-rw-r--r--grc/gui/Connection.py260
1 files changed, 143 insertions, 117 deletions
diff --git a/grc/gui/Connection.py b/grc/gui/Connection.py
index 50361c19d0..9862328d6a 100644
--- a/grc/gui/Connection.py
+++ b/grc/gui/Connection.py
@@ -17,18 +17,17 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-import gtk
+from __future__ import absolute_import
-import Colors
-import Utils
-from Constants import CONNECTOR_ARROW_BASE, CONNECTOR_ARROW_HEIGHT
-from Element import Element
+from . import Colors, Utils
+from .Constants import CONNECTOR_ARROW_BASE, CONNECTOR_ARROW_HEIGHT, GR_MESSAGE_DOMAIN
+from .Element import Element
-from ..core.Constants import GR_MESSAGE_DOMAIN
-from ..core.Connection import Connection as _Connection
+from ..core.Element import nop_write
+from ..core.Connection import Connection as CoreConnection
-class Connection(Element, _Connection):
+class Connection(CoreConnection, Element):
"""
A graphical connection for ports.
The connection has 2 parts, the arrow and the wire.
@@ -38,23 +37,25 @@ class Connection(Element, _Connection):
The arrow coloring exposes the enabled and valid states.
"""
- def __init__(self, **kwargs):
+ def __init__(self, *args, **kwargs):
+ super(self.__class__, self).__init__(*args, **kwargs)
Element.__init__(self)
- _Connection.__init__(self, **kwargs)
- # can't use Colors.CONNECTION_ENABLED_COLOR here, might not be defined (grcc)
- self._bg_color = self._arrow_color = self._color = None
- def get_coordinate(self):
- """
- Get the 0,0 coordinate.
- Coordinates are irrelevant in connection.
+ self._line = []
+ self._line_width_factor = 1.0
+ self._color = self._color2 = self._arrow_color = None
- Returns:
- 0, 0
- """
- return 0, 0
+ self._sink_rot = self._source_rot = None
+ self._sink_coor = self._source_coor = None
- def get_rotation(self):
+ @nop_write
+ @property
+ def coordinate(self):
+ return self.source_port.get_connector_coordinate()
+
+ @nop_write
+ @property
+ def rotation(self):
"""
Get the 0 degree rotation.
Rotations are irrelevant in connection.
@@ -65,117 +66,142 @@ class Connection(Element, _Connection):
return 0
def create_shapes(self):
- """Precalculate relative coordinates."""
- Element.create_shapes(self)
+ """Pre-calculate relative coordinates."""
self._sink_rot = None
self._source_rot = None
self._sink_coor = None
self._source_coor = None
#get the source coordinate
try:
- connector_length = self.get_source().get_connector_length()
+ connector_length = self.source_port.connector_length
except:
- return
- self.x1, self.y1 = Utils.get_rotated_coordinate((connector_length, 0), self.get_source().get_rotation())
+ return # todo: why?
+ self.x1, self.y1 = Utils.get_rotated_coordinate((connector_length, 0), self.source_port.rotation)
#get the sink coordinate
- connector_length = self.get_sink().get_connector_length() + CONNECTOR_ARROW_HEIGHT
- self.x2, self.y2 = Utils.get_rotated_coordinate((-connector_length, 0), self.get_sink().get_rotation())
+ connector_length = self.sink_port.connector_length + CONNECTOR_ARROW_HEIGHT
+ self.x2, self.y2 = Utils.get_rotated_coordinate((-connector_length, 0), self.sink_port.rotation)
#build the arrow
- self.arrow = [(0, 0),
- Utils.get_rotated_coordinate((-CONNECTOR_ARROW_HEIGHT, -CONNECTOR_ARROW_BASE/2), self.get_sink().get_rotation()),
- Utils.get_rotated_coordinate((-CONNECTOR_ARROW_HEIGHT, CONNECTOR_ARROW_BASE/2), self.get_sink().get_rotation()),
- ]
- source_domain = self.get_source().get_domain()
- sink_domain = self.get_sink().get_domain()
- self.line_attributes[0] = 2 if source_domain != sink_domain else 0
- self.line_attributes[1] = gtk.gdk.LINE_DOUBLE_DASH \
- if not source_domain == sink_domain == GR_MESSAGE_DOMAIN \
- else gtk.gdk.LINE_ON_OFF_DASH
- get_domain_color = lambda d: Colors.get_color((
- self.get_parent().get_parent().domains.get(d, {})
- ).get('color') or Colors.DEFAULT_DOMAIN_COLOR_CODE)
- self._color = get_domain_color(source_domain)
- self._bg_color = get_domain_color(sink_domain)
- self._arrow_color = self._bg_color if self.is_valid() else Colors.CONNECTION_ERROR_COLOR
+ self._arrow_base = [
+ (0, 0),
+ Utils.get_rotated_coordinate((-CONNECTOR_ARROW_HEIGHT, -CONNECTOR_ARROW_BASE/2), self.sink_port.rotation),
+ Utils.get_rotated_coordinate((-CONNECTOR_ARROW_HEIGHT, CONNECTOR_ARROW_BASE/2), self.sink_port.rotation),
+ ] if self.sink_block.state != 'bypassed' else []
+ source_domain = self.source_port.domain
+ sink_domain = self.sink_port.domain
+
+ def get_domain_color(domain_name):
+ domain = self.parent_platform.domains.get(domain_name, {})
+ color_spec = domain.get('color')
+ return Colors.get_color(color_spec) if color_spec else Colors.DEFAULT_DOMAIN_COLOR
+
+ if source_domain == GR_MESSAGE_DOMAIN:
+ self._line_width_factor = 1.0
+ self._color = None
+ self._color2 = Colors.CONNECTION_ENABLED_COLOR
+ else:
+ if source_domain != sink_domain:
+ self._line_width_factor = 2.0
+ self._color = get_domain_color(source_domain)
+ self._color2 = get_domain_color(sink_domain)
+ self._arrow_color = self._color2 if self.is_valid() else Colors.CONNECTION_ERROR_COLOR
self._update_after_move()
def _update_after_move(self):
"""Calculate coordinates."""
- self.clear() #FIXME do i want this here?
- #source connector
- source = self.get_source()
- X, Y = source.get_connector_coordinate()
- x1, y1 = self.x1 + X, self.y1 + Y
- self.add_line((x1, y1), (X, Y))
- #sink connector
- sink = self.get_sink()
- X, Y = sink.get_connector_coordinate()
- x2, y2 = self.x2 + X, self.y2 + Y
- self.add_line((x2, y2), (X, Y))
- #adjust arrow
- self._arrow = [(x+X, y+Y) for x,y in self.arrow]
- #add the horizontal and vertical lines in this connection
- if abs(source.get_connector_direction() - sink.get_connector_direction()) == 180:
- #2 possible point sets to create a 3-line connector
- mid_x, mid_y = (x1 + x2)/2.0, (y1 + y2)/2.0
- points = [((mid_x, y1), (mid_x, y2)), ((x1, mid_y), (x2, mid_y))]
- #source connector -> points[0][0] should be in the direction of source (if possible)
- if Utils.get_angle_from_coordinates((x1, y1), points[0][0]) != source.get_connector_direction(): points.reverse()
- #points[0][0] -> sink connector should not be in the direction of sink
- if Utils.get_angle_from_coordinates(points[0][0], (x2, y2)) == sink.get_connector_direction(): points.reverse()
- #points[0][0] -> source connector should not be in the direction of source
- if Utils.get_angle_from_coordinates(points[0][0], (x1, y1)) == source.get_connector_direction(): points.reverse()
- #create 3-line connector
- p1, p2 = map(int, points[0][0]), map(int, points[0][1])
- self.add_line((x1, y1), p1)
- self.add_line(p1, p2)
- self.add_line((x2, y2), p2)
+ source = self.source_port
+ sink = self.sink_port
+ source_dir = source.get_connector_direction()
+ sink_dir = sink.get_connector_direction()
+
+ x_pos, y_pos = self.coordinate
+ x_start, y_start = source.get_connector_coordinate()
+ x_end, y_end = sink.get_connector_coordinate()
+
+ p3 = x3, y3 = x_end - x_pos, y_end - y_pos
+ p2 = x2, y2 = self.x2 + x3, self.y2 + y3
+ p1 = x1, y1 = self.x1, self.y1
+ p0 = x_start - x_pos, y_start - y_pos
+ self._arrow = [(x + x3, y + y3) for x, y in self._arrow_base]
+
+ if abs(source_dir - sink.get_connector_direction()) == 180:
+ # 2 possible point sets to create a 3-line connector
+ mid_x, mid_y = (x1 + x2) / 2.0, (y1 + y2) / 2.0
+ points = ((mid_x, y1), (mid_x, y2))
+ alt = ((x1, mid_y), (x2, mid_y))
+ # source connector -> points[0][0] should be in the direction of source (if possible)
+ if Utils.get_angle_from_coordinates(p1, points[0]) != source_dir:
+ points, alt = alt, points
+ # points[0] -> sink connector should not be in the direction of sink
+ if Utils.get_angle_from_coordinates(points[0], p2) == sink_dir:
+ points, alt = alt, points
+ # points[0] -> source connector should not be in the direction of source
+ if Utils.get_angle_from_coordinates(points[0], p1) == source_dir:
+ points, alt = alt, points
+ # create 3-line connector
+ i1, i2 = points
+ self._line = [p0, p1, i1, i2, p2, p3]
else:
- #2 possible points to create a right-angled connector
- points = [(x1, y2), (x2, y1)]
- #source connector -> points[0] should be in the direction of source (if possible)
- if Utils.get_angle_from_coordinates((x1, y1), points[0]) != source.get_connector_direction(): points.reverse()
- #points[0] -> sink connector should not be in the direction of sink
- if Utils.get_angle_from_coordinates(points[0], (x2, y2)) == sink.get_connector_direction(): points.reverse()
- #points[0] -> source connector should not be in the direction of source
- if Utils.get_angle_from_coordinates(points[0], (x1, y1)) == source.get_connector_direction(): points.reverse()
- #create right-angled connector
- self.add_line((x1, y1), points[0])
- self.add_line((x2, y2), points[0])
-
- def draw(self, gc, window):
+ # 2 possible points to create a right-angled connector
+ point, alt = [(x1, y2), (x2, y1)]
+ # source connector -> point should be in the direction of source (if possible)
+ if Utils.get_angle_from_coordinates(p1, point) != source_dir:
+ point, alt = alt, point
+ # point -> sink connector should not be in the direction of sink
+ if Utils.get_angle_from_coordinates(point, p2) == sink_dir:
+ point, alt = alt, point
+ # point -> source connector should not be in the direction of source
+ 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.bounds_from_line(self._line)
+
+ def draw(self, cr):
"""
Draw the connection.
-
- Args:
- gc: the graphics context
- window: the gtk window to draw on
"""
- sink = self.get_sink()
- source = self.get_source()
- #check for changes
- if self._sink_rot != sink.get_rotation() or self._source_rot != source.get_rotation(): self.create_shapes()
- elif self._sink_coor != sink.get_coordinate() or self._source_coor != source.get_coordinate():
- try:
- self._update_after_move()
- except:
- return
- #cache values
- self._sink_rot = sink.get_rotation()
- self._source_rot = source.get_rotation()
- self._sink_coor = sink.get_coordinate()
- self._source_coor = source.get_coordinate()
- #draw
- mod_color = lambda color: (
- Colors.HIGHLIGHT_COLOR if self.is_highlighted() else
- Colors.CONNECTION_DISABLED_COLOR if not self.get_enabled() else
- color
+ sink = self.sink_port
+ source = self.source_port
+ # check for changes
+ if self._sink_rot != sink.rotation or self._source_rot != source.rotation:
+ self.create_shapes()
+ self._sink_rot = sink.rotation
+ self._source_rot = source.rotation
+
+ elif self._sink_coor != sink.parent_block.coordinate or self._source_coor != source.parent_block.coordinate:
+ self._update_after_move()
+ self._sink_coor = sink.parent_block.coordinate
+ self._source_coor = source.parent_block.coordinate
+ # draw
+ color1, color2, arrow_color = (
+ None if color is None else
+ Colors.HIGHLIGHT_COLOR if self.highlighted else
+ Colors.CONNECTION_DISABLED_COLOR if not self.enabled else color
+ for color in (self._color, self._color2, self._arrow_color)
)
- Element.draw(self, gc, window, mod_color(self._color), mod_color(self._bg_color))
- # draw arrow on sink port
- try:
- gc.set_foreground(mod_color(self._arrow_color))
- gc.set_line_attributes(0, gtk.gdk.LINE_SOLID, gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER)
- window.draw_polygon(gc, True, self._arrow)
- except:
- pass
+
+ cr.translate(*self.coordinate)
+ cr.set_line_width(self._line_width_factor * cr.get_line_width())
+ for point in self._line:
+ cr.line_to(*point)
+
+ if color1: # not a message connection
+ cr.set_source_rgba(*color1)
+ cr.stroke_preserve()
+
+ if color1 != color2:
+ cr.save()
+ cr.set_dash([5.0, 5.0], 5.0 if color1 else 0.0)
+ cr.set_source_rgba(*color2)
+ cr.stroke()
+ cr.restore()
+ else:
+ cr.new_path()
+
+ if self._arrow:
+ cr.set_source_rgba(*arrow_color)
+ cr.move_to(*self._arrow[0])
+ cr.line_to(*self._arrow[1])
+ cr.line_to(*self._arrow[2])
+ cr.close_path()
+ cr.fill()