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 Element import Element
00024 from grc.Constants import *
00025 import Colors
00026 import pygtk
00027 pygtk.require('2.0')
00028 import gtk
00029 import pango
00030
00031 class Port(Element):
00032 """The graphical port."""
00033
00034 def __init__(self, *args, **kwargs):
00035 """!
00036 Port contructor.
00037 Create list of connector coordinates.
00038 """
00039 Element.__init__(self)
00040 self.connector_coordinates = dict()
00041
00042 def update(self):
00043 """Create new areas and labels for the port."""
00044 self.clear()
00045 self.BG_color = Colors.get_color(self.get_color())
00046 self._create_labels()
00047
00048 rotation = self.get_rotation()
00049
00050 if self.is_source(): ports = self.get_parent().get_sources()
00051 elif self.is_sink(): ports = self.get_parent().get_sinks()
00052
00053 index = ports.index(self)
00054 length = len(ports)
00055
00056 if rotation in (180, 270): index = length-index-1
00057 offset = (self.get_parent().H - length*PORT_HEIGHT - (length-1)*PORT_SEPARATION)/2
00058
00059 if (self.is_sink() and rotation == 0) or (self.is_source() and rotation == 180):
00060 x = -1*PORT_WIDTH
00061 y = (PORT_SEPARATION+PORT_HEIGHT)*index+offset
00062 self.add_area((x, y), (PORT_WIDTH, PORT_HEIGHT))
00063 self._connector_coordinate = (x-1, y+PORT_HEIGHT/2)
00064 elif (self.is_source() and rotation == 0) or (self.is_sink() and rotation == 180):
00065 x = self.get_parent().W
00066 y = (PORT_SEPARATION+PORT_HEIGHT)*index+offset
00067 self.add_area((x, y), (PORT_WIDTH, PORT_HEIGHT))
00068 self._connector_coordinate = (x+1+PORT_WIDTH, y+PORT_HEIGHT/2)
00069 elif (self.is_source() and rotation == 90) or (self.is_sink() and rotation == 270):
00070 y = -1*PORT_WIDTH
00071 x = (PORT_SEPARATION+PORT_HEIGHT)*index+offset
00072 self.add_area((x, y), (PORT_HEIGHT, PORT_WIDTH))
00073 self._connector_coordinate = (x+PORT_HEIGHT/2, y-1)
00074 elif (self.is_sink() and rotation == 90) or (self.is_source() and rotation == 270):
00075 y = self.get_parent().W
00076 x = (PORT_SEPARATION+PORT_HEIGHT)*index+offset
00077 self.add_area((x, y), (PORT_HEIGHT, PORT_WIDTH))
00078 self._connector_coordinate = (x+PORT_HEIGHT/2, y+1+PORT_WIDTH)
00079
00080 self._connector_length = CONNECTOR_EXTENSION_INITIAL_LENGTH + CONNECTOR_EXTENSION_LENGTH*index
00081
00082 def _create_labels(self):
00083 """Create the labels for the socket."""
00084
00085 layout = gtk.DrawingArea().create_pango_layout(self.get_name())
00086 desc = pango.FontDescription(PORT_FONT)
00087 layout.set_font_description(desc)
00088 w,h = self.w,self.h = layout.get_pixel_size()
00089
00090 pixmap = gtk.gdk.Pixmap(self.get_parent().get_parent().get_window(), w, h, -1)
00091 gc = pixmap.new_gc()
00092 gc.foreground = self.BG_color
00093 pixmap.draw_rectangle(gc, True, 0, 0, w, h)
00094 gc.foreground = Colors.TXT_COLOR
00095 pixmap.draw_layout(gc, 0, 0, layout)
00096
00097 self.horizontal_label = image = pixmap.get_image(0, 0, w, h)
00098 if self.is_vertical():
00099 self.vertical_label = vimage = gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), h, w)
00100 for i in range(w):
00101 for j in range(h): vimage.put_pixel(j, w-i-1, image.get_pixel(i, j))
00102
00103 def draw(self, window):
00104 """!
00105 Draw the socket with a label.
00106 @param window the gtk window to draw on
00107 """
00108 Element.draw(self, window, BG_color=self.BG_color)
00109 gc = self.get_gc()
00110 gc.foreground = Colors.TXT_COLOR
00111 X,Y = self.get_coordinate()
00112 (x,y),(w,h) = self.areas_dict[self.get_rotation()][0]
00113 if self.is_horizontal():
00114 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)
00115 elif self.is_vertical():
00116 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)
00117
00118 def get_connector_coordinate(self):
00119 """!
00120 Get the coordinate where connections may attach to.
00121 @return the connector coordinate (x, y) tuple
00122 """
00123 x,y = self._connector_coordinate
00124 X,Y = self.get_coordinate()
00125 return (x+X, y+Y)
00126
00127 def get_connector_direction(self):
00128 """!
00129 Get the direction that the socket points: 0,90,180,270.
00130 This is the rotation degree if the socket is an output or
00131 the rotation degree + 180 if the socket is an input.
00132 @return the direction in degrees
00133 """
00134 if self.is_source(): return self.get_rotation()
00135 elif self.is_sink(): return (self.get_rotation() + 180)%360
00136
00137 def get_connector_length(self):
00138 """!
00139 Get the length of the connector.
00140 The connector length increases as the port index changes.
00141 @return the length in pixels
00142 """
00143 return self._connector_length
00144
00145 def get_rotation(self):
00146 """!
00147 Get the parent's rotation rather than self.
00148 @return the parent's rotation
00149 """
00150 return self.get_parent().get_rotation()
00151
00152 def move(self, delta_coor):
00153 """!
00154 Move the parent rather than self.
00155 @param delta_corr the (delta_x, delta_y) tuple
00156 """
00157 self.get_parent().move(delta_coor)
00158
00159 def rotate(self, direction):
00160 """!
00161 Rotate the parent rather than self.
00162 @param direction degrees to rotate
00163 """
00164 self.get_parent().rotate(direction)
00165
00166 def get_coordinate(self):
00167 """!
00168 Get the parent's coordinate rather than self.
00169 @return the parents coordinate
00170 """
00171 return self.get_parent().get_coordinate()
00172
00173 def set_highlighted(self, highlight):
00174 """!
00175 Set the parent highlight rather than self.
00176 @param highlight true to enable highlighting
00177 """
00178 self.get_parent().set_highlighted(highlight)
00179
00180 def is_highlighted(self):
00181 """!
00182 Get the parent's is highlight rather than self.
00183 @return the parent's highlighting status
00184 """
00185 return self.get_parent().is_highlighted()