00001 """
00002 Copyright 2007 Free Software Foundation, Inc.
00003 This file is part of GNU Radio
00004
00005 GNU Radio Companion is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU General Public License
00007 as published by the Free Software Foundation; either version 2
00008 of the License, or (at your option) any later version.
00009
00010 GNU Radio Companion is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013 GNU General Public License for more details.
00014
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
00018 """
00019
00020
00021
00022
00023 from grc import Preferences
00024 from Element import Element
00025 import Utils
00026 import Colors
00027 from grc.Constants import *
00028 import pygtk
00029 pygtk.require('2.0')
00030 import gtk
00031 import pango
00032
00033 class Block(Element):
00034 """The graphical signal block."""
00035
00036 def __init__(self, *args, **kwargs):
00037 """!
00038 Block contructor.
00039 Add graphics related params to the block.
00040 """
00041
00042 self._params['_coordinate'] = self.get_parent().get_parent().Param(
00043 self,
00044 {
00045 'name': 'GUI Coordinate',
00046 'key': '_coordinate',
00047 'type': 'raw',
00048 'value': '(0, 0)',
00049 'hide': 'all',
00050 }
00051 )
00052 self._params['_rotation'] = self.get_parent().get_parent().Param(
00053 self,
00054 {
00055 'name': 'GUI Rotation',
00056 'key': '_rotation',
00057 'type': 'raw',
00058 'value': '0',
00059 'hide': 'all',
00060 }
00061 )
00062 Element.__init__(self)
00063
00064 def get_coordinate(self):
00065 """!
00066 Get the coordinate from the position param.
00067 @return the coordinate tuple (x, y) or (0, 0) if failure
00068 """
00069 try:
00070 coor = eval(self.get_param('_coordinate').get_value())
00071 x, y = map(int, coor)
00072 fgW,fgH = self.get_parent().get_size()
00073 if x <= 0:
00074 x = 0
00075 elif x >= fgW - BORDER_PROXIMITY_SENSITIVITY:
00076 x = fgW - BORDER_PROXIMITY_SENSITIVITY
00077 if y <= 0:
00078 y = 0
00079 elif y >= fgH - BORDER_PROXIMITY_SENSITIVITY:
00080 y = fgH - BORDER_PROXIMITY_SENSITIVITY
00081 return (x, y)
00082 except:
00083 self.set_coordinate((0, 0))
00084 return (0, 0)
00085
00086 def set_coordinate(self, coor):
00087 """!
00088 Set the coordinate into the position param.
00089 @param coor the coordinate tuple (x, y)
00090 """
00091 self.get_param('_coordinate').set_value(str(coor))
00092
00093 def get_rotation(self):
00094 """!
00095 Get the rotation from the position param.
00096 @return the rotation in degrees or 0 if failure
00097 """
00098 try:
00099 rotation = eval(self.get_param('_rotation').get_value())
00100 return int(rotation)
00101 except:
00102 self.set_rotation(POSSIBLE_ROTATIONS[0])
00103 return POSSIBLE_ROTATIONS[0]
00104
00105 def set_rotation(self, rot):
00106 """!
00107 Set the rotation into the position param.
00108 @param rot the rotation in degrees
00109 """
00110 self.get_param('_rotation').set_value(str(rot))
00111
00112 def update(self):
00113 """Update the block, parameters, and ports when a change occurs."""
00114 self.bg_color = self.get_enabled() and Colors.BG_COLOR or Colors.DISABLED_BG_COLOR
00115 self.clear()
00116 self._create_labels()
00117 self.W = self.label_width + 2*LABEL_PADDING_WIDTH
00118 max_ports = max(len(self.get_sinks()), len(self.get_sources()), 1)
00119 self.H = max(self.label_height+2*LABEL_PADDING_HEIGHT, 2*PORT_BORDER_SEPARATION + max_ports*PORT_HEIGHT + (max_ports-1)*PORT_SEPARATION)
00120 if self.is_horizontal(): self.add_area((0,0),(self.W,self.H))
00121 elif self.is_vertical(): self.add_area((0,0),(self.H,self.W))
00122 map(lambda p: p.update(), self.get_sinks() + self.get_sources())
00123
00124 def _create_labels(self):
00125 """Create the labels for the signal block."""
00126 layouts = list()
00127
00128 layout = gtk.DrawingArea().create_pango_layout('')
00129 layouts.append(layout)
00130 if self.is_valid(): layout.set_markup('<b>'+Utils.xml_encode(self.get_name())+'</b>')
00131 else: layout.set_markup('<span foreground="red"><b>'+Utils.xml_encode(self.get_name())+'</b></span>')
00132 desc = pango.FontDescription(BLOCK_FONT)
00133 layout.set_font_description(desc)
00134 self.label_width, self.label_height = layout.get_pixel_size()
00135
00136 if Preferences.show_params():
00137 for param in filter(lambda p: p.get_hide() not in ('all', 'part'), self.get_params()):
00138 if not Preferences.show_id() and param.get_key() == 'id': continue
00139 layout = param.get_layout()
00140 layouts.append(layout)
00141 w,h = layout.get_pixel_size()
00142 self.label_width = max(w, self.label_width)
00143 self.label_height = self.label_height + h + LABEL_SEPARATION
00144 width = self.label_width
00145 height = self.label_height
00146
00147 pixmap = gtk.gdk.Pixmap(self.get_parent().get_window(), width, height, -1)
00148 gc = pixmap.new_gc()
00149 gc.foreground = self.bg_color
00150 pixmap.draw_rectangle(gc, True, 0, 0, width, height)
00151 gc.foreground = Colors.TXT_COLOR
00152
00153 h_off = 0
00154 for i,layout in enumerate(layouts):
00155 w,h = layout.get_pixel_size()
00156 if i == 0: w_off = (width-w)/2
00157 else: w_off = 0
00158 pixmap.draw_layout(gc, w_off, h_off, layout)
00159 h_off = h + h_off + LABEL_SEPARATION
00160
00161 self.horizontal_label = image = pixmap.get_image(0, 0, width, height)
00162 if self.is_vertical():
00163 self.vertical_label = vimage = gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), height, width)
00164 for i in range(width):
00165 for j in range(height): vimage.put_pixel(j, width-i-1, image.get_pixel(i, j))
00166
00167 def draw(self, window):
00168 """!
00169 Draw the signal block with label and inputs/outputs.
00170 @param window the gtk window to draw on
00171 """
00172 x, y = self.get_coordinate()
00173
00174 Element.draw(self, window, BG_color=self.bg_color)
00175
00176 gc = self.get_gc()
00177 if self.is_horizontal():
00178 window.draw_image(gc, self.horizontal_label, 0, 0, x+LABEL_PADDING_WIDTH, y+(self.H-self.label_height)/2, -1, -1)
00179 elif self.is_vertical():
00180 window.draw_image(gc, self.vertical_label, 0, 0, x+(self.H-self.label_height)/2, y+LABEL_PADDING_WIDTH, -1, -1)
00181
00182 map(lambda p: p.draw(window), self.get_ports())
00183
00184 def what_is_selected(self, coor, coor_m=None):
00185 """!
00186 Get the element that is selected.
00187 @param coor the (x,y) tuple
00188 @param coor_m the (x_m, y_m) tuple
00189 @return this block, a port, or None
00190 """
00191 for port in self.get_ports():
00192 port_selected = port.what_is_selected(coor, coor_m)
00193 if port_selected: return port_selected
00194 return Element.what_is_selected(self, coor, coor_m)
00195