"A sort of application framework for the Mac"

DEBUG=0

import MacOS
import traceback

from AE import *
from AppleEvents import *
from Ctl import *
from Controls import *
from Dlg import *
from Dialogs import *
from Evt import *
from Events import *
from Menu import *
from Menus import *
from Qd import *
from QuickDraw import *
#from Res import *
#from Resources import *
#from Snd import *
#from Sound import *
from Win import *
from Windows import *
import types

import EasyDialogs

kHighLevelEvent = 23	# Don't know what header file this should come from
SCROLLBARWIDTH = 16		# Again, not a clue...


# Map event 'what' field to strings
eventname = {}
eventname[1] = 'mouseDown'
eventname[2] = 'mouseUp'
eventname[3] = 'keyDown'
eventname[4] = 'keyUp'
eventname[5] = 'autoKey'
eventname[6] = 'updateEvt'
eventname[7] = 'diskEvt'
eventname[8] = 'activateEvt'
eventname[15] = 'osEvt'
eventname[23] = 'kHighLevelEvent'

# Map part codes returned by WhichWindow() to strings
partname = {}
partname[0] = 'inDesk'
partname[1] = 'inMenuBar'
partname[2] = 'inSysWindow'
partname[3] = 'inContent'
partname[4] = 'inDrag'
partname[5] = 'inGrow'
partname[6] = 'inGoAway'
partname[7] = 'inZoomIn'
partname[8] = 'inZoomOut'

#
# The useable portion of the screen
#	## but what happens with multiple screens? jvr
screenbounds = qd.screenBits.bounds
screenbounds = screenbounds[0]+4, screenbounds[1]+4, \
	screenbounds[2]-4, screenbounds[3]-4
	
next_window_x = 16		# jvr
next_window_y = 44		# jvr

def windowbounds(width, height):
	"Return sensible window bounds"
	global next_window_x, next_window_y
	r, b = next_window_x+width, next_window_y+height
	if r > screenbounds[2]:
		next_window_x = 16
	if b > screenbounds[3]:
		next_window_y = 44
	l, t = next_window_x, next_window_y
	r, b = next_window_x+width, next_window_y+height
	next_window_x, next_window_y = next_window_x + 8, next_window_y + 20	# jvr
	return l, t, r, b

_watch = None
def setwatchcursor():
	global _watch
	
	if _watch == None:
		_watch = GetCursor(4).data
	SetCursor(_watch)
	
def setarrowcursor():
	SetCursor(qd.arrow)

class Application:
	
	"Application framework -- your application should be a derived class"
	
	def __init__(self, nomenubar=0):
		self._doing_asyncevents = 0
		self.quitting = 0
		self.needmenubarredraw = 0
		self._windows = {}
		if nomenubar:
			self.menubar = None
		else:
			self.makemenubar()
			
	def __del__(self):
		if self._doing_asyncevents:
			self._doing_asyncevents = 0
			MacOS.SetEventHandler()
	
	def makemenubar(self):
		self.menubar = MenuBar(self)
		AppleMenu(self.menubar, self.getabouttext(), self.do_about)
		self.makeusermenus()

	def makeusermenus(self):
		self.filemenu = m = Menu(self.menubar, "File")
		self._quititem = MenuItem(m, "Quit", "Q", self._quit)
	
	def _quit(self, *args):
		self.quitting = 1
		
	def cleanup(self):
		for w in self._windows.values():
			w.do_close()
		return self._windows == {}
		
	def appendwindow(self, wid, window):
		self._windows[wid] = window
		
	def removewindow(self, wid):
		del self._windows[wid]
	
	def getabouttext(self):
		return "About %s..." % self.__class__.__name__
	
	def do_about(self, id, item, window, event):
		EasyDialogs.Message("Hello, world!" + "\015(%s)" % self.__class__.__name__)
	
	# The main event loop is broken up in several simple steps.
	# This is done so you can override each individual part,
	# if you have a need to do extra processing independent of the
	# event type.
	# Normally, however, you'd just define handlers for individual
	# events.
	
	schedparams = (0, 0)	# By default disable Python's event handling
	default_wait = None		# By default we wait GetCaretTime in WaitNextEvent
	
	def mainloop(self, mask = everyEvent, wait = None):
		self.quitting = 0
		saveparams = apply(MacOS.SchedParams, self.schedparams)
		try:
			while not self.quitting:
				try:
					self.do1event(mask, wait)
				except (Application, SystemExit):
					# Note: the raising of "self" is old-fashioned idiom to
					# exit the mainloop. Calling _quit() is better for new
					# applications.
					break
		finally:
			apply(MacOS.SchedParams, saveparams)
	
	def dopendingevents(self, mask = everyEvent):
		"""dopendingevents - Handle all pending events"""
		while self.do1event(mask, wait=0):
			pass
	
	def do1event(self, mask = everyEvent, wait = None):
		ok, event = self.getevent(mask, wait)
		if IsDialogEvent(event):
			if self.do_dialogevent(event):
				return
		if ok:
			self.dispatch(event)
		else:
			self.idle(event)
			
	def idle(self, event):
		pass
	
	def getevent(self, mask = everyEvent, wait = None):
		if self.needmenubarredraw:
			DrawMenuBar()
			self.needmenubarredraw = 0
		if wait is None:
			wait = self.default_wait
			if wait is None:
				wait = GetCaretTime()
		ok, event = WaitNextEvent(mask, wait)
		return ok, event
			
	def dispatch(self, event):
		# The following appears to be double work (already done in do1event)
		# but we need it for asynchronous event handling
		if IsDialogEvent(event):
			if self.do_dialogevent(event):
				return
		(what, message, when, where, modifiers) = event
		if eventname.has_key(what):
			name = "do_" + eventname[what]
		else:
			name = "do_%d" % what
		try:
			handler = getattr(self, name)
		except AttributeError:
			handler = self.do_unknownevent
		handler(event)
		
	def asyncevents(self, onoff):
		"""asyncevents - Set asynchronous event handling on or off"""
		old = self._doing_asyncevents
		if old:
			MacOS.SetEventHandler()
			apply(MacOS.SchedParams, self.schedparams)
		if onoff:
			MacOS.SetEventHandler(self.dispatch)
			doint, dummymask, benice, howoften, bgyield = \
			       self.schedparams
			MacOS.SchedParams(doint, everyEvent, benice,
					  howoften, bgyield)
		self._doing_asyncevents = onoff
		return old
			
	def do_dialogevent(self, event):
		gotone, dlg, item = DialogSelect(event)
		if gotone:
			window = dlg.GetDialogWindow()
			if self._windows.has_key(window):
				self._windows[window].do_itemhit(item, event)
			else:
				print 'Dialog event for unknown dialog'
			return 1
		return 0
	
	def do_mouseDown(self, event):
		(what, message, when, where, modifiers) = event
		partcode, wid = FindWindow(where)

		#
		# Find the correct name.
		#
		if partname.has_key(partcode):
			name = "do_" + partname[partcode]
		else:
			name = "do_%d" % partcode

		if wid == None:
			# No window, or a non-python window	
			try:
				handler = getattr(self, name)
			except AttributeError:
				# Not menubar or something, so assume someone
				# else's window
				MacOS.HandleEvent(event)
				return		
		elif self._windows.has_key(wid):
			# It is a window. Hand off to correct window.
			window = self._windows[wid]
			try:
				handler = getattr(window, name)
			except AttributeError:
				handler = self.do_unknownpartcode
		else:
			# It is a python-toolbox window, but not ours.
			handler = self.do_unknownwindow
		handler(partcode, wid, event)

	def do_inSysWindow(self, partcode, window, event):
		MacOS.HandleEvent(event)
	
	def do_inDesk(self, partcode, window, event):
		MacOS.HandleEvent(event)
	
	def do_inMenuBar(self, partcode, window, event):
		if not self.menubar:
			MacOS.HandleEvent(event)
			return
		(what, message, when, where, modifiers) = event
		result = MenuSelect(where)
		id = (result>>16) & 0xffff	# Hi word
		item = result & 0xffff		# Lo word
		self.do_rawmenu(id, item, window, event)
	
	def do_rawmenu(self, id, item, window, event):
		try:
			self.do_menu(id, item, window, event)
		finally:
			HiliteMenu(0)
	
	def do_menu(self, id, item, window, event):
		MacOS.OutputSeen()
		self.menubar.dispatch(id, item, window, event)
	
	
	def do_unknownpartcode(self, partcode, window, event):
		(what, message, when, where, modifiers) = event
		if DEBUG: print "Mouse down at global:", where
		if DEBUG: print "\tUnknown part code:", partcode
		if DEBUG: print "\tEvent:", self.printevent(event)
		MacOS.HandleEvent(event)
		
	def do_unknownwindow(self, partcode, window, event):
		if DEBUG: print 'Unknown window:', window
		MacOS.HandleEvent(event)
	
	def do_keyDown(self, event):
		self.do_key(event)
	
	def do_autoKey(self, event):
		if not event[-1] & cmdKey:
			self.do_key(event)
	
	def do_key(self, event):
		(what, message, when, where, modifiers) = event
		c = chr(message & charCodeMask)
		if self.menubar:
			result = MenuEvent(event)
			id = (result>>16) & 0xffff	# Hi word
			item = result & 0xffff		# Lo word
			if id:
				self.do_rawmenu(id, item, None, event)
				return
			# Otherwise we fall-through
		if modifiers & cmdKey:
			if c == '.':
				raise self
			else:
				if not self.menubar:
					MacOS.HandleEvent(event)
				return
		else:
			# See whether the front window wants it
			w = FrontWindow()
			if w and self._windows.has_key(w):
				window = self._windows[w]
				try:
					do_char = window.do_char
				except AttributeError:
					do_char = self.do_char
				do_char(c, event)
			# else it wasn't for us, sigh...
	
	def do_char(self, c, event):
		if DEBUG: print "Character", `c`
	
	def do_updateEvt(self, event):
		(what, message, when, where, modifiers) = event
		wid = WhichWindow(message)
		if wid and self._windows.has_key(wid):
			window = self._windows[wid]
			window.do_rawupdate(wid, event)
		else:
			MacOS.HandleEvent(event)
	
	def do_activateEvt(self, event):
		(what, message, when, where, modifiers) = event
		wid = WhichWindow(message)
		if wid and self._windows.has_key(wid):
			window = self._windows[wid]
			window.do_activate(modifiers & 1, event)
		else:
			MacOS.HandleEvent(event)
	
	def do_osEvt(self, event):
		(what, message, when, where, modifiers) = event
		which = (message >> 24) & 0xff
		if which == 1:	# suspend/resume
			self.do_suspendresume(event)
		else:
			if DEBUG:
				print 'unknown osEvt:',
				self.printevent(event)
	
	def do_suspendresume(self, event):
		(what, message, when, where, modifiers) = event
		wid = FrontWindow()
		if wid and self._windows.has_key(wid):
			window = self._windows[wid]
			window.do_activate(message & 1, event)
	
	def do_kHighLevelEvent(self, event):
		(what, message, when, where, modifiers) = event
		if DEBUG: 
			print "High Level Event:",
			self.printevent(event)
		try:
			AEProcessAppleEvent(event)
		except:
			print "AEProcessAppleEvent error:"
			traceback.print_exc()
	
	def do_unknownevent(self, event):
		if DEBUG:
			print "Unhandled event:",
			self.printevent(event)
	
	def printevent(self, event):
		(what, message, when, where, modifiers) = event
		nicewhat = `what`
		if eventname.has_key(what):
			nicewhat = eventname[what]
		print nicewhat,
		if what == kHighLevelEvent:
			h, v = where
			print `ostypecode(message)`, hex(when), `ostypecode(h | (v<<16))`,
		else:
			print hex(message), hex(when), where,
		print hex(modifiers)


class MenuBar:
	"""Represent a set of menus in a menu bar.
	
	Interface:
	
	- (constructor)
	- (destructor)
	- addmenu
	- addpopup (normally used internally)
	- dispatch (called from Application)
	"""
	
	nextid = 1	# Necessarily a class variable
	
	def getnextid(self):
		id = MenuBar.nextid
		MenuBar.nextid = id+1
		return id
	
	def __init__(self, parent=None):
		self.parent = parent
		ClearMenuBar()
		self.bar = GetMenuBar()
		self.menus = {}
	
	# XXX necessary?
	def close(self):
		self.parent = None
		self.bar = None
		self.menus = None
	
	def addmenu(self, title, after = 0):
		id = self.getnextid()
		if DEBUG: print 'Newmenu', title, id # XXXX
		m = NewMenu(id, title)
		m.InsertMenu(after)
		if after >= 0:
			if self.parent:
				self.parent.needmenubarredraw = 1
			else:
				DrawMenuBar()
		return id, m
		
	def delmenu(self, id):
		if DEBUG: print 'Delmenu', id # XXXX
		DeleteMenu(id)
	
	def addpopup(self, title = ''):
		return self.addmenu(title, -1)

# Useless:	
#	def install(self):
#		if not self.bar: return
#		SetMenuBar(self.bar)
#		if self.parent:
#			self.parent.needmenubarredraw = 1
#		else:
#			DrawMenuBar()
	
	def fixmenudimstate(self):
		for m in self.menus.keys():
			menu = self.menus[m]
			if menu.__class__ == FrameWork.AppleMenu:
				continue
			for i in range(len(menu.items)):
				label, shortcut, callback, kind = menu.items[i]
				if type(callback) == types.StringType:
					wid = Win.FrontWindow()
					if wid and self.parent._windows.has_key(wid):
						window = self.parent._windows[wid]
						if hasattr(window, "domenu_" + callback):
							menu.menu.EnableMenuItem(i + 1)
						elif hasattr(self.parent, "domenu_" + callback):
							menu.menu.EnableMenuItem(i + 1)
						else:
							menu.menu.DisableMenuItem(i + 1)
					elif hasattr(self.parent, "domenu_" + callback):
						menu.menu.EnableMenuItem(i + 1)
					else:
						menu.menu.DisableMenuItem(i + 1)
				elif callback:
					pass
					
	def dispatch(self, id, item, window, event):
		if self.menus.has_key(id):
			self.menus[id].dispatch(id, item, window, event)
		else:
			if DEBUG: print "MenuBar.dispatch(%d, %d, %s, %s)" % \
				(id, item, window, event)
	

# XXX Need a way to get menus as resources and bind them to callbacks

class Menu:
	"One menu."
	
	def __init__(self, bar, title, after=0):
		self.bar = bar
		self.id, self.menu = self.bar.addmenu(title, after)
		bar.menus[self.id] = self
		self.items = []
		self._parent = None
		
	def delete(self):
		self.bar.delmenu(self.id)
		del self.bar.menus[self.id]
		self.menu.DisposeMenu()
		del self.bar
		del self.items
		del self.menu
		del self.id
		del self._parent
		
	def additem(self, label, shortcut=None, callback=None, kind=None):
		self.menu.AppendMenu('x')		# add a dummy string
		self.items.append((label, shortcut, callback, kind))
		item = len(self.items)
		self.menu.SetMenuItemText(item, label)		# set the actual text
		if shortcut and type(shortcut) == type(()):
			modifiers, char = shortcut[:2]
			self.menu.SetItemCmd(item, ord(char))
			self.menu.SetMenuItemModifiers(item, modifiers)
			if len(shortcut) > 2:
				self.menu.SetMenuItemKeyGlyph(item, shortcut[2])
		elif shortcut:	
			self.menu.SetItemCmd(item, ord(shortcut))
		return item
		
	def delitem(self, item):
		if item != len(self.items):
			raise 'Can only delete last item of a menu'
		self.menu.DeleteMenuItem(item)
		del self.items[item-1]
	
	def addcheck(self, label, shortcut=None, callback=None):
		return self.additem(label, shortcut, callback, 'check')
	
	def addradio(self, label, shortcut=None, callback=None):
		return self.additem(label, shortcut, callback, 'radio')
	
	def addseparator(self):
		self.menu.AppendMenu('(-')
		self.items.append(('', None, None, 'separator'))
	
	def addsubmenu(self, label, title=''):
		sub = Menu(self.bar, title, -1)
		item = self.additem(label, '\x1B', None, 'submenu')
		self.menu.SetItemMark(item, sub.id)
		sub._parent = self
		sub._parent_item = item
		return sub
	
	def dispatch(self, id, item, window, event):
		title, shortcut, callback, mtype = self.items[item-1]
		if callback:
			if not self.bar.parent or type(callback) <> types.StringType:
				menuhandler = callback
			else: 
				# callback is string
				wid = Win.FrontWindow()
				if wid and self.bar.parent._windows.has_key(wid):
					window = self.bar.parent._windows[wid]
					if hasattr(window, "domenu_" + callback):
						menuhandler = getattr(window, "domenu_" + callback)
					elif hasattr(self.bar.parent, "domenu_" + callback):
						menuhandler = getattr(self.bar.parent, "domenu_" + callback)
					else:
						# nothing we can do. we shouldn't have come this far
						# since the menu item should have been disabled...
						return
				elif hasattr(self.bar.parent, "domenu_" + callback):
					menuhandler = getattr(self.bar.parent, "domenu_" + callback)
				else:
					# nothing we can do. we shouldn't have come this far
					# since the menu item should have been disabled...
					return
			menuhandler(id, item, window, event)

	def enable(self, onoff):
		if onoff:
			self.menu.EnableMenuItem(0)
			if self._parent:
				self._parent.menu.EnableMenuItem(self._parent_item)
		else:
			self.menu.DisableMenuItem(0)
			if self._parent:
				self._parent.menu.DisableMenuItem(self._parent_item)
		if self.bar and self.bar.parent:
				self.bar.parent.needmenubarredraw = 1
			
class PopupMenu(Menu):
	def __init__(self, bar):
		Menu.__init__(self, bar, '(popup)', -1)
		
	def popup(self, x, y, event, default=1, window=None):
		# NOTE that x and y are global coordinates, and they should probably
		# be topleft of the button the user clicked (not mouse-coordinates),
		# so the popup nicely overlaps.
		reply = self.menu.PopUpMenuSelect(x, y, default)
		if not reply:
			return
		id = (reply & 0xffff0000) >> 16
		item = reply & 0xffff
		if not window:
			wid = Win.FrontWindow()
			try:
				window = self.bar.parent._windows[wid]
			except:
				pass # If we can't find the window we pass None
		self.dispatch(id, item, window, event)

class MenuItem:
	def __init__(self, menu, title, shortcut=None, callback=None, kind=None):
		self.item = menu.additem(title, shortcut, callback)
		self.menu = menu
		
	def delete(self):
		self.menu.delitem(self.item)
		del self.menu
		del self.item
		
	def check(self, onoff):
		self.menu.menu.CheckMenuItem(self.item, onoff)

	def enable(self, onoff):
		if onoff:
			self.menu.menu.EnableMenuItem(self.item)
		else:
			self.menu.menu.DisableMenuItem(self.item)
			
	def settext(self, text):
		self.menu.menu.SetMenuItemText(self.item, text)
		
	def setstyle(self, style):
		self.menu.menu.SetItemStyle(self.item, style)
		
	def seticon(self, icon):
		self.menu.menu.SetItemIcon(self.item, icon)
		
	def setcmd(self, cmd):
		self.menu.menu.SetItemCmd(self.item, cmd)
		
	def setmark(self, cmd):
		self.menu.menu.SetItemMark(self.item, cmd)
		

class RadioItem(MenuItem):
	def __init__(self, menu, title, shortcut=None, callback=None):
		MenuItem.__init__(self, menu, title, shortcut, callback, 'radio')

class CheckItem(MenuItem):
	def __init__(self, menu, title, shortcut=None, callback=None):
		MenuItem.__init__(self, menu, title, shortcut, callback, 'check')

def Separator(menu):
	menu.addseparator()

def SubMenu(menu, label, title=''):
	return menu.addsubmenu(label, title)


class AppleMenu(Menu):
	
	def __init__(self, bar, abouttext="About me...", aboutcallback=None):
		Menu.__init__(self, bar, "\024")
		if MacOS.runtimemodel == 'ppc':
			self.additem(abouttext, None, aboutcallback)
			self.addseparator()
			self.menu.AppendResMenu('DRVR')
		else:
			# Additem()'s tricks do not work for "apple" menu under Carbon
			self.menu.InsertMenuItem(abouttext, 0)
			self.items.append((abouttext, None, aboutcallback, None))
	
	def dispatch(self, id, item, window, event):
		if item == 1:
			Menu.dispatch(self, id, item, window, event)
		elif MacOS.runtimemodel == 'ppc':
			name = self.menu.GetMenuItemText(item)
			OpenDeskAcc(name)

class Window:
	"""A single window belonging to an application"""
	
	def __init__(self, parent):
		self.wid = None
		self.parent = parent
		
	def open(self, bounds=(40, 40, 400, 400), resid=None):
		if resid <> None:
			self.wid = GetNewWindow(resid, -1)
		else:
			self.wid = NewWindow(bounds, self.__class__.__name__, 1,
				8, -1, 1, 0)	# changed to proc id 8 to include zoom box. jvr
		self.do_postopen()
		
	def do_postopen(self):
		"""Tell our parent we exist"""
		self.parent.appendwindow(self.wid, self)
		
	def close(self):
		self.do_postclose()
			
	def do_postclose(self):
		self.parent.removewindow(self.wid)
		self.parent = None
		self.wid = None
		
	def SetPort(self):
		# Convinience method
		SetPort(self.wid)
		
	def GetWindow(self):
		return self.wid
	
	def do_inDrag(self, partcode, window, event):
		where = event[3]
		window.DragWindow(where, self.draglimit)
	
	draglimit = screenbounds
	
	def do_inGoAway(self, partcode, window, event):
		where = event[3]
		if window.TrackGoAway(where):
			self.close()
	
	def do_inZoom(self, partcode, window, event):
		(what, message, when, where, modifiers) = event
		if window.TrackBox(where, partcode):
			window.ZoomWindow(partcode, 1)
			rect = window.GetWindowUserState()				# so that zoom really works... jvr
			self.do_postresize(rect[2] - rect[0], rect[3] - rect[1], window)	# jvr
	
	def do_inZoomIn(self, partcode, window, event):
		SetPort(window) # !!!
		self.do_inZoom(partcode, window, event)
	
	def do_inZoomOut(self, partcode, window, event):
		SetPort(window) # !!!
		self.do_inZoom(partcode, window, event)
	
	def do_inGrow(self, partcode, window, event):
		(what, message, when, where, modifiers) = event
		result = window.GrowWindow(where, self.growlimit)
		if result:
			height = (result>>16) & 0xffff	# Hi word
			width = result & 0xffff		# Lo word
			self.do_resize(width, height, window)
	
	growlimit = (50, 50, screenbounds[2] - screenbounds[0], screenbounds[3] - screenbounds[1])	# jvr
	
	def do_resize(self, width, height, window):
		l, t, r, b = self.wid.GetWindowPort().portRect			# jvr, forGrowIcon
		self.SetPort()							# jvr
		self.wid.InvalWindowRect((r - SCROLLBARWIDTH + 1, b - SCROLLBARWIDTH + 1, r, b))	# jvr
		window.SizeWindow(width, height, 1)		# changed updateFlag to true jvr
		self.do_postresize(width, height, window)
	
	def do_postresize(self, width, height, window):
		SetPort(window)
		self.wid.InvalWindowRect(window.GetWindowPort().portRect)
	
	def do_inContent(self, partcode, window, event):
		#
		# If we're not frontmost, select ourselves and wait for
		# the activate event.
		#
		if FrontWindow() <> window:
			window.SelectWindow()
			return
		# We are. Handle the event.
		(what, message, when, where, modifiers) = event
		SetPort(window)
		local = GlobalToLocal(where)
		self.do_contentclick(local, modifiers, event)
		
	def do_contentclick(self, local, modifiers, event):
		if DEBUG:
			print 'Click in contents at %s, modifiers %s'%(local, modifiers)
	
	def do_rawupdate(self, window, event):
		if DEBUG: print "raw update for", window
		SetPort(window)
		window.BeginUpdate()
		self.do_update(window, event)
		window.EndUpdate()
	
	def do_update(self, window, event):
		if DEBUG:
			import time
			for i in range(8):
				time.sleep(0.1)
				InvertRgn(window.GetWindowPort().visRgn)
			FillRgn(window.GetWindowPort().visRgn, qd.gray)
		else:
			EraseRgn(window.GetWindowPort().visRgn)
		
	def do_activate(self, activate, event):
		if DEBUG: print 'Activate %d for %s'%(activate, self.wid)
		
class ControlsWindow(Window):

	def do_rawupdate(self, window, event):
		if DEBUG: print "raw update for", window
		SetPort(window)
		window.BeginUpdate()
		self.do_update(window, event)
		#DrawControls(window)					# jvr
		UpdateControls(window, window.GetWindowPort().visRgn)	# jvr
		window.DrawGrowIcon()
		window.EndUpdate()
	
	def do_controlhit(self, window, control, pcode, event):
		if DEBUG: print "control hit in", window, "on", control, "; pcode =", pcode

	def do_inContent(self, partcode, window, event):
		if FrontWindow() <> window:
			window.SelectWindow()
			return
		(what, message, when, where, modifiers) = event
		SetPort(window)  # XXXX Needed?
		local = GlobalToLocal(where)
		pcode, control = FindControl(local, window)
		if pcode and control:
			self.do_rawcontrolhit(window, control, pcode, local, event)
		else:
			if DEBUG: print "FindControl(%s, %s) -> (%s, %s)" % \
				(local, window, pcode, control)
			self.do_contentclick(local, modifiers, event)
			
	def do_rawcontrolhit(self, window, control, pcode, local, event):
		pcode = control.TrackControl(local)
		if pcode:
			self.do_controlhit(window, control, pcode, event)
			
class ScrolledWindow(ControlsWindow):
	def __init__(self, parent):
		self.barx = self.bary = None
		self.barx_enabled = self.bary_enabled = 1
		self.activated = 1
		ControlsWindow.__init__(self, parent)

	def scrollbars(self, wantx=1, wanty=1):
		SetPort(self.wid)
		self.barx = self.bary = None
		self.barx_enabled = self.bary_enabled = 1
		x0, y0, x1, y1 = self.wid.GetWindowPort().portRect
		vx, vy = self.getscrollbarvalues()
		if vx == None: self.barx_enabled, vx = 0, 0
		if vy == None: self.bary_enabled, vy = 0, 0
		if wantx:
			rect = x0-1, y1-(SCROLLBARWIDTH-1), x1-(SCROLLBARWIDTH-2), y1+1
			self.barx = NewControl(self.wid, rect, "", 1, vx, 0, 32767, 16, 0)
			if not self.barx_enabled: self.barx.HiliteControl(255)
##			self.wid.InvalWindowRect(rect)
		if wanty:
			rect = x1-(SCROLLBARWIDTH-1), y0-1, x1+1, y1-(SCROLLBARWIDTH-2)
			self.bary = NewControl(self.wid, rect, "", 1, vy, 0, 32767, 16, 0)
			if not self.bary_enabled: self.bary.HiliteControl(255)
##			self.wid.InvalWindowRect(rect)
			
	def do_postclose(self):
		self.barx = self.bary = None
		ControlsWindow.do_postclose(self)
		
	def do_activate(self, onoff, event):
		self.activated = onoff
		if onoff:
			if self.barx and self.barx_enabled:
				self.barx.ShowControl()	# jvr
			if self.bary and self.bary_enabled:
				self.bary.ShowControl()	# jvr
		else:
			if self.barx:
				self.barx.HideControl()	# jvr; An inactive window should have *hidden*
							# scrollbars, not just dimmed (no matter what
							# BBEdit does... look at the Finder)
			if self.bary:
				self.bary.HideControl()	# jvr
		self.wid.DrawGrowIcon()			# jvr
			
	def do_postresize(self, width, height, window):
		l, t, r, b = self.wid.GetWindowPort().portRect
		self.SetPort()
		if self.barx:
			self.barx.HideControl()		# jvr
			self.barx.MoveControl(l-1, b-(SCROLLBARWIDTH-1))
			self.barx.SizeControl((r-l)-(SCROLLBARWIDTH-3), SCROLLBARWIDTH)	# jvr
		if self.bary:
			self.bary.HideControl()		# jvr
			self.bary.MoveControl(r-(SCROLLBARWIDTH-1), t-1)
			self.bary.SizeControl(SCROLLBARWIDTH, (b-t)-(SCROLLBARWIDTH-3))	# jvr
		if self.barx:
			self.barx.ShowControl()		# jvr
			self.wid.ValidWindowRect((l, b - SCROLLBARWIDTH + 1, r - SCROLLBARWIDTH + 2, b))	# jvr
		if self.bary:
			self.bary.ShowControl()		# jvr
			self.wid.ValidWindowRect((r - SCROLLBARWIDTH + 1, t, r, b - SCROLLBARWIDTH + 2))	# jvr
		self.wid.InvalWindowRect((r - SCROLLBARWIDTH + 1, b - SCROLLBARWIDTH + 1, r, b))	# jvr, growicon

			
	def do_rawcontrolhit(self, window, control, pcode, local, event):
		if control == self.barx:
			which = 'x'
		elif control == self.bary:
			which = 'y'
		else:
			return 0
		if pcode in (inUpButton, inDownButton, inPageUp, inPageDown):
			# We do the work for the buttons and grey area in the tracker
			dummy = control.TrackControl(local, self.do_controltrack)
		else:
			# but the thumb is handled here
			pcode = control.TrackControl(local)
			if pcode == inThumb:
				value = control.GetControlValue()
				print 'setbars', which, value #DBG
				self.scrollbar_callback(which, 'set', value)
				self.updatescrollbars()
			else:
				print 'funny part', pcode #DBG
		return 1
		
	def do_controltrack(self, control, pcode):
		if control == self.barx:
			which = 'x'
		elif control == self.bary:
			which = 'y'
		else:
			return

		if pcode == inUpButton:
			what = '-'
		elif pcode == inDownButton:
			what = '+'
		elif pcode == inPageUp:
			what = '--'
		elif pcode == inPageDown:
			what = '++'
		else:
			return
		self.scrollbar_callback(which, what, None)
		self.updatescrollbars()
		
	def updatescrollbars(self):
		SetPort(self.wid)
		vx, vy = self.getscrollbarvalues()
		if self.barx:
			if vx == None:
				self.barx.HiliteControl(255)
				self.barx_enabled = 0
			else:
				if not self.barx_enabled:
					self.barx_enabled = 1
					if self.activated:
						self.barx.HiliteControl(0)
				self.barx.SetControlValue(vx)
		if self.bary:
			if vy == None:
				self.bary.HiliteControl(255)
				self.bary_enabled = 0
			else:
				if not self.bary_enabled:
					self.bary_enabled = 1
					if self.activated:
						self.bary.HiliteControl(0)
				self.bary.SetControlValue(vy)
			
	# Auxiliary function: convert standard text/image/etc coordinate
	# to something palatable as getscrollbarvalues() return
	def scalebarvalue(self, absmin, absmax, curmin, curmax):
		if curmin <= absmin and curmax >= absmax:
			return None
		if curmin <= absmin:
			return 0
		if curmax >= absmax:
			return 32767
		perc = float(curmin-absmin)/float(absmax-absmin)
		return int(perc*32767)
			
	# To be overridden:
	
	def getscrollbarvalues(self):
		return 0, 0
		
	def scrollbar_callback(self, which, what, value):
		print 'scroll', which, what, value
	
class DialogWindow(Window):
	"""A modeless dialog window"""
	
	def open(self, resid):
		self.dlg = GetNewDialog(resid, -1)
		self.wid = self.dlg.GetDialogWindow()
		self.do_postopen()
		
	def close(self):
		self.do_postclose()
		
	def do_itemhit(self, item, event):
		print 'Dialog %s, item %d hit'%(self.dlg, item)
		
	def do_rawupdate(self, window, event):
		pass

def ostypecode(x):
	"Convert a long int to the 4-character code it really is"
	s = ''
	for i in range(4):
		x, c = divmod(x, 256)
		s = chr(c) + s
	return s


class TestApp(Application):
	
	"This class is used by the test() function"
	
	def makeusermenus(self):
		self.filemenu = m = Menu(self.menubar, "File")
		self.saveitem = MenuItem(m, "Save", "S", self.save)
		Separator(m)
		self.optionsmenu = mm = SubMenu(m, "Options")
		self.opt1 = CheckItem(mm, "Arguments", "A")
		self.opt2 = CheckItem(mm, "Being hit on the head lessons", (kMenuOptionModifier, "A"))
		self.opt3 = CheckItem(mm, "Complaints", (kMenuOptionModifier|kMenuNoCommandModifier, "A"))
		Separator(m)
		self.quititem = MenuItem(m, "Quit", "Q", self.quit)
	
	def save(self, *args):
		print "Save"
	
	def quit(self, *args):
		raise self


def test():
	"Test program"
	app = TestApp()
	app.mainloop()


if __name__ == '__main__':
	test()
