Removing PowerLine since we weren't using it and don't have plans to.
[debian/gnuradio] / grc / gui / Block.py
1 """
2 Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
3 This file is part of GNU Radio
4
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.
9
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.
14
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
18 """
19
20 from Element import Element
21 import Utils
22 import Colors
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
29 import pygtk
30 pygtk.require('2.0')
31 import gtk
32 import pango
33
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>"""
37
38 class Block(Element):
39         """The graphical signal block."""
40
41         def __init__(self):
42                 """
43                 Block contructor.
44                 Add graphics related params to the block.
45                 """
46                 #add the position param
47                 self.get_params().append(self.get_parent().get_parent().Param(
48                         block=self,
49                         n=odict({
50                                 'name': 'GUI Coordinate',
51                                 'key': '_coordinate',
52                                 'type': 'raw',
53                                 'value': '(0, 0)',
54                                 'hide': 'all',
55                         })
56                 ))
57                 self.get_params().append(self.get_parent().get_parent().Param(
58                         block=self,
59                         n=odict({
60                                 'name': 'GUI Rotation',
61                                 'key': '_rotation',
62                                 'type': 'raw',
63                                 'value': '0',
64                                 'hide': 'all',
65                         })
66                 ))
67                 Element.__init__(self)
68
69         def get_coordinate(self):
70                 """
71                 Get the coordinate from the position param.
72                 @return the coordinate tuple (x, y) or (0, 0) if failure
73                 """
74                 try: #should evaluate to tuple
75                         coor = eval(self.get_param('_coordinate').get_value())
76                         x, y = map(int, coor)
77                         fgW,fgH = self.get_parent().get_size()
78                         if x <= 0:
79                                 x = 0
80                         elif x >= fgW - BORDER_PROXIMITY_SENSITIVITY:
81                                 x = fgW - BORDER_PROXIMITY_SENSITIVITY
82                         if y <= 0:
83                                 y = 0
84                         elif y >= fgH - BORDER_PROXIMITY_SENSITIVITY:
85                                 y = fgH - BORDER_PROXIMITY_SENSITIVITY
86                         return (x, y)
87                 except:
88                         self.set_coordinate((0, 0))
89                         return (0, 0)
90
91         def set_coordinate(self, coor):
92                 """
93                 Set the coordinate into the position param.
94                 @param coor the coordinate tuple (x, y)
95                 """
96                 self.get_param('_coordinate').set_value(str(coor))
97
98         def get_rotation(self):
99                 """
100                 Get the rotation from the position param.
101                 @return the rotation in degrees or 0 if failure
102                 """
103                 try: #should evaluate to dict
104                         rotation = eval(self.get_param('_rotation').get_value())
105                         return int(rotation)
106                 except:
107                         self.set_rotation(POSSIBLE_ROTATIONS[0])
108                         return POSSIBLE_ROTATIONS[0]
109
110         def set_rotation(self, rot):
111                 """
112                 Set the rotation into the position param.
113                 @param rot the rotation in degrees
114                 """
115                 self.get_param('_rotation').set_value(str(rot))
116
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))
122
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
127                 layouts = list()
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()
133                 #display the params
134                 markups = [param.get_markup() for param in self.get_params() if param.get_hide() not in ('all', 'part')]
135                 if markups:
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
145                 #setup the pixmap
146                 pixmap = self.get_parent().new_pixmap(width, height)
147                 gc = pixmap.new_gc()
148                 gc.set_foreground(self._bg_color)
149                 pixmap.draw_rectangle(gc, True, 0, 0, width, height)
150                 #draw the layouts
151                 h_off = 0
152                 for i,layout in enumerate(layouts):
153                         w,h = layout.get_pixel_size()
154                         if i == 0: w_off = (width-w)/2
155                         else: w_off = 0
156                         pixmap.draw_layout(gc, w_off, h_off, layout)
157                         h_off = h + h_off + LABEL_SEPARATION
158                 #create vertical and horizontal pixmaps
159                 self.horizontal_label = pixmap
160                 if self.is_vertical():
161                         self.vertical_label = self.get_parent().new_pixmap(height, width)
162                         Utils.rotate_pixmap(gc, self.horizontal_label, self.vertical_label)
163                 #calculate width and height needed
164                 self.W = self.label_width + 2*BLOCK_LABEL_PADDING
165                 self.H = max(*(
166                         [self.label_height+2*BLOCK_LABEL_PADDING] + [2*PORT_BORDER_SEPARATION + \
167                         sum([port.H + PORT_SEPARATION for port in ports]) - PORT_SEPARATION
168                         for ports in (self.get_sources(), self.get_sinks())]
169                 ))
170
171         def draw(self, gc, window):
172                 """
173                 Draw the signal block with label and inputs/outputs.
174                 @param gc the graphics context
175                 @param window the gtk window to draw on
176                 """
177                 x, y = self.get_coordinate()
178                 #draw main block
179                 Element.draw(
180                         self, gc, window, bg_color=self._bg_color,
181                         border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or Colors.BORDER_COLOR,
182                 )
183                 #draw label image
184                 if self.is_horizontal():
185                         window.draw_drawable(gc, self.horizontal_label, 0, 0, x+BLOCK_LABEL_PADDING, y+(self.H-self.label_height)/2, -1, -1)
186                 elif self.is_vertical():
187                         window.draw_drawable(gc, self.vertical_label, 0, 0, x+(self.H-self.label_height)/2, y+BLOCK_LABEL_PADDING, -1, -1)
188                 #draw ports
189                 for port in self.get_ports(): port.draw(gc, window)
190
191         def what_is_selected(self, coor, coor_m=None):
192                 """
193                 Get the element that is selected.
194                 @param coor the (x,y) tuple
195                 @param coor_m the (x_m, y_m) tuple
196                 @return this block, a port, or None
197                 """
198                 for port in self.get_ports():
199                         port_selected = port.what_is_selected(coor, coor_m)
200                         if port_selected: return port_selected
201                 return Element.what_is_selected(self, coor, coor_m)