Element.py

Go to the documentation of this file.
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 ##@package grc.gui.elements.Element
00020 #Base class for graphical elements such as:
00021 #signal blocks, input sockets, output sockets and connections.
00022 #@author Josh Blum
00023 
00024 import Colors
00025 import pygtk
00026 pygtk.require('2.0')
00027 import gtk
00028 import pango
00029 from grc.Constants import *
00030 
00031 class Element(object):
00032         """
00033         GraphicalElement is the base class for all graphical elements.
00034         It contains an X,Y coordinate, a list of rectangular areas that the element occupies,
00035         and methods to detect selection of those areas.
00036         """
00037 
00038         def __init__(self, *args, **kwargs):
00039                 """!
00040                 Make a new list of rectangular areas and lines, and set the coordinate and the rotation.
00041                 """
00042                 self.set_rotation(POSSIBLE_ROTATIONS[0])
00043                 self.set_coordinate((0, 0))
00044                 self.clear()
00045                 self.set_highlighted(False)
00046 
00047         def is_horizontal(self, rotation=None):
00048                 """!
00049                 Is this element horizontal?
00050                 If rotation is None, use this element's rotation.
00051                 @param rotation the optional rotation
00052                 @return true if rotation is horizontal
00053                 """
00054                 rotation = rotation or self.get_rotation()
00055                 return rotation in (0, 180)
00056 
00057         def is_vertical(self, rotation=None):
00058                 """!
00059                 Is this element vertical?
00060                 If rotation is None, use this element's rotation.
00061                 @param rotation the optional rotation
00062                 @return true if rotation is vertical
00063                 """
00064                 rotation = rotation or self.get_rotation()
00065                 return rotation in (90, 270)
00066 
00067         def get_gc(self): return self._gc
00068 
00069         def draw(self, window, BG_color=Colors.BG_COLOR, FG_color=Colors.FG_COLOR):
00070                 """!
00071                 Draw in the given window.
00072                 @param window the gtk window to draw on
00073                 @param BG_color the background color
00074                 @param FG_color the foreground color
00075                 """
00076                 gc = self.get_parent().get_gc()
00077                 self._gc = gc
00078                 X,Y = self.get_coordinate()
00079                 for (rX,rY),(W,H) in self.areas_dict[self.get_rotation()]:
00080                         aX = X + rX
00081                         aY = Y + rY
00082                         gc.foreground = BG_color
00083                         window.draw_rectangle(gc, True, aX, aY, W, H)
00084                         gc.foreground = self.is_highlighted() and Colors.H_COLOR or FG_color
00085                         window.draw_rectangle(gc, False, aX, aY, W, H)
00086                 for (x1, y1),(x2, y2) in self.lines_dict[self.get_rotation()]:
00087                         gc.foreground = self.is_highlighted() and Colors.H_COLOR or FG_color
00088                         window.draw_line(gc, X+x1, Y+y1, X+x2, Y+y2)
00089 
00090         def rotate(self, direction):
00091                 """!
00092                 Rotate all of the areas by 90 degrees.
00093                 @param direction 90 or 270 degrees
00094                 """
00095                 self.set_rotation((self.get_rotation() + direction)%360)
00096 
00097         def clear(self):
00098                 """Empty the lines and areas."""
00099                 self.areas_dict = dict((rotation, list()) for rotation in POSSIBLE_ROTATIONS)
00100                 self.lines_dict = dict((rotation, list()) for rotation in POSSIBLE_ROTATIONS)
00101 
00102         def set_coordinate(self, coor):
00103                 """!
00104                 Set the reference coordinate.
00105                 @param coor the coordinate tuple (x,y)
00106                 """
00107                 self.coor = coor
00108 
00109         def get_parent(self):
00110                 """!
00111                 Get the parent of this element.
00112                 @return the parent
00113                 """
00114                 return self.parent
00115 
00116         def set_highlighted(self, highlighted):
00117                 """!
00118                 Set the highlight status.
00119                 @param highlighted true to enable highlighting
00120                 """
00121                 self.highlighted = highlighted
00122 
00123         def is_highlighted(self):
00124                 """!
00125                 Get the highlight status.
00126                 @return true if highlighted
00127                 """
00128                 return self.highlighted
00129 
00130         def get_coordinate(self):
00131                 """!Get the coordinate.
00132                 @return the coordinate tuple (x,y)
00133                 """
00134                 return self.coor
00135 
00136         def move(self, delta_coor):
00137                 """!
00138                 Move the element by adding the delta_coor to the current coordinate.
00139                 @param delta_coor (delta_x,delta_y) tuple
00140                 """
00141                 deltaX, deltaY = delta_coor
00142                 X, Y = self.get_coordinate()
00143                 self.set_coordinate((X+deltaX, Y+deltaY))
00144 
00145         def add_area(self, rel_coor, area, rotation=None):
00146                 """!
00147                 Add an area to the area list.
00148                 An area is actually a coordinate relative to the main coordinate
00149                 with a width/height pair relative to the area coordinate.
00150                 A positive width is to the right of the coordinate.
00151                 A positive height is above the coordinate.
00152                 The area is associated with a rotation.
00153                 If rotation is not specified, the element's current rotation is used.
00154                 @param rel_coor (x,y) offset from this element's coordinate
00155                 @param area (width,height) tuple
00156                 @param rotation rotation in degrees
00157                 """
00158                 self.areas_dict[rotation or self.get_rotation()].append((rel_coor, area))
00159 
00160         def add_line(self, rel_coor1, rel_coor2, rotation=None):
00161                 """!
00162                 Add a line to the line list.
00163                 A line is defined by 2 relative coordinates.
00164                 Lines must be horizontal or vertical.
00165                 The line is associated with a rotation.
00166                 If rotation is not specified, the element's current rotation is used.
00167                 @param rel_coor1 relative (x1,y1) tuple
00168                 @param rel_coor2 relative (x2,y2) tuple
00169                 @param rotation rotation in degrees
00170                 """
00171                 self.lines_dict[rotation or self.get_rotation()].append((rel_coor1, rel_coor2))
00172 
00173         def what_is_selected(self, coor, coor_m=None):
00174                 """!
00175                 One coordinate specified:
00176                         Is this element selected at given coordinate?
00177                         ie: is the coordinate encompassed by one of the areas or lines?
00178                 Both coordinates specified:
00179                         Is this element within the rectangular region defined by both coordinates?
00180                         ie: do any area corners or line endpoints fall within the region?
00181                 @param coor the selection coordinate, tuple x, y
00182                 @param coor_m an additional selection coordinate.
00183                 @return self if one of the areas/lines encompasses coor, else None.
00184                 """
00185                 #function to test if p is between a and b (inclusive)
00186                 in_between = lambda p, a, b: p >= min(a, b) and p <= max(a, b)
00187                 #relative coordinate
00188                 x, y = [a-b for a,b in zip(coor, self.get_coordinate())]
00189                 if coor_m:
00190                         x_m, y_m = [a-b for a,b in zip(coor_m, self.get_coordinate())]
00191                         #handle rectangular areas
00192                         for (x1,y1), (w,h) in self.areas_dict[self.get_rotation()]:
00193                                 if in_between(x1, x, x_m) and in_between(y1, y, y_m) or \
00194                                         in_between(x1+w, x, x_m) and in_between(y1, y, y_m) or \
00195                                         in_between(x1, x, x_m) and in_between(y1+h, y, y_m) or \
00196                                         in_between(x1+w, x, x_m) and in_between(y1+h, y, y_m):
00197                                         return self
00198                         #handle horizontal or vertical lines
00199                         for (x1, y1), (x2, y2) in self.lines_dict[self.get_rotation()]:
00200                                 if in_between(x1, x, x_m) and in_between(y1, y, y_m) or \
00201                                         in_between(x2, x, x_m) and in_between(y2, y, y_m):
00202                                         return self
00203                         return None
00204                 else:
00205                         #handle rectangular areas
00206                         for (x1,y1), (w,h) in self.areas_dict[self.get_rotation()]:
00207                                 if in_between(x, x1, x1+w) and in_between(y, y1, y1+h): return self
00208                         #handle horizontal or vertical lines
00209                         for (x1, y1), (x2, y2) in self.lines_dict[self.get_rotation()]:
00210                                 if x1 == x2: x1, x2 = x1-CONNECTION_SELECT_SENSITIVITY, x2+CONNECTION_SELECT_SENSITIVITY
00211                                 if y1 == y2: y1, y2 = y1-CONNECTION_SELECT_SENSITIVITY, y2+CONNECTION_SELECT_SENSITIVITY
00212                                 if in_between(x, x1, x2) and in_between(y, y1, y2): return self
00213                         return None
00214 
00215         def get_rotation(self):
00216                 """!
00217                 Get the rotation in degrees.
00218                 @return the rotation
00219                 """
00220                 return self.rotation
00221 
00222         def set_rotation(self, rotation):
00223                 """!
00224                 Set the rotation in degrees.
00225                 @param rotation the rotation"""
00226                 if rotation not in POSSIBLE_ROTATIONS:
00227                         raise Exception('"%s" is not one of the possible rotations: (%s)'%(rotation,POSSIBLE_ROTATIONS))
00228                 self.rotation = rotation
00229 
00230         def update(self):
00231                 """Do nothing for the update. Dummy method."""
00232                 pass
00233 
00234 

Generated on Sat Aug 23 02:00:11 2008 for GNU Radio Companion by  doxygen 1.5.4