From 9988664127b367fa8fee4409f8460673d6f265e1 Mon Sep 17 00:00:00 2001
From: jblum <jblum@221aa14e-8319-0410-a670-987f0aec2ac5>
Date: Tue, 23 Jun 2009 20:38:18 +0000
Subject: Merging r11186:11273 from grc branch. Fixes, features, and
 reorganization for grc. Minor fixes and features for wxgui forms.

git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@11274 221aa14e-8319-0410-a670-987f0aec2ac5
---
 grc/gui/Element.py | 226 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 226 insertions(+)
 create mode 100644 grc/gui/Element.py

(limited to 'grc/gui/Element.py')

diff --git a/grc/gui/Element.py b/grc/gui/Element.py
new file mode 100644
index 0000000000..3151917237
--- /dev/null
+++ b/grc/gui/Element.py
@@ -0,0 +1,226 @@
+"""
+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
-- 
cgit v1.2.3