2 Copyright 2007, 2008, 2009 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
20 from Element import Element
23 from .. base import odict
24 from Constants import BORDER_PROXIMITY_SENSITIVITY
25 from Constants import \
26 BLOCK_LABEL_PADDING, \
27 PORT_SEPARATION, LABEL_SEPARATION, \
28 PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS
34 BLOCK_MARKUP_TMPL="""\
35 #set $foreground = $block.is_valid() and 'black' or 'red'
36 <span foreground="$foreground" font_desc="Sans 8"><b>$encode($block.get_name())</b></span>"""
39 """The graphical signal block."""
44 Add graphics related params to the block.
46 #add the position param
47 self.get_params().append(self.get_parent().get_parent().Param(
50 'name': 'GUI Coordinate',
57 self.get_params().append(self.get_parent().get_parent().Param(
60 'name': 'GUI Rotation',
67 Element.__init__(self)
69 def get_coordinate(self):
71 Get the coordinate from the position param.
72 @return the coordinate tuple (x, y) or (0, 0) if failure
74 try: #should evaluate to tuple
75 coor = eval(self.get_param('_coordinate').get_value())
77 fgW,fgH = self.get_parent().get_size()
80 elif x >= fgW - BORDER_PROXIMITY_SENSITIVITY:
81 x = fgW - BORDER_PROXIMITY_SENSITIVITY
84 elif y >= fgH - BORDER_PROXIMITY_SENSITIVITY:
85 y = fgH - BORDER_PROXIMITY_SENSITIVITY
88 self.set_coordinate((0, 0))
91 def set_coordinate(self, coor):
93 Set the coordinate into the position param.
94 @param coor the coordinate tuple (x, y)
96 self.get_param('_coordinate').set_value(str(coor))
98 def get_rotation(self):
100 Get the rotation from the position param.
101 @return the rotation in degrees or 0 if failure
103 try: #should evaluate to dict
104 rotation = eval(self.get_param('_rotation').get_value())
107 self.set_rotation(POSSIBLE_ROTATIONS[0])
108 return POSSIBLE_ROTATIONS[0]
110 def set_rotation(self, rot):
112 Set the rotation into the position param.
113 @param rot the rotation in degrees
115 self.get_param('_rotation').set_value(str(rot))
117 def create_shapes(self):
118 """Update the block, parameters, and ports when a change occurs."""
119 Element.create_shapes(self)
120 if self.is_horizontal(): self.add_area((0, 0), (self.W, self.H))
121 elif self.is_vertical(): self.add_area((0, 0), (self.H, self.W))
123 def create_labels(self):
124 """Create the labels for the signal block."""
125 Element.create_labels(self)
126 self._bg_color = self.get_enabled() and Colors.BLOCK_ENABLED_COLOR or Colors.BLOCK_DISABLED_COLOR
128 #create the main layout
129 layout = gtk.DrawingArea().create_pango_layout('')
130 layouts.append(layout)
131 layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self))
132 self.label_width, self.label_height = layout.get_pixel_size()
134 markups = [param.get_markup() for param in self.get_params() if param.get_hide() not in ('all', 'part')]
136 layout = gtk.DrawingArea().create_pango_layout('')
137 layout.set_spacing(LABEL_SEPARATION*pango.SCALE)
138 layout.set_markup('\n'.join(markups))
139 layouts.append(layout)
140 w,h = layout.get_pixel_size()
141 self.label_width = max(w, self.label_width)
142 self.label_height += h + LABEL_SEPARATION
143 width = self.label_width
144 height = self.label_height
146 pixmap = self.get_parent().new_pixmap(width, height)
148 gc.set_foreground(self._bg_color)
149 pixmap.draw_rectangle(gc, True, 0, 0, width, height)
152 for i,layout in enumerate(layouts):
153 w,h = layout.get_pixel_size()
154 if i == 0: w_off = (width-w)/2
156 pixmap.draw_layout(gc, w_off, h_off, layout)
157 h_off = h + h_off + LABEL_SEPARATION
158 #create vertical and horizontal images
159 self.horizontal_label = image = pixmap.get_image(0, 0, width, height)
160 if self.is_vertical():
161 self.vertical_label = vimage = gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), height, width)
162 for i in range(width):
163 for j in range(height): vimage.put_pixel(j, width-i-1, image.get_pixel(i, j))
164 #calculate width and height needed
165 self.W = self.label_width + 2*BLOCK_LABEL_PADDING
167 [self.label_height+2*BLOCK_LABEL_PADDING] + [2*PORT_BORDER_SEPARATION + \
168 sum([port.H + PORT_SEPARATION for port in ports]) - PORT_SEPARATION
169 for ports in (self.get_sources(), self.get_sinks())]
172 def draw(self, gc, window):
174 Draw the signal block with label and inputs/outputs.
175 @param gc the graphics context
176 @param window the gtk window to draw on
178 x, y = self.get_coordinate()
181 self, gc, window, bg_color=self._bg_color,
182 border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or Colors.BORDER_COLOR,
185 if self.is_horizontal():
186 window.draw_image(gc, self.horizontal_label, 0, 0, x+BLOCK_LABEL_PADDING, y+(self.H-self.label_height)/2, -1, -1)
187 elif self.is_vertical():
188 window.draw_image(gc, self.vertical_label, 0, 0, x+(self.H-self.label_height)/2, y+BLOCK_LABEL_PADDING, -1, -1)
190 for port in self.get_ports(): port.draw(gc, window)
192 def what_is_selected(self, coor, coor_m=None):
194 Get the element that is selected.
195 @param coor the (x,y) tuple
196 @param coor_m the (x_m, y_m) tuple
197 @return this block, a port, or None
199 for port in self.get_ports():
200 port_selected = port.what_is_selected(coor, coor_m)
201 if port_selected: return port_selected
202 return Element.what_is_selected(self, coor, coor_m)