diff options
Diffstat (limited to 'grc/gui/canvas/port.py')
-rw-r--r-- | grc/gui/canvas/port.py | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/grc/gui/canvas/port.py b/grc/gui/canvas/port.py new file mode 100644 index 0000000000..b74e4adfcc --- /dev/null +++ b/grc/gui/canvas/port.py @@ -0,0 +1,225 @@ +""" +Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from __future__ import absolute_import, division + +import math + +from gi.repository import Gtk, PangoCairo, Pango + +from . import colors +from .drawable import Drawable +from .. import Actions, Utils, Constants +from ...core.Element import nop_write +from ...core.Port import Port as CorePort + + +class Port(CorePort, Drawable): + """The graphical port.""" + + def __init__(self, parent, direction, **n): + """ + Port constructor. + Create list of connector coordinates. + """ + super(self.__class__, self).__init__(parent, direction, **n) + Drawable.__init__(self) + self._connector_coordinate = (0, 0) + self._hovering = False + self.force_show_label = False + + self._area = [] + self._bg_color = self._border_color = 0, 0, 0, 0 + self._font_color = list(colors.FONT_COLOR) + + self._line_width_factor = 1.0 + self._label_layout_offsets = 0, 0 + + self.width_with_label = self.height = 0 + + self.label_layout = None + + @property + def width(self): + return self.width_with_label if self._show_label else Constants.PORT_LABEL_HIDDEN_WIDTH + + @width.setter + def width(self, value): + self.width_with_label = value + self.label_layout.set_width(value * Pango.SCALE) + + def _update_colors(self): + """ + Get the color that represents this port's type. + Codes differ for ports where the vec length is 1 or greater than 1. + + Returns: + a hex color code. + """ + if not self.parent_block.enabled: + self._font_color[-1] = 0.4 + color = colors.BLOCK_DISABLED_COLOR + else: + self._font_color[-1] = 1.0 + color = colors.PORT_TYPE_TO_COLOR.get(self.get_type()) or colors.PORT_TYPE_TO_COLOR.get('') + vlen = self.get_vlen() + if vlen > 1: + dark = (0, 0, 30 / 255.0, 50 / 255.0, 70 / 255.0)[min(4, vlen)] + color = tuple(max(c - dark, 0) for c in color) + self._bg_color = color + self._border_color = tuple(max(c - 0.3, 0) for c in color) + + def create_shapes(self): + """Create new areas and labels for the port.""" + if self.is_horizontal(): + self._area = (0, 0, self.width, self.height) + elif self.is_vertical(): + self._area = (0, 0, self.height, self.width) + self.bounds_from_area(self._area) + + self._connector_coordinate = { + 0: (self.width, self.height / 2), + 90: (self.height / 2, 0), + 180: (0, self.height / 2), + 270: (self.height / 2, self.width) + }[self.connector_direction] + + def create_labels(self, cr=None): + """Create the labels for the socket.""" + self.label_layout = Gtk.DrawingArea().create_pango_layout('') + self.label_layout.set_alignment(Pango.Alignment.CENTER) + + if cr: + PangoCairo.update_layout(cr, self.label_layout) + + if self.domain in (Constants.GR_MESSAGE_DOMAIN, Constants.DEFAULT_DOMAIN): + self._line_width_factor = 1.0 + else: + self._line_width_factor = 2.0 + + self._update_colors() + + layout = self.label_layout + layout.set_markup('<span font_desc="{font}">{name}</span>'.format( + name=Utils.encode(self.name), font=Constants.PORT_FONT + )) + label_width, label_height = self.label_layout.get_size() + + self.width = 2 * Constants.PORT_LABEL_PADDING + label_width / Pango.SCALE + self.height = 2 * Constants.PORT_LABEL_PADDING + label_height / Pango.SCALE + self._label_layout_offsets = [0, Constants.PORT_LABEL_PADDING] + if self.get_type() == 'bus': + self.height += Constants.PORT_EXTRA_BUS_HEIGHT + self._label_layout_offsets[1] += Constants.PORT_EXTRA_BUS_HEIGHT / 2 + self.height += self.height % 2 # uneven height + + def draw(self, cr): + """ + Draw the socket with a label. + """ + border_color = self._border_color + cr.set_line_width(self._line_width_factor * cr.get_line_width()) + cr.translate(*self.coordinate) + + cr.rectangle(*self._area) + cr.set_source_rgba(*self._bg_color) + cr.fill_preserve() + cr.set_source_rgba(*border_color) + cr.stroke() + + if not self._show_label: + return # this port is folded (no label) + + if self.is_vertical(): + cr.rotate(-math.pi / 2) + cr.translate(-self.width, 0) + cr.translate(*self._label_layout_offsets) + + cr.set_source_rgba(*self._font_color) + PangoCairo.update_layout(cr, self.label_layout) + PangoCairo.show_layout(cr, self.label_layout) + + @property + def connector_coordinate_absolute(self): + """the coordinate where connections may attach to""" + return [sum(c) for c in zip( + self._connector_coordinate, # relative to port + self.coordinate, # relative to block + self.parent_block.coordinate # abs + )] + + @property + def connector_direction(self): + """Get the direction that the socket points: 0,90,180,270.""" + if self.is_source: + return self.rotation + elif self.is_sink: + return (self.rotation + 180) % 360 + + @nop_write + @property + def rotation(self): + return self.parent_block.rotation + + def rotate(self, direction): + """ + Rotate the parent rather than self. + + Args: + direction: degrees to rotate + """ + self.parent_block.rotate(direction) + + def move(self, delta_coor): + """Move the parent rather than self.""" + self.parent_block.move(delta_coor) + + @property + def highlighted(self): + return self.parent_block.highlighted + + @highlighted.setter + def highlighted(self, value): + self.parent_block.highlighted = value + + @property + def _show_label(self): + """ + Figure out if the label should be hidden + + Returns: + true if the label should not be shown + """ + return self._hovering or self.force_show_label or not Actions.TOGGLE_AUTO_HIDE_PORT_LABELS.get_active() + + def mouse_over(self): + """ + Called from flow graph on mouse-over + """ + changed = not self._show_label + self._hovering = True + return changed + + def mouse_out(self): + """ + Called from flow graph on mouse-out + """ + label_was_shown = self._show_label + self._hovering = False + return label_was_shown != self._show_label |