diff options
author | Sebastian Koslowski <koslowski@kit.edu> | 2016-07-12 17:41:08 +0200 |
---|---|---|
committer | Sebastian Koslowski <koslowski@kit.edu> | 2016-07-13 16:35:50 +0200 |
commit | 11c4f515b250ccdef366da222c10d16229f5d347 (patch) | |
tree | e068649ae93e73bebea386f3fadd88ced4b91af4 | |
parent | b479f54903c0b1b164393af2e844723aed8a1072 (diff) |
grc: gtk3: update & fix port drawing code
-rw-r--r-- | grc/gui/Block.py | 65 | ||||
-rw-r--r-- | grc/gui/Connection.py | 17 | ||||
-rw-r--r-- | grc/gui/Port.py | 139 |
3 files changed, 107 insertions, 114 deletions
diff --git a/grc/gui/Block.py b/grc/gui/Block.py index 3d60a80443..7321a0495b 100644 --- a/grc/gui/Block.py +++ b/grc/gui/Block.py @@ -24,7 +24,7 @@ gi.require_version('Gtk', '3.0') gi.require_version('PangoCairo', '1.0') from gi.repository import Gtk, Pango, PangoCairo -from . import Actions, Colors, Utils +from . import Actions, Colors, Utils, Constants from .Constants import ( BLOCK_LABEL_PADDING, PORT_SPACING, PORT_SEPARATION, LABEL_SEPARATION, @@ -104,15 +104,34 @@ class Block(_Block, Element): def create_shapes(self): """Update the block, parameters, and ports when a change occurs.""" - Element.create_shapes(self) + self.clear() + if self.is_horizontal(): self.add_area(0, 0, self.W, self.H) elif self.is_vertical(): self.add_area(0, 0, self.H, self.W) + for ports, has_busses in zip((self.active_sources, self.active_sinks), self.has_busses): + if not ports: + continue + port_separation = PORT_SEPARATION if not has_busses else ports[0].H + PORT_SPACING + offset = (self.H - (len(ports) - 1) * port_separation - ports[0].H) / 2 + for index, port in enumerate(ports): + port.create_shapes() + + port.set_coordinate({ + 0: (+self.W, offset), + 90: (offset, -port.W), + 180: (-port.W, offset), + 270: (offset, +self.W), + }[port.get_connector_direction()]) + offset += PORT_SEPARATION if not has_busses else port.H + PORT_SPACING + + port.connector_length = Constants.CONNECTOR_EXTENSION_MINIMAL + \ + Constants.CONNECTOR_EXTENSION_INCREMENT * index + def create_labels(self): """Create the labels for the signal block.""" - Element.create_labels(self) self._bg_color = Colors.MISSING_BLOCK_BACKGROUND_COLOR if self.is_dummy_block else \ Colors.BLOCK_BYPASSED_COLOR if self.get_bypassed() else \ Colors.BLOCK_ENABLED_COLOR if self.get_enabled() else \ @@ -152,18 +171,19 @@ class Block(_Block, Element): width = label_width + 2 * BLOCK_LABEL_PADDING height = label_height + 2 * BLOCK_LABEL_PADDING + self.create_port_labels() + def get_min_height_for_ports(): - visible_ports = [p for p in ports if not p.get_hide()] - min_height = 2*PORT_BORDER_SEPARATION + len(visible_ports) * PORT_SEPARATION - if visible_ports: - min_height -= ports[0].H + min_height = 2 * PORT_BORDER_SEPARATION + len(ports) * PORT_SEPARATION + if ports: + min_height -= ports[-1].H return min_height height = max( [ # labels height ] + [ # ports - get_min_height_for_ports() for ports in (self.get_sources_gui(), self.get_sinks_gui()) + get_min_height_for_ports() for ports in (self.active_sources, self.active_sinks) ] + [ # bus ports only 2 * PORT_BORDER_SEPARATION + @@ -184,6 +204,15 @@ class Block(_Block, Element): ] self.create_comment_layout() + def create_port_labels(self): + for ports in (self.active_sinks, self.active_sources): + max_width = 0 + for port in ports: + port.create_labels() + max_width = max(max_width, port.W) + for port in ports: + port.W = max_width + def create_comment_layout(self): markups = [] @@ -218,18 +247,16 @@ class Block(_Block, Element): Colors.MISSING_BLOCK_BORDER_COLOR if self.is_dummy_block else Colors.BORDER_COLOR ) - - for port in self.get_ports_gui(): + # draw main block + Element.draw(self, widget, cr, border_color, bg_color) + for port in self.active_ports(): cr.save() port.draw(widget, cr, border_color, bg_color) cr.restore() - # draw main block - Element.draw(self, widget, cr, border_color, bg_color) - # title and params label if self.is_vertical(): - cr.rotate(-90 * math.pi / 180.) + cr.rotate(-math.pi / 2) cr.translate(-self.W, 0) cr.translate(*self._surface_layout_offsets) @@ -250,9 +277,13 @@ class Block(_Block, Element): Returns: this block, a port, or None """ - for port in self.get_ports_gui(): - port_selected = port.what_is_selected(coor, coor_m) - if port_selected: return port_selected + for port in self.active_ports(): + port_selected = port.what_is_selected( + coor=[a - b for a, b in zip(coor, self.get_coordinate())], + coor_m=[a - b for a, b in zip(coor, self.get_coordinate())] if coor_m is not None else None + ) + if port_selected: + return port_selected return Element.what_is_selected(self, coor, coor_m) def draw_comment(self, widget, cr): diff --git a/grc/gui/Connection.py b/grc/gui/Connection.py index 9035e5e207..5e3353c5c1 100644 --- a/grc/gui/Connection.py +++ b/grc/gui/Connection.py @@ -158,16 +158,13 @@ class Connection(Element, _Connection): #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 # todo: why? - #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() + self._sink_rot = sink.get_rotation() + self._source_rot = source.get_rotation() + + elif self._sink_coor != sink.parent_block.get_coordinate() or self._source_coor != source.parent_block.get_coordinate(): + self._update_after_move() + self._sink_coor = sink.parent_block.get_coordinate() + self._source_coor = source.parent_block.get_coordinate() # draw color1, color2 = ( Colors.HIGHLIGHT_COLOR if self.is_highlighted() else diff --git a/grc/gui/Port.py b/grc/gui/Port.py index b28881e6c8..298b22e19f 100644 --- a/grc/gui/Port.py +++ b/grc/gui/Port.py @@ -19,9 +19,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA from __future__ import absolute_import import math -import gi -gi.require_version('Gtk', '3.0') -from gi.repository import Gtk, PangoCairo + +from gi.repository import Gtk, PangoCairo, Pango from . import Actions, Colors, Utils, Constants from .Element import Element @@ -34,7 +33,7 @@ class Port(_Port, Element): def __init__(self, block, n, dir): """ - Port contructor. + Port constructor. Create list of connector coordinates. """ _Port.__init__(self, block, n, dir) @@ -45,11 +44,20 @@ class Port(_Port, Element): self._bg_color = (0, 0, 0) self._line_width_factor = 1.0 - self.W = 0 - self.H = 20 # todo: fix + self._W = self.H = 0 self.connector_length = 0 - self.layout = Gtk.DrawingArea().create_pango_layout('') + self.label_layout = Gtk.DrawingArea().create_pango_layout('') + self.label_layout.set_alignment(Pango.Alignment.CENTER) + + @property + def W(self): + return self._W if not self._label_hidden() else Constants.PORT_LABEL_HIDDEN_WIDTH + + @W.setter + def W(self, value): + self._W = value + self.label_layout.set_width(value * Pango.SCALE) def _get_color(self): """ @@ -68,92 +76,59 @@ class Port(_Port, Element): def create_shapes(self): """Create new areas and labels for the port.""" - Element.create_shapes(self) - self._bg_color = self._get_color() + self.clear() + + if self.is_horizontal(): + self.add_area(0, 0, self.W, self.H) + elif self.is_vertical(): + self.add_area(0, 0, self.H, self.W) + + self._connector_coordinate = { + 0: (self.W, self.H / 2), + 90: (self.H / 2, 0), + 180: (0, self.H / 2), + 270: (self.H / 2, self.W) + }[self.get_connector_direction()] + + def create_labels(self): + """Create the labels for the socket.""" - if self.get_hide(): - return # this port is hidden, no need to create shapes if self.domain in (Constants.GR_MESSAGE_DOMAIN, Constants.DEFAULT_DOMAIN): self._line_width_factor = 1.0 else: self._line_width_factor = 2.0 - #get current rotation - rotation = self.get_rotation() - #get all sibling ports - ports = self.parent.get_sources_gui() \ - if self.is_source else self.parent.get_sinks_gui() - ports = [p for p in ports if not p.get_hide()] - #get the max width - self.W = max([port.W for port in ports] + [Constants.PORT_MIN_WIDTH]) - W = self.W if not self._label_hidden() else Constants.PORT_LABEL_HIDDEN_WIDTH - #get a numeric index for this port relative to its sibling ports - try: - index = ports.index(self) - except: - if hasattr(self, 'connector_length'): - del self.connector_length - return - #reverse the order of ports for these rotations - if rotation in (180, 270): - index = len(ports)-index-1 - - port_separation = Constants.PORT_SEPARATION \ - if not self.parent.has_busses[self.is_source] \ - else max([port.H for port in ports]) + Constants.PORT_SPACING - - offset = (self.parent.H - (len(ports)-1)*port_separation - self.H)/2 - #create areas and connector coordinates - if (self.is_sink and rotation == 0) or (self.is_source and rotation == 180): - x = -W - y = port_separation*index+offset - self.add_area(x, y, W, self.H) - self._connector_coordinate = (x-1, y+self.H/2) - elif (self.is_source and rotation == 0) or (self.is_sink and rotation == 180): - x = self.parent.W - y = port_separation*index+offset - self.add_area(x, y, W, self.H) - self._connector_coordinate = (x+1+W, y+self.H/2) - elif (self.is_source and rotation == 90) or (self.is_sink and rotation == 270): - y = -W - x = port_separation*index+offset - self.add_area(x, y, self.H, W) - self._connector_coordinate = (x+self.H/2, y-1) - elif (self.is_sink and rotation == 90) or (self.is_source and rotation == 270): - y = self.parent.W - x = port_separation*index+offset - self.add_area(x, y, self.H, W) - self._connector_coordinate = (x+self.H/2, y+1+W) - #the connector length - self.connector_length = Constants.CONNECTOR_EXTENSION_MINIMAL + Constants.CONNECTOR_EXTENSION_INCREMENT * index - def create_labels(self): - """Create the labels for the socket.""" - self.layout.set_markup("""<span foreground="black" font_desc="{font}">{name}</span>""".format( + self._bg_color = self._get_color() + + layout = self.label_layout + layout.set_markup("""<span foreground="black" font_desc="{font}">{name}</span>""".format( name=Utils.encode(self.get_name()), font=Constants.PORT_FONT )) + label_width, label_height = self.label_layout.get_pixel_size() + + self.W = 2 * Constants.PORT_LABEL_PADDING + label_width + self.H = 2 * Constants.PORT_LABEL_PADDING + label_height + if self.get_type() == 'bus': + self.H += 2 * label_height + self.H += self.H % 2 # uneven height def draw(self, widget, cr, border_color, bg_color): """ Draw the socket with a label. """ - cr.set_line_width(self._line_width_factor * cr.get_line_width()) Element.draw(self, widget, cr, border_color, self._bg_color) - if not self._areas_list or self._label_hidden(): - return # this port is either hidden (no areas) or folded (no label) + if self._label_hidden(): + return # this port is folded (no label) - x, y, _, __ = self._areas_list[0] + if self.is_vertical(): + cr.rotate(-math.pi / 2) + cr.translate(-self.W, 0) + cr.translate(0, Constants.PORT_LABEL_PADDING) - cr.set_source_rgb(*self._bg_color) - if self.is_horizontal(): - cr.translate(x + (self.W - self.w) / 2, y + (self.H - self.h) / 2) - elif self.is_vertical(): - cr.translate(x + (self.H - self.h) / 2, y + (self.W - self.w) / 2) - cr.rotate(-90 * math.pi / 180.) - cr.translate(-self.w, 0) - PangoCairo.update_layout(cr, self.layout) - PangoCairo.show_layout(cr, self.layout) + PangoCairo.update_layout(cr, self.label_layout) + PangoCairo.show_layout(cr, self.label_layout) def get_connector_coordinate(self): """ @@ -162,9 +137,8 @@ class Port(_Port, Element): Returns: the connector coordinate (x, y) tuple """ - x, y = self._connector_coordinate - x_pos, y_pos = self.get_coordinate() - return x + x_pos, y + y_pos + return [sum(c) for c in zip(self._connector_coordinate, self.get_coordinate(), + self.parent_block.get_coordinate())] def get_connector_direction(self): """ @@ -207,15 +181,6 @@ class Port(_Port, Element): """ self.parent.rotate(direction) - def get_coordinate(self): - """ - Get the parent's coordinate rather than self. - - Returns: - the parents coordinate - """ - return self.parent.get_coordinate() - def set_highlighted(self, highlight): """ Set the parent highlight rather than self. |