summaryrefslogtreecommitdiff
path: root/grc/src/platforms/gui
diff options
context:
space:
mode:
Diffstat (limited to 'grc/src/platforms/gui')
-rw-r--r--grc/src/platforms/gui/Block.py199
-rw-r--r--grc/src/platforms/gui/Colors.py37
-rw-r--r--grc/src/platforms/gui/Connection.py140
-rw-r--r--grc/src/platforms/gui/Constants.py44
-rw-r--r--grc/src/platforms/gui/Element.py226
-rw-r--r--grc/src/platforms/gui/FlowGraph.py488
-rw-r--r--grc/src/platforms/gui/Makefile.am37
-rw-r--r--grc/src/platforms/gui/Param.py103
-rw-r--r--grc/src/platforms/gui/Platform.py48
-rw-r--r--grc/src/platforms/gui/Port.py190
-rw-r--r--grc/src/platforms/gui/Utils.py82
-rw-r--r--grc/src/platforms/gui/__init__.py1
12 files changed, 0 insertions, 1595 deletions
diff --git a/grc/src/platforms/gui/Block.py b/grc/src/platforms/gui/Block.py
deleted file mode 100644
index 862a59393..000000000
--- a/grc/src/platforms/gui/Block.py
+++ /dev/null
@@ -1,199 +0,0 @@
-"""
-Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-"""
-
-from Element import Element
-import Utils
-import Colors
-from ... utils import odict
-from Constants import BORDER_PROXIMITY_SENSITIVITY
-from Constants import \
- BLOCK_LABEL_PADDING, \
- PORT_SEPARATION, LABEL_SEPARATION, \
- PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS
-import pygtk
-pygtk.require('2.0')
-import gtk
-
-BLOCK_MARKUP_TMPL="""\
-#set $foreground = $block.is_valid() and 'black' or 'red'
-<span foreground="$foreground" font_desc="Sans 8"><b>$encode($block.get_name())</b></span>"""
-
-class Block(Element):
- """The graphical signal block."""
-
- def __init__(self, *args, **kwargs):
- """
- Block contructor.
- Add graphics related params to the block.
- """
- #add the position param
- self._params['_coordinate'] = self.get_parent().get_parent().Param(
- self,
- odict({
- 'name': 'GUI Coordinate',
- 'key': '_coordinate',
- 'type': 'raw',
- 'value': '(0, 0)',
- 'hide': 'all',
- })
- )
- self._params['_rotation'] = self.get_parent().get_parent().Param(
- self,
- odict({
- 'name': 'GUI Rotation',
- 'key': '_rotation',
- 'type': 'raw',
- 'value': '0',
- 'hide': 'all',
- })
- )
- Element.__init__(self)
-
- def get_coordinate(self):
- """
- Get the coordinate from the position param.
- @return the coordinate tuple (x, y) or (0, 0) if failure
- """
- try: #should evaluate to tuple
- coor = eval(self.get_param('_coordinate').get_value())
- x, y = map(int, coor)
- fgW,fgH = self.get_parent().get_size()
- if x <= 0:
- x = 0
- elif x >= fgW - BORDER_PROXIMITY_SENSITIVITY:
- x = fgW - BORDER_PROXIMITY_SENSITIVITY
- if y <= 0:
- y = 0
- elif y >= fgH - BORDER_PROXIMITY_SENSITIVITY:
- y = fgH - BORDER_PROXIMITY_SENSITIVITY
- return (x, y)
- except:
- self.set_coordinate((0, 0))
- return (0, 0)
-
- def set_coordinate(self, coor):
- """
- Set the coordinate into the position param.
- @param coor the coordinate tuple (x, y)
- """
- self.get_param('_coordinate').set_value(str(coor))
-
- def get_rotation(self):
- """
- Get the rotation from the position param.
- @return the rotation in degrees or 0 if failure
- """
- try: #should evaluate to dict
- rotation = eval(self.get_param('_rotation').get_value())
- return int(rotation)
- except:
- self.set_rotation(POSSIBLE_ROTATIONS[0])
- return POSSIBLE_ROTATIONS[0]
-
- def set_rotation(self, rot):
- """
- Set the rotation into the position param.
- @param rot the rotation in degrees
- """
- self.get_param('_rotation').set_value(str(rot))
-
- def update(self):
- """Update the block, parameters, and ports when a change occurs."""
- self._bg_color = self.get_enabled() and Colors.BLOCK_ENABLED_COLOR or Colors.BLOCK_DISABLED_COLOR
- self.clear()
- self._create_labels()
- self.W = self.label_width + 2*BLOCK_LABEL_PADDING
- self.H = max(*(
- [self.label_height+2*BLOCK_LABEL_PADDING] + [2*PORT_BORDER_SEPARATION + \
- sum([port.H + PORT_SEPARATION for port in ports]) - PORT_SEPARATION
- for ports in (self.get_sources(), self.get_sinks())]
- ))
- if self.is_horizontal(): self.add_area((0, 0), (self.W, self.H))
- elif self.is_vertical(): self.add_area((0, 0), (self.H, self.W))
- map(lambda p: p.update(), self.get_ports())
-
- def _create_labels(self):
- """Create the labels for the signal block."""
- layouts = list()
- #create the main layout
- layout = gtk.DrawingArea().create_pango_layout('')
- layouts.append(layout)
- layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self))
- self.label_width, self.label_height = layout.get_pixel_size()
- #display the params
- for param in filter(lambda p: p.get_hide() not in ('all', 'part'), self.get_params()):
- layout = param.get_layout()
- layouts.append(layout)
- w,h = layout.get_pixel_size()
- self.label_width = max(w, self.label_width)
- self.label_height = self.label_height + h + LABEL_SEPARATION
- width = self.label_width
- height = self.label_height
- #setup the pixmap
- pixmap = self.get_parent().new_pixmap(width, height)
- gc = pixmap.new_gc()
- gc.set_foreground(self._bg_color)
- pixmap.draw_rectangle(gc, True, 0, 0, width, height)
- #draw the layouts
- h_off = 0
- for i,layout in enumerate(layouts):
- w,h = layout.get_pixel_size()
- if i == 0: w_off = (width-w)/2
- else: w_off = 0
- pixmap.draw_layout(gc, w_off, h_off, layout)
- h_off = h + h_off + LABEL_SEPARATION
- #create vertical and horizontal images
- self.horizontal_label = image = pixmap.get_image(0, 0, width, height)
- if self.is_vertical():
- self.vertical_label = vimage = gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), height, width)
- for i in range(width):
- for j in range(height): vimage.put_pixel(j, width-i-1, image.get_pixel(i, j))
- map(lambda p: p._create_labels(), self.get_ports())
-
- def draw(self, gc, window):
- """
- Draw the signal block with label and inputs/outputs.
- @param gc the graphics context
- @param window the gtk window to draw on
- """
- x, y = self.get_coordinate()
- #draw main block
- Element.draw(
- self, gc, window, bg_color=self._bg_color,
- border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or Colors.BORDER_COLOR,
- )
- #draw label image
- if self.is_horizontal():
- window.draw_image(gc, self.horizontal_label, 0, 0, x+BLOCK_LABEL_PADDING, y+(self.H-self.label_height)/2, -1, -1)
- elif self.is_vertical():
- window.draw_image(gc, self.vertical_label, 0, 0, x+(self.H-self.label_height)/2, y+BLOCK_LABEL_PADDING, -1, -1)
- #draw ports
- for port in self.get_ports(): port.draw(gc, window)
-
- def what_is_selected(self, coor, coor_m=None):
- """
- Get the element that is selected.
- @param coor the (x,y) tuple
- @param coor_m the (x_m, y_m) tuple
- @return this block, a port, or None
- """
- for port in self.get_ports():
- port_selected = port.what_is_selected(coor, coor_m)
- if port_selected: return port_selected
- return Element.what_is_selected(self, coor, coor_m)
diff --git a/grc/src/platforms/gui/Colors.py b/grc/src/platforms/gui/Colors.py
deleted file mode 100644
index f0b989b37..000000000
--- a/grc/src/platforms/gui/Colors.py
+++ /dev/null
@@ -1,37 +0,0 @@
-"""
-Copyright 2008 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-"""
-
-import pygtk
-pygtk.require('2.0')
-import gtk
-
-_COLORMAP = gtk.gdk.colormap_get_system() #create all of the colors
-def get_color(color_code): return _COLORMAP.alloc_color(color_code, True, True)
-
-HIGHLIGHT_COLOR = get_color('#00FFFF')
-BORDER_COLOR = get_color('black')
-#flow graph color constants
-FLOWGRAPH_BACKGROUND_COLOR = get_color('#FFF9FF')
-#block color constants
-BLOCK_ENABLED_COLOR = get_color('#F1ECFF')
-BLOCK_DISABLED_COLOR = get_color('#CCCCCC')
-#connection color constants
-CONNECTION_ENABLED_COLOR = get_color('black')
-CONNECTION_DISABLED_COLOR = get_color('#999999')
-CONNECTION_ERROR_COLOR = get_color('red')
diff --git a/grc/src/platforms/gui/Connection.py b/grc/src/platforms/gui/Connection.py
deleted file mode 100644
index 013bcb00f..000000000
--- a/grc/src/platforms/gui/Connection.py
+++ /dev/null
@@ -1,140 +0,0 @@
-"""
-Copyright 2007, 2008 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-"""
-
-import Utils
-from Element import Element
-import Colors
-from Constants import CONNECTOR_ARROW_BASE, CONNECTOR_ARROW_HEIGHT
-
-class Connection(Element):
- """
- A graphical connection for ports.
- The connection has 2 parts, the arrow and the wire.
- The coloring of the arrow and wire exposes the status of 3 states:
- enabled/disabled, valid/invalid, highlighted/non-highlighted.
- The wire coloring exposes the enabled and highlighted states.
- The arrow coloring exposes the enabled and valid states.
- """
-
- def get_coordinate(self):
- """
- Get the 0,0 coordinate.
- Coordinates are irrelevant in connection.
- @return 0, 0
- """
- return (0, 0)
-
- def get_rotation(self):
- """
- Get the 0 degree rotation.
- Rotations are irrelevant in connection.
- @return 0
- """
- return 0
-
- def update(self):
- """Precalculate relative coordinates."""
- self._sink_rot = None
- self._source_rot = None
- self._sink_coor = None
- self._source_coor = None
- #get the source coordinate
- connector_length = self.get_source().get_connector_length()
- self.x1, self.y1 = Utils.get_rotated_coordinate((connector_length, 0), self.get_source().get_rotation())
- #get the sink coordinate
- connector_length = self.get_sink().get_connector_length() + CONNECTOR_ARROW_HEIGHT
- self.x2, self.y2 = Utils.get_rotated_coordinate((-connector_length, 0), self.get_sink().get_rotation())
- #build the arrow
- self.arrow = [(0, 0),
- Utils.get_rotated_coordinate((-CONNECTOR_ARROW_HEIGHT, -CONNECTOR_ARROW_BASE/2), self.get_sink().get_rotation()),
- Utils.get_rotated_coordinate((-CONNECTOR_ARROW_HEIGHT, CONNECTOR_ARROW_BASE/2), self.get_sink().get_rotation()),
- ]
- self._update_after_move()
- if not self.get_enabled(): self._arrow_color = Colors.CONNECTION_DISABLED_COLOR
- elif not self.is_valid(): self._arrow_color = Colors.CONNECTION_ERROR_COLOR
- else: self._arrow_color = Colors.CONNECTION_ENABLED_COLOR
-
- def _update_after_move(self):
- """Calculate coordinates."""
- self.clear()
- #source connector
- source = self.get_source()
- X, Y = source.get_connector_coordinate()
- x1, y1 = self.x1 + X, self.y1 + Y
- self.add_line((x1, y1), (X, Y))
- #sink connector
- sink = self.get_sink()
- X, Y = sink.get_connector_coordinate()
- x2, y2 = self.x2 + X, self.y2 + Y
- self.add_line((x2, y2), (X, Y))
- #adjust arrow
- self._arrow = [(x+X, y+Y) for x,y in self.arrow]
- #add the horizontal and vertical lines in this connection
- if abs(source.get_connector_direction() - sink.get_connector_direction()) == 180:
- #2 possible point sets to create a 3-line connector
- mid_x, mid_y = (x1 + x2)/2.0, (y1 + y2)/2.0
- points = [((mid_x, y1), (mid_x, y2)), ((x1, mid_y), (x2, mid_y))]
- #source connector -> points[0][0] should be in the direction of source (if possible)
- if Utils.get_angle_from_coordinates((x1, y1), points[0][0]) != source.get_connector_direction(): points.reverse()
- #points[0][0] -> sink connector should not be in the direction of sink
- if Utils.get_angle_from_coordinates(points[0][0], (x2, y2)) == sink.get_connector_direction(): points.reverse()
- #points[0][0] -> source connector should not be in the direction of source
- if Utils.get_angle_from_coordinates(points[0][0], (x1, y1)) == source.get_connector_direction(): points.reverse()
- #create 3-line connector
- p1, p2 = map(int, points[0][0]), map(int, points[0][1])
- self.add_line((x1, y1), p1)
- self.add_line(p1, p2)
- self.add_line((x2, y2), p2)
- else:
- #2 possible points to create a right-angled connector
- points = [(x1, y2), (x2, y1)]
- #source connector -> points[0] should be in the direction of source (if possible)
- if Utils.get_angle_from_coordinates((x1, y1), points[0]) != source.get_connector_direction(): points.reverse()
- #points[0] -> sink connector should not be in the direction of sink
- if Utils.get_angle_from_coordinates(points[0], (x2, y2)) == sink.get_connector_direction(): points.reverse()
- #points[0] -> source connector should not be in the direction of source
- if Utils.get_angle_from_coordinates(points[0], (x1, y1)) == source.get_connector_direction(): points.reverse()
- #create right-angled connector
- self.add_line((x1, y1), points[0])
- self.add_line((x2, y2), points[0])
-
- def draw(self, gc, window):
- """
- Draw the connection.
- @param gc the graphics context
- @param window the gtk window to draw on
- """
- sink = self.get_sink()
- source = self.get_source()
- #check for changes
- if self._sink_rot != sink.get_rotation() or self._source_rot != source.get_rotation(): self.update()
- elif self._sink_coor != sink.get_coordinate() or self._source_coor != source.get_coordinate(): self._update_after_move()
- #cache values
- self._sink_rot = sink.get_rotation()
- self._source_rot = source.get_rotation()
- self._sink_coor = sink.get_coordinate()
- self._source_coor = source.get_coordinate()
- #draw
- if self.is_highlighted(): border_color = Colors.HIGHLIGHT_COLOR
- elif self.get_enabled(): border_color = Colors.CONNECTION_ENABLED_COLOR
- else: border_color = Colors.CONNECTION_DISABLED_COLOR
- Element.draw(self, gc, window, bg_color=None, border_color=border_color)
- #draw arrow on sink port
- gc.set_foreground(self._arrow_color)
- window.draw_polygon(gc, True, self._arrow)
diff --git a/grc/src/platforms/gui/Constants.py b/grc/src/platforms/gui/Constants.py
deleted file mode 100644
index 90c8c1c38..000000000
--- a/grc/src/platforms/gui/Constants.py
+++ /dev/null
@@ -1,44 +0,0 @@
-"""
-Copyright 2008, 2009 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-"""
-
-#label constraint dimensions
-LABEL_SEPARATION = 3
-BLOCK_LABEL_PADDING = 7
-PORT_LABEL_PADDING = 2
-#port constraint dimensions
-PORT_SEPARATION = 17
-PORT_BORDER_SEPARATION = 9
-PORT_MIN_WIDTH = 20
-#minimal length of connector
-CONNECTOR_EXTENSION_MINIMAL = 11
-#increment length for connector
-CONNECTOR_EXTENSION_INCREMENT = 11
-#connection arrow dimensions
-CONNECTOR_ARROW_BASE = 13
-CONNECTOR_ARROW_HEIGHT = 17
-#possible rotations in degrees
-POSSIBLE_ROTATIONS = (0, 90, 180, 270)
-#How close can the mouse get to the window border before mouse events are ignored.
-BORDER_PROXIMITY_SENSITIVITY = 50
-#How close the mouse can get to the edge of the visible window before scrolling is invoked.
-SCROLL_PROXIMITY_SENSITIVITY = 30
-#When the window has to be scrolled, move it this distance in the required direction.
-SCROLL_DISTANCE = 15
-#How close the mouse click can be to a line and register a connection select.
-LINE_SELECT_SENSITIVITY = 5
diff --git a/grc/src/platforms/gui/Element.py b/grc/src/platforms/gui/Element.py
deleted file mode 100644
index 315191723..000000000
--- a/grc/src/platforms/gui/Element.py
+++ /dev/null
@@ -1,226 +0,0 @@
-"""
-Copyright 2007 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-"""
-
-import Colors
-import pygtk
-pygtk.require('2.0')
-import gtk
-import pango
-from Constants import LINE_SELECT_SENSITIVITY
-from Constants import POSSIBLE_ROTATIONS
-
-class Element(object):
- """
- GraphicalElement is the base class for all graphical elements.
- It contains an X,Y coordinate, a list of rectangular areas that the element occupies,
- and methods to detect selection of those areas.
- """
-
- def __init__(self, *args, **kwargs):
- """
- Make a new list of rectangular areas and lines, and set the coordinate and the rotation.
- """
- self.set_rotation(POSSIBLE_ROTATIONS[0])
- self.set_coordinate((0, 0))
- self.clear()
- self.set_highlighted(False)
-
- def is_horizontal(self, rotation=None):
- """
- Is this element horizontal?
- If rotation is None, use this element's rotation.
- @param rotation the optional rotation
- @return true if rotation is horizontal
- """
- rotation = rotation or self.get_rotation()
- return rotation in (0, 180)
-
- def is_vertical(self, rotation=None):
- """
- Is this element vertical?
- If rotation is None, use this element's rotation.
- @param rotation the optional rotation
- @return true if rotation is vertical
- """
- rotation = rotation or self.get_rotation()
- return rotation in (90, 270)
-
- def draw(self, gc, window, border_color, bg_color):
- """
- Draw in the given window.
- @param gc the graphics context
- @param window the gtk window to draw on
- @param border_color the color for lines and rectangle borders
- @param bg_color the color for the inside of the rectangle
- """
- X,Y = self.get_coordinate()
- for (rX,rY),(W,H) in self.areas_dict[self.get_rotation()]:
- aX = X + rX
- aY = Y + rY
- gc.set_foreground(bg_color)
- window.draw_rectangle(gc, True, aX, aY, W, H)
- gc.set_foreground(border_color)
- window.draw_rectangle(gc, False, aX, aY, W, H)
- for (x1, y1),(x2, y2) in self.lines_dict[self.get_rotation()]:
- gc.set_foreground(border_color)
- window.draw_line(gc, X+x1, Y+y1, X+x2, Y+y2)
-
- def rotate(self, rotation):
- """
- Rotate all of the areas by 90 degrees.
- @param rotation multiple of 90 degrees
- """
- self.set_rotation((self.get_rotation() + rotation)%360)
-
- def clear(self):
- """Empty the lines and areas."""
- self.areas_dict = dict((rotation, list()) for rotation in POSSIBLE_ROTATIONS)
- self.lines_dict = dict((rotation, list()) for rotation in POSSIBLE_ROTATIONS)
-
- def set_coordinate(self, coor):
- """
- Set the reference coordinate.
- @param coor the coordinate tuple (x,y)
- """
- self.coor = coor
-
- def get_parent(self):
- """
- Get the parent of this element.
- @return the parent
- """
- return self.parent
-
- def set_highlighted(self, highlighted):
- """
- Set the highlight status.
- @param highlighted true to enable highlighting
- """
- self.highlighted = highlighted
-
- def is_highlighted(self):
- """
- Get the highlight status.
- @return true if highlighted
- """
- return self.highlighted
-
- def get_coordinate(self):
- """Get the coordinate.
- @return the coordinate tuple (x,y)
- """
- return self.coor
-
- def move(self, delta_coor):
- """
- Move the element by adding the delta_coor to the current coordinate.
- @param delta_coor (delta_x,delta_y) tuple
- """
- deltaX, deltaY = delta_coor
- X, Y = self.get_coordinate()
- self.set_coordinate((X+deltaX, Y+deltaY))
-
- def add_area(self, rel_coor, area, rotation=None):
- """
- Add an area to the area list.
- An area is actually a coordinate relative to the main coordinate
- with a width/height pair relative to the area coordinate.
- A positive width is to the right of the coordinate.
- A positive height is above the coordinate.
- The area is associated with a rotation.
- If rotation is not specified, the element's current rotation is used.
- @param rel_coor (x,y) offset from this element's coordinate
- @param area (width,height) tuple
- @param rotation rotation in degrees
- """
- self.areas_dict[rotation or self.get_rotation()].append((rel_coor, area))
-
- def add_line(self, rel_coor1, rel_coor2, rotation=None):
- """
- Add a line to the line list.
- A line is defined by 2 relative coordinates.
- Lines must be horizontal or vertical.
- The line is associated with a rotation.
- If rotation is not specified, the element's current rotation is used.
- @param rel_coor1 relative (x1,y1) tuple
- @param rel_coor2 relative (x2,y2) tuple
- @param rotation rotation in degrees
- """
- self.lines_dict[rotation or self.get_rotation()].append((rel_coor1, rel_coor2))
-
- def what_is_selected(self, coor, coor_m=None):
- """
- One coordinate specified:
- Is this element selected at given coordinate?
- ie: is the coordinate encompassed by one of the areas or lines?
- Both coordinates specified:
- Is this element within the rectangular region defined by both coordinates?
- ie: do any area corners or line endpoints fall within the region?
- @param coor the selection coordinate, tuple x, y
- @param coor_m an additional selection coordinate.
- @return self if one of the areas/lines encompasses coor, else None.
- """
- #function to test if p is between a and b (inclusive)
- in_between = lambda p, a, b: p >= min(a, b) and p <= max(a, b)
- #relative coordinate
- x, y = [a-b for a,b in zip(coor, self.get_coordinate())]
- if coor_m:
- x_m, y_m = [a-b for a,b in zip(coor_m, self.get_coordinate())]
- #handle rectangular areas
- for (x1,y1), (w,h) in self.areas_dict[self.get_rotation()]:
- if in_between(x1, x, x_m) and in_between(y1, y, y_m) or \
- in_between(x1+w, x, x_m) and in_between(y1, y, y_m) or \
- in_between(x1, x, x_m) and in_between(y1+h, y, y_m) or \
- in_between(x1+w, x, x_m) and in_between(y1+h, y, y_m):
- return self
- #handle horizontal or vertical lines
- for (x1, y1), (x2, y2) in self.lines_dict[self.get_rotation()]:
- if in_between(x1, x, x_m) and in_between(y1, y, y_m) or \
- in_between(x2, x, x_m) and in_between(y2, y, y_m):
- return self
- return None
- else:
- #handle rectangular areas
- for (x1,y1), (w,h) in self.areas_dict[self.get_rotation()]:
- if in_between(x, x1, x1+w) and in_between(y, y1, y1+h): return self
- #handle horizontal or vertical lines
- for (x1, y1), (x2, y2) in self.lines_dict[self.get_rotation()]:
- if x1 == x2: x1, x2 = x1-LINE_SELECT_SENSITIVITY, x2+LINE_SELECT_SENSITIVITY
- if y1 == y2: y1, y2 = y1-LINE_SELECT_SENSITIVITY, y2+LINE_SELECT_SENSITIVITY
- if in_between(x, x1, x2) and in_between(y, y1, y2): return self
- return None
-
- def get_rotation(self):
- """
- Get the rotation in degrees.
- @return the rotation
- """
- return self.rotation
-
- def set_rotation(self, rotation):
- """
- Set the rotation in degrees.
- @param rotation the rotation"""
- if rotation not in POSSIBLE_ROTATIONS:
- raise Exception('"%s" is not one of the possible rotations: (%s)'%(rotation, POSSIBLE_ROTATIONS))
- self.rotation = rotation
-
- def update(self):
- """Do nothing for the update. Dummy method."""
- pass
diff --git a/grc/src/platforms/gui/FlowGraph.py b/grc/src/platforms/gui/FlowGraph.py
deleted file mode 100644
index 40f391811..000000000
--- a/grc/src/platforms/gui/FlowGraph.py
+++ /dev/null
@@ -1,488 +0,0 @@
-"""
-Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-"""
-
-from Constants import SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE
-from ... gui.Actions import \
- ELEMENT_CREATE, ELEMENT_SELECT, \
- BLOCK_PARAM_MODIFY, BLOCK_MOVE, \
- ELEMENT_DELETE
-import Colors
-import Utils
-from Element import Element
-from .. base import FlowGraph as _FlowGraph
-import pygtk
-pygtk.require('2.0')
-import gtk
-import random
-from ... gui import Messages
-
-class FlowGraph(Element):
- """
- FlowGraph is the data structure to store graphical signal blocks,
- graphical inputs and outputs,
- and the connections between inputs and outputs.
- """
-
- def __init__(self, *args, **kwargs):
- """
- FlowGraph contructor.
- Create a list for signal blocks and connections. Connect mouse handlers.
- """
- Element.__init__(self)
- #when is the flow graph selected? (used by keyboard event handler)
- self.is_selected = lambda: bool(self.get_selected_elements())
- #important vars dealing with mouse event tracking
- self.element_moved = False
- self.mouse_pressed = False
- self.unselect()
- self.press_coor = (0, 0)
- #selected ports
- self._old_selected_port = None
- self._new_selected_port = None
-
- ###########################################################################
- # Access Drawing Area
- ###########################################################################
- def get_drawing_area(self): return self.drawing_area
- def queue_draw(self): self.get_drawing_area().queue_draw()
- def get_size(self): return self.get_drawing_area().get_size_request()
- def set_size(self, *args): self.get_drawing_area().set_size_request(*args)
- def get_scroll_pane(self): return self.drawing_area.get_parent()
- def get_ctrl_mask(self): return self.drawing_area.ctrl_mask
- def new_pixmap(self, *args): return self.get_drawing_area().new_pixmap(*args)
-
- def add_new_block(self, key, coor=None):
- """
- Add a block of the given key to this flow graph.
- @param key the block key
- @param coor an optional coordinate or None for random
- """
- id = self._get_unique_id(key)
- #calculate the position coordinate
- h_adj = self.get_scroll_pane().get_hadjustment()
- v_adj = self.get_scroll_pane().get_vadjustment()
- if coor is None: coor = (
- int(random.uniform(.25, .75)*h_adj.page_size + h_adj.get_value()),
- int(random.uniform(.25, .75)*v_adj.page_size + v_adj.get_value()),
- )
- #get the new block
- block = self.get_new_block(key)
- block.set_coordinate(coor)
- block.set_rotation(0)
- block.get_param('id').set_value(id)
- self.handle_states(ELEMENT_CREATE)
-
- ###########################################################################
- # Copy Paste
- ###########################################################################
- def copy_to_clipboard(self):
- """
- Copy the selected blocks and connections into the clipboard.
- @return the clipboard
- """
- #get selected blocks
- blocks = self.get_selected_blocks()
- if not blocks: return None
- #calc x and y min
- x_min, y_min = blocks[0].get_coordinate()
- for block in blocks:
- x, y = block.get_coordinate()
- x_min = min(x, x_min)
- y_min = min(y, y_min)
- #get connections between selected blocks
- connections = filter(
- lambda c: c.get_source().get_parent() in blocks and c.get_sink().get_parent() in blocks,
- self.get_connections(),
- )
- clipboard = (
- (x_min, y_min),
- [block.export_data() for block in blocks],
- [connection.export_data() for connection in connections],
- )
- return clipboard
-
- def paste_from_clipboard(self, clipboard):
- """
- Paste the blocks and connections from the clipboard.
- @param clipboard the nested data of blocks, connections
- """
- selected = set()
- (x_min, y_min), blocks_n, connections_n = clipboard
- old_id2block = dict()
- #recalc the position
- h_adj = self.get_scroll_pane().get_hadjustment()
- v_adj = self.get_scroll_pane().get_vadjustment()
- x_off = h_adj.get_value() - x_min + h_adj.page_size/4
- y_off = v_adj.get_value() - y_min + v_adj.page_size/4
- #create blocks
- for block_n in blocks_n:
- block_key = block_n.find('key')
- if block_key == 'options': continue
- block = self.get_new_block(block_key)
- selected.add(block)
- #set params
- params_n = block_n.findall('param')
- for param_n in params_n:
- param_key = param_n.find('key')
- param_value = param_n.find('value')
- #setup id parameter
- if param_key == 'id':
- old_id2block[param_value] = block
- #if the block id is not unique, get a new block id
- if param_value in [block.get_id() for block in self.get_blocks()]:
- param_value = self._get_unique_id(param_value)
- #set value to key
- block.get_param(param_key).set_value(param_value)
- #move block to offset coordinate
- block.move((x_off, y_off))
- #update before creating connections
- self.update()
- #create connections
- for connection_n in connections_n:
- source = old_id2block[connection_n.find('source_block_id')].get_source(connection_n.find('source_key'))
- sink = old_id2block[connection_n.find('sink_block_id')].get_sink(connection_n.find('sink_key'))
- self.connect(source, sink)
- #set all pasted elements selected
- for block in selected: selected = selected.union(set(block.get_connections()))
- self._selected_elements = list(selected)
-
- ###########################################################################
- # Modify Selected
- ###########################################################################
- def type_controller_modify_selected(self, direction):
- """
- Change the registered type controller for the selected signal blocks.
- @param direction +1 or -1
- @return true for change
- """
- return any([sb.type_controller_modify(direction) for sb in self.get_selected_blocks()])
-
- def port_controller_modify_selected(self, direction):
- """
- Change port controller for the selected signal blocks.
- @param direction +1 or -1
- @return true for changed
- """
- return any([sb.port_controller_modify(direction) for sb in self.get_selected_blocks()])
-
- def enable_selected(self, enable):
- """
- Enable/disable the selected blocks.
- @param enable true to enable
- @return true if changed
- """
- changed = False
- for selected_block in self.get_selected_blocks():
- if selected_block.get_enabled() != enable:
- selected_block.set_enabled(enable)
- changed = True
- return changed
-
- def move_selected(self, delta_coordinate):
- """
- Move the element and by the change in coordinates.
- @param delta_coordinate the change in coordinates
- """
- for selected_block in self.get_selected_blocks():
- selected_block.move(delta_coordinate)
- self.element_moved = True
-
- def rotate_selected(self, rotation):
- """
- Rotate the selected blocks by multiples of 90 degrees.
- @param rotation the rotation in degrees
- @return true if changed, otherwise false.
- """
- if not self.get_selected_blocks(): return False
- #initialize min and max coordinates
- min_x, min_y = self.get_selected_block().get_coordinate()
- max_x, max_y = self.get_selected_block().get_coordinate()
- #rotate each selected block, and find min/max coordinate
- for selected_block in self.get_selected_blocks():
- selected_block.rotate(rotation)
- #update the min/max coordinate
- x, y = selected_block.get_coordinate()
- min_x, min_y = min(min_x, x), min(min_y, y)
- max_x, max_y = max(max_x, x), max(max_y, y)
- #calculate center point of slected blocks
- ctr_x, ctr_y = (max_x + min_x)/2, (max_y + min_y)/2
- #rotate the blocks around the center point
- for selected_block in self.get_selected_blocks():
- x, y = selected_block.get_coordinate()
- x, y = Utils.get_rotated_coordinate((x - ctr_x, y - ctr_y), rotation)
- selected_block.set_coordinate((x + ctr_x, y + ctr_y))
- return True
-
- def remove_selected(self):
- """
- Remove selected elements
- @return true if changed.
- """
- changed = False
- for selected_element in self.get_selected_elements():
- self.remove_element(selected_element)
- changed = True
- return changed
-
- def draw(self, gc, window):
- """
- Draw the background and grid if enabled.
- Draw all of the elements in this flow graph onto the pixmap.
- Draw the pixmap to the drawable window of this flow graph.
- """
- W,H = self.get_size()
- #draw the background
- gc.set_foreground(Colors.FLOWGRAPH_BACKGROUND_COLOR)
- window.draw_rectangle(gc, True, 0, 0, W, H)
- #draw multi select rectangle
- if self.mouse_pressed and (not self.get_selected_elements() or self.get_ctrl_mask()):
- #coordinates
- x1, y1 = self.press_coor
- x2, y2 = self.get_coordinate()
- #calculate top-left coordinate and width/height
- x, y = int(min(x1, x2)), int(min(y1, y2))
- w, h = int(abs(x1 - x2)), int(abs(y1 - y2))
- #draw
- gc.set_foreground(Colors.HIGHLIGHT_COLOR)
- window.draw_rectangle(gc, True, x, y, w, h)
- gc.set_foreground(Colors.BORDER_COLOR)
- window.draw_rectangle(gc, False, x, y, w, h)
- #draw blocks on top of connections
- for element in self.get_connections() + self.get_blocks():
- element.draw(gc, window)
- #draw selected blocks on top of selected connections
- for selected_element in self.get_selected_connections() + self.get_selected_blocks():
- selected_element.draw(gc, window)
-
- def update_selected(self):
- """
- Remove deleted elements from the selected elements list.
- Update highlighting so only the selected are highlighted.
- """
- selected_elements = self.get_selected_elements()
- elements = self.get_elements()
- #remove deleted elements
- for selected in selected_elements:
- if selected in elements: continue
- selected_elements.remove(selected)
- #update highlighting
- for element in elements:
- element.set_highlighted(element in selected_elements)
-
- def update(self):
- """
- Call update on all elements.
- """
- for element in self.get_elements(): element.update()
-
- ##########################################################################
- ## Get Selected
- ##########################################################################
- def unselect(self):
- """
- Set selected elements to an empty set.
- """
- self._selected_elements = []
-
- def what_is_selected(self, coor, coor_m=None):
- """
- What is selected?
- At the given coordinate, return the elements found to be selected.
- If coor_m is unspecified, return a list of only the first element found to be selected:
- Iterate though the elements backwards since top elements are at the end of the list.
- If an element is selected, place it at the end of the list so that is is drawn last,
- and hence on top. Update the selected port information.
- @param coor the coordinate of the mouse click
- @param coor_m the coordinate for multi select
- @return the selected blocks and connections or an empty list
- """
- selected_port = None
- selected = set()
- #check the elements
- for element in reversed(self.get_elements()):
- selected_element = element.what_is_selected(coor, coor_m)
- if not selected_element: continue
- #update the selected port information
- if selected_element.is_port():
- if not coor_m: selected_port = selected_element
- selected_element = selected_element.get_parent()
- selected.add(selected_element)
- #place at the end of the list
- self.get_elements().remove(element)
- self.get_elements().append(element)
- #single select mode, break
- if not coor_m: break
- #update selected ports
- self._old_selected_port = self._new_selected_port
- self._new_selected_port = selected_port
- return list(selected)
-
- def get_selected_connections(self):
- """
- Get a group of selected connections.
- @return sub set of connections in this flow graph
- """
- selected = set()
- for selected_element in self.get_selected_elements():
- if selected_element.is_connection(): selected.add(selected_element)
- return list(selected)
-
- def get_selected_blocks(self):
- """
- Get a group of selected blocks.
- @return sub set of blocks in this flow graph
- """
- selected = set()
- for selected_element in self.get_selected_elements():
- if selected_element.is_block(): selected.add(selected_element)
- return list(selected)
-
- def get_selected_block(self):
- """
- Get the selected block when a block or port is selected.
- @return a block or None
- """
- return self.get_selected_blocks() and self.get_selected_blocks()[0] or None
-
- def get_selected_elements(self):
- """
- Get the group of selected elements.
- @return sub set of elements in this flow graph
- """
- return self._selected_elements
-
- def get_selected_element(self):
- """
- Get the selected element.
- @return a block, port, or connection or None
- """
- return self.get_selected_elements() and self.get_selected_elements()[0] or None
-
- def update_selected_elements(self):
- """
- Update the selected elements.
- The update behavior depends on the state of the mouse button.
- When the mouse button pressed the selection will change when
- the control mask is set or the new selection is not in the current group.
- When the mouse button is released the selection will change when
- the mouse has moved and the control mask is set or the current group is empty.
- Attempt to make a new connection if the old and ports are filled.
- If the control mask is set, merge with the current elements.
- """
- selected_elements = None
- if self.mouse_pressed:
- new_selections = self.what_is_selected(self.get_coordinate())
- #update the selections if the new selection is not in the current selections
- #allows us to move entire selected groups of elements
- if self.get_ctrl_mask() or not (
- new_selections and new_selections[0] in self.get_selected_elements()
- ): selected_elements = new_selections
- else: #called from a mouse release
- if not self.element_moved and (not self.get_selected_elements() or self.get_ctrl_mask()):
- selected_elements = self.what_is_selected(self.get_coordinate(), self.press_coor)
- #this selection and the last were ports, try to connect them
- if self._old_selected_port and self._new_selected_port and \
- self._old_selected_port is not self._new_selected_port:
- try:
- self.connect(self._old_selected_port, self._new_selected_port)
- self.handle_states(ELEMENT_CREATE)
- except: Messages.send_fail_connection()
- self._old_selected_port = None
- self._new_selected_port = None
- return
- #update selected elements
- if selected_elements is None: return
- old_elements = set(self.get_selected_elements())
- self._selected_elements = list(set(selected_elements))
- new_elements = set(self.get_selected_elements())
- #if ctrl, set the selected elements to the union - intersection of old and new
- if self.get_ctrl_mask():
- self._selected_elements = list(
- set.union(old_elements, new_elements) - set.intersection(old_elements, new_elements)
- )
- self.handle_states(ELEMENT_SELECT)
-
- ##########################################################################
- ## Event Handlers
- ##########################################################################
- def handle_mouse_button_press(self, left_click, double_click, coordinate):
- """
- A mouse button is pressed, only respond to left clicks.
- Find the selected element. Attempt a new connection if possible.
- Open the block params window on a double click.
- Update the selection state of the flow graph.
- """
- if not left_click: return
- self.press_coor = coordinate
- self.set_coordinate(coordinate)
- self.time = 0
- self.mouse_pressed = True
- if double_click: self.unselect()
- self.update_selected_elements()
- #double click detected, bring up params dialog if possible
- if double_click and self.get_selected_block():
- self.mouse_pressed = False
- self.handle_states(BLOCK_PARAM_MODIFY)
-
- def handle_mouse_button_release(self, left_click, coordinate):
- """
- A mouse button is released, record the state.
- """
- if not left_click: return
- self.set_coordinate(coordinate)
- self.time = 0
- self.mouse_pressed = False
- if self.element_moved:
- self.handle_states(BLOCK_MOVE)
- self.element_moved = False
- self.update_selected_elements()
-
- def handle_mouse_motion(self, coordinate):
- """
- The mouse has moved, respond to mouse dragging.
- Move a selected element to the new coordinate.
- Auto-scroll the scroll bars at the boundaries.
- """
- #to perform a movement, the mouse must be pressed, no pending events
- if gtk.events_pending() or not self.mouse_pressed: return
- #perform autoscrolling
- width, height = self.get_size()
- x, y = coordinate
- h_adj = self.get_scroll_pane().get_hadjustment()
- v_adj = self.get_scroll_pane().get_vadjustment()
- for pos, length, adj, adj_val, adj_len in (
- (x, width, h_adj, h_adj.get_value(), h_adj.page_size),
- (y, height, v_adj, v_adj.get_value(), v_adj.page_size),
- ):
- #scroll if we moved near the border
- if pos-adj_val > adj_len-SCROLL_PROXIMITY_SENSITIVITY and adj_val+SCROLL_DISTANCE < length-adj_len:
- adj.set_value(adj_val+SCROLL_DISTANCE)
- adj.emit('changed')
- elif pos-adj_val < SCROLL_PROXIMITY_SENSITIVITY:
- adj.set_value(adj_val-SCROLL_DISTANCE)
- adj.emit('changed')
- #remove the connection if selected in drag event
- if len(self.get_selected_elements()) == 1 and self.get_selected_element().is_connection():
- self.handle_states(ELEMENT_DELETE)
- #move the selected elements and record the new coordinate
- X, Y = self.get_coordinate()
- if not self.get_ctrl_mask(): self.move_selected((int(x - X), int(y - Y)))
- self.set_coordinate((x, y))
- #queue draw for animation
- self.queue_draw()
diff --git a/grc/src/platforms/gui/Makefile.am b/grc/src/platforms/gui/Makefile.am
deleted file mode 100644
index 2e3972ef3..000000000
--- a/grc/src/platforms/gui/Makefile.am
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright 2008 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GNU Radio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Radio; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-#
-
-include $(top_srcdir)/grc/Makefile.inc
-
-ourpythondir = $(grc_src_prefix)/platforms/gui
-
-ourpython_PYTHON = \
- Block.py \
- Colors.py \
- Constants.py \
- Connection.py \
- Element.py \
- FlowGraph.py \
- Param.py \
- Platform.py \
- Port.py \
- Utils.py \
- __init__.py
diff --git a/grc/src/platforms/gui/Param.py b/grc/src/platforms/gui/Param.py
deleted file mode 100644
index 33a9b1f52..000000000
--- a/grc/src/platforms/gui/Param.py
+++ /dev/null
@@ -1,103 +0,0 @@
-"""
-Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-"""
-
-import Utils
-from Element import Element
-import pygtk
-pygtk.require('2.0')
-import gtk
-
-PARAM_MARKUP_TMPL="""\
-#set $foreground = $param.is_valid() and 'black' or 'red'
-#set $value = not $param.is_valid() and 'error' or repr($param)
-<span foreground="$foreground" font_desc="Sans 7.5"><b>$encode($param.get_name()): </b>$encode($value)</span>"""
-
-PARAM_LABEL_MARKUP_TMPL="""\
-#set $foreground = $param.is_valid() and 'black' or 'red'
-#set $underline = $has_cb and 'low' or 'none'
-<span underline="$underline" foreground="$foreground" font_desc="Sans 9">$encode($param.get_name())</span>"""
-
-TIP_MARKUP_TMPL="""\
-Key: $param.get_key()
-Type: $param.get_type()
-#if $param.is_valid()
-Value: $param.evaluate()
-#elif len($param.get_error_messages()) == 1
-Error: $(param.get_error_messages()[0])
-#else
-Error:
- #for $error_msg in $param.get_error_messages()
- * $error_msg
- #end for
-#end if"""
-
-class Param(Element):
- """The graphical parameter."""
-
- def update(self):
- """
- Called when an external change occurs.
- Update the graphical input by calling the change handler.
- """
- if hasattr(self, '_input'): self._handle_changed()
-
- def get_input_object(self, callback=None):
- """
- Get the graphical gtk object to represent this parameter.
- Create the input object with this data type and the handle changed method.
- @param callback a function of one argument(this param) to be called from the change handler
- @return gtk input object
- """
- self._callback = callback
- self._input = self.get_input_class()(self, self._handle_changed)
- if not self._callback: self.update()
- return self._input
-
- def _handle_changed(self, widget=None):
- """
- When the input changes, write the inputs to the data type.
- Finish by calling the exteral callback.
- """
- self.set_value(self._input.get_text())
- #is param is involved in a callback? #FIXME: messy
- has_cb = \
- hasattr(self.get_parent(), 'get_callbacks') and \
- filter(lambda c: self.get_key() in c, self.get_parent()._callbacks)
- self._input.set_markup(Utils.parse_template(PARAM_LABEL_MARKUP_TMPL, param=self, has_cb=has_cb))
- #hide/show
- if self.get_hide() == 'all': self._input.hide_all()
- else: self._input.show_all()
- #set the color
- self._input.set_color(self.get_color())
- #set the tooltip
- if self._input.tp: self._input.tp.set_tip(
- self._input.entry,
- Utils.parse_template(TIP_MARKUP_TMPL, param=self).strip(),
- )
- #execute the external callback
- if self._callback: self._callback(self)
-
- def get_layout(self):
- """
- Create a layout based on the current markup.
- @return the pango layout
- """
- layout = gtk.DrawingArea().create_pango_layout('')
- layout.set_markup(Utils.parse_template(PARAM_MARKUP_TMPL, param=self))
- return layout
diff --git a/grc/src/platforms/gui/Platform.py b/grc/src/platforms/gui/Platform.py
deleted file mode 100644
index a32b0209f..000000000
--- a/grc/src/platforms/gui/Platform.py
+++ /dev/null
@@ -1,48 +0,0 @@
-"""
-Copyright 2008 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-"""
-
-from FlowGraph import FlowGraph
-from Connection import Connection
-from Block import Block
-from Port import Port
-from Param import Param
-
-def conjoin_classes(name, c1, c2):
- exec("""
-class %s(c1, c2):
- def __init__(self, *args, **kwargs):
- c1.__init__(self, *args, **kwargs)
- c2.__init__(self, *args, **kwargs)
-"""%name, locals())
- return locals()[name]
-
-def Platform(platform):
- #combine with gui class
- for attr, value in (
- ('FlowGraph', FlowGraph),
- ('Connection', Connection),
- ('Block', Block),
- ('Source', Port),
- ('Sink', Port),
- ('Param', Param),
- ):
- old_value = getattr(platform, attr)
- c = conjoin_classes(attr, old_value, value)
- setattr(platform, attr, c)
- return platform
diff --git a/grc/src/platforms/gui/Port.py b/grc/src/platforms/gui/Port.py
deleted file mode 100644
index d1f36f8b9..000000000
--- a/grc/src/platforms/gui/Port.py
+++ /dev/null
@@ -1,190 +0,0 @@
-"""
-Copyright 2007 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-"""
-
-from Element import Element
-from Constants import \
- PORT_SEPARATION, CONNECTOR_EXTENSION_MINIMAL, \
- CONNECTOR_EXTENSION_INCREMENT, \
- PORT_LABEL_PADDING, PORT_MIN_WIDTH
-import Utils
-import Colors
-import pygtk
-pygtk.require('2.0')
-import gtk
-
-PORT_MARKUP_TMPL="""\
-<span foreground="black" font_desc="Sans 7.5">$encode($port.get_name())</span>"""
-
-class Port(Element):
- """The graphical port."""
-
- def __init__(self, *args, **kwargs):
- """
- Port contructor.
- Create list of connector coordinates.
- """
- Element.__init__(self)
- self.connector_coordinates = dict()
-
- def update(self):
- """Create new areas and labels for the port."""
- self.clear()
- #get current rotation
- rotation = self.get_rotation()
- #get all sibling ports
- if self.is_source(): ports = self.get_parent().get_sources()
- elif self.is_sink(): ports = self.get_parent().get_sinks()
- #get the max width
- self.W = max([port.W for port in ports] + [PORT_MIN_WIDTH])
- #get a numeric index for this port relative to its sibling ports
- index = ports.index(self)
- length = len(ports)
- #reverse the order of ports for these rotations
- if rotation in (180, 270): index = length-index-1
- offset = (self.get_parent().H - length*self.H - (length-1)*PORT_SEPARATION)/2
- #create areas and connector coordinates
- if (self.is_sink() and rotation == 0) or (self.is_source() and rotation == 180):
- x = -1*self.W
- y = (PORT_SEPARATION+self.H)*index+offset
- self.add_area((x, y), (self.W, self.H))
- self._connector_coordinate = (x-1, y+self.H/2)
- elif (self.is_source() and rotation == 0) or (self.is_sink() and rotation == 180):
- x = self.get_parent().W
- y = (PORT_SEPARATION+self.H)*index+offset
- self.add_area((x, y), (self.W, self.H))
- self._connector_coordinate = (x+1+self.W, y+self.H/2)
- elif (self.is_source() and rotation == 90) or (self.is_sink() and rotation == 270):
- y = -1*self.W
- x = (PORT_SEPARATION+self.H)*index+offset
- self.add_area((x, y), (self.H, self.W))
- self._connector_coordinate = (x+self.H/2, y-1)
- elif (self.is_sink() and rotation == 90) or (self.is_source() and rotation == 270):
- y = self.get_parent().W
- x = (PORT_SEPARATION+self.H)*index+offset
- self.add_area((x, y), (self.H, self.W))
- self._connector_coordinate = (x+self.H/2, y+1+self.W)
- #the connector length
- self._connector_length = CONNECTOR_EXTENSION_MINIMAL + CONNECTOR_EXTENSION_INCREMENT*index
-
- def _create_labels(self):
- """Create the labels for the socket."""
- self._bg_color = Colors.get_color(self.get_color())
- #create the layout
- layout = gtk.DrawingArea().create_pango_layout('')
- layout.set_markup(Utils.parse_template(PORT_MARKUP_TMPL, port=self))
- self.w, self.h = layout.get_pixel_size()
- self.W, self.H = 2*PORT_LABEL_PADDING+self.w, 2*PORT_LABEL_PADDING+self.h
- #create the pixmap
- pixmap = self.get_parent().get_parent().new_pixmap(self.w, self.h)
- gc = pixmap.new_gc()
- gc.set_foreground(self._bg_color)
- pixmap.draw_rectangle(gc, True, 0, 0, self.w, self.h)
- pixmap.draw_layout(gc, 0, 0, layout)
- #create the images
- self.horizontal_label = image = pixmap.get_image(0, 0, self.w, self.h)
- if self.is_vertical():
- self.vertical_label = vimage = gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), self.h, self.w)
- for i in range(self.w):
- for j in range(self.h): vimage.put_pixel(j, self.w-i-1, image.get_pixel(i, j))
-
- def draw(self, gc, window):
- """
- Draw the socket with a label.
- @param gc the graphics context
- @param window the gtk window to draw on
- """
- Element.draw(
- self, gc, window, bg_color=self._bg_color,
- border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or Colors.BORDER_COLOR,
- )
- X,Y = self.get_coordinate()
- (x,y),(w,h) = self.areas_dict[self.get_rotation()][0] #use the first area's sizes to place the labels
- if self.is_horizontal():
- window.draw_image(gc, self.horizontal_label, 0, 0, x+X+(self.W-self.w)/2, y+Y+(self.H-self.h)/2, -1, -1)
- elif self.is_vertical():
- window.draw_image(gc, self.vertical_label, 0, 0, x+X+(self.H-self.h)/2, y+Y+(self.W-self.w)/2, -1, -1)
-
- def get_connector_coordinate(self):
- """
- Get the coordinate where connections may attach to.
- @return the connector coordinate (x, y) tuple
- """
- x,y = self._connector_coordinate
- X,Y = self.get_coordinate()
- return (x+X, y+Y)
-
- def get_connector_direction(self):
- """
- Get the direction that the socket points: 0,90,180,270.
- This is the rotation degree if the socket is an output or
- the rotation degree + 180 if the socket is an input.
- @return the direction in degrees
- """
- if self.is_source(): return self.get_rotation()
- elif self.is_sink(): return (self.get_rotation() + 180)%360
-
- def get_connector_length(self):
- """
- Get the length of the connector.
- The connector length increases as the port index changes.
- @return the length in pixels
- """
- return self._connector_length
-
- def get_rotation(self):
- """
- Get the parent's rotation rather than self.
- @return the parent's rotation
- """
- return self.get_parent().get_rotation()
-
- def move(self, delta_coor):
- """
- Move the parent rather than self.
- @param delta_corr the (delta_x, delta_y) tuple
- """
- self.get_parent().move(delta_coor)
-
- def rotate(self, direction):
- """
- Rotate the parent rather than self.
- @param direction degrees to rotate
- """
- self.get_parent().rotate(direction)
-
- def get_coordinate(self):
- """
- Get the parent's coordinate rather than self.
- @return the parents coordinate
- """
- return self.get_parent().get_coordinate()
-
- def set_highlighted(self, highlight):
- """
- Set the parent highlight rather than self.
- @param highlight true to enable highlighting
- """
- self.get_parent().set_highlighted(highlight)
-
- def is_highlighted(self):
- """
- Get the parent's is highlight rather than self.
- @return the parent's highlighting status
- """
- return self.get_parent().is_highlighted()
diff --git a/grc/src/platforms/gui/Utils.py b/grc/src/platforms/gui/Utils.py
deleted file mode 100644
index ee6dc6cdc..000000000
--- a/grc/src/platforms/gui/Utils.py
+++ /dev/null
@@ -1,82 +0,0 @@
-"""
-Copyright 2008, 2009 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-"""
-
-from Constants import POSSIBLE_ROTATIONS
-from Cheetah.Template import Template
-
-def get_rotated_coordinate(coor, rotation):
- """
- Rotate the coordinate by the given rotation.
- @param coor the coordinate x, y tuple
- @param rotation the angle in degrees
- @return the rotated coordinates
- """
- #handles negative angles
- rotation = (rotation + 360)%360
- assert rotation in POSSIBLE_ROTATIONS
- #determine the number of degrees to rotate
- cos_r, sin_r = {
- 0: (1, 0),
- 90: (0, 1),
- 180: (-1, 0),
- 270: (0, -1),
- }[rotation]
- x, y = coor
- return (x*cos_r + y*sin_r, -x*sin_r + y*cos_r)
-
-def get_angle_from_coordinates((x1,y1), (x2,y2)):
- """
- Given two points, calculate the vector direction from point1 to point2, directions are multiples of 90 degrees.
- @param (x1,y1) the coordinate of point 1
- @param (x2,y2) the coordinate of point 2
- @return the direction in degrees
- """
- if y1 == y2:#0 or 180
- if x2 > x1: return 0
- else: return 180
- else:#90 or 270
- if y2 > y1: return 270
- else: return 90
-
-def xml_encode(string):
- """
- Encode a string into an xml safe string by replacing special characters.
- Needed for gtk pango markup in labels.
- @param string the input string
- @return output string with safe characters
- """
- string = str(string)
- for char, safe in (
- ('&', '&amp;'),
- ('<', '&lt;'),
- ('>', '&gt;'),
- ('"', '&quot;'),
- ("'", '&apos;'),
- ): string = string.replace(char, safe)
- return string
-
-def parse_template(tmpl_str, **kwargs):
- """
- Parse the template string with the given args.
- Pass in the xml encode method for pango escape chars.
- @param tmpl_str the template as a string
- @return a string of the parsed template
- """
- kwargs['encode'] = xml_encode
- return str(Template(tmpl_str, kwargs))
diff --git a/grc/src/platforms/gui/__init__.py b/grc/src/platforms/gui/__init__.py
deleted file mode 100644
index 8b1378917..000000000
--- a/grc/src/platforms/gui/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-