2 Copyright 2007 Free Software Foundation, Inc.
3 This file is part of GNU Radio
5 GNU Radio Companion is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 GNU Radio Companion is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 ##@package grc.gui.elements.Block
20 #The graphical signal block.
22 from grc import Preferences
23 from Element import Element
26 from grc.Constants import *
33 """The graphical signal block."""
35 def __init__(self, *args, **kwargs):
38 Add graphics related params to the block.
40 #add the position param
41 self._params['_coordinate'] = self.get_parent().get_parent().Param(
44 'name': 'GUI Coordinate',
51 self._params['_rotation'] = self.get_parent().get_parent().Param(
54 'name': 'GUI Rotation',
61 Element.__init__(self)
63 def get_coordinate(self):
65 Get the coordinate from the position param.
66 @return the coordinate tuple (x, y) or (0, 0) if failure
68 try: #should evaluate to tuple
69 coor = eval(self.get_param('_coordinate').get_value())
71 fgW,fgH = self.get_parent().get_size()
74 elif x >= fgW - BORDER_PROXIMITY_SENSITIVITY:
75 x = fgW - BORDER_PROXIMITY_SENSITIVITY
78 elif y >= fgH - BORDER_PROXIMITY_SENSITIVITY:
79 y = fgH - BORDER_PROXIMITY_SENSITIVITY
82 self.set_coordinate((0, 0))
85 def set_coordinate(self, coor):
87 Set the coordinate into the position param.
88 @param coor the coordinate tuple (x, y)
90 self.get_param('_coordinate').set_value(str(coor))
92 def get_rotation(self):
94 Get the rotation from the position param.
95 @return the rotation in degrees or 0 if failure
97 try: #should evaluate to dict
98 rotation = eval(self.get_param('_rotation').get_value())
101 self.set_rotation(POSSIBLE_ROTATIONS[0])
102 return POSSIBLE_ROTATIONS[0]
104 def set_rotation(self, rot):
106 Set the rotation into the position param.
107 @param rot the rotation in degrees
109 self.get_param('_rotation').set_value(str(rot))
112 """Update the block, parameters, and ports when a change occurs."""
113 self.bg_color = self.get_enabled() and Colors.BG_COLOR or Colors.DISABLED_BG_COLOR
115 self._create_labels()
116 self.W = self.label_width + 2*LABEL_PADDING_WIDTH
117 max_ports = max(len(self.get_sinks()), len(self.get_sources()), 1)
118 self.H = max(self.label_height+2*LABEL_PADDING_HEIGHT, 2*PORT_BORDER_SEPARATION + max_ports*PORT_HEIGHT + (max_ports-1)*PORT_SEPARATION)
119 if self.is_horizontal(): self.add_area((0,0),(self.W,self.H))
120 elif self.is_vertical(): self.add_area((0,0),(self.H,self.W))
121 map(lambda p: p.update(), self.get_sinks() + self.get_sources())
123 def _create_labels(self):
124 """Create the labels for the signal block."""
126 #create the main layout
127 layout = gtk.DrawingArea().create_pango_layout('')
128 layouts.append(layout)
129 if self.is_valid(): layout.set_markup('<b>'+Utils.xml_encode(self.get_name())+'</b>')
130 else: layout.set_markup('<span foreground="red"><b>'+Utils.xml_encode(self.get_name())+'</b></span>')
131 desc = pango.FontDescription(BLOCK_FONT)
132 layout.set_font_description(desc)
133 self.label_width, self.label_height = layout.get_pixel_size()
134 #display the params (except for the special params id and position)
135 if Preferences.show_params():
136 for param in filter(lambda p: p.get_hide() not in ('all', 'part'), self.get_params()):
137 if not Preferences.show_id() and param.get_key() == 'id': continue
138 layout = param.get_layout()
139 layouts.append(layout)
140 w,h = layout.get_pixel_size()
141 self.label_width = max(w, self.label_width)
142 self.label_height = self.label_height + h + LABEL_SEPARATION
143 width = self.label_width
144 height = self.label_height
146 pixmap = gtk.gdk.Pixmap(self.get_parent().get_window(), width, height, -1)
148 gc.foreground = self.bg_color
149 pixmap.draw_rectangle(gc, True, 0, 0, width, height)
150 gc.foreground = Colors.TXT_COLOR
153 for i,layout in enumerate(layouts):
154 w,h = layout.get_pixel_size()
155 if i == 0: w_off = (width-w)/2
157 pixmap.draw_layout(gc, w_off, h_off, layout)
158 h_off = h + h_off + LABEL_SEPARATION
159 #create vertical and horizontal images
160 self.horizontal_label = image = pixmap.get_image(0, 0, width, height)
161 if self.is_vertical():
162 self.vertical_label = vimage = gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), height, width)
163 for i in range(width):
164 for j in range(height): vimage.put_pixel(j, width-i-1, image.get_pixel(i, j))
166 def draw(self, window):
168 Draw the signal block with label and inputs/outputs.
169 @param window the gtk window to draw on
171 x, y = self.get_coordinate()
173 Element.draw(self, window, BG_color=self.bg_color)
176 if self.is_horizontal():
177 window.draw_image(gc, self.horizontal_label, 0, 0, x+LABEL_PADDING_WIDTH, y+(self.H-self.label_height)/2, -1, -1)
178 elif self.is_vertical():
179 window.draw_image(gc, self.vertical_label, 0, 0, x+(self.H-self.label_height)/2, y+LABEL_PADDING_WIDTH, -1, -1)
181 map(lambda p: p.draw(window), self.get_ports())
183 def what_is_selected(self, coor, coor_m=None):
185 Get the element that is selected.
186 @param coor the (x,y) tuple
187 @param coor_m the (x_m, y_m) tuple
188 @return this block, a port, or None
190 for port in self.get_ports():
191 port_selected = port.what_is_selected(coor, coor_m)
192 if port_selected: return port_selected
193 return Element.what_is_selected(self, coor, coor_m)