]> git.gag.com Git - debian/gnuradio/blobdiff - grc/gui/Block.py
Imported Upstream version 3.2.2
[debian/gnuradio] / grc / gui / Block.py
diff --git a/grc/gui/Block.py b/grc/gui/Block.py
new file mode 100644 (file)
index 0000000..0496f0a
--- /dev/null
@@ -0,0 +1,199 @@
+"""
+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 Element import Element
+import Utils
+import Colors
+from .. base import odict
+from Constants import BORDER_PROXIMITY_SENSITIVITY
+from Constants import \
+       BLOCK_LABEL_PADDING, \
+       PORT_SEPARATION, LABEL_SEPARATION, \
+       PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS
+import pygtk
+pygtk.require('2.0')
+import gtk
+
+BLOCK_MARKUP_TMPL="""\
+#set $foreground = $block.is_valid() and 'black' or 'red'
+<span foreground="$foreground" font_desc="Sans 8"><b>$encode($block.get_name())</b></span>"""
+
+class Block(Element):
+       """The graphical signal block."""
+
+       def __init__(self, *args, **kwargs):
+               """
+               Block contructor.
+               Add graphics related params to the block.
+               """
+               #add the position param
+               self._params['_coordinate'] = self.get_parent().get_parent().Param(
+                       self,
+                       odict({
+                               'name': 'GUI Coordinate',
+                               'key': '_coordinate',
+                               'type': 'raw',
+                               'value': '(0, 0)',
+                               'hide': 'all',
+                       })
+               )
+               self._params['_rotation'] = self.get_parent().get_parent().Param(
+                       self,
+                       odict({
+                               'name': 'GUI Rotation',
+                               'key': '_rotation',
+                               'type': 'raw',
+                               'value': '0',
+                               'hide': 'all',
+                       })
+               )
+               Element.__init__(self)
+
+       def get_coordinate(self):
+               """
+               Get the coordinate from the position param.
+               @return the coordinate tuple (x, y) or (0, 0) if failure
+               """
+               try: #should evaluate to tuple
+                       coor = eval(self.get_param('_coordinate').get_value())
+                       x, y = map(int, coor)
+                       fgW,fgH = self.get_parent().get_size()
+                       if x <= 0:
+                               x = 0
+                       elif x >= fgW - BORDER_PROXIMITY_SENSITIVITY:
+                               x = fgW - BORDER_PROXIMITY_SENSITIVITY
+                       if y <= 0:
+                               y = 0
+                       elif y >= fgH - BORDER_PROXIMITY_SENSITIVITY:
+                               y = fgH - BORDER_PROXIMITY_SENSITIVITY
+                       return (x, y)
+               except:
+                       self.set_coordinate((0, 0))
+                       return (0, 0)
+
+       def set_coordinate(self, coor):
+               """
+               Set the coordinate into the position param.
+               @param coor the coordinate tuple (x, y)
+               """
+               self.get_param('_coordinate').set_value(str(coor))
+
+       def get_rotation(self):
+               """
+               Get the rotation from the position param.
+               @return the rotation in degrees or 0 if failure
+               """
+               try: #should evaluate to dict
+                       rotation = eval(self.get_param('_rotation').get_value())
+                       return int(rotation)
+               except:
+                       self.set_rotation(POSSIBLE_ROTATIONS[0])
+                       return POSSIBLE_ROTATIONS[0]
+
+       def set_rotation(self, rot):
+               """
+               Set the rotation into the position param.
+               @param rot the rotation in degrees
+               """
+               self.get_param('_rotation').set_value(str(rot))
+
+       def update(self):
+               """Update the block, parameters, and ports when a change occurs."""
+               self._bg_color = self.get_enabled() and Colors.BLOCK_ENABLED_COLOR or Colors.BLOCK_DISABLED_COLOR
+               self.clear()
+               self._create_labels()
+               self.W = self.label_width + 2*BLOCK_LABEL_PADDING
+               self.H = max(*(
+                       [self.label_height+2*BLOCK_LABEL_PADDING] + [2*PORT_BORDER_SEPARATION + \
+                       sum([port.H + PORT_SEPARATION for port in ports]) - PORT_SEPARATION
+                       for ports in (self.get_sources(), self.get_sinks())]
+               ))
+               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))
+               map(lambda p: p.update(), self.get_ports())
+
+       def _create_labels(self):
+               """Create the labels for the signal block."""
+               layouts = list()
+               #create the main layout
+               layout = gtk.DrawingArea().create_pango_layout('')
+               layouts.append(layout)
+               layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self))
+               self.label_width, self.label_height = layout.get_pixel_size()
+               #display the params
+               for param in filter(lambda p: p.get_hide() not in ('all', 'part'), self.get_params()):
+                       layout = param.get_layout()
+                       layouts.append(layout)
+                       w,h = layout.get_pixel_size()
+                       self.label_width = max(w, self.label_width)
+                       self.label_height = self.label_height + h + LABEL_SEPARATION
+               width = self.label_width
+               height = self.label_height
+               #setup the pixmap
+               pixmap = self.get_parent().new_pixmap(width, height)
+               gc = pixmap.new_gc()
+               gc.set_foreground(self._bg_color)
+               pixmap.draw_rectangle(gc, True, 0, 0, width, height)
+               #draw the layouts
+               h_off = 0
+               for i,layout in enumerate(layouts):
+                       w,h = layout.get_pixel_size()
+                       if i == 0: w_off = (width-w)/2
+                       else: w_off = 0
+                       pixmap.draw_layout(gc, w_off, h_off, layout)
+                       h_off = h + h_off + LABEL_SEPARATION
+               #create vertical and horizontal images
+               self.horizontal_label = image = pixmap.get_image(0, 0, width, height)
+               if self.is_vertical():
+                       self.vertical_label = vimage = gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), height, width)
+                       for i in range(width):
+                               for j in range(height): vimage.put_pixel(j, width-i-1, image.get_pixel(i, j))
+               map(lambda p: p._create_labels(), self.get_ports())
+
+       def draw(self, gc, window):
+               """
+               Draw the signal block with label and inputs/outputs.
+               @param gc the graphics context
+               @param window the gtk window to draw on
+               """
+               x, y = self.get_coordinate()
+               #draw main block
+               Element.draw(
+                       self, gc, window, bg_color=self._bg_color,
+                       border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or Colors.BORDER_COLOR,
+               )
+               #draw label image
+               if self.is_horizontal():
+                       window.draw_image(gc, self.horizontal_label, 0, 0, x+BLOCK_LABEL_PADDING, y+(self.H-self.label_height)/2, -1, -1)
+               elif self.is_vertical():
+                       window.draw_image(gc, self.vertical_label, 0, 0, x+(self.H-self.label_height)/2, y+BLOCK_LABEL_PADDING, -1, -1)
+               #draw ports
+               for port in self.get_ports(): port.draw(gc, window)
+
+       def what_is_selected(self, coor, coor_m=None):
+               """
+               Get the element that is selected.
+               @param coor the (x,y) tuple
+               @param coor_m the (x_m, y_m) tuple
+               @return this block, a port, or None
+               """
+               for port in self.get_ports():
+                       port_selected = port.what_is_selected(coor, coor_m)
+                       if port_selected: return port_selected
+               return Element.what_is_selected(self, coor, coor_m)