| 
									
										
										
										
											2001-08-25 12:15:04 +00:00
										 |  |  | from Carbon import Qd | 
					
						
							|  |  |  | from Carbon import Win | 
					
						
							|  |  |  | from Carbon import QuickDraw | 
					
						
							|  |  |  | from Carbon import Evt | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | import string | 
					
						
							|  |  |  | from types import * | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | WidgetsError = "WidgetsError" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEBUG = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Widget: | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	"""Base class for all widgets.""" | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	_selectable = 0 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __init__(self, possize): | 
					
						
							|  |  |  | 		self._widgets = [] | 
					
						
							|  |  |  | 		self._widgetsdict = {} | 
					
						
							|  |  |  | 		self._possize = possize | 
					
						
							|  |  |  | 		self._bounds = None | 
					
						
							|  |  |  | 		self._visible = 1 | 
					
						
							|  |  |  | 		self._enabled = 0 | 
					
						
							|  |  |  | 		self._selected = 0 | 
					
						
							|  |  |  | 		self._activated = 0 | 
					
						
							|  |  |  | 		self._callback = None | 
					
						
							|  |  |  | 		self._parent = None | 
					
						
							|  |  |  | 		self._parentwindow = None | 
					
						
							|  |  |  | 		self._bindings = {} | 
					
						
							|  |  |  | 		self._backcolor = None | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def show(self, onoff): | 
					
						
							|  |  |  | 		self._visible = onoff | 
					
						
							|  |  |  | 		for w in self._widgets: | 
					
						
							|  |  |  | 			w.show(onoff) | 
					
						
							|  |  |  | 		if self._parentwindow is not None and self._parentwindow.wid is not None: | 
					
						
							|  |  |  | 			self.SetPort() | 
					
						
							|  |  |  | 			if onoff: | 
					
						
							|  |  |  | 				self.draw() | 
					
						
							|  |  |  | 			else: | 
					
						
							|  |  |  | 				Qd.EraseRect(self._bounds) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def draw(self, visRgn = None): | 
					
						
							|  |  |  | 		if self._visible: | 
					
						
							|  |  |  | 			# draw your stuff here | 
					
						
							|  |  |  | 			pass | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def getpossize(self): | 
					
						
							|  |  |  | 		return self._possize | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def getbounds(self): | 
					
						
							|  |  |  | 		return self._bounds | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def move(self, x, y = None): | 
					
						
							|  |  |  | 		"""absolute move""" | 
					
						
							|  |  |  | 		if y == None: | 
					
						
							|  |  |  | 			x, y = x | 
					
						
							|  |  |  | 		if type(self._possize) <> TupleType: | 
					
						
							|  |  |  | 			raise WidgetsError, "can't move widget with bounds function" | 
					
						
							|  |  |  | 		l, t, r, b = self._possize | 
					
						
							|  |  |  | 		self.resize(x, y, r, b) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def rmove(self, x, y = None): | 
					
						
							|  |  |  | 		"""relative move""" | 
					
						
							|  |  |  | 		if y == None: | 
					
						
							|  |  |  | 			x, y = x | 
					
						
							|  |  |  | 		if type(self._possize) <> TupleType: | 
					
						
							|  |  |  | 			raise WidgetsError, "can't move widget with bounds function" | 
					
						
							|  |  |  | 		l, t, r, b = self._possize | 
					
						
							|  |  |  | 		self.resize(l + x, t + y, r, b) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	def resize(self, *args): | 
					
						
							|  |  |  | 		if len(args) == 1: | 
					
						
							|  |  |  | 			if type(args[0]) == FunctionType or type(args[0]) == MethodType: | 
					
						
							|  |  |  | 				self._possize = args[0] | 
					
						
							|  |  |  | 			else: | 
					
						
							|  |  |  | 				apply(self.resize, args[0]) | 
					
						
							|  |  |  | 		elif len(args) == 2: | 
					
						
							|  |  |  | 			self._possize = (0, 0) + args | 
					
						
							|  |  |  | 		elif len(args) == 4: | 
					
						
							|  |  |  | 			self._possize = args | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			raise TypeError, "wrong number of arguments" | 
					
						
							|  |  |  | 		self._calcbounds() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def open(self): | 
					
						
							|  |  |  | 		self._calcbounds() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def close(self): | 
					
						
							|  |  |  | 		del self._callback | 
					
						
							|  |  |  | 		del self._possize | 
					
						
							|  |  |  | 		del self._bindings | 
					
						
							|  |  |  | 		del self._parent | 
					
						
							|  |  |  | 		del self._parentwindow | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def bind(self, key, callback): | 
					
						
							|  |  |  | 		"""bind a key or an 'event' to a callback""" | 
					
						
							|  |  |  | 		if callback: | 
					
						
							|  |  |  | 			self._bindings[key] = callback | 
					
						
							|  |  |  | 		elif self._bindings.has_key(key): | 
					
						
							|  |  |  | 			del self._bindings[key] | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def adjust(self, oldbounds): | 
					
						
							|  |  |  | 		self.SetPort() | 
					
						
							| 
									
										
										
										
											2001-01-23 14:58:20 +00:00
										 |  |  | 		self.GetWindow().InvalWindowRect(oldbounds) | 
					
						
							|  |  |  | 		self.GetWindow().InvalWindowRect(self._bounds) | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	def _calcbounds(self): | 
					
						
							|  |  |  | 		# calculate absolute bounds relative to the window origin from our | 
					
						
							|  |  |  | 		# abstract _possize attribute, which is either a 4-tuple or a callable object | 
					
						
							|  |  |  | 		oldbounds = self._bounds | 
					
						
							|  |  |  | 		pl, pt, pr, pb = self._parent._bounds | 
					
						
							|  |  |  | 		if callable(self._possize): | 
					
						
							|  |  |  | 			# _possize is callable, let it figure it out by itself: it should return  | 
					
						
							|  |  |  | 			# the bounds relative to our parent widget. | 
					
						
							|  |  |  | 			width = pr - pl | 
					
						
							|  |  |  | 			height = pb - pt | 
					
						
							|  |  |  | 			self._bounds = Qd.OffsetRect(self._possize(width, height), pl, pt) | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			# _possize must be a 4-tuple. This is where the algorithm by Peter Kriens and | 
					
						
							|  |  |  | 			# Petr van Blokland kicks in. (*** Parts of this algorithm are applied for  | 
					
						
							|  |  |  | 			# patents by Ericsson, Sweden ***) | 
					
						
							|  |  |  | 			l, t, r, b = self._possize | 
					
						
							|  |  |  | 			# depending on the values of l(eft), t(op), r(right) and b(ottom),  | 
					
						
							|  |  |  | 			# they mean different things: | 
					
						
							|  |  |  | 			if l < -1: | 
					
						
							|  |  |  | 				# l is less than -1, this mean it measures from the *right* of it's parent | 
					
						
							|  |  |  | 				l = pr + l | 
					
						
							|  |  |  | 			else: | 
					
						
							|  |  |  | 				# l is -1 or greater, this mean it measures from the *left* of it's parent | 
					
						
							|  |  |  | 				l = pl + l | 
					
						
							|  |  |  | 			if t < -1: | 
					
						
							|  |  |  | 				# t is less than -1, this mean it measures from the *bottom* of it's parent | 
					
						
							|  |  |  | 				t = pb + t | 
					
						
							|  |  |  | 			else: | 
					
						
							|  |  |  | 				# t is -1 or greater, this mean it measures from the *top* of it's parent | 
					
						
							|  |  |  | 				t = pt + t | 
					
						
							|  |  |  | 			if r > 1: | 
					
						
							|  |  |  | 				# r is greater than 1, this means r is the *width* of the widget | 
					
						
							|  |  |  | 				r = l + r | 
					
						
							|  |  |  | 			else: | 
					
						
							|  |  |  | 				# r is less than 1, this means it measures from the *right* of it's parent | 
					
						
							|  |  |  | 				r = pr + r | 
					
						
							|  |  |  | 			if b > 1: | 
					
						
							|  |  |  | 				# b is greater than 1, this means b is the *height* of the widget | 
					
						
							|  |  |  | 				b = t + b | 
					
						
							|  |  |  | 			else: | 
					
						
							|  |  |  | 				# b is less than 1, this means it measures from the *bottom* of it's parent | 
					
						
							|  |  |  | 				b = pb + b | 
					
						
							|  |  |  | 			self._bounds = (l, t, r, b) | 
					
						
							|  |  |  | 		if oldbounds and oldbounds <> self._bounds: | 
					
						
							|  |  |  | 			self.adjust(oldbounds) | 
					
						
							|  |  |  | 		for w in self._widgets: | 
					
						
							|  |  |  | 			w._calcbounds() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def test(self, point): | 
					
						
							|  |  |  | 		if Qd.PtInRect(point, self._bounds): | 
					
						
							|  |  |  | 			return 1 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def click(self, point, modifiers): | 
					
						
							|  |  |  | 		pass | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def findwidget(self, point, onlyenabled = 1): | 
					
						
							|  |  |  | 		if self.test(point): | 
					
						
							|  |  |  | 			for w in self._widgets: | 
					
						
							|  |  |  | 				widget = w.findwidget(point) | 
					
						
							|  |  |  | 				if widget is not None: | 
					
						
							|  |  |  | 					return widget | 
					
						
							|  |  |  | 			if self._enabled or not onlyenabled: | 
					
						
							|  |  |  | 				return self | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def forall(self, methodname, *args): | 
					
						
							|  |  |  | 		for w in self._widgets: | 
					
						
							|  |  |  | 			rv = apply(w.forall, (methodname,) + args) | 
					
						
							|  |  |  | 			if rv:  | 
					
						
							|  |  |  | 				return rv | 
					
						
							|  |  |  | 		if self._bindings.has_key("<" + methodname + ">"): | 
					
						
							|  |  |  | 			callback = self._bindings["<" + methodname + ">"] | 
					
						
							|  |  |  | 			rv = apply(callback, args) | 
					
						
							|  |  |  | 			if rv:  | 
					
						
							|  |  |  | 				return rv | 
					
						
							|  |  |  | 		if hasattr(self, methodname): | 
					
						
							|  |  |  | 			method = getattr(self, methodname) | 
					
						
							|  |  |  | 			return apply(method, args) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def forall_butself(self, methodname, *args): | 
					
						
							|  |  |  | 		for w in self._widgets: | 
					
						
							|  |  |  | 			rv = apply(w.forall, (methodname,) + args) | 
					
						
							|  |  |  | 			if rv:  | 
					
						
							|  |  |  | 				return rv | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def forall_frombottom(self, methodname, *args): | 
					
						
							|  |  |  | 		if self._bindings.has_key("<" + methodname + ">"): | 
					
						
							|  |  |  | 			callback = self._bindings["<" + methodname + ">"] | 
					
						
							|  |  |  | 			rv = apply(callback, args) | 
					
						
							|  |  |  | 			if rv:  | 
					
						
							|  |  |  | 				return rv | 
					
						
							|  |  |  | 		if hasattr(self, methodname): | 
					
						
							|  |  |  | 			method = getattr(self, methodname) | 
					
						
							|  |  |  | 			rv = apply(method, args) | 
					
						
							|  |  |  | 			if rv:  | 
					
						
							|  |  |  | 				return rv | 
					
						
							|  |  |  | 		for w in self._widgets: | 
					
						
							|  |  |  | 			rv = apply(w.forall_frombottom, (methodname,) + args) | 
					
						
							|  |  |  | 			if rv:  | 
					
						
							|  |  |  | 				return rv | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def _addwidget(self, key, widget): | 
					
						
							|  |  |  | 		if widget in self._widgets: | 
					
						
							|  |  |  | 			raise ValueError, "duplicate widget" | 
					
						
							|  |  |  | 		if self._widgetsdict.has_key(key): | 
					
						
							|  |  |  | 			self._removewidget(key) | 
					
						
							|  |  |  | 		self._widgets.append(widget) | 
					
						
							|  |  |  | 		self._widgetsdict[key] = widget | 
					
						
							|  |  |  | 		widget._parent = self | 
					
						
							|  |  |  | 		self._setparentwindow(widget) | 
					
						
							|  |  |  | 		if self._parentwindow and self._parentwindow.wid: | 
					
						
							|  |  |  | 			widget.forall_frombottom("open") | 
					
						
							| 
									
										
										
										
											2001-01-23 14:58:20 +00:00
										 |  |  | 			self.GetWindow().InvalWindowRect(widget._bounds) | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	def _setparentwindow(self, widget): | 
					
						
							|  |  |  | 		widget._parentwindow = self._parentwindow | 
					
						
							|  |  |  | 		for w in widget._widgets: | 
					
						
							|  |  |  | 			self._setparentwindow(w) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def _removewidget(self, key): | 
					
						
							|  |  |  | 		if not self._widgetsdict.has_key(key): | 
					
						
							|  |  |  | 			raise KeyError, "no widget with key " + `key` | 
					
						
							|  |  |  | 		widget = self._widgetsdict[key] | 
					
						
							|  |  |  | 		for k in widget._widgetsdict.keys(): | 
					
						
							|  |  |  | 			widget._removewidget(k) | 
					
						
							|  |  |  | 		if self._parentwindow._currentwidget == widget: | 
					
						
							|  |  |  | 			widget.select(0) | 
					
						
							|  |  |  | 			self._parentwindow._currentwidget = None | 
					
						
							|  |  |  | 		self.SetPort() | 
					
						
							| 
									
										
										
										
											2001-01-23 14:58:20 +00:00
										 |  |  | 		self.GetWindow().InvalWindowRect(widget._bounds) | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 		widget.close() | 
					
						
							|  |  |  | 		del self._widgetsdict[key] | 
					
						
							|  |  |  | 		self._widgets.remove(widget) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __setattr__(self, attr, value): | 
					
						
							|  |  |  | 		if type(value) == InstanceType and isinstance(value, Widget) and	\ | 
					
						
							|  |  |  | 				attr not in ("_currentwidget", "_lastrollover",  | 
					
						
							|  |  |  | 				"_parent", "_parentwindow", "_defaultbutton"): | 
					
						
							|  |  |  | 			if hasattr(self, attr): | 
					
						
							|  |  |  | 				raise ValueError, "Can't replace existing attribute: " + attr | 
					
						
							|  |  |  | 			self._addwidget(attr, value) | 
					
						
							|  |  |  | 		self.__dict__[attr] = value | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __delattr__(self, attr): | 
					
						
							|  |  |  | 		if attr == "_widgetsdict": | 
					
						
							|  |  |  | 			raise AttributeError, "cannot delete attribute _widgetsdict" | 
					
						
							|  |  |  | 		if self._widgetsdict.has_key(attr): | 
					
						
							|  |  |  | 			self._removewidget(attr) | 
					
						
							|  |  |  | 			if self.__dict__.has_key(attr): | 
					
						
							|  |  |  | 				del self.__dict__[attr] | 
					
						
							|  |  |  | 		elif self.__dict__.has_key(attr): | 
					
						
							|  |  |  | 			del self.__dict__[attr] | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			raise AttributeError, attr | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __setitem__(self, key, value): | 
					
						
							|  |  |  | 		self._addwidget(key, value) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __getitem__(self, key): | 
					
						
							|  |  |  | 		if not self._widgetsdict.has_key(key): | 
					
						
							|  |  |  | 			raise KeyError, key | 
					
						
							|  |  |  | 		return self._widgetsdict[key] | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __delitem__(self, key): | 
					
						
							|  |  |  | 		self._removewidget(key) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def SetPort(self): | 
					
						
							|  |  |  | 		self._parentwindow.SetPort() | 
					
						
							| 
									
										
										
										
											2001-01-23 14:58:20 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def GetWindow(self): | 
					
						
							|  |  |  | 		return self._parentwindow.GetWindow() | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 	def __del__(self): | 
					
						
							|  |  |  | 		if DEBUG: | 
					
						
							|  |  |  | 			print "%s instance deleted" % self.__class__.__name__ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def _drawbounds(self): | 
					
						
							|  |  |  | 		Qd.FrameRect(self._bounds) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ClickableWidget(Widget): | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	"""Base class for clickable widgets. (note: self._enabled must be true to receive click events.)""" | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def click(self, point, modifiers): | 
					
						
							|  |  |  | 		pass | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def enable(self, onoff): | 
					
						
							|  |  |  | 		self._enabled = onoff | 
					
						
							|  |  |  | 		self.SetPort() | 
					
						
							|  |  |  | 		self.draw() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def callback(self): | 
					
						
							|  |  |  | 		if self._callback: | 
					
						
							|  |  |  | 			return CallbackCall(self._callback, 1) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class SelectableWidget(ClickableWidget): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"""Base class for selectable widgets.""" | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	_selectable = 1 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def select(self, onoff, isclick = 0): | 
					
						
							|  |  |  | 		if onoff == self._selected: | 
					
						
							|  |  |  | 			return 1 | 
					
						
							|  |  |  | 		if self._bindings.has_key("<select>"): | 
					
						
							|  |  |  | 			callback = self._bindings["<select>"] | 
					
						
							|  |  |  | 			if callback(onoff): | 
					
						
							|  |  |  | 				return 1 | 
					
						
							|  |  |  | 		self._selected = onoff | 
					
						
							|  |  |  | 		if onoff: | 
					
						
							|  |  |  | 			if self._parentwindow._currentwidget is not None: | 
					
						
							|  |  |  | 				self._parentwindow._currentwidget.select(0) | 
					
						
							|  |  |  | 			self._parentwindow._currentwidget = self | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			self._parentwindow._currentwidget = None | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def key(self, char, event): | 
					
						
							|  |  |  | 		pass | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def drawselframe(self, onoff): | 
					
						
							|  |  |  | 		if not self._parentwindow._hasselframes: | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		thickrect = Qd.InsetRect(self._bounds, -3, -3) | 
					
						
							|  |  |  | 		state = Qd.GetPenState() | 
					
						
							|  |  |  | 		Qd.PenSize(2, 2) | 
					
						
							|  |  |  | 		if onoff: | 
					
						
							|  |  |  | 			Qd.PenPat(Qd.qd.black) | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			Qd.PenPat(Qd.qd.white) | 
					
						
							|  |  |  | 		Qd.FrameRect(thickrect) | 
					
						
							|  |  |  | 		Qd.SetPenState(state) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def adjust(self, oldbounds): | 
					
						
							|  |  |  | 		self.SetPort() | 
					
						
							|  |  |  | 		if self._selected: | 
					
						
							| 
									
										
										
										
											2001-01-23 14:58:20 +00:00
										 |  |  | 			self.GetWindow().InvalWindowRect(Qd.InsetRect(oldbounds, -3, -3)) | 
					
						
							|  |  |  | 			self.GetWindow().InvalWindowRect(Qd.InsetRect(self._bounds, -3, -3)) | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 		else: | 
					
						
							| 
									
										
										
										
											2001-01-23 14:58:20 +00:00
										 |  |  | 			self.GetWindow().InvalWindowRect(oldbounds) | 
					
						
							|  |  |  | 			self.GetWindow().InvalWindowRect(self._bounds) | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _Line(Widget): | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __init__(self, possize, thickness = 1): | 
					
						
							|  |  |  | 		Widget.__init__(self, possize) | 
					
						
							|  |  |  | 		self._thickness = thickness | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def open(self): | 
					
						
							|  |  |  | 		self._calcbounds() | 
					
						
							|  |  |  | 		self.SetPort() | 
					
						
							|  |  |  | 		self.draw() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def draw(self, visRgn = None): | 
					
						
							|  |  |  | 		if self._visible: | 
					
						
							|  |  |  | 			Qd.PaintRect(self._bounds) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def _drawbounds(self): | 
					
						
							|  |  |  | 		pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class HorizontalLine(_Line): | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def _calcbounds(self): | 
					
						
							|  |  |  | 		Widget._calcbounds(self) | 
					
						
							|  |  |  | 		l, t, r, b = self._bounds | 
					
						
							|  |  |  | 		self._bounds = l, t, r, t + self._thickness | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class VerticalLine(_Line): | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def _calcbounds(self): | 
					
						
							|  |  |  | 		Widget._calcbounds(self) | 
					
						
							|  |  |  | 		l, t, r, b = self._bounds | 
					
						
							|  |  |  | 		self._bounds = l, t, l + self._thickness, b | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Frame(Widget): | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __init__(self, possize, pattern = Qd.qd.black, color = (0, 0, 0)): | 
					
						
							|  |  |  | 		Widget.__init__(self, possize) | 
					
						
							|  |  |  | 		self._framepattern = pattern | 
					
						
							|  |  |  | 		self._framecolor = color | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def setcolor(self, color): | 
					
						
							|  |  |  | 		self._framecolor = color | 
					
						
							|  |  |  | 		self.SetPort() | 
					
						
							|  |  |  | 		self.draw() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def setpattern(self, pattern): | 
					
						
							|  |  |  | 		self._framepattern = pattern | 
					
						
							|  |  |  | 		self.SetPort() | 
					
						
							|  |  |  | 		self.draw() | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	def draw(self, visRgn = None): | 
					
						
							|  |  |  | 		if self._visible: | 
					
						
							|  |  |  | 			penstate = Qd.GetPenState() | 
					
						
							|  |  |  | 			Qd.PenPat(self._framepattern) | 
					
						
							|  |  |  | 			Qd.RGBForeColor(self._framecolor) | 
					
						
							|  |  |  | 			Qd.FrameRect(self._bounds) | 
					
						
							|  |  |  | 			Qd.RGBForeColor((0, 0, 0)) | 
					
						
							|  |  |  | 			Qd.SetPenState(penstate) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _darkencolor((r, g, b)): | 
					
						
							|  |  |  | 	return 0.75 * r, 0.75 * g, 0.75 * b | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class BevelBox(Widget): | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	"""'Platinum' beveled rectangle.""" | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __init__(self, possize, color = (0xe000, 0xe000, 0xe000)): | 
					
						
							|  |  |  | 		Widget.__init__(self, possize) | 
					
						
							|  |  |  | 		self._color = color | 
					
						
							|  |  |  | 		self._darkercolor = _darkencolor(color) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def setcolor(self, color): | 
					
						
							|  |  |  | 		self._color = color | 
					
						
							|  |  |  | 		self.SetPort() | 
					
						
							|  |  |  | 		self.draw() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def draw(self, visRgn = None): | 
					
						
							|  |  |  | 		if self._visible: | 
					
						
							|  |  |  | 			l, t, r, b = Qd.InsetRect(self._bounds, 1, 1) | 
					
						
							|  |  |  | 			Qd.RGBForeColor(self._color) | 
					
						
							|  |  |  | 			Qd.PaintRect((l, t, r, b)) | 
					
						
							|  |  |  | 			Qd.RGBForeColor(self._darkercolor) | 
					
						
							|  |  |  | 			Qd.MoveTo(l, b) | 
					
						
							|  |  |  | 			Qd.LineTo(r, b) | 
					
						
							|  |  |  | 			Qd.LineTo(r, t) | 
					
						
							|  |  |  | 			Qd.RGBForeColor((0, 0, 0)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Group(Widget): | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	"""A container for subwidgets""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class HorizontalPanes(Widget): | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	"""Panes, a.k.a. frames. Works a bit like a group. Devides the widget area into "panes",
 | 
					
						
							|  |  |  | 	which can be resized by the user by clicking and dragging between the subwidgets."""
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	_direction = 1 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __init__(self, possize, panesizes = None, gutter = 8): | 
					
						
							|  |  |  | 		"""panesizes should be a tuple of numbers. The length of the tuple is the number of panes, 
 | 
					
						
							|  |  |  | 		the items in the tuple are the relative sizes of these panes; these numbers should add up  | 
					
						
							|  |  |  | 		to 1 (the total size of all panes)."""
 | 
					
						
							| 
									
										
										
										
											2001-10-31 12:55:07 +00:00
										 |  |  | 		Widget.__init__(self, possize) | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 		self._panesizes = panesizes | 
					
						
							|  |  |  | 		self._gutter = gutter | 
					
						
							|  |  |  | 		self._enabled = 1 | 
					
						
							|  |  |  | 		self.setuppanes() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	#def open(self): | 
					
						
							|  |  |  | 	#	self.installbounds() | 
					
						
							|  |  |  | 	#	ClickableWidget.open(self) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def _calcbounds(self): | 
					
						
							|  |  |  | 		# hmmm. It should not neccesary be override _calcbounds :-( | 
					
						
							|  |  |  | 		self.installbounds() | 
					
						
							|  |  |  | 		Widget._calcbounds(self) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def setuppanes(self): | 
					
						
							|  |  |  | 		panesizes = self._panesizes | 
					
						
							|  |  |  | 		total = 0 | 
					
						
							|  |  |  | 		if panesizes is not None: | 
					
						
							|  |  |  | 			#if len(self._widgets) <> len(panesizes): | 
					
						
							|  |  |  | 			#	raise TypeError, 'number of widgets does not match number of panes' | 
					
						
							|  |  |  | 			for panesize in panesizes: | 
					
						
							|  |  |  | 				if not 0 < panesize < 1: | 
					
						
							|  |  |  | 					raise TypeError, 'pane sizes must be between 0 and 1, not including.' | 
					
						
							|  |  |  | 				total = total + panesize | 
					
						
							|  |  |  | 			if round(total, 4) <> 1.0: | 
					
						
							|  |  |  | 				raise TypeError, 'pane sizes must add up to 1' | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			# XXX does not work! | 
					
						
							|  |  |  | 			step = 1.0 / len(self._widgets) | 
					
						
							|  |  |  | 			panesizes = [] | 
					
						
							|  |  |  | 			for i in range(len(self._widgets)): | 
					
						
							|  |  |  | 				panesizes.append(step) | 
					
						
							|  |  |  | 		current = 0 | 
					
						
							|  |  |  | 		self._panesizes = [] | 
					
						
							|  |  |  | 		self._gutters = [] | 
					
						
							|  |  |  | 		for panesize in panesizes: | 
					
						
							|  |  |  | 			if current: | 
					
						
							|  |  |  | 				self._gutters.append(current) | 
					
						
							| 
									
										
										
										
											2000-03-07 23:40:13 +00:00
										 |  |  | 			self._panesizes.append((current, current + panesize)) | 
					
						
							| 
									
										
										
										
											1999-01-30 22:39:17 +00:00
										 |  |  | 			current = current + panesize | 
					
						
							|  |  |  | 		self.makepanebounds() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def getpanesizes(self): | 
					
						
							|  |  |  | 		return map(lambda (fr, to): to-fr,  self._panesizes) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	boundstemplate = "lambda width, height: (0, height * %s + %d, width, height * %s + %d)" | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def makepanebounds(self): | 
					
						
							|  |  |  | 		halfgutter = self._gutter / 2 | 
					
						
							|  |  |  | 		self._panebounds = [] | 
					
						
							|  |  |  | 		for i in range(len(self._panesizes)): | 
					
						
							|  |  |  | 			panestart, paneend = self._panesizes[i] | 
					
						
							|  |  |  | 			boundsstring = self.boundstemplate % (`panestart`, panestart and halfgutter,  | 
					
						
							|  |  |  | 							`paneend`, (paneend <> 1.0) and -halfgutter) | 
					
						
							|  |  |  | 			self._panebounds.append(eval(boundsstring)) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def installbounds(self): | 
					
						
							|  |  |  | 		#self.setuppanes() | 
					
						
							|  |  |  | 		for i in range(len(self._widgets)): | 
					
						
							|  |  |  | 			w = self._widgets[i] | 
					
						
							|  |  |  | 			w._possize = self._panebounds[i] | 
					
						
							|  |  |  | 			#if hasattr(w, "setuppanes"): | 
					
						
							|  |  |  | 			#	w.setuppanes() | 
					
						
							|  |  |  | 			if hasattr(w, "installbounds"): | 
					
						
							|  |  |  | 				w.installbounds() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def rollover(self, point, onoff): | 
					
						
							|  |  |  | 		if onoff: | 
					
						
							|  |  |  | 			orgmouse = point[self._direction] | 
					
						
							|  |  |  | 			halfgutter = self._gutter / 2 | 
					
						
							|  |  |  | 			l, t, r, b = self._bounds | 
					
						
							|  |  |  | 			if self._direction: | 
					
						
							|  |  |  | 				begin, end = t, b | 
					
						
							|  |  |  | 			else: | 
					
						
							|  |  |  | 				begin, end = l, r | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			i = self.findgutter(orgmouse, begin, end) | 
					
						
							|  |  |  | 			if i is None: | 
					
						
							|  |  |  | 				SetCursor("arrow") | 
					
						
							|  |  |  | 			else: | 
					
						
							|  |  |  | 				SetCursor(self._direction and 'vmover' or 'hmover') | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def findgutter(self, orgmouse, begin, end): | 
					
						
							|  |  |  | 		tolerance = max(4, self._gutter) / 2 | 
					
						
							|  |  |  | 		for i in range(len(self._gutters)): | 
					
						
							|  |  |  | 			pos = begin + (end - begin) * self._gutters[i] | 
					
						
							|  |  |  | 			if abs(orgmouse - pos) <= tolerance: | 
					
						
							|  |  |  | 				break | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		return i | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def click(self, point, modifiers): | 
					
						
							|  |  |  | 		# what a mess... | 
					
						
							|  |  |  | 		orgmouse = point[self._direction] | 
					
						
							|  |  |  | 		halfgutter = self._gutter / 2 | 
					
						
							|  |  |  | 		l, t, r, b = self._bounds | 
					
						
							|  |  |  | 		if self._direction: | 
					
						
							|  |  |  | 			begin, end = t, b | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			begin, end = l, r | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		i = self.findgutter(orgmouse, begin, end) | 
					
						
							|  |  |  | 		if i is None: | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		pos = orgpos = begin + (end - begin) * self._gutters[i]	# init pos too, for fast click on border, bug done by Petr | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		minpos = self._panesizes[i][0] | 
					
						
							|  |  |  | 		maxpos = self._panesizes[i+1][1] | 
					
						
							|  |  |  | 		minpos = begin + (end - begin) * minpos + 64 | 
					
						
							|  |  |  | 		maxpos = begin + (end - begin) * maxpos - 64 | 
					
						
							|  |  |  | 		if minpos > orgpos and maxpos < orgpos: | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		#SetCursor("fist") | 
					
						
							|  |  |  | 		self.SetPort() | 
					
						
							|  |  |  | 		if self._direction: | 
					
						
							|  |  |  | 			rect = l, orgpos - 1, r, orgpos | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			rect = orgpos - 1, t, orgpos, b | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		# track mouse --- XXX  move to separate method? | 
					
						
							|  |  |  | 		Qd.PenMode(QuickDraw.srcXor) | 
					
						
							|  |  |  | 		Qd.PenPat(Qd.qd.gray) | 
					
						
							|  |  |  | 		Qd.PaintRect(rect) | 
					
						
							|  |  |  | 		lastpos = None | 
					
						
							|  |  |  | 		while Evt.Button(): | 
					
						
							|  |  |  | 			pos = orgpos - orgmouse + Evt.GetMouse()[self._direction] | 
					
						
							|  |  |  | 			pos = max(pos, minpos) | 
					
						
							|  |  |  | 			pos = min(pos, maxpos) | 
					
						
							|  |  |  | 			if pos == lastpos: | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			Qd.PenPat(Qd.qd.gray) | 
					
						
							|  |  |  | 			Qd.PaintRect(rect) | 
					
						
							|  |  |  | 			if self._direction: | 
					
						
							|  |  |  | 				rect = l, pos - 1, r, pos | 
					
						
							|  |  |  | 			else: | 
					
						
							|  |  |  | 				rect = pos - 1, t, pos, b | 
					
						
							|  |  |  | 			Qd.PenPat(Qd.qd.gray) | 
					
						
							|  |  |  | 			Qd.PaintRect(rect) | 
					
						
							|  |  |  | 			lastpos = pos | 
					
						
							|  |  |  | 		Qd.PaintRect(rect) | 
					
						
							|  |  |  | 		Qd.PenNormal() | 
					
						
							|  |  |  | 		SetCursor("watch") | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		newpos = (pos - begin) / float(end - begin) | 
					
						
							|  |  |  | 		self._gutters[i] = newpos | 
					
						
							|  |  |  | 		self._panesizes[i] = self._panesizes[i][0], newpos | 
					
						
							|  |  |  | 		self._panesizes[i+1] = newpos, self._panesizes[i+1][1] | 
					
						
							|  |  |  | 		self.makepanebounds() | 
					
						
							|  |  |  | 		self.installbounds() | 
					
						
							|  |  |  | 		self._calcbounds() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class VerticalPanes(HorizontalPanes): | 
					
						
							|  |  |  | 	"""see HorizontalPanes""" | 
					
						
							|  |  |  | 	_direction = 0 | 
					
						
							|  |  |  | 	boundstemplate = "lambda width, height: (width * %s + %d, 0, width * %s + %d, height)" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ColorPicker(ClickableWidget): | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	"""Color picker widget. Allows the user to choose a color.""" | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __init__(self, possize, color = (0, 0, 0), callback = None): | 
					
						
							|  |  |  | 		ClickableWidget.__init__(self, possize) | 
					
						
							|  |  |  | 		self._color = color | 
					
						
							|  |  |  | 		self._callback = callback | 
					
						
							|  |  |  | 		self._enabled = 1 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def click(self, point, modifiers): | 
					
						
							|  |  |  | 		if not self._enabled: | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		import ColorPicker | 
					
						
							|  |  |  | 		newcolor, ok = ColorPicker.GetColor("", self._color) | 
					
						
							|  |  |  | 		if ok: | 
					
						
							|  |  |  | 			self._color = newcolor | 
					
						
							|  |  |  | 			self.SetPort() | 
					
						
							|  |  |  | 			self.draw() | 
					
						
							|  |  |  | 			if self._callback: | 
					
						
							|  |  |  | 				return CallbackCall(self._callback, 0, self._color) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def set(self, color): | 
					
						
							|  |  |  | 		self._color = color | 
					
						
							|  |  |  | 		self.SetPort() | 
					
						
							|  |  |  | 		self.draw() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def get(self): | 
					
						
							|  |  |  | 		return self._color | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def draw(self, visRgn=None): | 
					
						
							|  |  |  | 		if self._visible: | 
					
						
							|  |  |  | 			if not visRgn: | 
					
						
							|  |  |  | 				visRgn = self._parentwindow.wid.GetWindowPort().visRgn | 
					
						
							|  |  |  | 			Qd.PenPat(Qd.qd.gray) | 
					
						
							|  |  |  | 			rect = self._bounds | 
					
						
							|  |  |  | 			Qd.FrameRect(rect) | 
					
						
							|  |  |  | 			rect = Qd.InsetRect(rect, 3, 3) | 
					
						
							|  |  |  | 			Qd.PenNormal() | 
					
						
							|  |  |  | 			Qd.RGBForeColor(self._color) | 
					
						
							|  |  |  | 			Qd.PaintRect(rect) | 
					
						
							|  |  |  | 			Qd.RGBForeColor((0, 0, 0)) | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # misc utils | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def CallbackCall(callback, mustfit, *args): | 
					
						
							|  |  |  | 	"""internal helper routine for W""" | 
					
						
							|  |  |  | 	# XXX this function should die. | 
					
						
							|  |  |  | 	if type(callback) == FunctionType: | 
					
						
							|  |  |  | 		func = callback | 
					
						
							|  |  |  | 		maxargs = func.func_code.co_argcount | 
					
						
							|  |  |  | 	elif type(callback) == MethodType: | 
					
						
							|  |  |  | 		func = callback.im_func | 
					
						
							|  |  |  | 		maxargs = func.func_code.co_argcount - 1 | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		if callable(callback): | 
					
						
							|  |  |  | 			return apply(callback, args) | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			raise TypeError, "uncallable callback object" | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if func.func_defaults: | 
					
						
							|  |  |  | 		minargs = maxargs - len(func.func_defaults) | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		minargs = maxargs | 
					
						
							|  |  |  | 	if minargs <= len(args) <= maxargs: | 
					
						
							|  |  |  | 		return apply(callback, args) | 
					
						
							|  |  |  | 	elif not mustfit and minargs == 0: | 
					
						
							|  |  |  | 		return callback() | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		if mustfit: | 
					
						
							|  |  |  | 			raise TypeError, "callback accepts wrong number of arguments: " + `len(args)` | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			raise TypeError, "callback accepts wrong number of arguments: 0 or " + `len(args)` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def HasBaseClass(obj, class_): | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		raise obj | 
					
						
							|  |  |  | 	except class_: | 
					
						
							|  |  |  | 		return 1 | 
					
						
							|  |  |  | 	except: | 
					
						
							|  |  |  | 		pass | 
					
						
							|  |  |  | 	return 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _cursors = { | 
					
						
							|  |  |  | 	"watch"	: Qd.GetCursor(QuickDraw.watchCursor).data, | 
					
						
							|  |  |  | 	"arrow"	: Qd.qd.arrow, | 
					
						
							|  |  |  | 	"iBeam"	: Qd.GetCursor(QuickDraw.iBeamCursor).data, | 
					
						
							|  |  |  | 	"cross"	: Qd.GetCursor(QuickDraw.crossCursor).data, | 
					
						
							|  |  |  | 	"plus"		: Qd.GetCursor(QuickDraw.plusCursor).data, | 
					
						
							|  |  |  | 	"hand"	: Qd.GetCursor(468).data, | 
					
						
							|  |  |  | 	"fist"		: Qd.GetCursor(469).data, | 
					
						
							|  |  |  | 	"hmover"	: Qd.GetCursor(470).data, | 
					
						
							|  |  |  | 	"vmover"	: Qd.GetCursor(471).data, | 
					
						
							|  |  |  | 	"zoomin"	: Qd.GetCursor(472).data, | 
					
						
							|  |  |  | 	"zoomout"	: Qd.GetCursor(473).data, | 
					
						
							|  |  |  | 	"zoom"	: Qd.GetCursor(474).data, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def SetCursor(what): | 
					
						
							|  |  |  | 	"""Set the cursorshape to any of these: 'arrow', 'cross', 'fist', 'hand', 'hmover', 'iBeam', 
 | 
					
						
							|  |  |  | 	'plus', 'vmover', 'watch', 'zoom', 'zoomin', 'zoomout'."""
 | 
					
						
							|  |  |  | 	Qd.SetCursor(_cursors[what]) |