# copyright 1997-2001 Just van Rossum, Letterror. just@letterror.com

import Splash

import FrameWork
import Wapplication
import W
import os
import sys
import macfs
import MacOS

if MacOS.runtimemodel == 'macho':
	ELIPSES = '...'
else:
	ELIPSES = '\xc9'

def runningOnOSX():
	from gestalt import gestalt
	gestaltMenuMgrAquaLayoutBit = 1  # menus have the Aqua 1.0 layout
	gestaltMenuMgrAquaLayoutMask = (1L << gestaltMenuMgrAquaLayoutBit)
	value = gestalt("menu") & gestaltMenuMgrAquaLayoutMask
	return not not value


class PythonIDE(Wapplication.Application):
	
	def __init__(self):
		self.preffilepath = os.path.join("Python", "PythonIDE preferences")
		Wapplication.Application.__init__(self, 'Pide')
		from Carbon import AE
		from Carbon import AppleEvents
		
		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEOpenApplication, 
				self.ignoreevent)
		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEReopenApplication, 
				self.ignoreevent)
		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEPrintDocuments, 
				self.ignoreevent)
		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEOpenDocuments, 
				self.opendocsevent)
		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEQuitApplication, 
				self.quitevent)
		import PyConsole, PyEdit
		Splash.wait()
		# With -D option (OSX command line only) keep stderr, for debugging the IDE
		# itself.
		debug_stderr = None
		if len(sys.argv) >= 2 and sys.argv[1] == '-D':
			debug_stderr = sys.stderr
			del sys.argv[1]
		PyConsole.installoutput()
		PyConsole.installconsole()
		if debug_stderr:
			sys.stderr = debug_stderr
		for path in sys.argv[1:]:
			self.opendoc(path)
		try:
			import Wthreading
		except ImportError:
			self.mainloop()
		else:
			if Wthreading.haveThreading:
				self.mainthread = Wthreading.Thread("IDE event loop", self.mainloop)
				self.mainthread.start()
				#self.mainthread.setResistant(1)
				Wthreading.run()
			else:
				self.mainloop()
	
	def makeusermenus(self):
		m = Wapplication.Menu(self.menubar, "File")
		newitem = FrameWork.MenuItem(m, "New", "N", 'new')
		openitem = FrameWork.MenuItem(m, "Open"+ELIPSES, "O", 'open')
		FrameWork.Separator(m)
		closeitem = FrameWork.MenuItem(m, "Close", "W", 'close')
		saveitem = FrameWork.MenuItem(m, "Save", "S", 'save')
		saveasitem = FrameWork.MenuItem(m, "Save as"+ELIPSES, None, 'save_as')
		FrameWork.Separator(m)
		saveasappletitem = FrameWork.MenuItem(m, "Save as Applet"+ELIPSES, None, 'save_as_applet')
		if not runningOnOSX():
			# On OSX there's a special "magic" quit menu, so we shouldn't add
			# it to the File menu.
			FrameWork.Separator(m)
			quititem = FrameWork.MenuItem(m, "Quit", "Q", 'quit')
		
		m = Wapplication.Menu(self.menubar, "Edit")
		undoitem = FrameWork.MenuItem(m, "Undo", 'Z', "undo")
		FrameWork.Separator(m)
		cutitem = FrameWork.MenuItem(m, "Cut", 'X', "cut")
		copyitem = FrameWork.MenuItem(m, "Copy", "C", "copy")
		pasteitem = FrameWork.MenuItem(m, "Paste", "V", "paste")
		FrameWork.MenuItem(m, "Clear", None,  "clear")
		FrameWork.Separator(m)
		selallitem = FrameWork.MenuItem(m, "Select all", "A", "selectall")
		sellineitem = FrameWork.MenuItem(m, "Select line", "L", "selectline")
		FrameWork.Separator(m)
		finditem = FrameWork.MenuItem(m, "Find"+ELIPSES, "F", "find")
		findagainitem = FrameWork.MenuItem(m, "Find again", 'G', "findnext")
		enterselitem = FrameWork.MenuItem(m, "Enter search string", "E", "entersearchstring")
		replaceitem = FrameWork.MenuItem(m, "Replace", None, "replace")
		replacefinditem = FrameWork.MenuItem(m, "Replace & find again", 'T', "replacefind")
		FrameWork.Separator(m)
		shiftleftitem = FrameWork.MenuItem(m, "Shift left", "[", "shiftleft")
		shiftrightitem = FrameWork.MenuItem(m, "Shift right", "]", "shiftright")
		
		m = Wapplication.Menu(self.menubar, "Python")
		runitem = FrameWork.MenuItem(m, "Run window", "R", 'run')
		runselitem = FrameWork.MenuItem(m, "Run selection", None, 'runselection')
		FrameWork.Separator(m)
		moditem = FrameWork.MenuItem(m, "Module browser"+ELIPSES, "M", self.domenu_modulebrowser)
		FrameWork.Separator(m)
		mm = FrameWork.SubMenu(m, "Preferences")
		FrameWork.MenuItem(mm, "Set Scripts folder"+ELIPSES, None, self.do_setscriptsfolder)
		FrameWork.MenuItem(mm, "Editor default settings"+ELIPSES, None, self.do_editorprefs)
		FrameWork.MenuItem(mm, "Set default window font"+ELIPSES, None, self.do_setwindowfont)
		
		self.openwindowsmenu = Wapplication.Menu(self.menubar, 'Windows')
		self.makeopenwindowsmenu()
		self._menustocheck = [closeitem, saveitem, saveasitem, saveasappletitem,
				undoitem, cutitem, copyitem, pasteitem, 
				selallitem, sellineitem, 
				finditem, findagainitem, enterselitem, replaceitem, replacefinditem,
				shiftleftitem, shiftrightitem, 
				runitem, runselitem]
		
		prefs = self.getprefs()
		try:
			fss, fss_changed = macfs.RawAlias(prefs.scriptsfolder).Resolve()
			self.scriptsfolder = fss.NewAlias()
		except:
			path = os.path.join(os.getcwd(), ":Mac:IDE scripts")
			if not os.path.exists(path):
				path = os.path.join(os.getcwd(), "Scripts")
				if not os.path.exists(path):
					os.mkdir(path)
					f = open(os.path.join(path, "Place your scripts here"+ELIPSES), "w")
					f.close()
			fss = macfs.FSSpec(path)
			self.scriptsfolder = fss.NewAlias()
			self.scriptsfoldermodtime = fss.GetDates()[1]
		else:
			self.scriptsfoldermodtime = fss.GetDates()[1]
		prefs.scriptsfolder = self.scriptsfolder.data
		self._scripts = {}
		self.scriptsmenu = None
		self.makescriptsmenu()
	
	def quitevent(self, theAppleEvent, theReply):
		from Carbon import AE
		AE.AEInteractWithUser(50000000)
		self._quit()
	
	def suspendresume(self, onoff):
		if onoff:
			fss, fss_changed = self.scriptsfolder.Resolve()
			modtime = fss.GetDates()[1]
			if self.scriptsfoldermodtime <> modtime or fss_changed:
				self.scriptsfoldermodtime = modtime
				W.SetCursor('watch')
				self.makescriptsmenu()
	
	def ignoreevent(self, theAppleEvent, theReply):
		pass
	
	def opendocsevent(self, theAppleEvent, theReply):
		W.SetCursor('watch')
		import aetools
		parameters, args = aetools.unpackevent(theAppleEvent)
		docs = parameters['----']
		if type(docs) <> type([]):
			docs = [docs]
		for doc in docs:
			fss, a = doc.Resolve()
			path = fss.as_pathname()
			self.opendoc(path)
	
	def opendoc(self, path):
		fcreator, ftype = macfs.FSSpec(path).GetCreatorType()
		if ftype == 'TEXT':
			self.openscript(path)
		elif ftype == '\0\0\0\0' and path[-3:] == '.py':
			self.openscript(path)
		else:
			W.Message("Can't open file of type '%s'." % ftype)
	
	def getabouttext(self):
		return "About Python IDE"+ELIPSES
	
	def do_about(self, id, item, window, event):
		Splash.about()
	
	def do_setscriptsfolder(self, *args):
		fss, ok = macfs.GetDirectory("Select Scripts Folder")
		if ok:
			prefs = self.getprefs()
			alis = fss.NewAlias()
			prefs.scriptsfolder = alis.data
			self.scriptsfolder = alis
			self.makescriptsmenu()
			prefs.save()
	
	def domenu_modulebrowser(self, *args):
		W.SetCursor('watch')
		import ModuleBrowser
		ModuleBrowser.ModuleBrowser()
	
	def domenu_open(self, *args):
		fss, ok = macfs.StandardGetFile("TEXT")
		if ok:
			self.openscript(fss.as_pathname())
	
	def domenu_new(self, *args):
		W.SetCursor('watch')
		import PyEdit
		return PyEdit.Editor()
	
	def makescriptsmenu(self):
		W.SetCursor('watch')
		if self._scripts:
			for id, item in self._scripts.keys():
				if self.menubar.menus.has_key(id):
					m = self.menubar.menus[id]
					m.delete()
			self._scripts = {}
		if self.scriptsmenu:
			if hasattr(self.scriptsmenu, 'id') and self.menubar.menus.has_key(self.scriptsmenu.id):
				self.scriptsmenu.delete()
		self.scriptsmenu = FrameWork.Menu(self.menubar, "Scripts")
		#FrameWork.MenuItem(self.scriptsmenu, "New script", None, self.domenu_new)
		#self.scriptsmenu.addseparator()
		fss, fss_changed = self.scriptsfolder.Resolve()
		self.scriptswalk(fss.as_pathname(), self.scriptsmenu)
	
	def makeopenwindowsmenu(self):
		for i in range(len(self.openwindowsmenu.items)):
			self.openwindowsmenu.menu.DeleteMenuItem(1)
			self.openwindowsmenu.items = []
		windows = []
		self._openwindows = {}
		for window in self._windows.keys():
			title = window.GetWTitle()
			if not title:
				title = "<no title>"
			windows.append((title, window))
		windows.sort()
		for title, window in windows:
			if title == "Python Interactive":	# ugly but useful hack by Joe Strout
				shortcut = '0'
			else: 
				shortcut = None
			item = FrameWork.MenuItem(self.openwindowsmenu, title, shortcut, callback = self.domenu_openwindows)
			self._openwindows[item.item] = window
		self._openwindowscheckmark = 0
		self.checkopenwindowsmenu()
		
	def domenu_openwindows(self, id, item, window, event):
		w = self._openwindows[item]
		w.ShowWindow()
		w.SelectWindow()
	
	def domenu_quit(self):
		self._quit()
	
	def domenu_save(self, *args):
		print "Save"
	
	def _quit(self):
		import PyConsole, PyEdit
		PyConsole.console.writeprefs()
		PyConsole.output.writeprefs()
		PyEdit.searchengine.writeprefs()
		for window in self._windows.values():
			try:
				rv = window.close() # ignore any errors while quitting
			except:
				rv = 0   # (otherwise, we can get stuck!)
			if rv and rv > 0:
				return
		self.quitting = 1

PythonIDE()

