summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Koslowski <koslowski@kit.edu>2016-07-12 17:41:08 +0200
committerSebastian Koslowski <koslowski@kit.edu>2016-07-13 16:35:50 +0200
commit11c4f515b250ccdef366da222c10d16229f5d347 (patch)
treee068649ae93e73bebea386f3fadd88ced4b91af4
parentb479f54903c0b1b164393af2e844723aed8a1072 (diff)
grc: gtk3: update & fix port drawing code
-rw-r--r--grc/gui/Block.py65
-rw-r--r--grc/gui/Connection.py17
-rw-r--r--grc/gui/Port.py139
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.