moved author attribution out of individual files and put in AUTHORS
[debian/gnuradio] / grc / src / grc / gui / elements / Port.py
1 """
2 Copyright 2007 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 ##@package grc.gui.elements.Port
20 #The graphical input/output sockets of the signal block.
21
22 from Element import Element
23 from grc.Constants import *
24 import Colors
25 import pygtk
26 pygtk.require('2.0')
27 import gtk
28 import pango
29
30 class Port(Element):
31         """The graphical port."""
32
33         def __init__(self, *args, **kwargs):
34                 """!
35                 Port contructor.
36                 Create list of connector coordinates.
37                 """
38                 Element.__init__(self)
39                 self.connector_coordinates = dict()
40
41         def update(self):
42                 """Create new areas and labels for the port."""
43                 self.clear()
44                 self.BG_color = Colors.get_color(self.get_color())
45                 self._create_labels()
46                 #get current rotation
47                 rotation = self.get_rotation()
48                 #get all sibling ports
49                 if self.is_source(): ports = self.get_parent().get_sources()
50                 elif self.is_sink(): ports = self.get_parent().get_sinks()
51                 #get a numeric index for this port relative to its sibling ports
52                 index = ports.index(self)
53                 length = len(ports)
54                 #reverse the order of ports     for these rotations
55                 if rotation in (180, 270): index = length-index-1
56                 offset = (self.get_parent().H - length*PORT_HEIGHT - (length-1)*PORT_SEPARATION)/2
57                 #create areas and connector coordinates
58                 if (self.is_sink() and rotation == 0) or (self.is_source() and rotation == 180):
59                         x = -1*PORT_WIDTH
60                         y = (PORT_SEPARATION+PORT_HEIGHT)*index+offset
61                         self.add_area((x, y), (PORT_WIDTH, PORT_HEIGHT))
62                         self._connector_coordinate = (x-1, y+PORT_HEIGHT/2)
63                 elif (self.is_source() and rotation == 0) or (self.is_sink() and rotation == 180):
64                         x = self.get_parent().W
65                         y = (PORT_SEPARATION+PORT_HEIGHT)*index+offset
66                         self.add_area((x, y), (PORT_WIDTH, PORT_HEIGHT))
67                         self._connector_coordinate = (x+1+PORT_WIDTH, y+PORT_HEIGHT/2)
68                 elif (self.is_source() and rotation == 90) or (self.is_sink() and rotation == 270):
69                         y = -1*PORT_WIDTH
70                         x = (PORT_SEPARATION+PORT_HEIGHT)*index+offset
71                         self.add_area((x, y), (PORT_HEIGHT, PORT_WIDTH))
72                         self._connector_coordinate = (x+PORT_HEIGHT/2, y-1)
73                 elif (self.is_sink() and rotation == 90) or (self.is_source() and rotation == 270):
74                         y = self.get_parent().W
75                         x = (PORT_SEPARATION+PORT_HEIGHT)*index+offset
76                         self.add_area((x, y), (PORT_HEIGHT, PORT_WIDTH))
77                         self._connector_coordinate = (x+PORT_HEIGHT/2, y+1+PORT_WIDTH)
78                 #the connector length
79                 self._connector_length = CONNECTOR_EXTENSION_INITIAL_LENGTH + CONNECTOR_EXTENSION_LENGTH*index
80
81         def _create_labels(self):
82                 """Create the labels for the socket."""
83                 #create the layout
84                 layout = gtk.DrawingArea().create_pango_layout(self.get_name())
85                 desc = pango.FontDescription(PORT_FONT)
86                 layout.set_font_description(desc)
87                 w,h = self.w,self.h = layout.get_pixel_size()
88                 #create the pixmap
89                 pixmap = gtk.gdk.Pixmap(self.get_parent().get_parent().get_window(), w, h, -1)
90                 gc = pixmap.new_gc()
91                 gc.foreground = self.BG_color
92                 pixmap.draw_rectangle(gc, True, 0, 0, w, h)
93                 gc.foreground = Colors.TXT_COLOR
94                 pixmap.draw_layout(gc, 0, 0, layout)
95                 #create the images
96                 self.horizontal_label = image = pixmap.get_image(0, 0, w, h)
97                 if self.is_vertical():
98                         self.vertical_label = vimage = gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), h, w)
99                         for i in range(w):
100                                 for j in range(h): vimage.put_pixel(j, w-i-1, image.get_pixel(i, j))
101
102         def draw(self, window):
103                 """!
104                 Draw the socket with a label.
105                 @param window the gtk window to draw on
106                 """
107                 Element.draw(self, window, BG_color=self.BG_color)
108                 gc = self.get_gc()
109                 gc.foreground = Colors.TXT_COLOR
110                 X,Y = self.get_coordinate()
111                 (x,y),(w,h) = self.areas_dict[self.get_rotation()][0] #use the first area's sizes to place the labels
112                 if self.is_horizontal():
113                         window.draw_image(gc, self.horizontal_label, 0, 0, x+X+(PORT_WIDTH-self.w)/2, y+Y+(PORT_HEIGHT-self.h)/2, -1, -1)
114                 elif self.is_vertical():
115                         window.draw_image(gc, self.vertical_label, 0, 0, x+X+(PORT_HEIGHT-self.h)/2, y+Y+(PORT_WIDTH-self.w)/2, -1, -1)
116
117         def get_connector_coordinate(self):
118                 """!
119                 Get the coordinate where connections may attach to.
120                 @return the connector coordinate (x, y) tuple
121                 """
122                 x,y = self._connector_coordinate
123                 X,Y = self.get_coordinate()
124                 return (x+X, y+Y)
125
126         def get_connector_direction(self):
127                 """!
128                 Get the direction that the socket points: 0,90,180,270.
129                 This is the rotation degree if the socket is an output or
130                 the rotation degree + 180 if the socket is an input.
131                 @return the direction in degrees
132                 """
133                 if self.is_source(): return self.get_rotation()
134                 elif self.is_sink(): return (self.get_rotation() + 180)%360
135
136         def get_connector_length(self):
137                 """!
138                 Get the length of the connector.
139                 The connector length increases as the port index changes.
140                 @return the length in pixels
141                 """
142                 return self._connector_length
143
144         def get_rotation(self):
145                 """!
146                 Get the parent's rotation rather than self.
147                 @return the parent's rotation
148                 """
149                 return self.get_parent().get_rotation()
150
151         def move(self, delta_coor):
152                 """!
153                 Move the parent rather than self.
154                 @param delta_corr the (delta_x, delta_y) tuple
155                 """
156                 self.get_parent().move(delta_coor)
157
158         def rotate(self, direction):
159                 """!
160                 Rotate the parent rather than self.
161                 @param direction degrees to rotate
162                 """
163                 self.get_parent().rotate(direction)
164
165         def get_coordinate(self):
166                 """!
167                 Get the parent's coordinate rather than self.
168                 @return the parents coordinate
169                 """
170                 return self.get_parent().get_coordinate()
171
172         def set_highlighted(self, highlight):
173                 """!
174                 Set the parent highlight rather than self.
175                 @param highlight true to enable highlighting
176                 """
177                 self.get_parent().set_highlighted(highlight)
178
179         def is_highlighted(self):
180                 """!
181                 Get the parent's is highlight rather than self.
182                 @return the parent's highlighting status
183                 """
184                 return self.get_parent().is_highlighted()