diff options
author | Jack Jansen <jack.jansen@cwi.nl> | 1998-08-18 14:59:10 (GMT) |
---|---|---|
committer | Jack Jansen <jack.jansen@cwi.nl> | 1998-08-18 14:59:10 (GMT) |
commit | cb5704e6a8f4a97d9fc5554df83fa88d058287b9 (patch) | |
tree | a2b6032cccb6d4ba130b07fa415d64d613d76e0c /Mac/Contrib/PyIDE-src/IDELib | |
parent | 7cc5735ef26a60df9d1bc3554c1912f951a90308 (diff) | |
download | cpython-cb5704e6a8f4a97d9fc5554df83fa88d058287b9.zip cpython-cb5704e6a8f4a97d9fc5554df83fa88d058287b9.tar.gz cpython-cb5704e6a8f4a97d9fc5554df83fa88d058287b9.tar.bz2 |
Initial revision
Diffstat (limited to 'Mac/Contrib/PyIDE-src/IDELib')
26 files changed, 7819 insertions, 0 deletions
diff --git a/Mac/Contrib/PyIDE-src/IDELib/PythonIDEMain.py b/Mac/Contrib/PyIDE-src/IDELib/PythonIDEMain.py new file mode 100644 index 0000000..4b14bcd --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/PythonIDEMain.py @@ -0,0 +1,224 @@ +# copyright 1997 Just van Rossum, Letterror. just@knoware.nl + +import Splash + +import FrameWork +import WFrameWorkPatch +import Win +import W +import os +import macfs + +class PythonIDE(WFrameWorkPatch.Application): + + def __init__(self): + self.preffilepath = ":Python:PythonIDE preferences" + WFrameWorkPatch.Application.__init__(self, 'Pyth') + import AE, AppleEvents + + AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEOpenApplication, + 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() + PyConsole.installconsole() + PyConsole.installoutput() + import sys + for path in sys.argv[1:]: + self.opendoc(path) + self.mainloop() + + def makeusermenus(self): + m = WFrameWorkPatch.Menu(self.menubar, "File") + newitem = FrameWork.MenuItem(m, "New", "N", 'new') + openitem = FrameWork.MenuItem(m, "Open", "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", None, 'save_as') + FrameWork.Separator(m) + quititem = FrameWork.MenuItem(m, "Quit", "Q", 'quit') + + m = WFrameWorkPatch.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", "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 = WFrameWorkPatch.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", "M", self.domenu_modulebrowser) + FrameWork.Separator(m) + mm = FrameWork.SubMenu(m, "Preferences") + FrameWork.MenuItem(mm, "Set Scripts folder", None, self.do_setscriptsfolder) + + self.openwindowsmenu = WFrameWorkPatch.Menu(self.menubar, 'Windows') + self.makeopenwindowsmenu() + self._menustocheck = [closeitem, saveitem, saveasitem, + undoitem, cutitem, copyitem, pasteitem, + selallitem, sellineitem, + finditem, findagainitem, enterselitem, replaceitem, replacefinditem, + shiftleftitem, shiftrightitem, + runitem, runselitem] + + prefs = self.getprefs() + if prefs.scriptsfolder: + fss, fss_changed = macfs.RawAlias(prefs.scriptsfolder).Resolve() + self.scriptsfolder = fss.NewAlias() + prefs.scriptsfolder = self.scriptsfolder.data + self.scriptsfoldermodtime = fss.GetDates()[1] + else: + path = os.path.join(os.getcwd(), 'Scripts') + if not os.path.exists(path): + os.mkdir(path) + fss = macfs.FSSpec(path) + self.scriptsfolder = fss.NewAlias() + self.scriptsfoldermodtime = fss.GetDates()[1] + self._scripts = {} + self.scriptsmenu = None + self.makescriptsmenu() + + def quitevent(self, theAppleEvent, theReply): + 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) + else: + W.Message("Canıt open file of type '%s'." % ftype) + + def getabouttext(self): + return "About Python IDE" + + 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: + item = FrameWork.MenuItem(self.openwindowsmenu, title, 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() + PyEdit.searchengine.writeprefs() + for window in self._windows.values(): + if window.close() > 0: + return + self.quitting = 1 + +PythonIDE() diff --git a/Mac/Contrib/PyIDE-src/IDELib/Resources/Widgets.rsrc.hqx b/Mac/Contrib/PyIDE-src/IDELib/Resources/Widgets.rsrc.hqx new file mode 100644 index 0000000..beb56e6 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Resources/Widgets.rsrc.hqx @@ -0,0 +1,89 @@ +(This file must be converted with BinHex 4.0) + +:$>C'GPG(-ZFR0bB`"bFh*M8P0&4!%!N!F5HcQ*!*!%!3!!!"%3!!!3%!!!!@X +*!!!!E'PZC@CTC@aNF`N!!!"6Bh*[E'aLBA*c"`!!!!aAD@4RCA4c,R*cFQ0bEfa +c)&"bC@Cc1'XJ-LiiBMGi!!"bFh*M8P0&4!%!rj!%!*!5X6"P#!#3"K*lEhKc#!! +!!'PZCQpdCAKdF`B!!!"#GA4dEfjc!`!!!(*eER-*!!!!FR9ZBR9dG'pZF``!!!" +bG@jcC@aPBh4TEfjc$!!!!(*eER0PE'*eG(4[ER-%!!!!BQPZC(-%!!!!F(9cD(- +0!!!!E@9ZG9pREh4[E'PZCA-*!!!!FfKTCR4XC3!!!-3!a!#3"3X!#`!4![m-!2r +q!!!!5!!!!%J!N!F,!!X!N!8"!!S!N!8,!!X!N!#!"!#3"3X!#`#3#8J!!!")!*! +&!J!"!!)!N!e(IP3!!!!#!!$rN!B!!Cb3"2rr!!)!N!X,!!X!N!8,!!X!!!#!!!! +!S!!!!*J!!!#'!!!!NB!!!)4J!!#4J!!!KJ!!!*J!!!#J!!!!J!!!!2m!!!$%!-3 +!N!8,!!X!%3,r$!$rrJ!!!%J!!!")!*!(#`!,!*!&!3!+!*!&#`!,!*!!J!3!N!8 +,!!X!N!P)!!!!5!#3"3)!!3!#!*!04hq$!!!!!J!!rj!'!!'FN!6rr`!#!*!,#`! +,!*!&#`!,!*!1UUUS!#4%B!!*%B!!!NB!!!#B!!!!)!#3#rm!!!",!%X!N!8,!!X +4!3%!#J#3"3X!#j!!!!)!N!8,!!X!N!8,!!X!N!8,!!X!!!J!$!!1!!m!$i!2`!q +!$`!1!!`!#!$r!!!!5`",!*!&#`!,%3%"!!S!N!8,!!Z3!!!#!*!&#`!,!*!&#`! +,!*!&#`!,!*!)rq"r`$q!(`!1!!3!N!Ar!!!!53"*!*!&#J!+%3%"!!S!N!8+!!U +3!!!#!*!&#J!+!*!&#J!+!*!&#J!+!!!3!"J!(!!H!"m!(`!H!"`!'!!3!2m!!!" +*!%N!N!8+!!S4!3%!#J#3"3S!#T!!!!)!N!8+!!S!N!8+!!S!N!8+!!S!N!Mr`(q +!2`!H!!`!N!Ar!!!#bQ!1!!"-4%9'!)!!N!C"q[rZ6R&1F@!!!!*19J!!,`XQEJ! +)-#i!'QF1DejA3'G5DPK53'SXB!S[#dkk!'*BMf"),`Xr,J!-2bi!$LmZ!"![,J! +8(bi!'%kk!&T2l`!5B#J[#cmZ!!`r,J!1,bi!%#mZ!"3I,J!B6VS"d%r[!"*J##m +,6VS#,&L2*Pp1AL"I6qm!&%l3K'eKD@i!!!"19J!!6Pj1GBT0H8a%48C*EQPd!!! +!6PEr[NMR(c!q,J!5*Qi!#L4Z!"C#E[r-I!"#E[r+5'lrr+Kd)&)[+!!)U(0#TkM +B+Km["DKk,`ZSHdKZrqUSQ+LH,`ZSSdKZrpDS05JZrpC`%1#N)#lrfR)3iU!Y32r +1)LlrhR33j+%Y3Ir5d)63J5e!rmBJ5U!T5Qi!&'F!!,Jf"f!5)&)JD!"3)&!--!! +0-!"R$&*$-#i!&0"(X%0Zj$!$N!"(28$rc$`Z!"6F4ja$8dCb!G*$28(rbR3%e'X +!!Mm#0"284$m#U*-J8L"S!&![%$m(2blrc+L&5NC[*(!%d'X!!Mm!-"2340"ZrmJ +r!+L6)&)JD!"3,a!r,[r+2`DSK8KZrlj)HJ"mU'C)E[qqU*dr+`!#-#lrb0"!d&0 +53$m!U*-r+`!'-#lrb0"!d&053$m!U*%J5U!U5Li!#'FD,`Sr,J!82`F[,J!1,`X +I,J!)6VS!3Nr[!")[,[rmU(-["DKj,`@Sf8KZrqUSQ8cI$2K1ANjeLNej6%4&4N4 +bBAF!!")3-C!3!%j@rqS[#dKZrrbSG#"Z!"BJ8#mS!!LSFd+RU0JQAbm,U(S[,J! ++U(Y)E[rUU*LSRMmm!$+SR#mZ!!USSLmZrrbSFbm,U(N[#kMC5'lrkULC*Pp1ANj +eMdej6%4&4NKTCfKXD@GSG!!!6PB!!%jH6R@,6AP-4%9'3fa[Ff8!N!9%!B!DF#C +)*NS564**D!QB!BJ#3!)J!L!%%!3)#!3)"!J"J"[`2rJrqKrr(rp[rj!%rRrq2ri +rr"rm$rJ(q!Ii!!N!#!!!!%3!N!30J"*`%N`55LJ++!*)!N!#)!)J""!%#!J%#!3 +)!*!%$B!Im"rm(rirrMrqIrjrrMrq2r`Ir!ri"rJ(q!!*!!J!!!"%!!!"J!'!!B! +"J"')-BarrM'-%BJ"J!'!!B!"J!#3"!2!!m!$`!2!'pJlh(rqrrprrM[F'pJ$`!2 +!!m!$`!!!!!F!"`!!!2)!N!5!"!#3"4!!%!#3#8J!!!")!*!&!J!"!!)!N"%#!*! +&%!!3!*!&!J#3"4!!%!#3#!)!!`!$J!2!!q!$m!2J!m!$J!-!!J#3#`)!!`!#J!* +!!L!#%!)J!N!#J!-!!J#3$J)!!2q3"J!"QC!%rrm!!`#3$``!!!!2!!!!$F!!!!a +`!!!0(!!!$%F!!!dF!!!-F!!!$F!!!!m!!!!-!*!4mJ#3")!%!*!&%!!3!*!*5!! +!!%J!N!8#!!%!!J#3%3)!N!83!"!!N!8#!*!&%!!3!*!12rJIm!rJ"m!$J!%!N"8 +rq"!3##!%3!+!!3#3%J)!!2q3"J!"QC!%rrm!!`#3'Jrrrm!$4%F!!0%F!!!dF!! +!$F!!!!-!N"R+!*!%J!)!N!83!"!!N!P)!!!!5!#3"3%!!3!"!*!4!J#3"4!!%!# +3"3)!N!83!"!!N!J#!!-!!i!$`!2J!r!$i!2!!i!$!!)!N!X#!!-!!i!$`!2J!r! +$i!2!!i!$!!)!N!i"!!$rN!B!!3#3#J)!!`!$J!2!!q!$m!2J!m!$J!-!!J#3#XS +!N!5!!J#3"4!!%!#3#8J!!!")!*!&!3!"!!%!N"%#!*!&%!!3!*!&!J#3"4!!%!# +3$Mri(r!2i!I!!i!"!*!92rJIm!rJ"m!$J!%!N")"!!$rN!B!!3#3%$ri(r!2i!I +!!i!"!*!0"FjJ#J!!6%4&4J(A!!"1qJ9'6R919[r'51FI-#4Z!!Jk,J!-1#i!$LC +Z!"!-4!!"E!K#8h!"B!!"L%KZrrbSG#"Zrr`@+!"'98m[#N*R2`@SKM!I2!"+4QF +%[%4Z#$D&F!"J!!&FF!!3!`"!!#!r!+L)98m[#N*R2`@SKM!I2!#m4'i)0S9`!@! +!!6B-4J!"E!K#8h!"B!!"+$e'rmC)E[r'5'lraMmm)!kTkdKZrmC)E[r'2c`3%+R +V286rd%KZrp")E[r32c`J$URV5'lrd%KZrp!r2"!3UHXp4IrD5'lrfNKZrpSr2#! +1UHY)E[rD5'lrfMmm%"#TkdKZrpT)E[rN2c`3$URV5'lrd%KZrq3r2"!%UHY)E[r +'5'lrj$mm%!DTkdKZrq4)E[rZ2c`3%+RV5'lrlNKZrr)r2"!1UHY)E[rb2c`!&UR +V5'lrmNKZrr)r2#J3UHXf,[rd98p"qJ"f5&#SM$!I2J"+3fi%GJ"J5P92,`T#Ccm +$U)B`(p"(2!"96bm+3QF`!e*!2`#SKM!Id%Fk!,a%EJbi4@i)Z%9Q'P*$B"Dm4'm +#8d0+3fi%GJ"J#,T%E,*53f#Z0S0`!8cI$2K1ANjeLh4bG@jMFh4bD@jR!!)"b8j +@rrj)ja``*Qi!#$BZ!!`NEJ!11#S!"TKU!!)JEJ!8)&!JD!!)'LJ!4M!U!!*83$m +!-",3EJ!52`#SNdKZrri`"&G!2`!r!bm,6VVpm%S!6qm!$'FJ,`Y#CcmZrrkSKEC +Zrrj["MmmrmQSJh!!%!8r!+L)B!J[#d*R2`1SK8cI$$K1ANjeM%4bBAG8CAKd3f9 +XE!!!!%j@rkj)jam`*Qi!$$JZ!"BU,J!B5'lraUKd)%8J8#mS!!LSFeP2U0JJAbe +)rqi[,[rZU(S[#kKl5'lrY+LBU*j+,J!)CJ!#(Lm,U+0)E[rDU$8J,[rDFK$LS#e +!rr)Q,[rHiU-X,[rLiUBZ!0k$hSB-4!!'E3!"EL"&)&!YD!"3rp3JE[r8S#NNE[r +8*&,8lJ!829,rdMeU!!,rXMeU!!6rf&b+A83Y5[qZ2!3Z#N*ZrrC+E[r5CeTC6cm +Zrp+U(L"I*JK+JfG+)%-J8#eS!!Erq#eS!!Vrr%KZrrJr+`!#2a1SU%KZrrK#Cc! +Zrrb3!'lrq#"&)&!b+!!3NN!`!H")lNM33H*!2`#SU%KZrrJ[!kSIGJ"J(J`b!!N +`!'B82!053b"+d--Z#$!%N!"$28$rpQ!'8N1f4'hH5NCY!!#J)%8J8(!3d'J!!Y" +Zrl)h3!!#)%8J8$!S!!,3E[rB0d!!"L"&)&!`+`!'X'J!"Qm+)%8J8$GS!!B!"M! +V!!+`D`!'E"B["6mZrr3[#cm',blrVNkkrGK2l`!3)%8J8$!S!!,3E[rB0d!!!L" +&)&!hD!!'!!B`+`!#X'X!"Q`@,`8r,[rd,`Xr,[rf,`G1Z[fH6qm!%#"&)&!hD!! +'!!BJE[r8S#TJ(NT%CaS["6mZrr3[#cmm!!0"qJ$+5&"1Z[eZ6qm!%#e6rrJYD`! +%rr`J45"3-#J!!Y"ZrpK63$e!rrT53$e!rriJ45"3##J!!!!4C`J),J!!rrPR$NK +ZrmT"qJ#'5&#SCQ!-5'lrbN(k!)T)8+KQ5'lrbULG3QHSR%KZrrLSSULH5Li!#QB +'5Li!#'FL)%8J8(!3d'J!!MG!!!)J45"30fJ!"J!'2c`!-ULF,`ZSSLmZrmDSFbm +ZrqkSH5mZrqkSf8KZrl5SQ8cI$2K1ANjeLNej6%4&4N4bBAF!!#Jr2cm!%'CQ-$" +QCM!`CQB`-'CQ-$!!%$!`CQB`-'CQ-$"QCM!`CQB!6PB!!%MR($!D,J!B*Qi!&$J +Z!!if,J!-*'i!#$!Z!"TR3P0!C`T63'FJ8d"R0Q!d,`Sr!cm%,bi!%#m,(`9#*dk +kr0C2l`!8B"S[#Mm$2`3[,J!3,`XI"4mm!!&1Z[bk6qm!&%cI$$K1AL"I6qm!&%l +3K'eKD@i!N!C%!!!"!!1!"m!"!!%!!3"rr(rm!3!"!!%!"m!$J!%!!!!"!!1!"m! +2i!rJ!i$rr[rqrrlrrJ1!$q!2i!I!!i!"!!!(!!F!!!%!!!!4%!!!%"!!!!&V"cG +,$#RH!!!!(!$q!!035808!!8!)Na%48B!!3"U3e958`!$!)*MD@0Z!!-!XJ(8!!` +!N!J"e3!B!!!!b!#3"!(@!#)!!!'3!!#3"!(A!$-!!!(I!*!%!GJ!3J!!!Li!N!3 +"f3"0!!!#H`#3"!(8!!!J!!,)!*!%!GF!B3!!#IB!N!3"e!"A)!!&PJ#3"!(9!&` +J!!AH!*!%!GErr`!!"LB!N!3"errr!!!2b!#3"!(8rrm!!!CZ!*!%!GArr`!!"f3 +!N!3"e[rr!!!)@J#3"!(Arrm!!!NS!*!%#e4hEdaTEQ9-4%9'#f0XEh0PC'&bFQp +h#@p`C@jKFR*[Ga"ME'pcC@4KFR*[Gh0[E'PN$Qp`C@jKFR*[Gh0[E'PN#Q&bFQp +hFQPRD(3*BA*bEhGNEhGZ"%KKEQ3%4QPcG!Y#FQphFf9b6%4&4V4I: diff --git a/Mac/Contrib/PyIDE-src/IDELib/Splash.py b/Mac/Contrib/PyIDE-src/IDELib/Splash.py new file mode 100644 index 0000000..99a36fa --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Splash.py @@ -0,0 +1,162 @@ +import Dlg +import Res + +splash = Dlg.GetNewDialog(468, -1) +splash.DrawDialog() + +import Qd, TE, Fm, sys + +_real__import__ = None + +def install_importhook(): + global _real__import__ + import __builtin__ + if _real__import__ is None: + _real__import__ = __builtin__.__import__ + __builtin__.__import__ = my__import__ + +def uninstall_importhook(): + global _real__import__ + if _real__import__ is not None: + import __builtin__ + __builtin__.__import__ = _real__import__ + _real__import__ = None + +_progress = 0 + +def importing(module): + global _progress + Qd.SetPort(splash) + fontID = Fm.GetFNum("Python-Sans") + if not fontID: + fontID = geneva + Qd.TextFont(fontID) + Qd.TextSize(9) + rect = (35, 260, 365, 276) + if module: + TE.TETextBox('Importing: ' + module, rect, 0) + if not _progress: + Qd.FrameRect((35, 276, 365, 284)) + pos = min(36 + 330 * _progress / 44, 364) + Qd.PaintRect((36, 277, pos, 283)) + _progress = _progress + 1 + else: + Qd.EraseRect(rect) + Qd.PaintRect((36, 277, pos, 283)) + +def my__import__(name, globals=None, locals=None, fromlist=None): + try: + return sys.modules[name] + except KeyError: + try: + importing(name) + except: + try: + rv = _real__import__(name) + finally: + uninstall_importhook() + return rv + return _real__import__(name) + +install_importhook() + +kHighLevelEvent = 23 +import Win +from Fonts import * +from QuickDraw import * +from TextEdit import * +import string +import sys +import random + +_keepsplashscreenopen = 0 + +abouttext1 = """The Python Integrated Developement Environment for the Macintosh +Version: %s +Copyright 1997 Just van Rossum, Letterror. <just@knoware.nl> + +Python %s +%s +Written by Guido van Rossum with Jack Jansen (and others) + +See: <http://www.python.org/> for information and documentation.""" + +flauwekul = [ 'Goodday, Bruce.', + 'Whatıs new?', + 'Nudge, nudge, say no more!', + 'No, no sir, itıs not dead. Itıs resting.', + 'Albatros!', + 'Itıs . . .', + 'Is your name not Bruce, then?', + """But Mr F.G. Superman has a secret identity . . . +when trouble strikes at any time . . . +at any place . . . he is ready to become . . . +Bicycle Repair Man!""" + ] + +def nl2return(text): + return string.join(string.split(text, '\n'), '\r') + +def UpdateSplash(drawdialog = 0, what = 0): + if drawdialog: + splash.DrawDialog() + drawtext(what) + Win.ValidRect(splash.GetWindowPort().portRect) + +def drawtext(what = 0): + Qd.SetPort(splash) + fontID = Fm.GetFNum("Python-Sans") + if not fontID: + fontID = geneva + Qd.TextFont(fontID) + Qd.TextSize(9) + rect = (10, 125, 390, 260) + if not what: + import __main__ + abouttxt = nl2return(abouttext1 \ + % (__main__.__version__, sys.version, sys.copyright)) + else: + abouttxt = nl2return(random.choice(flauwekul)) + TE.TETextBox(abouttxt, rect, teJustCenter) + +UpdateSplash(1) + +def wait(): + import Evt + from Events import * + global splash + try: + splash + except NameError: + return + Qd.InitCursor() + time = Evt.TickCount() + whattext = 0 + while _keepsplashscreenopen: + ok, event = Evt.EventAvail(highLevelEventMask) + if ok: + # got apple event, back to mainloop + break + ok, event = Evt.EventAvail(mDownMask | keyDownMask | updateMask) + if ok: + ok, event = Evt.WaitNextEvent(mDownMask | keyDownMask | updateMask, 30) + if ok: + (what, message, when, where, modifiers) = event + if what == updateEvt: + if Win.WhichWindow(message) == splash: + UpdateSplash(1, whattext) + else: + break + if Evt.TickCount() - time > 360: + whattext = not whattext + drawtext(whattext) + time = Evt.TickCount() + del splash + #Res.CloseResFile(splashresfile) + +def about(): + global splash, splashresfile, _keepsplashscreenopen + _keepsplashscreenopen = 1 + splash = Dlg.GetNewDialog(468, -1) + splash.DrawDialog() + wait() diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/FontSettings.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/FontSettings.py new file mode 100644 index 0000000..0a331df --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/FontSettings.py @@ -0,0 +1,139 @@ +"""usage: +newsettings = print FontDialog(('Chicago', 0, 12, (0, 0, 0))) # font name or id, style flags, size, color (color is ignored) +if newsettings: + font, style, size, color = newsettings # 'font' is always the font name, not the id number + # do something +""" + +import W +import PyEdit +import TextEdit +import string +import types + +_stylenames = ["Plain", "Bold", "Italic", "Underline", "Outline", "Shadow", "Condensed", "Extended"] + + +class _FontDialog: + + def __init__(self, fontsettings): + leftmargin = 46 + self.w = W.ModalDialog((440, 180), 'Font settings') + self.w.fonttitle = W.TextBox((10, 12, 30, 14), "Font:", TextEdit.teJustRight) + self.w.pop = W.FontMenu((leftmargin, 10, 16, 16), self.setfont) + self.w.fontname = W.TextBox((leftmargin + 20, 12, 150, 14)) + self.w.sizetitle = W.TextBox((10, 38, 30, 14), "Size:", TextEdit.teJustRight) + self.w.sizeedit = W.EditText((leftmargin, 35, 40, 20), "", self.checksize) + styletop = 64 + self.w.styletitle = W.TextBox((10, styletop + 2, 30, 14), "Style:", TextEdit.teJustRight) + for i in range(len(_stylenames)): + top = styletop + (i % 4) * 20 + left = leftmargin + 80 * (i > 3) - 2 + if i: + self.w[i] = W.CheckBox((left, top, 76, 16), _stylenames[i], self.dostyle) + else: + self.w[i] = W.CheckBox((left, top, 70, 16), _stylenames[i], self.doplain) + self.w.cancelbutton = W.Button((-180, -26, 80, 16), "Cancel", self.cancel) + self.w.donebutton = W.Button((-90, -26, 80, 16), "Done", self.done) + + sampletext = "Sample text." + self.w.sample = W.EditText((230, 10, -10, 130), sampletext, fontsettings = fontsettings) + + self.w.setdefaultbutton(self.w.donebutton) + self.w.bind('cmd.', self.w.cancelbutton.push) + self.w.bind('cmdw', self.w.donebutton.push) + self.lastsize = fontsettings[2] + self._rv = None + self.set(fontsettings) + self.w.open() + + def set(self, fontsettings): + font, style, size, color = fontsettings + if type(font) <> types.StringType: + import Res + res = Res.GetResource('FOND', font) + font = res.GetResInfo()[2] + self.w.fontname.set(font) + self.w.sizeedit.set(str(size)) + if style: + for i in range(1, len(_stylenames)): + self.w[i].set(style & 0x01) + style = style >> 1 + else: + self.w[0].set(1) + + def get(self): + font = self.w.fontname.get() + style = 0 + if not self.w[0].get(): + flag = 0x01 + for i in range(1, len(_stylenames)): + if self.w[i].get(): + style = style | flag + flag = flag << 1 + size = self.lastsize + return (font, style, size, (0, 0, 0)) + + def doit(self): + if self.w[0].get(): + style = 0 + else: + style = 0 + for i in range(1, len(_stylenames)): + if self.w[i].get(): + style = style | 2 ** (i - 1) + #self.w.sample.set(`style`) + self.w.sample.setfontsettings(self.get()) + + def checksize(self): + size = self.w.sizeedit.get() + if not size: + return + try: + size = string.atoi(size) + except (ValueError, OverflowError): + good = 0 + else: + good = 1 <= size <= 500 + if good: + if self.lastsize <> size: + self.lastsize = size + self.doit() + else: + # beep! + self.w.sizeedit.set(`self.lastsize`) + self.w.sizeedit.selectall() + + def doplain(self): + for i in range(1, len(_stylenames)): + self.w[i].set(0) + self.w[0].set(1) + self.doit() + + def dostyle(self): + for i in range(1, len(_stylenames)): + if self.w[i].get(): + self.w[0].set(0) + break + else: + self.w[0].set(1) + self.doit() + + def cancel(self): + self.w.close() + + def done(self): + self._rv = self.get() + self.w.close() + + def setfont(self, fontname): + self.w.fontname.set(fontname) + self.doit() + + +def FontDialog(fontsettings): + fd = _FontDialog(fontsettings) + return fd._rv + +def test(): + print FontDialog(('Zapata-Light', 0, 25, (0, 0, 0))) diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/MacPrefs.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/MacPrefs.py new file mode 100644 index 0000000..caf71b8 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/MacPrefs.py @@ -0,0 +1,109 @@ +import macfs +import marshal +import os +import macostools +import types + +kOnSystemDisk = 0x8000 + + +class PrefObject: + + def __init__(self, dict = None): + if dict == None: + self._prefsdict = {} + else: + self._prefsdict = dict + + def __len__(self): + return len(self._prefsdict) + + def __delattr__(self, attr): + if self._prefsdict.has_key(attr): + del self._prefsdict[attr] + else: + raise AttributeError, 'delete non-existing instance attribute' + + def __getattr__(self, attr): + if attr == '__members__': + keys = self._prefsdict.keys() + keys.sort() + return keys + try: + return self._prefsdict[attr] + except KeyError: + raise AttributeError, attr + + def __setattr__(self, attr, value): + if attr[0] <> '_': + self._prefsdict[attr] = value + else: + self.__dict__[attr] = value + + def getprefsdict(self): + return self._prefsdict + + +class PrefFile(PrefObject): + + def __init__(self, path, creator = 'Pyth'): + # Find the preferences folder and our prefs file, create if needed. + self.__path = path + self.__creator = creator + self._prefsdict = {} + try: + prefdict = marshal.load(open(self.__path, 'rb')) + except IOError: + pass + else: + for key, value in prefdict.items(): + if type(value) == types.DictType: + self._prefsdict[key] = PrefObject(value) + else: + self._prefsdict[key] = value + + def save(self): + prefdict = {} + for key, value in self._prefsdict.items(): + if type(value) == types.InstanceType: + prefdict[key] = value.getprefsdict() + if not prefdict[key]: + del prefdict[key] + else: + prefdict[key] = value + marshal.dump(prefdict, open(self.__path, 'wb')) + fss = macfs.FSSpec(self.__path) + fss.SetCreatorType(self.__creator, 'pref') + + def __getattr__(self, attr): + if attr == '__members__': + keys = self._prefsdict.keys() + keys.sort() + return keys + try: + return self._prefsdict[attr] + except KeyError: + if attr[0] <> '_': + self._prefsdict[attr] = PrefObject() + return self._prefsdict[attr] + else: + raise AttributeError, attr + + +_prefscache = {} + +def GetPrefs(prefname, creator = 'Pyth'): + if _prefscache.has_key(prefname): + return _prefscache[prefname] + # Find the preferences folder and our prefs file, create if needed. + vrefnum, dirid = macfs.FindFolder(kOnSystemDisk, 'pref', 0) + prefsfolder_fss = macfs.FSSpec((vrefnum, dirid, '')) + prefsfolder = prefsfolder_fss.as_pathname() + path = os.path.join(prefsfolder, prefname) + head, tail = os.path.split(path) + # make sure the folder(s) exist + macostools.mkdirs(head) + + preffile = PrefFile(path, creator) + _prefscache[prefname] = preffile + return preffile diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/ModuleBrowser.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/ModuleBrowser.py new file mode 100644 index 0000000..67685b8 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/ModuleBrowser.py @@ -0,0 +1,164 @@ +import W +import sys + +__version__ = "0.2" +__author__ = "jvr" + +class _modulebrowser: + + def __init__(self): + self.editmodules = [] + self.modules = [] + self.window = W.Window((194, 1000), "Module Browser", minsize = (194, 160), maxsize = (340, 20000)) + + self.window.openbutton = W.Button((10, 8, 80, 16), "Open", self.openbuttonhit) + self.window.browsebutton = W.Button((100, 8, 80, 16), "Browse", self.browsebuttonhit) + self.window.reloadbutton = W.Button((10, 32, 80, 16), "Reload", self.reloadbuttonhit) + self.window.openotherbutton = W.Button((100, 32, 80, 16), "Open other", self.openother) + + self.window.openbutton.enable(0) + self.window.reloadbutton.enable(0) + self.window.browsebutton.enable(0) + self.window.setdefaultbutton(self.window.browsebutton) + + self.window.bind("cmdr", self.window.reloadbutton.push) + self.window.bind("cmdb", self.window.browsebutton.push) + + self.window.bind("<activate>", self.activate) + self.window.bind("<close>", self.close) + + self.window.list = W.List((-1, 56, 1, -14), [], self.listhit) + + self.window.open() + self.checkbuttons() + + def close(self): + global _browser + _browser = None + + def activate(self, onoff): + if onoff: + self.makelist() + + def listhit(self, isdbl): + self.checkbuttons() + if isdbl: + if self.window._defaultbutton: + self.window._defaultbutton.push() + + def checkbuttons(self): + sel = self.window.list.getselection() + if sel: + for i in sel: + if self.editmodules[i]: + self.window.openbutton.enable(1) + self.window.reloadbutton.enable(1) + self.window.setdefaultbutton(self.window.openbutton) + break + else: + self.window.openbutton.enable(0) + self.window.reloadbutton.enable(0) + self.window.setdefaultbutton(self.window.browsebutton) + self.window.browsebutton.enable(1) + else: + #self.window.setdefaultbutton(self.window.browsebutton) + self.window.openbutton.enable(0) + self.window.reloadbutton.enable(0) + self.window.browsebutton.enable(0) + + def openbuttonhit(self): + import imp + sel = self.window.list.getselection() + W.SetCursor("watch") + for i in sel: + modname = self.window.list[i] + try: + self.openscript(sys.modules[modname].__file__, modname) + except IOError: + try: + file, path, description = imp.find_module(modname) + except ImportError: + W.SetCursor("arrow") + W.Message("Canıt find file for module ³%s²." + % modname) + else: + self.openscript(path, modname) + + def openscript(self, path, modname): + if path[-3:] == '.py': + W.getapplication().openscript(path) + else: + W.Message("Canıt edit ³%s²; it might be a shared library or a .pyc file." + % modname) + + def openother(self): + import imp + import EasyDialogs + + modname = EasyDialogs.AskString("Open module:") + if modname: + try: + file, path, description = imp.find_module(modname) + except ImportError: + if modname in sys.builtin_module_names: + alerttext = "³%s² is a builtin module, which you canıt edit." % modname + else: + alerttext = "No module named ³%s²." % modname + raise W.AlertError, alerttext + self.openscript(path, modname) + + def reloadbuttonhit(self): + sel = self.window.list.getselection() + W.SetCursor("watch") + for i in sel: + m = sys.modules[self.window.list[i]] + reload(m) + + def browsebuttonhit(self): + sel = self.window.list.getselection() + if not sel: + return + import PyBrowser + for i in sel: + PyBrowser.Browser(sys.modules[self.window.list[i]]) + + def makelist(self): + editmodules, modules = getmoduleslist() + if modules == self.modules: + return + self.editmodules, self.modules = editmodules, modules + self.window.list.setdrawingmode(0) + sel = self.window.list.getselectedobjects() + self.window.list.set(self.modules) + self.window.list.setselectedobjects(sel) + self.window.list.setdrawingmode(1) + + +def getmoduleslist(): + import PyBrowser # for caselesssort function + modules = sys.modules.keys() + modules = PyBrowser.caselesssort(modules) + editmodules = [] + sysmodules = sys.modules + modulesappend = editmodules.append + for m in modules: + module = sysmodules[m] + try: + if sysmodules[m].__file__[-3:] == '.py': + modulesappend(1) + else: + modulesappend(0) + except AttributeError: + modulesappend(0) + return editmodules, modules + + + +_browser = None + +def ModuleBrowser(): + global _browser + if _browser is not None: + _browser.window.select() + else: + _browser = _modulebrowser() diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/ProfileBrowser.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/ProfileBrowser.py new file mode 100644 index 0000000..710481c --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/ProfileBrowser.py @@ -0,0 +1,82 @@ +import W +import Evt + +import sys +import StringIO +import string + +def timer(TickCount = Evt.TickCount): + return TickCount() / 60.0 + +class ProfileBrowser: + + def __init__(self, stats = None): + self.sortkeys = ('calls',) + self.setupwidgets() + self.setstats(stats) + + def setupwidgets(self): + self.w = W.Window((580, 400), "Profile Statistics", minsize = (200, 100), tabbable = 0) + self.w.divline = W.HorizontalLine((0, 20, 0, 0)) + self.w.titlebar = W.TextBox((4, 4, 40, 12), 'Sort by:') + self.buttons = [] + self.w.button_calls = W.RadioButton((54, 4, 45, 12), 'calls', self.buttons, self.setsort) + self.w.button_time = W.RadioButton((104, 4, 40, 12), 'time', self.buttons, self.setsort) + self.w.button_cumulative = W.RadioButton((154, 4, 75, 12), 'cumulative', self.buttons, self.setsort) + self.w.button_stdname = W.RadioButton((234, 4, 60, 12), 'stdname', self.buttons, self.setsort) + self.w.button_calls.set(1) + self.w.button_file = W.RadioButton((304, 4, 40, 12), 'file', self.buttons, self.setsort) + self.w.button_line = W.RadioButton((354, 4, 50, 12), 'line', self.buttons, self.setsort) + self.w.button_module = W.RadioButton((404, 4, 55, 12), 'module', self.buttons, self.setsort) + self.w.button_name = W.RadioButton((464, 4, 50, 12), 'name', self.buttons, self.setsort) +## self.w.button_nfl = W.RadioButton((4, 4, 12, 12), 'nfl', self.buttons, self.setsort) +## self.w.button_pcalls = W.RadioButton((4, 4, 12, 12), 'pcalls', self.buttons, self.setsort) + self.w.text = W.TextEditor((0, 21, -15, -15), inset = (6, 5), + readonly = 1, wrap = 0, fontsettings = ('Monaco', 0, 9, (0, 0, 0))) + self.w._bary = W.Scrollbar((-15, 20, 16, -14), self.w.text.vscroll, max = 32767) + self.w._barx = W.Scrollbar((-1, -15, -14, 16), self.w.text.hscroll, max = 32767) + self.w.open() + + def setstats(self, stats): + self.stats = stats + self.stats.strip_dirs() + self.displaystats() + + def setsort(self): + # Grmpf. The callback doesn't give us the button:-( + for b in self.buttons: + if b.get(): + if b._title == self.sortkeys[0]: + return + self.sortkeys = (b._title,) + self.sortkeys[:3] + break + self.displaystats() + + def displaystats(self): + W.SetCursor('watch') + apply(self.stats.sort_stats, self.sortkeys) + saveout = sys.stdout + try: + s = sys.stdout = StringIO.StringIO() + self.stats.print_stats() + finally: + sys.stdout = saveout + text = string.join(string.split(s.getvalue(), '\n'), '\r') + self.w.text.set(text) + + +def main(): + import pstats + args = sys.argv[1:] + for i in args: + stats = pstats.Stats(i) + browser = ProfileBrowser(stats) + else: + import macfs + fss, ok = macfs.PromptGetFile('Profiler data') + if not ok: sys.exit(0) + stats = pstats.Stats(fss.as_pathname()) + browser = ProfileBrowser(stats) + +if __name__ == '__main__': + main() diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyBrowser.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyBrowser.py new file mode 100644 index 0000000..8d5f46c --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyBrowser.py @@ -0,0 +1,439 @@ +import W, SpecialKeys +import struct +import string +import types +import regex + +nullid = '\0\0' +closedid = struct.pack('h', 468) +openid = struct.pack('h', 469) +closedsolidid = struct.pack('h', 470) +opensolidid = struct.pack('h', 471) + +arrows = (nullid, closedid, openid, closedsolidid, opensolidid) + +has_ctlcharsRE = regex.compile('[\000-\037\177-\377]') + +def double_repr(key, value, truncvalue = 0, + type = type, StringType = types.StringType, + has_ctlchars = has_ctlcharsRE.search, _repr = repr, str = str): + if type(key) == StringType and has_ctlchars(key) < 0: + key = str(key) + else: + key = _repr(key) + if type(value) == StringType and has_ctlchars(value) < 0: + value = str(value) + elif key == '__builtins__': + value = "<" + type(value).__name__ + " '__builtin__'>" + elif key == '__return__': + # bleh, when returning from a class codeblock we get infinite recursion in repr. + # Use safe repr instead. + import repr + value = repr.repr(value) + else: + try: + value = _repr(value) + '' + value # test to see if it is a string, in case a __repr__ method is buggy + except: + value = ' exception in repr()' + if truncvalue: + return key + '\t' + value[:255] + return key + '\t' + value + + +class BrowserWidget(W.List): + + LDEF_ID = 471 + + def __init__(self, possize, object = None, col = 100, closechildren = 0): + W.List.__init__(self, possize, callback = self.listhit) + self.object = None, + self.indent = 16 + self.lastmaxindent = 0 + self.closechildren = closechildren + self.children = [] + self.mincol = 64 + self.setcolumn(col) + self.bind('return', self.openselection) + self.bind('enter', self.openselection) + if object is not None: + self.set(object) + + def set(self, object): + if self.object[0] <> object: + self.object = object, + self[:] = self.unpack(object, 0) + elif self._parentwindow is not None and self._parentwindow.wid: + self.update() + + def unpack(self, object, indent): + return unpack_object(object, indent) + + def update(self): + # for now... + W.SetCursor('watch') + self.setdrawingmode(0) + sel = self.getselectedobjects() + fold = self.getunfoldedobjects() + topcell = self.gettopcell() + self[:] = self.unpack(self.object[0], 0) + self.unfoldobjects(fold) + self.setselectedobjects(sel) + self.settopcell(topcell) + self.setdrawingmode(1) + + def setcolumn(self, col): + self.col = col + self.colstr = struct.pack('h', col) + if self._list: + sel = self.getselection() + self.setitems(self.items) + self.setselection(sel) + + def key(self, char, event): + if char in (SpecialKeys.leftarrowkey, SpecialKeys.rightarrowkey): + sel = self.getselection() + sel.reverse() + self.setdrawingmode(0) + for index in sel: + self.fold(index, char == SpecialKeys.rightarrowkey) + self.setdrawingmode(1) + else: + W.List.key(self, char, event) + + def rollover(self, (x, y), onoff): + if onoff: + if self.incolumn((x, y)): + W.SetCursor('hmover') + else: + W.SetCursor('arrow') + + def inarrow(self, (x, y)): + cl, ct, cr, cb = self._list.LRect((0, 0)) + l, t, r, b = self._bounds + if (x - cl) < 16: + cellheight = cb - ct + index = (y - ct) / cellheight + if index < len(self.items): + return 1, index + return None, None + + def incolumn(self, (x, y)): + l, t, r, b = self._list.LRect((0, 0)) + abscol = l + self.col + return abs(abscol - x) < 3 + + def trackcolumn(self, (x, y)): + import Qd, QuickDraw, Evt + self.SetPort() + l, t, r, b = self._bounds + bounds = l, t, r, b = l + 1, t + 1, r - 16, b - 1 + abscol = l + self.col + mincol = l + self.mincol + maxcol = r - 10 + diff = abscol - x + Qd.PenPat('\000\377\000\377\000\377\000\377') + Qd.PenMode(QuickDraw.srcXor) + rect = abscol - 1, t, abscol, b + Qd.PaintRect(rect) + lastpoint = (x, y) + newcol = -1 + #W.SetCursor('fist') + while Evt.Button(): + (x, y) = Evt.GetMouse() + if (x, y) <> lastpoint: + newcol = x + diff + newcol = max(newcol, mincol) + newcol = min(newcol, maxcol) + Qd.PaintRect(rect) + rect = newcol - 1, t, newcol, b + Qd.PaintRect(rect) + lastpoint = (x, y) + Qd.PaintRect(rect) + Qd.PenPat(Qd.qd.black) + Qd.PenNormal() + if newcol > 0 and newcol <> abscol: + self.setcolumn(newcol - l) + + def click(self, point, modifiers): + if point == (-1, -1): # gross. + W.List.click(self, point ,modifiers) + return + hit, index = self.inarrow(point) + if hit: + (key, value, arrow, indent) = self.items[index] + self.fold(index, arrow == 1) + elif self.incolumn(point): + self.trackcolumn(point) + else: + W.List.click(self, point, modifiers) + + # for W.List.key + def findmatch(self, tag): + lower = string.lower + items = self.items + taglen = len(tag) + match = '\377' * 100 + match_i = -1 + for i in range(len(items)): + item = lower(str(items[i][0])) + if tag <= item < match: + match = item + match_i = i + if match_i >= 0: + return match_i + else: + return len(items) - 1 + + def close(self): + if self.closechildren: + for window in self.children: + window.close() + self.children = [] + W.List.close(self) + + def fold(self, index, onoff): + (key, value, arrow, indent) = self.items[index] + if arrow == 0 or (onoff and arrow == 2) or (not onoff and arrow == 1): + return + W.SetCursor('watch') + topcell = self.gettopcell() + if onoff: + self[index] = (key, value, 4, indent) + self.setdrawingmode(0) + self[index+1:index+1] = self.unpack(value, indent + 1) + self[index] = (key, value, 2, indent) + else: + self[index] = (key, value, 3, indent) + self.setdrawingmode(0) + count = 0 + for i in range(index + 1, len(self.items)): + (dummy, dummy, dummy, subindent) = self.items[i] + if subindent <= indent: + break + count = count + 1 + self[index+1:index+1+count] = [] + self[index] = (key, value, 1, indent) + maxindent = self.getmaxindent() + if maxindent <> self.lastmaxindent: + newabsindent = self.col + (maxindent - self.lastmaxindent) * self.indent + if newabsindent >= self.mincol: + self.setcolumn(newabsindent) + self.lastmaxindent = maxindent + self.settopcell(topcell) + self.setdrawingmode(1) + + def unfoldobjects(self, objects): + for obj in objects: + try: + index = self.items.index(obj) + except ValueError: + pass + else: + self.fold(index, 1) + + def getunfoldedobjects(self): + curindent = 0 + objects = [] + for index in range(len(self.items)): + (key, value, arrow, indent) = self.items[index] + if indent > curindent: + (k, v, a, i) = self.items[index - 1] + objects.append((k, v, 1, i)) + curindent = indent + elif indent < curindent: + curindent = indent + return objects + + def listhit(self, isdbl): + if isdbl: + self.openselection() + + def openselection(self): + import os + sel = self.getselection() + for index in sel: + (key, value, arrow, indent) = self[index] + if arrow: + self.children.append(Browser(value)) + elif type(value) == types.StringType and '\0' not in value: + editor = self._parentwindow.parent.getscript(value) + if editor: + editor.select() + return + elif os.path.exists(value) and os.path.isfile(value): + import macfs + fss = macfs.FSSpec(value) + if fss.GetCreatorType()[1] == 'TEXT': + W.getapplication().openscript(value) + + def itemrepr(self, (key, value, arrow, indent), str = str, double_repr = double_repr, + arrows = arrows, pack = struct.pack): + arrow = arrows[arrow] + return arrow + pack('h', self.indent * indent) + self.colstr + \ + double_repr(key, value, 1) + + def getmaxindent(self, max = max): + maxindent = 0 + for item in self.items: + maxindent = max(maxindent, item[3]) + return maxindent + + def domenu_copy(self, *args): + sel = self.getselectedobjects() + selitems = [] + for key, value, dummy, dummy in sel: + selitems.append(double_repr(key, value)) + text = string.join(selitems, '\r') + if text: + import Scrap + Scrap.ZeroScrap() + Scrap.PutScrap('TEXT', text) + + +class Browser: + + def __init__(self, object = None, title = None, closechildren = 0): + if hasattr(object, '__name__'): + name = object.__name__ + else: + name = '' + if title is None: + title = 'Object browser' + if name: + title = title + ': ' + name + self.w = w = W.Window((300, 400), title, minsize = (100, 100)) + w.info = W.TextBox((18, 8, -70, 15)) + w.updatebutton = W.Button((-64, 4, 50, 16), 'Update', self.update) + w.browser = BrowserWidget((-1, 24, 1, -14), None) + w.bind('cmdu', w.updatebutton.push) + w.open() + self.set(object, name) + + def close(self): + if self.w.wid: + self.w.close() + + def set(self, object, name = ''): + W.SetCursor('watch') + tp = type(object).__name__ + try: + length = len(object) + except: + length = -1 + if not name and hasattr(object, '__name__'): + name = object.__name__ + if name: + info = name + ': ' + tp + else: + info = tp + if length >= 0: + if length == 1: + info = info + ' (%d element)' % length + else: + info = info + ' (%d elements)' % length + self.w.info.set(info) + self.w.browser.set(object) + + def update(self): + self.w.browser.update() + + +SIMPLE_TYPES = ( + types.NoneType, + types.IntType, + types.LongType, + types.FloatType, + types.ComplexType, + types.StringType +) + +INDEXING_TYPES = ( + types.TupleType, + types.ListType, + types.DictionaryType +) + +def unpack_object(object, indent = 0): + tp = type(object) + if tp in SIMPLE_TYPES and tp is not types.NoneType: + raise TypeError, 'canıt browse simple type: %s' % tp.__name__ + elif tp == types.DictionaryType: + return unpack_dict(object, indent) + elif tp in (types.TupleType, types.ListType): + return unpack_sequence(object, indent) + elif tp == types.InstanceType: + return unpack_instance(object, indent) + elif tp == types.ClassType: + return unpack_class(object, indent) + elif tp == types.ModuleType: + return unpack_dict(object.__dict__, indent) + else: + return unpack_other(object, indent) + +def unpack_sequence(seq, indent = 0): + items = map(None, range(len(seq)), seq) + items = map(lambda (k, v), type = type, simp = SIMPLE_TYPES, indent = indent: + (k, v, not type(v) in simp, indent), items) + return items + +def unpack_dict(dict, indent = 0): + items = dict.items() + return pack_items(items, indent) + +def unpack_instance(inst, indent = 0): + if hasattr(inst, '__pybrowse_unpack__'): + return unpack_object(inst.__pybrowse_unpack__(), indent) + else: + items = [('__class__', inst.__class__)] + inst.__dict__.items() + return pack_items(items, indent) + +def unpack_class(clss, indent = 0): + items = [('__bases__', clss.__bases__), ('__name__', clss.__name__)] + clss.__dict__.items() + return pack_items(items, indent) + +def unpack_other(object, indent = 0): + attrs = [] + if hasattr(object, '__members__'): + attrs = attrs + object.__members__ + if hasattr(object, '__methods__'): + attrs = attrs + object.__methods__ + items = [] + for attr in attrs: + items.append((attr, getattr(object, attr))) + return pack_items(items, indent) + +def pack_items(items, indent = 0): + items = map(lambda (k, v), type = type, simp = SIMPLE_TYPES, indent = indent: + (k, v, not type(v) in simp, indent), + items) + return tuple_caselesssort(items) + +def caselesssort(alist): + """Return a sorted copy of a list. If there are only strings in the list, + it will not consider case""" + + try: + # turn ['FOO', 'aaBc', 'ABcD'] into [('foo', 'FOO'), ('aabc', 'aaBc'), ('abcd', 'ABcD')], if possible + tupledlist = map(lambda item, lower = string.lower: (lower(item), item), alist) + except TypeError: + # at least one element in alist is not a string, proceed the normal way... + alist = alist[:] + alist.sort() + return alist + else: + tupledlist.sort() + # turn [('aabc', 'aaBc'), ('abcd', 'ABcD'), ('foo', 'FOO')] into ['aaBc', 'ABcD', 'FOO'] + return map(lambda x: x[1], tupledlist) + +def tuple_caselesssort(items): + try: + tupledlist = map(lambda tuple, lower = string.lower: (lower(tuple[0]), tuple), items) + except TypeError: + items = items[:] + items.sort() + return items + else: + tupledlist.sort() + return map(lambda (low, tuple): tuple, tupledlist) + diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyConsole.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyConsole.py new file mode 100644 index 0000000..8cb2e4b --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyConsole.py @@ -0,0 +1,293 @@ +import W +import Fm +from WASTEconst import * +from SpecialKeys import * +from types import * +import Events +import string +import sys,os +import traceback +import MacOS +import MacPrefs +import PyInteractive + +if not hasattr(sys, 'ps1'): + sys.ps1 = '>>> ' +if not hasattr(sys, 'ps2'): + sys.ps2 = '... ' + + +class ConsoleTextWidget(W.EditText): + + def __init__(self, *args, **kwargs): + apply(W.EditText.__init__, (self,) + args, kwargs) + self._inputstart = 0 + self._buf = '' + self.pyinteractive = PyInteractive.PyInteractive() + + import __main__ + self._namespace = __main__.__dict__ + + def insert(self, text): + self.checkselection() + self.ted.WEInsert(text, None, None) + self.changed = 1 + self.selchanged = 1 + + def set_namespace(self, dict): + if type(dict) <> DictionaryType: + raise TypeError, "The namespace needs to be a dictionary" + self._namespace = dict + + def open(self): + W.EditText.open(self) + self.write('Python ' + sys.version + '\n' + sys.copyright + '\n') + self.write(sys.ps1) + self.flush() + + def key(self, char, event): + (what, message, when, where, modifiers) = event + if self._enabled and not modifiers & Events.cmdKey or char in arrowkeys: + if char not in navigationkeys: + self.checkselection() + if char == enterkey: + char = returnkey + selstart, selend = self.getselection() + if char == backspacekey: + if selstart <= (self._inputstart - (selstart <> selend)): + return + self.ted.WEKey(ord(char), modifiers) + if char not in navigationkeys: + self.changed = 1 + if char not in scrollkeys: + self.selchanged = 1 + self.updatescrollbars() + if char == returnkey: + text = self.get()[self._inputstart:selstart] + saveyield = MacOS.EnableAppswitch(0) + self.pyinteractive.executeline(text, self, self._namespace) + MacOS.EnableAppswitch(saveyield) + selstart, selend = self.getselection() + self._inputstart = selstart + + def domenu_save_as(self, *args): + import macfs + fss, ok = macfs.StandardPutFile('Save console text as:', 'console.txt') + if not ok: + return + f = open(fss.as_pathname(), 'wb') + f.write(self.get()) + f.close() + fss.SetCreatorType(W._signature, 'TEXT') + + def write(self, text): + self._buf = self._buf + text + if '\n' in self._buf: + self.flush() + + def flush(self): + stuff = string.split(self._buf, '\n') + stuff = string.join(stuff, '\r') + self.setselection_at_end() + self.ted.WEInsert(stuff, None, None) + selstart, selend = self.getselection() + self._inputstart = selstart + self._buf = "" + self.ted.WEClearUndo() + self.updatescrollbars() + + def selection_ok(self): + selstart, selend = self.getselection() + return not (selstart < self._inputstart or selend < self._inputstart) + + def checkselection(self): + if not self.selection_ok(): + self.setselection_at_end() + + def setselection_at_end(self): + end = self.ted.WEGetTextLength() + self.setselection(end, end) + self.updatescrollbars() + + def domenu_cut(self, *args): + if not self.selection_ok(): + return + W.EditText.domenu_cut(self) + + def domenu_paste(self, *args): + if not self.selection_ok(): + self.setselection_at_end() + W.EditText.domenu_paste(self) + + def domenu_clear(self, *args): + if not self.selection_ok(): + return + W.EditText.domenu_clear(self) + + +class PyConsole(W.Window): + + def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)), unclosable = 0): + W.Window.__init__(self, + bounds, + "Python Interactive", + minsize = (200, 100), + tabbable = 0, + show = show) + + self._unclosable = unclosable + consoletext = ConsoleTextWidget((-1, -1, -14, 1), inset = (6, 5), fontsettings = fontsettings) + self._bary = W.Scrollbar((-15, 14, 16, -14), consoletext.vscroll, max = 32767) + self.consoletext = consoletext + self.namespacemenu = W.PopupMenu((-15, -1, 16, 16), [], self.consoletext.set_namespace) + self.namespacemenu.bind('<click>', self.makenamespacemenu) + self.open() + + def makenamespacemenu(self, *args): + W.SetCursor('watch') + namespacelist = self.getnamespacelist() + self.namespacemenu.set([("Font settings", self.dofontsettings), + ["Namespace"] + namespacelist, ("Clear buffer", self.clearbuffer), ("Browse namespace", self.browsenamespace)]) + currentname = self.consoletext._namespace["__name__"] + for i in range(len(namespacelist)): + if namespacelist[i][0] == currentname: + break + else: + return + # XXX this functionality should be generally available in Wmenus + submenuid = self.namespacemenu.menu.menu.GetItemMark(2) + menu = self.namespacemenu.menu.bar.menus[submenuid] + menu.menu.CheckItem(i + 1, 1) + + def browsenamespace(self): + import PyBrowser, W + W.SetCursor('watch') + PyBrowser.Browser(self.consoletext._namespace, self.consoletext._namespace["__name__"]) + + def clearbuffer(self): + import Res + self.consoletext.ted.WEUseText(Res.Resource('')) + self.consoletext.write(sys.ps1) + self.consoletext.flush() + + def getnamespacelist(self): + import __main__ + editors = filter(lambda x: x.__class__.__name__ == "Editor", self.parent._windows.values()) + + namespaces = [ ("__main__",__main__.__dict__) ] + for ed in editors: + modname = os.path.splitext(ed.title)[0] + if sys.modules.has_key(modname): + module = sys.modules[modname] + namespaces.append((modname, module.__dict__)) + else: + if ed.title[-3:] == '.py': + modname = ed.title[:-3] + else: + modname = ed.title + ed.globals["__name__"] = modname + namespaces.append((modname, ed.globals)) + return namespaces + + def dofontsettings(self): + import FontSettings + fontsettings = FontSettings.FontDialog(self.consoletext.getfontsettings()) + if fontsettings: + self.consoletext.setfontsettings(fontsettings) + + def show(self, onoff = 1): + W.Window.show(self, onoff) + if onoff: + self.select() + + def close(self): + if self._unclosable: + self.show(0) + return -1 + W.Window.close(self) + + def writeprefs(self): + prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath) + prefs.console.show = self.isvisible() + prefs.console.windowbounds = self.getbounds() + prefs.console.fontsettings = self.consoletext.getfontsettings() + prefs.save() + + +class OutputTextWidget(W.EditText): + + def _getflags(self): + import WASTEconst + return WASTEconst.weDoAutoScroll | WASTEconst.weDoMonoStyled | \ + WASTEconst.weDoUndo + +class PyOutput: + + def __init__(self): + self.w = None + self.closed = 1 + self._buf = '' + # should be able to set this + self.savestdout, self.savestderr = sys.stdout, sys.stderr + sys.stderr = sys.stdout = self + + def write(self, text): + self._buf = self._buf + text + if '\n' in self._buf: + self.flush() + + def flush(self): + self.show() + stuff = string.split(self._buf, '\n') + stuff = string.join(stuff, '\r') + end = self.w.outputtext.ted.WEGetTextLength() + self.w.outputtext.setselection(end, end) + self.w.outputtext.ted.WEInsert(stuff, None, None) + self._buf = "" + self.w.outputtext.ted.WEClearUndo() + self.w.outputtext.updatescrollbars() + + def show(self): + if self.closed: + if not self.w: + self.setupwidgets() + self.w.open() + self.closed = 0 + else: + self.w.show(1) + self.closed = 0 + self.w.select() + + def setupwidgets(self): + self.w = W.Window((450, 200), "Output", minsize = (200, 100), tabbable = 0) + self.w.outputtext = OutputTextWidget((-1, -1, -14, 1), inset = (6, 5)) + self.w._bary = W.Scrollbar((-15, -1, 16, -14), self.w.outputtext.vscroll, max = 32767) + self.w.bind("<close>", self.close) + self.w.bind("<activate>", self.activate) + + def activate(self, onoff): + if onoff: + self.closed = 0 + + def close(self): + self.w.show(0) + self.closed = 1 + return -1 + + +def installconsole(defaultshow = 1): + global console + prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath) + if not prefs.console or not hasattr(prefs.console, 'show'): + prefs.console.show = defaultshow + if not hasattr(prefs.console, "windowbounds"): + prefs.console.windowbounds = (450, 250) + if not hasattr(prefs.console, "fontsettings"): + prefs.console.fontsettings = ("Monaco", 0, 9, (0, 0, 0)) + console = PyConsole(prefs.console.windowbounds, prefs.console.show, prefs.console.fontsettings, 1) + +def installoutput(): + global output + output = PyOutput() + + diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyDebugger.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyDebugger.py new file mode 100644 index 0000000..c1f5ce0 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyDebugger.py @@ -0,0 +1,880 @@ +import sys +import bdb +import types +import os + +import W +import WASTEconst +import PyBrowser +import Qd +import Evt +import Lists +import MacOS +_filenames = {} + +SIMPLE_TYPES = ( + types.NoneType, + types.IntType, + types.LongType, + types.FloatType, + types.ComplexType, + types.StringType +) + + +class Debugger(bdb.Bdb): + + def __init__(self, title = 'Debugger'): + bdb.Bdb.__init__(self) + self.closed = 1 + self.title = title + self.breaksviewer = None + self.reset() + self.tracing = 0 + self.tracingmonitortime = Evt.TickCount() + + prefs = W.getapplication().getprefs() + if prefs.debugger: + self.breaks = prefs.debugger.breaks + self.bounds, self.horpanes, self.verpanes = prefs.debugger.windowsettings + self.tracemagic = prefs.debugger.tracemagic + for key in self.breaks.keys(): + if key[:1] == '<' and key[-1:] == '>': + del self.breaks[key] + else: + self.breaks = {} + self.horpanes = (0.4, 0.6) + self.verpanes = (0.3, 0.35, 0.35) + self.bounds = (600, 400) + self.tracemagic = 0 + self.laststacksel = None + self.editors = {} + + def reset(self): + self.currentframe = None + self.file = None + self.laststack = None + self.reason = 'Not running' + self.continuewithoutdebugger = 0 + bdb.Bdb.reset(self) + self.forget() + + def start(self, bottomframe = None, running = 0): + W.getapplication().DebuggerQuit = bdb.BdbQuit + import Menu + Menu.HiliteMenu(0) + if self.closed: + self.setupwidgets(self.title) + self.closed = 0 + if not self.w.parent.debugger_quitting: + self.w.select() + raise W.AlertError, 'There is another debugger session busy.' + self.reset() + self.botframe = bottomframe + if running: + self.set_continue() + self.reason = 'Running' + self.setstate('running') + else: + self.set_step() + self.reason = 'stopped' + self.setstate('stopped') + sys.settrace(self.trace_dispatch) + + def stop(self): + self.set_quit() + if self.w.parent: + self.exit_mainloop() + self.resetwidgets() + + def set_continue_without_debugger(self): + sys.settrace(None) + self.set_quit() + self.clear_tracefuncs() + self.continuewithoutdebugger = 1 + if self.w.parent: + self.exit_mainloop() + self.resetwidgets() + + def clear_tracefuncs(self): + try: + raise 'spam' + except: + pass + frame = sys.exc_traceback.tb_frame + while frame is not None: + del frame.f_trace + frame = frame.f_back + + def postmortem(self, exc_type, exc_value, traceback): + if self.closed: + self.setupwidgets(self.title) + self.closed = 0 + if not self.w.parent.debugger_quitting: + raise W.AlertError, 'There is another debugger session busy.' + self.reset() + if traceback: + self.botframe = traceback.tb_frame + while traceback.tb_next <> None: + traceback = traceback.tb_next + frame = traceback.tb_frame + else: + self.botframe = None + frame = None + self.w.panes.bottom.buttons.killbutton.enable(1) + self.reason = '(dead) ' + self.formatexception(exc_type, exc_value) + self.w.select() + self.setup(frame, traceback) + self.setstate('dead') + self.showstack(self.curindex) + self.showframe(self.curindex) + + def setupwidgets(self, title): + self.w = w = W.Window(self.bounds, title, minsize = (500, 300)) + + w.panes = W.HorizontalPanes((8, 4, -8, -8), self.horpanes) + + w.panes.browserpanes = browserpanes = W.VerticalPanes(None, self.verpanes) + + browserpanes.stacklist = W.Group(None) + browserpanes.stacklist.title = W.TextBox((4, 0, 0, 12), 'Stack') + browserpanes.stacklist.stack = W.List((0, 16, 0, 0), callback = self.do_stack, flags = Lists.lOnlyOne) + + browserpanes.locals = W.Group(None) + browserpanes.locals.title = W.TextBox((4, 0, 0, 12), 'Local variables') + browserpanes.locals.browser = PyBrowser.BrowserWidget((0, 16, 0, 0)) + + browserpanes.globals = W.Group(None) + browserpanes.globals.title = W.TextBox((4, 0, 0, 12), 'Global variables') + browserpanes.globals.browser = PyBrowser.BrowserWidget((0, 16, 0, 0)) + + w.panes.bottom = bottom = W.Group(None) + bottom.src = src = W.Group((0, 52, 0, 0)) + source = SourceViewer((1, 1, -15, -15), readonly = 1, debugger = self) + src.optionsmenu = W.PopupMenu((-16, 0, 16, 16), []) + src.optionsmenu.bind('<click>', self.makeoptionsmenu) + + src._barx = W.Scrollbar((0, -16, -15, 16), source.hscroll, max = 32767) + src._bary = W.Scrollbar((-16, 15, 16, -15), source.vscroll, max = 32767) + src.source = source + src.frame = W.Frame((0, 0, -15, -15)) + + bottom.tracingmonitor = TracingMonitor((0, 23, 6, 6)) + bottom.state = W.TextBox((12, 20, 0, 16), self.reason) + + bottom.srctitle = W.TextBox((12, 36, 0, 14)) + bottom.buttons = buttons = W.Group((12, 0, 0, 16)) + + buttons.runbutton = W.Button((0, 0, 50, 16), "Run", self.do_run) + buttons.stopbutton = W.Button((58, 0, 50, 16), "Stop", self.do_stop) + buttons.killbutton = W.Button((116, 0, 50, 16), "Kill", self.do_kill) + buttons.line = W.VerticalLine((173, 0, 0, 0)) + buttons.stepbutton = W.Button((181, 0, 50, 16), "Step", self.do_step) + buttons.stepinbutton = W.Button((239, 0, 50, 16), "Step in", self.do_stepin) + buttons.stepoutbutton = W.Button((297, 0, 50, 16), "Step out", self.do_stepout) + + w.bind('cmdr', buttons.runbutton.push) + w.bind('cmd.', buttons.stopbutton.push) + w.bind('cmdk', buttons.killbutton.push) + w.bind('cmds', buttons.stepbutton.push) + w.bind('cmdt', buttons.stepinbutton.push) + w.bind('cmdu', buttons.stepoutbutton.push) + + w.bind('<close>', self.close) + + w.open() + w.xxx___select(w.panes.bottom.src.source) + + def makeoptionsmenu(self): + options = [('Clear breakpoints', self.w.panes.bottom.src.source.clearbreakpoints), + ('Clear all breakpoints', self.clear_all_breaks), + ('Edit breakpoints', self.edit_breaks), '-', + (self.tracemagic and + 'Disable __magic__ tracing' or 'Enable __magic__ tracing', self.togglemagic)] + self.w.panes.bottom.src.optionsmenu.set(options) + + def edit_breaks(self): + if self.breaksviewer: + self.breaksviewer.select() + else: + self.breaksviewer = BreakpointsViewer(self) + + def togglemagic(self): + self.tracemagic = not self.tracemagic + + def setstate(self, state): + self.w.panes.bottom.tracingmonitor.reset() + self.w.panes.bottom.state.set(self.reason) + buttons = self.w.panes.bottom.buttons + if state == 'stopped': + buttons.runbutton.enable(1) + buttons.stopbutton.enable(0) + buttons.killbutton.enable(1) + buttons.stepbutton.enable(1) + buttons.stepinbutton.enable(1) + buttons.stepoutbutton.enable(1) + elif state == 'running': + buttons.runbutton.enable(0) + buttons.stopbutton.enable(1) + buttons.killbutton.enable(1) + buttons.stepbutton.enable(0) + buttons.stepinbutton.enable(0) + buttons.stepoutbutton.enable(0) + elif state == 'idle': + buttons.runbutton.enable(0) + buttons.stopbutton.enable(0) + buttons.killbutton.enable(0) + buttons.stepbutton.enable(0) + buttons.stepinbutton.enable(0) + buttons.stepoutbutton.enable(0) + elif state == 'dead': + buttons.runbutton.enable(0) + buttons.stopbutton.enable(0) + buttons.killbutton.enable(1) + buttons.stepbutton.enable(0) + buttons.stepinbutton.enable(0) + buttons.stepoutbutton.enable(0) + else: + print 'unknown state:', state + + def resetwidgets(self): + self.reason = '' + self.w.panes.bottom.srctitle.set('') + self.w.panes.bottom.src.source.set('') + self.w.panes.browserpanes.stacklist.stack.set([]) + self.w.panes.browserpanes.locals.browser.set({}) + self.w.panes.browserpanes.globals.browser.set({}) + self.setstate('idle') + + # W callbacks + + def close(self): + self.set_quit() + self.exit_mainloop() + self.closed = 1 + + self.unregister_editor(self.w.panes.bottom.src.source, + self.w.panes.bottom.src.source.file) + self.horpanes = self.w.panes.getpanesizes() + self.verpanes = self.w.panes.browserpanes.getpanesizes() + self.bounds = self.w.getbounds() + prefs = W.getapplication().getprefs() + prefs.debugger.breaks = self.breaks + prefs.debugger.windowsettings = self.bounds, self.horpanes, self.verpanes + prefs.debugger.tracemagic = self.tracemagic + prefs.save() + + # stack list callback + + def do_stack(self, isdbl): + sel = self.w.panes.browserpanes.stacklist.stack.getselection() + if isdbl: + if sel: + frame, lineno = self.stack[sel[0] + 1] + filename = frame.f_code.co_filename + editor = self.w._parentwindow.parent.openscript(filename, lineno) + if self.breaks.has_key(filename): + editor.showbreakpoints(1) + else: + if sel and sel <> self.laststacksel: + self.showframe(sel[0] + 1) + self.laststacksel = sel + + def geteditor(self, filename): + if filename[:1] == '<' and filename[-1:] == '>': + editor = W.getapplication().getscript(filename[1:-1]) + else: + editor = W.getapplication().getscript(filename) + return editor + + # button callbacks + + def do_run(self): + self.running() + self.set_continue() + self.exit_mainloop() + + def do_stop(self): + self.set_step() + + def do_kill(self): + self.set_quit() + self.exit_mainloop() + self.resetwidgets() + + def do_step(self): + self.running() + self.set_next(self.curframe) + self.exit_mainloop() + + def do_stepin(self): + self.running() + self.set_step() + self.exit_mainloop() + + def do_stepout(self): + self.running() + self.set_return(self.curframe) + self.exit_mainloop() + + def running(self): + W.SetCursor('watch') + self.reason = 'Running' + self.setstate('running') + #self.w.panes.bottom.src.source.set('') + #self.w.panes.browserpanes.stacklist.stack.set([]) + #self.w.panes.browserpanes.locals.browser.set({}) + #self.w.panes.browserpanes.globals.browser.set({}) + + def exit_mainloop(self): + self.w.parent.debugger_quitting = 1 + + # + + def showframe(self, stackindex): + (frame, lineno) = self.stack[stackindex] + W.SetCursor('watch') + filename = frame.f_code.co_filename + if filename <> self.file: + editor = self.geteditor(filename) + if editor: + self.w.panes.bottom.src.source.set(editor.get(), filename) + else: + try: + f = open(filename, 'rb') + data = f.read() + f.close() + except IOError: + if filename[-3:] == '.py': + import imp + modname = os.path.basename(filename)[:-3] + try: + f, filename, (suff, mode, dummy) = imp.find_module(modname) + except ImportError: + self.w.panes.bottom.src.source.set('canıt find file') + else: + f.close() + if suff == '.py': + f = open(filename, 'rb') + data = f.read() + f.close() + self.w.panes.bottom.src.source.set(data, filename) + else: + self.w.panes.bottom.src.source.set('canıt find file') + else: + self.w.panes.bottom.src.source.set('canıt find file') + else: + self.w.panes.bottom.src.source.set(data, filename) + self.file = filename + self.w.panes.bottom.srctitle.set('Source: ' + filename + ((lineno > 0) and (' (line %d)' % lineno) or ' ')) + self.goto_line(lineno) + self.lineno = lineno + self.showvars((frame, lineno)) + + def showvars(self, (frame, lineno)): + if frame.f_locals is not frame.f_globals: + locals = frame.f_locals + else: + locals = {'Same as Globals':''} + filteredlocals = {} + for key, value in locals.items(): + # empty key is magic for Python 1.4; '.' is magic for 1.5... + if not key or key[0] <> '.': + filteredlocals[key] = value + self.w.panes.browserpanes.locals.browser.set(filteredlocals) + self.w.panes.browserpanes.globals.browser.set(frame.f_globals) + + def showstack(self, stackindex): + stack = [] + for frame, lineno in self.stack[1:]: + filename = frame.f_code.co_filename + try: + filename = _filenames[filename] + except KeyError: + if filename[:1] + filename[-1:] <> '<>': + filename = os.path.basename(filename) + _filenames[frame.f_code.co_filename] = filename + funcname = frame.f_code.co_name + if funcname == '?': + funcname = '<toplevel>' + stack.append(filename + ': ' + funcname) + if stack <> self.laststack: + self.w.panes.browserpanes.stacklist.stack.set(stack) + self.laststack = stack + sel = [stackindex - 1] + self.w.panes.browserpanes.stacklist.stack.setselection(sel) + self.laststacksel = sel + + def goto_line(self, lineno): + if lineno > 0: + self.w.panes.bottom.src.source.selectline(lineno - 1) + else: + self.w.panes.bottom.src.source.setselection(0, 0) + + # bdb entry points + +# def user_call(self, frame, argument_list): +# self.reason = 'Calling' +# self.interaction(frame, None) + + def user_line(self, frame): + # This function is called when we stop or break at this line + self.reason = 'Stopped' + self.interaction(frame, None) + + def user_return(self, frame, return_value): + # This function is called when a return trap is set here + fname = frame.f_code.co_name + if fname <> '?': + self.reason = 'Returning from %s()' % frame.f_code.co_name + frame.f_locals['__return__'] = return_value + elif frame.f_back is self.botframe: + self.reason = 'Done' + else: + self.reason = 'Returning' + self.interaction(frame, None, 1) + + def user_exception(self, frame, (exc_type, exc_value, exc_traceback)): + # This function is called when we stop or break at this line + self.reason = self.formatexception(exc_type, exc_value) + self.interaction(frame, exc_traceback) + + def formatexception(self, exc_type, exc_value): + if exc_type == SyntaxError: + try: + value, (filename, lineno, charno, line) = exc_value + except: + pass + else: + return str(exc_type) + ': ' + str(value) + if type(exc_type) == types.ClassType: + nice = exc_type.__name__ + else: + nice = str(exc_type) + value = str(exc_value) + if exc_value and value: + nice = nice + ": " + value + return nice + + def forget(self): + self.stack = [] + self.curindex = 0 + self.curframe = None + + def setup(self, f, t, isreturning = 0): + self.forget() + self.stack, self.curindex = self.get_stack(f, t) + self.curframe = self.stack[self.curindex - isreturning][0] + + def interaction(self, frame, traceback, isreturning = 0): + saveport = Qd.GetPort() + self.w.select() + try: + self.setup(frame, traceback, isreturning) + self.setstate('stopped') + stackindex = self.curindex + if isreturning: + if frame.f_back is not self.botframe: + stackindex = stackindex - 1 + self.showstack(stackindex) + self.showframe(stackindex) + self.w.parent.debugger_mainloop() + self.forget() + finally: + Qd.SetPort(saveport) + + # bdb customization + + def trace_dispatch(self, frame, event, arg, TickCount = Evt.TickCount): + if TickCount() - self.tracingmonitortime > 15: + self.tracingmonitortime = TickCount() + self.w.panes.bottom.tracingmonitor.toggle() + try: + try: + MacOS.EnableAppswitch(0) + if self.quitting: + # returning None is not enough, a former BdbQuit exception + # might have been eaten by the print statement + raise bdb.BdbQuit + if event == 'line': + return self.dispatch_line(frame) + if event == 'call': + return self.dispatch_call(frame, arg) + if event == 'return': + return self.dispatch_return(frame, arg) + if event == 'exception': + return self.dispatch_exception(frame, arg) + print 'bdb.Bdb.dispatch: unknown debugging event:', `event` + return self.trace_dispatch + finally: + MacOS.EnableAppswitch(-1) + except KeyboardInterrupt: + self.set_step() + return self.trace_dispatch + except bdb.BdbQuit: + if self.continuewithoutdebugger: + self.clear_tracefuncs() + return + else: + raise bdb.BdbQuit + except: + print 'XXX Exception during debugger interaction.', \ + self.formatexception(sys.exc_type, sys.exc_value) + return self.trace_dispatch + + def dispatch_call(self, frame, arg): + if not self.tracemagic and \ + frame.f_code.co_name[:2] == '__' == frame.f_code.co_name[-2:] and \ + frame.f_code.co_name <> '__init__': + return + if self.botframe is None: + # First call of dispatch since reset() + self.botframe = frame.f_back # xxx !!! added f_back + return self.trace_dispatch + if not (self.stop_here(frame) or self.break_anywhere(frame)): + # No need to trace this function + return # None + self.user_call(frame, arg) + if self.quitting: + raise bdb.BdbQuit + return self.trace_dispatch + + def set_continue(self): + # Don't stop except at breakpoints or when finished + self.stopframe = self.botframe + self.returnframe = None + self.quitting = 0 + # unlike in bdb/pdb, there's a chance that breakpoints change + # *while* a program (this program ;-) is running. It's actually quite likely. + # So we don't delete frame.f_trace until the bottom frame if there are no breakpoints. + + def set_break(self, filename, lineno): + if not self.breaks.has_key(filename): + self.breaks[filename] = [] + list = self.breaks[filename] + if lineno in list: + return 'There is already a breakpoint there!' + list.append(lineno) + list.sort() # I want to keep them neatly sorted; easier for drawing + self.update_breaks(filename) + + def clear_break(self, filename, lineno): + bdb.Bdb.clear_break(self, filename, lineno) + self.update_breaks(filename) + + def clear_all_file_breaks(self, filename): + bdb.Bdb.clear_all_file_breaks(self, filename) + self.update_breaks(filename) + + def clear_all_breaks(self): + bdb.Bdb.clear_all_breaks(self) + for editors in self.editors.values(): + for editor in editors: + editor.drawbreakpoints() + + # special + + def toggle_break(self, filename, lineno): + if self.get_break(filename, lineno): + self.clear_break(filename, lineno) + else: + self.set_break(filename, lineno) + + def clear_breaks_above(self, filename, above): + if not self.breaks.has_key(filename): + return 'There are no breakpoints in that file!' + for lineno in self.breaks[filename][:]: + if lineno > above: + self.breaks[filename].remove(lineno) + if not self.breaks[filename]: + del self.breaks[filename] + + # editor stuff + + def update_breaks(self, filename): + if self.breaksviewer: + self.breaksviewer.update() + if self.editors.has_key(filename): + for editor in self.editors[filename]: + if editor._debugger: # XXX + editor.drawbreakpoints() + else: + print 'xxx dead editor!' + + def update_allbreaks(self): + if self.breaksviewer: + self.breaksviewer.update() + for filename in self.breaks.keys(): + if self.editors.has_key(filename): + for editor in self.editors[filename]: + if editor._debugger: # XXX + editor.drawbreakpoints() + else: + print 'xxx dead editor!' + + def register_editor(self, editor, filename): + if not filename: + return + if not self.editors.has_key(filename): + self.editors[filename] = [editor] + elif editor not in self.editors[filename]: + self.editors[filename].append(editor) + + def unregister_editor(self, editor, filename): + if not filename: + return + try: + self.editors[filename].remove(editor) + if not self.editors[filename]: + del self.editors[filename] + # if this was an untitled window, clear the breaks. + if filename[:1] == '<' and filename[-1:] == '>' and \ + self.breaks.has_key(filename): + self.clear_all_file_breaks(filename) + except (KeyError, ValueError): + pass + + +class SourceViewer(W.PyEditor): + + def __init__(self, *args, **kwargs): + apply(W.PyEditor.__init__, (self,) + args, kwargs) + self.bind('<click>', self.clickintercept) + + def clickintercept(self, point, modifiers): + if self._parentwindow._currentwidget <> self and not self.pt_in_breaks(point): + self._parentwindow.xxx___select(self) + return 1 + + def _getviewrect(self): + l, t, r, b = self._bounds + if self._debugger: + return (l + 12, t + 2, r - 1, b - 2) + else: + return (l + 5, t + 2, r - 1, b - 2) + + def select(self, onoff, isclick = 0): + if W.SelectableWidget.select(self, onoff): + return + self.SetPort() + #if onoff: + # self.ted.WEActivate() + #else: + # self.ted.WEDeactivate() + self.drawselframe(onoff) + + def drawselframe(self, onoff): + pass + + +class BreakpointsViewer: + + def __init__(self, debugger): + self.debugger = debugger + import Lists + self.w = W.Window((300, 250), 'Breakpoints', minsize = (200, 200)) + self.w.panes = W.HorizontalPanes((8, 8, -8, -32), (0.3, 0.7)) + self.w.panes.files = W.List(None, callback = self.filehit) #, flags = Lists.lOnlyOne) + self.w.panes.gr = W.Group(None) + self.w.panes.gr.breaks = W.List((0, 0, -130, 0), callback = self.linehit) #, flags = Lists.lOnlyOne) + self.w.panes.gr.openbutton = W.Button((-80, 4, 0, 16), 'View', self.openbuttonhit) + self.w.panes.gr.deletebutton = W.Button((-80, 28, 0, 16), 'Delete', self.deletebuttonhit) + + self.w.bind('<close>', self.close) + self.w.bind('backspace', self.w.panes.gr.deletebutton.push) + + self.setup() + self.w.open() + self.w.panes.gr.openbutton.enable(0) + self.w.panes.gr.deletebutton.enable(0) + self.curfile = None + + def deletebuttonhit(self): + if self.w._currentwidget == self.w.panes.files: + self.del_filename() + else: + self.del_number() + self.checkbuttons() + + def del_number(self): + if self.curfile is None: + return + sel = self.w.panes.gr.breaks.getselectedobjects() + for lineno in sel: + self.debugger.clear_break(self.curfile, lineno) + + def del_filename(self): + sel = self.w.panes.files.getselectedobjects() + for filename in sel: + self.debugger.clear_all_file_breaks(filename) + self.debugger.update_allbreaks() + + def setup(self): + files = self.debugger.breaks.keys() + files.sort() + self.w.panes.files.set(files) + + def close(self): + self.debugger.breaksviewer = None + self.debugger = None + + def update(self): + sel = self.w.panes.files.getselectedobjects() + self.setup() + self.w.panes.files.setselectedobjects(sel) + sel = self.w.panes.files.getselection() + if len(sel) == 0 and self.curfile: + self.w.panes.files.setselectedobjects([self.curfile]) + self.filehit(0) + + def select(self): + self.w.select() + + def selectfile(self, file): + self.w.panes.files.setselectedobjects([file]) + self.filehit(0) + + def openbuttonhit(self): + self.filehit(1) + + def filehit(self, isdbl): + sel = self.w.panes.files.getselectedobjects() + if isdbl: + for filename in sel: + lineno = None + if filename == self.curfile: + linesel = self.w.panes.gr.breaks.getselectedobjects() + if linesel: + lineno = linesel[-1] + elif self.w.panes.gr.breaks: + lineno = self.w.panes.gr.breaks[0] + editor = self.w._parentwindow.parent.openscript(filename, lineno) + editor.showbreakpoints(1) + return + if len(sel) == 1: + file = sel[0] + filebreaks = self.debugger.breaks[file][:] + if self.curfile == file: + linesel = self.w.panes.gr.breaks.getselectedobjects() + self.w.panes.gr.breaks.set(filebreaks) + if self.curfile == file: + self.w.panes.gr.breaks.setselectedobjects(linesel) + self.curfile = file + else: + if len(sel) <> 0: + self.curfile = None + self.w.panes.gr.breaks.set([]) + self.checkbuttons() + + def linehit(self, isdbl): + if isdbl: + files = self.w.panes.files.getselectedobjects() + if len(files) <> 1: + return + filename = files[0] + linenos = self.w.panes.gr.breaks.getselectedobjects() + if not linenos: + return + lineno = linenos[-1] + editor = self.w._parentwindow.parent.openscript(filename, lineno) + editor.showbreakpoints(1) + self.checkbuttons() + + def checkbuttons(self): + if self.w.panes.files.getselection(): + self.w.panes.gr.openbutton.enable(1) + self.w._parentwindow.setdefaultbutton(self.w.panes.gr.openbutton) + if self.w._currentwidget == self.w.panes.files: + if self.w.panes.files.getselection(): + self.w.panes.gr.deletebutton.enable(1) + else: + self.w.panes.gr.deletebutton.enable(0) + else: + if self.w.panes.gr.breaks.getselection(): + self.w.panes.gr.deletebutton.enable(1) + else: + self.w.panes.gr.deletebutton.enable(0) + else: + self.w.panes.gr.openbutton.enable(0) + self.w.panes.gr.deletebutton.enable(0) + + +class TracingMonitor(W.Widget): + + def __init__(self, *args, **kwargs): + apply(W.Widget.__init__, (self,) + args, kwargs) + self.state = 0 + + def toggle(self): + if hasattr(self, "_parentwindow") and self._parentwindow is not None: + self.state = self.state % 2 + 1 + port = Qd.GetPort() + self.SetPort() + self.draw() + Qd.SetPort(port) + + def reset(self): + if self._parentwindow: + self.state = 0 + port = Qd.GetPort() + self.SetPort() + self.draw() + Qd.SetPort(port) + + def draw(self, visRgn = None): + if self.state == 2: + Qd.PaintOval(self._bounds) + else: + Qd.EraseOval(self._bounds) + + +# convenience funcs + +def postmortem(exc_type, exc_value, tb): + d = getdebugger() + d.postmortem(exc_type, exc_value, tb) + +def start(bottomframe = None): + d = getdebugger() + d.start(bottomframe) + +def startfromhere(): + d = getdebugger() + try: + raise 'spam' + except: + frame = sys.exc_traceback.tb_frame.f_back + d.start(frame) + +def startfrombottom(): + d = getdebugger() + d.start(_getbottomframe(), 1) + +def stop(): + d = getdebugger() + d.stop() + +def cont(): + sys.settrace(None) + d = getdebugger() + d.set_continue_without_debugger() + +def _getbottomframe(): + try: + raise 'spam' + except: + pass + frame = sys.exc_traceback.tb_frame + while 1: + if frame.f_code.co_name == 'mainloop' or frame.f_back is None: + break + frame = frame.f_back + return frame + +_debugger = None + +def getdebugger(): + global _debugger + if _debugger is None: + _debugger = Debugger() + return _debugger diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyEdit.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyEdit.py new file mode 100644 index 0000000..10f92ff --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyEdit.py @@ -0,0 +1,963 @@ +"""a simple python editor""" + +import W +import Wtraceback +from SpecialKeys import * + +import macfs +import MacOS +import Win +import Res +import Evt +import os +import imp +import sys +import string +import marshal +import regex + +_scriptuntitledcounter = 1 +_wordchars = string.letters + string.digits + "_" + + +class Editor(W.Window): + + def __init__(self, path = "", title = ""): + global _scriptuntitledcounter + if not path: + if title: + self.title = title + else: + self.title = "Untitled Script " + `_scriptuntitledcounter` + _scriptuntitledcounter = _scriptuntitledcounter + 1 + text = "" + self._creator = W._signature + elif os.path.exists(path): + self.title = os.path.basename(path) + f = open(path, "rb") + text = f.read() + f.close() + fss = macfs.FSSpec(path) + self._creator, filetype = fss.GetCreatorType() + else: + raise IOError, "file '%s' does not exist" % path + self.path = path + + self.settings = {} + if self.path: + self.readwindowsettings() + if self.settings.has_key("windowbounds"): + bounds = self.settings["windowbounds"] + else: + bounds = (500, 250) + if self.settings.has_key("fontsettings"): + self.fontsettings = self.settings["fontsettings"] + else: + self.fontsettings = ("Python-Sans", 0, 9, (0, 0, 0)) + W.Window.__init__(self, bounds, self.title, minsize = (330, 120), tabbable = 0) + + self.setupwidgets(text) + if self.settings.has_key("selection"): + selstart, selend = self.settings["selection"] + self.setselection(selstart, selend) + self.open() + self.setinfotext() + self.globals = {} + self._buf = "" # for write method + self.debugging = 0 + self.profiling = 0 + if self.settings.has_key("run_as_main"): + self.run_as_main = self.settings["run_as_main"] + else: + self.run_as_main = 0 + + def readwindowsettings(self): + try: + resref = Res.OpenResFile(self.path) + except Res.Error: + return + try: + Res.UseResFile(resref) + data = Res.Get1Resource('PyWS', 128) + self.settings = marshal.loads(data.data) + except: + pass + Res.CloseResFile(resref) + + def writewindowsettings(self): + try: + resref = Res.OpenResFile(self.path) + except Res.Error: + Res.CreateResFile(self.path) + resref = Res.OpenResFile(self.path) + try: + data = Res.Resource(marshal.dumps(self.settings)) + Res.UseResFile(resref) + try: + temp = Res.Get1Resource('PyWS', 128) + temp.RemoveResource() + except Res.Error: + pass + data.AddResource('PyWS', 128, "window settings") + finally: + Res.UpdateResFile(resref) + Res.CloseResFile(resref) + + def getsettings(self): + self.settings = {} + self.settings["windowbounds"] = self.getbounds() + self.settings["selection"] = self.getselection() + self.settings["fontsettings"] = self.editgroup.editor.getfontsettings() + self.settings["run_as_main"] = self.run_as_main + + def get(self): + return self.editgroup.editor.get() + + def getselection(self): + return self.editgroup.editor.ted.WEGetSelection() + + def setselection(self, selstart, selend): + self.editgroup.editor.setselection(selstart, selend) + + def getfilename(self): + if self.path: + return self.path + return '<%s>' % self.title + + def setupwidgets(self, text): + topbarheight = 24 + popfieldwidth = 80 + self.lastlineno = None + + # make an editor + self.editgroup = W.Group((0, topbarheight + 1, 0, 0)) + editor = W.PyEditor((0, 0, -15,-15), text, fontsettings = self.fontsettings, + file = self.getfilename()) + + # make the widgets + self.popfield = ClassFinder((popfieldwidth - 17, -15, 16, 16), [], self.popselectline) + self.linefield = W.EditText((-1, -15, popfieldwidth - 15, 16), inset = (6, 2)) + self.editgroup._barx = W.Scrollbar((popfieldwidth - 2, -15, -14, 16), editor.hscroll, max = 32767) + self.editgroup._bary = W.Scrollbar((-15, 14, 16, -14), editor.vscroll, max = 32767) + self.editgroup.editor = editor # add editor *after* scrollbars + + self.editgroup.optionsmenu = W.PopupMenu((-15, -1, 16, 16), []) + self.editgroup.optionsmenu.bind('<click>', self.makeoptionsmenu) + self.hline = W.HorizontalLine((0, topbarheight, 0, 0)) + self.infotext = W.TextBox((175, 6, -4, 14)) + self.runbutton = W.Button((5, 4, 80, 16), "Run all", self.run) + self.runselbutton = W.Button((90, 4, 80, 16), "Run selection", self.runselection) + + # bind some keys + editor.bind("cmdr", self.runbutton.push) + editor.bind("enter", self.runselbutton.push) + editor.bind("cmdj", self.domenu_gotoline) + editor.bind("cmdd", self.domenu_toggledebugger) + editor.bind("<idle>", self.updateselection) + + editor.bind("cmde", searchengine.setfindstring) + editor.bind("cmdf", searchengine.show) + editor.bind("cmdg", searchengine.findnext) + editor.bind("cmdshiftr", searchengine.replace) + editor.bind("cmdt", searchengine.replacefind) + + self.linefield.bind("return", self.dolinefield) + self.linefield.bind("enter", self.dolinefield) + self.linefield.bind("tab", self.dolinefield) + + # intercept clicks + editor.bind("<click>", self.clickeditor) + self.linefield.bind("<click>", self.clicklinefield) + + def makeoptionsmenu(self): + menuitems = [('Font settings', self.domenu_fontsettings), + ('\0' + chr(self.run_as_main) + 'Run as __main__', self.domenu_toggle_run_as_main), + ('Modularize', self.domenu_modularize), + ('Browse namespace', self.domenu_browsenamespace), + '-'] + if self.editgroup.editor._debugger: + menuitems = menuitems + [('Disable debugger', self.domenu_toggledebugger), + ('Clear breakpoints', self.domenu_clearbreakpoints), + ('Edit breakpoints', self.domenu_editbreakpoints)] + else: + menuitems = menuitems + [('Enable debugger', self.domenu_toggledebugger)] + if self.profiling: + menuitems = menuitems + [('Disable profiler', self.domenu_toggleprofiler)] + else: + menuitems = menuitems + [('Enable profiler', self.domenu_toggleprofiler)] + self.editgroup.optionsmenu.set(menuitems) + + def domenu_toggle_run_as_main(self): + self.run_as_main = not self.run_as_main + self.editgroup.editor.selchanged = 1 + + def showbreakpoints(self, onoff): + self.editgroup.editor.showbreakpoints(onoff) + self.debugging = onoff + + def domenu_clearbreakpoints(self, *args): + self.editgroup.editor.clearbreakpoints() + + def domenu_editbreakpoints(self, *args): + self.editgroup.editor.editbreakpoints() + + def domenu_toggledebugger(self, *args): + if not self.debugging: + W.SetCursor('watch') + self.debugging = not self.debugging + self.editgroup.editor.togglebreakpoints() + + def domenu_toggleprofiler(self, *args): + self.profiling = not self.profiling + + def domenu_browsenamespace(self, *args): + import PyBrowser, W + W.SetCursor('watch') + globals, file = self.getenvironment() + modname = _filename_as_modname(self.title) + if not modname: + modname = self.title + PyBrowser.Browser(globals, "Object browser: " + modname) + + def domenu_modularize(self, *args): + modname = _filename_as_modname(self.title) + if not modname: + raise W.AlertError, 'Canıt modularize ³%s²' % self.title + self.run() + if self.path: + file = self.path + else: + file = self.title + + if self.globals and not sys.modules.has_key(modname): + module = imp.new_module(modname) + for attr in self.globals.keys(): + setattr(module,attr,self.globals[attr]) + sys.modules[modname] = module + self.globals = {} + + def domenu_fontsettings(self, *args): + import FontSettings + fontsettings = FontSettings.FontDialog(self.editgroup.editor.getfontsettings()) + if fontsettings: + self.editgroup.editor.setfontsettings(fontsettings) + + def clicklinefield(self): + if self._currentwidget <> self.linefield: + self.linefield.select(1) + self.linefield.selectall() + return 1 + + def clickeditor(self): + if self._currentwidget <> self.editgroup.editor: + self.dolinefield() + return 1 + + def updateselection(self, force = 0): + sel = min(self.editgroup.editor.getselection()) + lineno = self.editgroup.editor.offsettoline(sel) + if lineno <> self.lastlineno or force: + self.lastlineno = lineno + self.linefield.set(str(lineno + 1)) + self.linefield.selview() + + def dolinefield(self): + try: + lineno = string.atoi(self.linefield.get()) - 1 + if lineno <> self.lastlineno: + self.editgroup.editor.selectline(lineno) + self.updateselection(1) + except: + self.updateselection(1) + self.editgroup.editor.select(1) + + def setinfotext(self): + if not hasattr(self, 'infotext'): + return + if self.path: + self.infotext.set(self.path) + else: + self.infotext.set("") + + def close(self): + if self.editgroup.editor.changed: + import EasyDialogs + import Qd + Qd.InitCursor() # XXX should be done by dialog + save = EasyDialogs.AskYesNoCancel('Save window ³%s² before closing?' % self.title, 1) + if save > 0: + if self.domenu_save(): + return 1 + elif save < 0: + return 1 + self.globals = None # XXX doesn't help... all globals leak :-( + W.Window.close(self) + + def domenu_close(self, *args): + return self.close() + + def domenu_save(self, *args): + if not self.path: + # Will call us recursively + return self.domenu_save_as() + data = self.editgroup.editor.get() + fp = open(self.path, 'wb') # open file in binary mode, data has '\r' line-endings + fp.write(data) + fp.close() + fss = macfs.FSSpec(self.path) + fss.SetCreatorType(self._creator, 'TEXT') + self.getsettings() + self.writewindowsettings() + self.editgroup.editor.changed = 0 + self.editgroup.editor.selchanged = 0 + import linecache + if linecache.cache.has_key(self.path): + del linecache.cache[self.path] + import macostools + macostools.touched(self.path) + + def can_save(self, menuitem): + return self.editgroup.editor.changed or self.editgroup.editor.selchanged + + def domenu_save_as(self, *args): + fss, ok = macfs.StandardPutFile('Save as:', self.title) + if not ok: + return 1 + self.showbreakpoints(0) + self.path = fss.as_pathname() + self.setinfotext() + self.title = os.path.split(self.path)[-1] + self.wid.SetWTitle(self.title) + self.domenu_save() + self.editgroup.editor.setfile(self.getfilename()) + app = W.getapplication() + app.makeopenwindowsmenu() + if hasattr(app, 'makescriptsmenu'): + app = W.getapplication() + fss, fss_changed = app.scriptsfolder.Resolve() + path = fss.as_pathname() + if path == self.path[:len(path)]: + W.getapplication().makescriptsmenu() + + def domenu_gotoline(self, *args): + self.linefield.selectall() + self.linefield.select(1) + self.linefield.selectall() + + def domenu_selectline(self, *args): + self.editgroup.editor.expandselection() + + def domenu_shiftleft(self, *args): + self.editgroup.editor.shiftleft() + + def domenu_shiftright(self, *args): + self.editgroup.editor.shiftright() + + def domenu_find(self, *args): + searchengine.show() + + def domenu_entersearchstring(self, *args): + searchengine.setfindstring() + + def domenu_replace(self, *args): + searchengine.replace() + + def domenu_findnext(self, *args): + searchengine.findnext() + + def domenu_replacefind(self, *args): + searchengine.replacefind() + + def domenu_run(self, *args): + self.runbutton.push() + + def domenu_runselection(self, *args): + self.runselbutton.push() + + def run(self): + pytext = self.editgroup.editor.get() + globals, file = self.getenvironment() + if self.path: + cwd = os.getcwd() + os.chdir(os.path.dirname(self.path) + ':') + else: + cwd = None + execstring(pytext, globals, globals, file, self.debugging, self.run_as_main, self.profiling) + if cwd: + os.chdir(cwd) + + def runselection(self): + self._runselection() + + def _runselection(self): + globals, file = self.getenvironment() + locals = globals + # select whole lines + self.editgroup.editor.expandselection() + + # get lineno of first selected line + selstart, selend = self.editgroup.editor.getselection() + selstart, selend = min(selstart, selend), max(selstart, selend) + selfirstline = self.editgroup.editor.offsettoline(selstart) + alltext = self.editgroup.editor.get() + pytext = alltext[selstart:selend] + lines = string.split(pytext, '\r') + indent = getminindent(lines) + if indent == 1: + classname = '' + alllines = string.split(alltext, '\r') + identifieRE_match = _identifieRE.match + for i in range(selfirstline - 1, -1, -1): + line = alllines[i] + if line[:6] == 'class ': + classname = string.split(string.strip(line[6:]))[0] + classend = identifieRE_match(classname) + if classend < 1: + raise W.AlertError, 'Canıt find a class.' + classname = classname[:classend] + break + elif line and line[0] not in '\t#': + raise W.AlertError, 'Canıt find a class.' + else: + raise W.AlertError, 'Canıt find a class.' + if globals.has_key(classname): + locals = globals[classname].__dict__ + else: + raise W.AlertError, 'Canıt find class ³%s².' % classname + for i in range(len(lines)): + lines[i] = lines[i][1:] + pytext = string.join(lines, '\r') + elif indent > 0: + raise W.AlertError, 'Canıt run indented code.' + + # add newlines to fool compile/exec: a traceback will give the right line number + pytext = selfirstline * '\r' + pytext + + if self.path: + cwd = os.getcwd() + os.chdir(os.path.dirname(self.path) + ':') + else: + cwd = None + execstring(pytext, globals, locals, file, self.debugging, self.run_as_main, self.profiling) + if cwd: + os.chdir(cwd) + + def getenvironment(self): + if self.path: + file = self.path + modname = _filename_as_modname(self.title) + if sys.modules.has_key(modname): + globals = sys.modules[modname].__dict__ + self.globals = {} + else: + globals = self.globals + else: + file = '<%s>' % self.title + globals = self.globals + return globals, file + + def write(self, stuff): + """for use as stdout""" + self._buf = self._buf + stuff + if '\n' in self._buf: + self.flush() + + def flush(self): + stuff = string.split(self._buf, '\n') + stuff = string.join(stuff, '\r') + end = self.editgroup.editor.ted.WEGetTextLength() + self.editgroup.editor.ted.WESetSelection(end, end) + self.editgroup.editor.ted.WEInsert(stuff, None, None) + self.editgroup.editor.updatescrollbars() + self._buf = "" + # ? optional: + #self.wid.SelectWindow() + + def getclasslist(self): + from string import find, strip + editor = self.editgroup.editor + text = editor.get() + list = [] + append = list.append + functag = "func" + classtag = "class" + methodtag = "method" + pos = -1 + if text[:4] == 'def ': + append((pos + 4, functag)) + pos = 4 + while 1: + pos = find(text, '\rdef ', pos + 1) + if pos < 0: + break + append((pos + 5, functag)) + pos = -1 + if text[:6] == 'class ': + append((pos + 6, classtag)) + pos = 6 + while 1: + pos = find(text, '\rclass ', pos + 1) + if pos < 0: + break + append((pos + 7, classtag)) + pos = 0 + while 1: + pos = find(text, '\r\tdef ', pos + 1) + if pos < 0: + break + append((pos + 6, methodtag)) + list.sort() + classlist = [] + methodlistappend = None + offsetToLine = editor.ted.WEOffsetToLine + getLineRange = editor.ted.WEGetLineRange + append = classlist.append + identifieRE_match = _identifieRE.match + for pos, tag in list: + lineno = offsetToLine(pos) + lineStart, lineEnd = getLineRange(lineno) + line = strip(text[pos:lineEnd]) + line = line[:identifieRE_match(line)] + if tag is functag: + append(("def " + line, lineno + 1)) + methodlistappend = None + elif tag is classtag: + append(["class " + line]) + methodlistappend = classlist[-1].append + elif methodlistappend and tag is methodtag: + methodlistappend(("def " + line, lineno + 1)) + return classlist + + def popselectline(self, lineno): + self.editgroup.editor.selectline(lineno - 1) + + def selectline(self, lineno, charoffset = 0): + self.editgroup.editor.selectline(lineno - 1, charoffset) + + +class Reporter(Editor): + + def close(self): + self.globals = None + W.Window.close(self) + + def domenu_run(self, *args): + self.run() + + def domenu_runselection(self, *args): + self.runselection() + + def setupwidgets(self, text): + topbarheight = -1 + popfieldwidth = 80 + self.lastlineno = None + + # make an editor + self.editgroup = W.Group((0, topbarheight + 1, 0, 0)) + self.editgroup.editor = W.PyEditor((0, 0, -15,-15), text) + + # make the widgets + self.editgroup._barx = W.Scrollbar((popfieldwidth-2, -15, -14, 16), self.editgroup.editor.hscroll, max = 32767) + self.editgroup._bary = W.Scrollbar((-15, -1, 16, -14), self.editgroup.editor.vscroll, max = 32767) + self.hline = W.HorizontalLine((0, -15, 0, 0)) + + # bind some keys + self.editgroup.editor.bind("cmdr", self.run) + self.editgroup.editor.bind("enter", self.runselection) + + self.editgroup.editor.bind("cmde", searchengine.setfindstring) + self.editgroup.editor.bind("cmdf", searchengine.show) + self.editgroup.editor.bind("cmdg", searchengine.findnext) + self.editgroup.editor.bind("cmdshiftr", searchengine.replace) + self.editgroup.editor.bind("cmdt", searchengine.replacefind) + + +def _escape(where, what) : + return string.join(string.split(where, what), '\\' + what) + +def _makewholewordpattern(word): + # first, escape special regex chars + for esc in "\\[].*^+$?": + word = _escape(word, esc) + import regex + notwordcharspat = '[^' + _wordchars + ']' + pattern = '\(' + word + '\)' + if word[0] in _wordchars: + pattern = notwordcharspat + pattern + if word[-1] in _wordchars: + pattern = pattern + notwordcharspat + return regex.compile(pattern) + +class SearchEngine: + + def __init__(self): + self.visible = 0 + self.w = None + self.parms = { "find": "", + "replace": "", + "wrap": 1, + "casesens": 1, + "wholeword": 1 + } + import MacPrefs + prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath) + if prefs.searchengine: + self.parms["casesens"] = prefs.searchengine.casesens + self.parms["wrap"] = prefs.searchengine.wrap + self.parms["wholeword"] = prefs.searchengine.wholeword + + def show(self): + self.visible = 1 + if self.w: + self.w.wid.ShowWindow() + self.w.wid.SelectWindow() + self.w.find.edit.select(1) + self.w.find.edit.selectall() + return + self.w = W.Dialog((420, 150), "Find") + + self.w.find = TitledEditText((10, 4, 300, 36), "Search for:") + self.w.replace = TitledEditText((10, 100, 300, 36), "Replace with:") + + self.w.boxes = W.Group((10, 50, 300, 40)) + self.w.boxes.casesens = W.CheckBox((0, 0, 100, 16), "Case sensitive") + self.w.boxes.wholeword = W.CheckBox((0, 20, 100, 16), "Whole word") + self.w.boxes.wrap = W.CheckBox((110, 0, 100, 16), "Wrap around") + + self.buttons = [ ("Find", "cmdf", self.find), + ("Replace", "cmdr", self.replace), + ("Replace all", None, self.replaceall), + ("Donıt find", "cmdd", self.dont), + ("Cancel", "cmd.", self.cancel) + ] + for i in range(len(self.buttons)): + bounds = -90, 22 + i * 24, 80, 16 + title, shortcut, callback = self.buttons[i] + self.w[title] = W.Button(bounds, title, callback) + if shortcut: + self.w.bind(shortcut, self.w[title].push) + self.w.setdefaultbutton(self.w["Donıt find"]) + self.w.find.edit.bind("<key>", self.key) + self.w.bind("<activate>", self.activate) + self.w.open() + self.setparms() + self.w.find.edit.select(1) + self.w.find.edit.selectall() + self.checkbuttons() + + def key(self, char, modifiers): + self.w.find.edit.key(char, modifiers) + self.checkbuttons() + return 1 + + def activate(self, onoff): + if onoff: + self.checkbuttons() + + def checkbuttons(self): + editor = findeditor(self) + if editor: + if self.w.find.get(): + for title, cmd, call in self.buttons[:-2]: + self.w[title].enable(1) + self.w.setdefaultbutton(self.w["Find"]) + else: + for title, cmd, call in self.buttons[:-2]: + self.w[title].enable(0) + self.w.setdefaultbutton(self.w["Donıt find"]) + else: + for title, cmd, call in self.buttons[:-2]: + self.w[title].enable(0) + self.w.setdefaultbutton(self.w["Donıt find"]) + + def find(self): + self.getparmsfromwindow() + if self.findnext(): + self.hide() + + def replace(self): + editor = findeditor(self) + if not editor: + return + if self.visible: + self.getparmsfromwindow() + text = editor.getselectedtext() + find = self.parms["find"] + if not self.parms["casesens"]: + find = string.lower(find) + text = string.lower(text) + if text == find: + self.hide() + editor.insert(self.parms["replace"]) + + def replaceall(self): + editor = findeditor(self) + if not editor: + return + if self.visible: + self.getparmsfromwindow() + W.SetCursor("watch") + find = self.parms["find"] + if not find: + return + findlen = len(find) + replace = self.parms["replace"] + replacelen = len(replace) + Text = editor.get() + if not self.parms["casesens"]: + find = string.lower(find) + text = string.lower(Text) + else: + text = Text + newtext = "" + pos = 0 + counter = 0 + while 1: + if self.parms["wholeword"]: + wholewordRE = _makewholewordpattern(find) + wholewordRE.search(text, pos) + if wholewordRE.regs: + pos = wholewordRE.regs[1][0] + else: + pos = -1 + else: + pos = string.find(text, find, pos) + if pos < 0: + break + counter = counter + 1 + text = text[:pos] + replace + text[pos + findlen:] + Text = Text[:pos] + replace + Text[pos + findlen:] + pos = pos + replacelen + W.SetCursor("arrow") + if counter: + self.hide() + import EasyDialogs + import Res + editor.changed = 1 + editor.selchanged = 1 + editor.ted.WEUseText(Res.Resource(Text)) + editor.ted.WECalText() + editor.SetPort() + Win.InvalRect(editor._bounds) + #editor.ted.WEUpdate(self.w.wid.GetWindowPort().visRgn) + EasyDialogs.Message("Replaced %d occurrences" % counter) + + def dont(self): + self.getparmsfromwindow() + self.hide() + + def replacefind(self): + self.replace() + self.findnext() + + def setfindstring(self): + editor = findeditor(self) + if not editor: + return + find = editor.getselectedtext() + if not find: + return + self.parms["find"] = find + if self.w: + self.w.find.edit.set(self.parms["find"]) + self.w.find.edit.selectall() + + def findnext(self): + editor = findeditor(self) + if not editor: + return + find = self.parms["find"] + if not find: + return + text = editor.get() + if not self.parms["casesens"]: + find = string.lower(find) + text = string.lower(text) + selstart, selend = editor.getselection() + selstart, selend = min(selstart, selend), max(selstart, selend) + if self.parms["wholeword"]: + wholewordRE = _makewholewordpattern(find) + wholewordRE.search(text, selend) + if wholewordRE.regs: + pos = wholewordRE.regs[1][0] + else: + pos = -1 + else: + pos = string.find(text, find, selend) + if pos >= 0: + editor.setselection(pos, pos + len(find)) + return 1 + elif self.parms["wrap"]: + if self.parms["wholeword"]: + wholewordRE.search(text, 0) + if wholewordRE.regs: + pos = wholewordRE.regs[1][0] + else: + pos = -1 + else: + pos = string.find(text, find) + if selstart > pos >= 0: + editor.setselection(pos, pos + len(find)) + return 1 + + def setparms(self): + for key, value in self.parms.items(): + try: + self.w[key].set(value) + except KeyError: + self.w.boxes[key].set(value) + + def getparmsfromwindow(self): + if not self.w: + return + for key, value in self.parms.items(): + try: + value = self.w[key].get() + except KeyError: + value = self.w.boxes[key].get() + self.parms[key] = value + + def cancel(self): + self.hide() + self.setparms() + + def hide(self): + if self.w: + self.w.wid.HideWindow() + self.visible = 0 + + def writeprefs(self): + import MacPrefs + self.getparmsfromwindow() + prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath) + prefs.searchengine.casesens = self.parms["casesens"] + prefs.searchengine.wrap = self.parms["wrap"] + prefs.searchengine.wholeword = self.parms["wholeword"] + prefs.save() + + +class TitledEditText(W.Group): + + def __init__(self, possize, title, text = ""): + W.Group.__init__(self, possize) + self.title = W.TextBox((0, 0, 0, 16), title) + self.edit = W.EditText((0, 16, 0, 0), text) + + def set(self, value): + self.edit.set(value) + + def get(self): + return self.edit.get() + + +class ClassFinder(W.PopupWidget): + + def click(self, point, modifiers): + W.SetCursor("watch") + self.set(self._parentwindow.getclasslist()) + W.PopupWidget.click(self, point, modifiers) + + +def getminindent(lines): + indent = -1 + for line in lines: + stripped = string.strip(line) + if not stripped or stripped[0] == '#': + continue + if indent < 0 or line[:indent] <> indent * '\t': + indent = 0 + for c in line: + if c <> '\t': + break + indent = indent + 1 + return indent + + +def getoptionkey(): + return not not ord(Evt.GetKeys()[7]) & 0x04 + + +def execstring(pytext, globals, locals, filename = "<string>", debugging = 0, + run_as_main = 0, profiling = 0): + if debugging: + import PyDebugger, bdb + BdbQuit = bdb.BdbQuit + else: + BdbQuit = 'BdbQuitDummyException' + pytext = string.split(pytext, '\r') + pytext = string.join(pytext, '\n') + '\n' + W.SetCursor("watch") + modname = os.path.basename(filename) + if modname[-3:] == '.py': + modname = modname[:-3] + if run_as_main: + globals['__name__'] = '__main__' + else: + globals['__name__'] = modname + globals['__file__'] = filename + sys.argv = [filename] + try: + code = compile(pytext, filename, "exec") + except: + tracebackwindow.traceback(1, filename) + return + try: + if debugging: + PyDebugger.startfromhere() + else: + MacOS.EnableAppswitch(0) + try: + if profiling: + import profile, ProfileBrowser + p = profile.Profile(ProfileBrowser.timer) + p.set_cmd(filename) + try: + p.runctx(code, globals, locals) + finally: + import pstats + + stats = pstats.Stats(p) + ProfileBrowser.ProfileBrowser(stats) + else: + exec code in globals, locals + finally: + MacOS.EnableAppswitch(-1) + except W.AlertError, detail: + raise W.AlertError, detail + except (KeyboardInterrupt, BdbQuit): + pass + except: + if debugging: + sys.settrace(None) + PyDebugger.postmortem(sys.exc_type, sys.exc_value, sys.exc_traceback) + return + else: + tracebackwindow.traceback(1, filename) + if debugging: + sys.settrace(None) + PyDebugger.stop() + + +_identifieRE = regex.compile("[A-Za-z_][A-Za-z_0-9]*") + +def _filename_as_modname(fname): + if fname[-3:] == '.py': + mname = fname[:-3] + if _identifieRE.match(mname) == len(mname): + return mname + +def findeditor(topwindow, fromtop = 0): + wid = Win.FrontWindow() + if not fromtop: + if topwindow.w and wid == topwindow.w.wid: + wid = topwindow.w.wid.GetNextWindow() + if not wid: + return + window = W.getapplication()._windows[wid] + if not W.HasBaseClass(window, Editor): + return + return window.editgroup.editor + + +searchengine = SearchEngine() +tracebackwindow = Wtraceback.TraceBack() diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyFontify.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyFontify.py new file mode 100644 index 0000000..6503636 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyFontify.py @@ -0,0 +1,153 @@ +"""Module to analyze Python source code; for syntax coloring tools. + +Interface: + tags = fontify(pytext, searchfrom, searchto) + +The 'pytext' argument is a string containing Python source code. +The (optional) arguments 'searchfrom' and 'searchto' may contain a slice in pytext. +The returned value is a lists of tuples, formatted like this: + [('keyword', 0, 6, None), ('keyword', 11, 17, None), ('comment', 23, 53, None), etc. ] +The tuple contents are always like this: + (tag, startindex, endindex, sublist) +tag is one of 'keyword', 'string', 'comment' or 'identifier' +sublist is not used, hence always None. +""" + +# Based on FontText.py by Mitchell S. Chapman, +# which was modified by Zachary Roadhouse, +# then un-Tk'd by Just van Rossum. +# Many thanks for regular expression debugging & authoring are due to: +# Tim (the-incredib-ly y'rs) Peters and Cristian Tismer +# So, who owns the copyright? ;-) How about this: +# Copyright 1996-1997: +# Mitchell S. Chapman, +# Zachary Roadhouse, +# Tim Peters, +# Just van Rossum + +__version__ = "0.3.1" + +import string, regex + +# First a little helper, since I don't like to repeat things. (Tismer speaking) +import string +def replace(where, what, with): + return string.join(string.split(where, what), with) + +# This list of keywords is taken from ref/node13.html of the +# Python 1.3 HTML documentation. ("access" is intentionally omitted.) +keywordsList = [ + "del", "from", "lambda", "return", + "and", "elif", "global", "not", "try", + "break", "else", "if", "or", "while", + "class", "except", "import", "pass", + "continue", "finally", "in", "print", + "def", "for", "is", "raise"] + +# Build up a regular expression which will match anything +# interesting, including multi-line triple-quoted strings. +commentPat = "#.*" + +pat = "q[^\q\n]*\(\\\\[\000-\377][^\q\n]*\)*q" +quotePat = replace(pat, "q", "'") + "\|" + replace(pat, 'q', '"') + +# Way to go, Tim! +pat = """ + qqq + [^\\q]* + \( + \( \\\\[\000-\377] + \| q + \( \\\\[\000-\377] + \| [^\\q] + \| q + \( \\\\[\000-\377] + \| [^\\q] + \) + \) + \) + [^\\q]* + \)* + qqq +""" +pat = string.join(string.split(pat), '') # get rid of whitespace +tripleQuotePat = replace(pat, "q", "'") + "\|" + replace(pat, 'q', '"') + +# Build up a regular expression which matches all and only +# Python keywords. This will let us skip the uninteresting +# identifier references. +# nonKeyPat identifies characters which may legally precede +# a keyword pattern. +nonKeyPat = "\(^\|[^a-zA-Z0-9_.\"']\)" + +keyPat = nonKeyPat + "\(" +for keyword in keywordsList: + keyPat = keyPat + keyword + "\|" +keyPat = keyPat[:-2] + "\)" + nonKeyPat + +matchPat = keyPat + "\|" + commentPat + "\|" + tripleQuotePat + "\|" + quotePat +matchRE = regex.compile(matchPat) + +idKeyPat = "[ \t]*[A-Za-z_][A-Za-z_0-9.]*" # Ident w. leading whitespace. +idRE = regex.compile(idKeyPat) + + +def fontify(pytext, searchfrom = 0, searchto = None): + if searchto is None: + searchto = len(pytext) + # Cache a few attributes for quicker reference. + search = matchRE.search + group = matchRE.group + idSearch = idRE.search + idGroup = idRE.group + + tags = [] + tags_append = tags.append + commentTag = 'comment' + stringTag = 'string' + keywordTag = 'keyword' + identifierTag = 'identifier' + + start = 0 + end = searchfrom + while 1: + start = search(pytext, end) + if start < 0 or start >= searchto: + break # EXIT LOOP + match = group(0) + end = start + len(match) + c = match[0] + if c not in "#'\"": + # Must have matched a keyword. + if start <> searchfrom: + # there's still a redundant char before and after it, strip! + match = match[1:-1] + start = start + 1 + else: + # this is the first keyword in the text. + # Only a space at the end. + match = match[:-1] + end = end - 1 + tags_append((keywordTag, start, end, None)) + # If this was a defining keyword, look ahead to the + # following identifier. + if match in ["def", "class"]: + start = idSearch(pytext, end) + if start == end: + match = idGroup(0) + end = start + len(match) + tags_append((identifierTag, start, end, None)) + elif c == "#": + tags_append((commentTag, start, end, None)) + else: + tags_append((stringTag, start, end, None)) + return tags + + +def test(path): + f = open(path) + text = f.read() + f.close() + tags = fontify(text) + for tag, start, end, sublist in tags: + print tag, `text[start:end]` diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyInteractive.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyInteractive.py new file mode 100644 index 0000000..dc75e4b --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/PyInteractive.py @@ -0,0 +1,115 @@ +import string +import sys +import traceback + + +try: + sys.ps1 +except AttributeError: + sys.ps1 = ">>> " +try: + sys.ps2 +except AttributeError: + sys.ps2 = "... " + + +def print_exc(limit=None, file=None): + if not file: + file = sys.stderr + # we're going to skip the outermost traceback object, we don't + # want people to see the line which excecuted their code. + tb = sys.exc_traceback + if tb: + tb = tb.tb_next + try: + sys.last_type = sys.exc_type + sys.last_value = sys.exc_value + sys.last_traceback = tb + traceback.print_exception(sys.last_type, sys.last_value, + sys.last_traceback, limit, file) + except: + print '--- hola! ---' + traceback.print_exception(sys.exc_type, sys.exc_value, + sys.exc_traceback, limit, file) + + +class PyInteractive: + + def __init__(self): + self._pybuf = "" + + def executeline(self, stuff, out = None, env = None): + if env is None: + import __main__ + env = __main__.__dict__ + if out: + saveerr, saveout = sys.stderr, sys.stdout + sys.stderr = sys.stdout = out + try: + if self._pybuf: + self._pybuf = self._pybuf + '\n' + stuff + else: + self._pybuf = stuff + + # Compile three times: as is, with \n, and with \n\n appended. + # If it compiles as is, it's complete. If it compiles with + # one \n appended, we expect more. If it doesn't compile + # either way, we compare the error we get when compiling with + # \n or \n\n appended. If the errors are the same, the code + # is broken. But if the errors are different, we expect more. + # Not intuitive; not even guaranteed to hold in future + # releases; but this matches the compiler's behavior in Python + # 1.4 and 1.5. + err = err1 = err2 = None + code = code1 = code2 = None + + # quickly get out of here when the line is 'empty' or is a comment + stripped = string.strip(self._pybuf) + if not stripped or stripped[0] == '#': + self._pybuf = '' + sys.stdout.write(sys.ps1) + sys.stdout.flush() + return + + try: + code = compile(self._pybuf, "<input>", "single") + except SyntaxError, err: + pass + except: + # OverflowError. More? + print_exc() + self._pybuf = "" + sys.stdout.write(sys.ps1) + sys.stdout.flush() + return + + try: + code1 = compile(self._pybuf + "\n", "<input>", "single") + except SyntaxError, err1: + pass + + try: + code2 = compile(self._pybuf + "\n\n", "<input>", "single") + except SyntaxError, err2: + pass + + if code: + try: + exec code in env + except: + print_exc() + self._pybuf = "" + elif code1: + pass + elif err1 == err2 or (not stuff and self._pybuf): + print_exc() + self._pybuf = "" + if self._pybuf: + sys.stdout.write(sys.ps2) + sys.stdout.flush() + else: + sys.stdout.write(sys.ps1) + sys.stdout.flush() + finally: + if out: + sys.stderr, sys.stdout = saveerr, saveout diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/SpecialKeys.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/SpecialKeys.py new file mode 100644 index 0000000..a7ee5d8 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/SpecialKeys.py @@ -0,0 +1,44 @@ +spacekey = ' ' +returnkey = '\r' +tabkey = '\t' +enterkey = '\003' +backspacekey = '\010' +deletekey = '\177' + +helpkey = '\005' + +leftarrowkey = '\034' +rightarrowkey = '\035' +uparrowkey = '\036' +downarrowkey = '\037' +arrowkeys = [leftarrowkey, rightarrowkey, uparrowkey, downarrowkey] + +topkey = '\001' +bottomkey = '\004' +pageupkey = '\013' +pagedownkey = '\014' +scrollkeys = [topkey, bottomkey, pageupkey, pagedownkey] + +navigationkeys = arrowkeys + scrollkeys + +keycodes = { + "space" : ' ', + "return" : '\r', + "tab" : '\t', + "enter" : '\003', + "backspace" : '\010', + "delete" : '\177', + "help" : '\005', + "leftarrow" : '\034', + "rightarrow" : '\035', + "uparrow" : '\036', + "downarrow" : '\037', + "top" : '\001', + "bottom" : '\004', + "pageup" : '\013', + "pagedown" : '\014' +} + +keynames = {} +for k, v in keycodes.items(): + keynames[v] = k diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/W.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/W.py new file mode 100644 index 0000000..161ddd6 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/W.py @@ -0,0 +1,33 @@ +"""Widgets for the Macintosh. Built on top of FrameWork""" + +__version__ = "0.1" + +from Wbase import * +from Wcontrols import * +from Wtext import * +from Wlist import * +from Wwindows import * +from Wmenus import * + +_application = None +_signature = None + +AlertError = 'AlertError' + +def setapplication(app, sig): + global _application, _signature + _application = app + _signature = sig + +def getapplication(): + if _application is None: + raise WidgetsError, 'W not properly initialized: unknown Application' + return _application + +def Message(text): + import EasyDialogs, Qd + Qd.InitCursor() + if text: + EasyDialogs.Message(text) + else: + EasyDialogs.Message('<Alert text not specified>') diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/WFrameWorkPatch.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/WFrameWorkPatch.py new file mode 100644 index 0000000..267d8ac --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/WFrameWorkPatch.py @@ -0,0 +1,344 @@ +import FrameWork +import Win +import Qd +import MacOS +import Events +import traceback +from types import * + +import Menu; MenuToolbox = Menu; del Menu + + +class Application(FrameWork.Application): + + def __init__(self, signature = 'Pyth'): + import W + W.setapplication(self, signature) + FrameWork.Application.__init__(self) + self._suspended = 0 + self.quitting = 0 + self.debugger_quitting = 1 + self.DebuggerQuit = 'DebuggerQuitDummyException' + + def mainloop(self, mask = FrameWork.everyEvent, wait = 0): + import W + self.quitting = 0 + saveyield = MacOS.EnableAppswitch(-1) + try: + while not self.quitting: + try: + self.do1event(mask, wait) + except W.AlertError, detail: + MacOS.EnableAppswitch(-1) + W.Message(detail) + except self.DebuggerQuit: + MacOS.EnableAppswitch(-1) + except: + MacOS.EnableAppswitch(-1) + import PyEdit + PyEdit.tracebackwindow.traceback() + finally: + MacOS.EnableAppswitch(1) + + def debugger_mainloop(self, mask = FrameWork.everyEvent, wait = 0): + import W + self.debugger_quitting = 0 + saveyield = MacOS.EnableAppswitch(-1) + try: + while not self.quitting and not self.debugger_quitting: + try: + self.do1event(mask, wait) + except W.AlertError, detail: + W.Message(detail) + except: + import PyEdit + PyEdit.tracebackwindow.traceback() + finally: + MacOS.EnableAppswitch(saveyield) + + def idle(self, event): + if not self._suspended: + if not self.do_frontWindowMethod("idle", event): + Qd.InitCursor() + + def do_frontWindowMethod(self, attr, *args): + wid = Win.FrontWindow() + if wid and self._windows.has_key(wid): + window = self._windows[wid] + if hasattr(window, attr): + handler = getattr(window, attr) + apply(handler, args) + return 1 + + def appendwindow(self, wid, window): + self._windows[wid] = window + self.makeopenwindowsmenu() + + def removewindow(self, wid): + del self._windows[wid] + self.makeopenwindowsmenu() + + def do_key(self, event): + (what, message, when, where, modifiers) = event + ch = chr(message & FrameWork.charCodeMask) + rest = message & ~FrameWork.charCodeMask + wid = Win.FrontWindow() + if modifiers & FrameWork.cmdKey: + if wid and self._windows.has_key(wid): + self.checkmenus(self._windows[wid]) + else: + self.checkmenus(None) + event = (what, ord(ch) | rest, when, where, modifiers) + result = MenuToolbox.MenuKey(ord(ch)) + id = (result>>16) & 0xffff # Hi word + item = result & 0xffff # Lo word + if id: + self.do_rawmenu(id, item, None, event) + return # here! we had a menukey! + #else: + # print "XXX Command-" +`ch` + # See whether the front window wants it + if wid and self._windows.has_key(wid): + window = self._windows[wid] + try: + do_char = window.do_char + except AttributeError: + do_char = self.do_char + do_char(ch, event) + # else it wasn't for us, sigh... + + def do_inMenuBar(self, partcode, window, event): + Qd.InitCursor() + (what, message, when, where, modifiers) = event + self.checkopenwindowsmenu() + wid = Win.FrontWindow() + if wid and self._windows.has_key(wid): + self.checkmenus(self._windows[wid]) + else: + self.checkmenus(None) + result = MenuToolbox.MenuSelect(where) + id = (result>>16) & 0xffff # Hi word + item = result & 0xffff # Lo word + self.do_rawmenu(id, item, window, event) + + def do_updateEvt(self, event): + (what, message, when, where, modifiers) = event + wid = Win.WhichWindow(message) + if wid and self._windows.has_key(wid): + window = self._windows[wid] + window.do_rawupdate(wid, event) + else: + if wid: + wid.HideWindow() + import sys + sys.stderr.write("XXX killed unknown (crashed?) Python window.\n") + else: + MacOS.HandleEvent(event) + + def suspendresume(self, onoff): + pass + + def do_suspendresume(self, event): + # Is this a good idea??? + (what, message, when, where, modifiers) = event + self._suspended = not message & 1 + self.suspendresume(message & 1) + w = Win.FrontWindow() + if w: + # XXXX Incorrect, should stuff windowptr into message field + nev = (Events.activateEvt, w, when, where, message&1) + self.do_activateEvt(nev) + + def checkopenwindowsmenu(self): + if self._openwindowscheckmark: + self.openwindowsmenu.menu.CheckItem(self._openwindowscheckmark, 0) + window = Win.FrontWindow() + if window: + for item, wid in self._openwindows.items(): + if wid == window: + #self.pythonwindowsmenuitem.check(1) + self.openwindowsmenu.menu.CheckItem(item, 1) + self._openwindowscheckmark = item + break + else: + self._openwindowscheckmark = 0 + #if self._openwindows: + # self.pythonwindowsmenuitem.enable(1) + #else: + # self.pythonwindowsmenuitem.enable(0) + + def checkmenus(self, window): + for item in self._menustocheck: + callback = item.menu.items[item.item-1][2] + if type(callback) <> StringType: + item.enable(1) + elif hasattr(window, "domenu_" + callback): + if hasattr(window, "can_" + callback): + canhandler = getattr(window, "can_" + callback) + if canhandler(item): + item.enable(1) + else: + item.enable(0) + else: + item.enable(1) + else: + item.enable(0) + + def makemenubar(self): + self.menubar = MenuBar(self) + FrameWork.AppleMenu(self.menubar, self.getabouttext(), self.do_about) + self.makeusermenus() + + def scriptswalk(self, top, menu): + import os, macfs, string + try: + names = os.listdir(top) + except os.error: + FrameWork.MenuItem(menu, '(Scripts Folder not found)', None, None) + return + for name in names: + path = os.path.join(top, name) + name = string.strip(name) + if name[-3:] == '---': + menu.addseparator() + elif os.path.isdir(path): + submenu = FrameWork.SubMenu(menu, name) + self.scriptswalk(path, submenu) + else: + fss = macfs.FSSpec(path) + creator, type = fss.GetCreatorType() + if type == 'TEXT': + if name[-3:] == '.py': + name = name[:-3] + item = FrameWork.MenuItem(menu, name, None, self.domenu_script) + self._scripts[(menu.id, item.item)] = path + + def domenu_script(self, id, item, window, event): + (what, message, when, where, modifiers) = event + path = self._scripts[(id, item)] + import os + if not os.path.exists(path): + self.makescriptsmenu() + import W + raise W.AlertError, "File not found." + if modifiers & FrameWork.optionKey: + self.openscript(path) + else: + import W, MacOS, sys + W.SetCursor("watch") + sys.argv = [path] + #cwd = os.getcwd() + #os.chdir(os.path.dirname(path) + ':') + try: + # xxx if there is a script window for this file, + # exec in that window's namespace. + # xxx what to do when it's not saved??? + # promt to save? + MacOS.EnableAppswitch(0) + execfile(path, {'__name__': '__main__', '__file__': path}) + except W.AlertError, detail: + MacOS.EnableAppswitch(-1) + raise W.AlertError, detail + except KeyboardInterrupt: + MacOS.EnableAppswitch(-1) + except: + MacOS.EnableAppswitch(-1) + import PyEdit + PyEdit.tracebackwindow.traceback(1) + else: + MacOS.EnableAppswitch(-1) + #os.chdir(cwd) + + def openscript(self, filename, lineno = None, charoffset = 0): + import os, PyEdit, W + editor = self.getscript(filename) + if editor: + editor.select() + elif os.path.exists(filename): + editor = PyEdit.Editor(filename) + elif filename[-3:] == '.py': + import imp + modname = os.path.basename(filename)[:-3] + try: + f, filename, (suff, mode, dummy) = imp.find_module(modname) + except ImportError: + raise W.AlertError, "Canıt find file for ³%s²" % modname + else: + f.close() + if suff == '.py': + self.openscript(filename, lineno, charoffset) + return + else: + raise W.AlertError, "Canıt find file for ³%s²" % modname + else: + raise W.AlertError, "Canıt find file %sı" % filename + if lineno is not None: + editor.selectline(lineno, charoffset) + return editor + + def getscript(self, filename): + if filename[:1] == '<' and filename[-1:] == '>': + filename = filename[1:-1] + import string + lowpath = string.lower(filename) + for wid, window in self._windows.items(): + if hasattr(window, "path") and lowpath == string.lower(window.path): + return window + elif hasattr(window, "path") and filename == wid.GetWTitle(): + return window + + def getprefs(self): + import MacPrefs + return MacPrefs.GetPrefs(self.preffilepath) + + + +class MenuBar(FrameWork.MenuBar): + + possibleIDs = range(10, 256) + + def getnextid(self): + id = self.possibleIDs[0] + del self.possibleIDs[0] + return id + + def __init__(self, parent = None): + self.bar = MenuToolbox.GetMenuBar() + MenuToolbox.ClearMenuBar() + self.menus = {} + self.parent = parent + + def dispatch(self, id, item, window, event): + if self.menus.has_key(id): + self.menus[id].dispatch(id, item, window, event) + + def delmenu(self, id): + MenuToolbox.DeleteMenu(id) + if id in self.possibleIDs: + print "XXX duplicate menu ID!", id + self.possibleIDs.append(id) + + +class Menu(FrameWork.Menu): + + def dispatch(self, id, item, window, event): + title, shortcut, callback, kind = self.items[item-1] + if type(callback) == StringType: + callback = self._getmenuhandler(callback) + if callback: + import W + W.CallbackCall(callback, 0, id, item, window, event) + + def _getmenuhandler(self, callback): + menuhandler = None + 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) + elif hasattr(self.bar.parent, "domenu_" + callback): + menuhandler = getattr(self.bar.parent, "domenu_" + callback) + return menuhandler + diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wbase.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wbase.py new file mode 100644 index 0000000..bcd7789 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wbase.py @@ -0,0 +1,612 @@ +import Qd +import Win +import QuickDraw +import Evt +import string +from types import * +from SpecialKeys import * +import sys + +WidgetsError = "WidgetsError" + +DEBUG = 0 + +class Widget: + + _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.SetPort() + self._visible = onoff + print 'Background' + if self._visible and self._backcolor: + penstate = Qd.GetPenState() + Qd.RGBForeColor(self._backcolor) + Qd.FrameRect(self._bounds) + Qd.RGBForeColor((0, 0, 0)) + Qd.SetPenState(penstate) + + for w in self._widgets: + w.show(onoff) + 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): + #print "yep.", 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): + #print "xxx Closing Widget" + 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() + Win.InvalRect(oldbounds) + Win.InvalRect(self._bounds) + + def _calcbounds(self): + oldbounds = self._bounds + pl, pt, pr, pb = self._parent._bounds + if callable(self._possize): + width = pr - pl + height = pb - pt + self._bounds = Qd.OffsetRect(self._possize(width, height), pl, pt) + else: + l, t, r, b = self._possize + if l < -1: + l = pr + l + else: + l = pl + l + if t < -1: + t = pb + t + else: + t = pt + t + if r > 1: + r = l + r + else: + r = pr + r + if b > 1: + b = t + b + else: + 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") + Win.InvalRect(widget._bounds) + + 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() + Win.InvalRect(widget._bounds) + widget.close() + del self._widgetsdict[key] + self._widgets.remove(widget) + + def __setattr__(self, attr, value): + if type(value) == InstanceType and HasBaseClass(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() + + def __del__(self): + if DEBUG: + print "%s instance deleted" % self.__class__.__name__ + + def _drawbounds(self): + Qd.FrameRect(self._bounds) + + +class ClickableWidget(Widget): + + 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): + + _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: + Win.InvalRect(Qd.InsetRect(oldbounds, -3, -3)) + Win.InvalRect(Qd.InsetRect(self._bounds, -3, -3)) + else: + Win.InvalRect(oldbounds) + Win.InvalRect(self._bounds) + + +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.draw() + + def setpattern(self, pattern): + self._framepattern = pattern + 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) + + +class Group(Widget): pass + + +class HorizontalPanes(Widget): + + _direction = 1 + + def __init__(self, possize, panesizes = None, gutter = 8): + ClickableWidget.__init__(self, possize) + self._panesizes = panesizes + self._gutter = gutter + self._enabled = 1 + self.setuppanes() + + def open(self): + self.installbounds() + ClickableWidget.open(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: + 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) + self._panesizes.append(current, current + panesize) + 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): + + _direction = 0 + boundstemplate = "lambda width, height: (width * %s + %d, 0, width * %s + %d, height)" + + +# misc utils + +def CallbackCall(callback, mustfit, *args): + 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 +} + +def SetCursor(what): + Qd.SetCursor(_cursors[what]) diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wcontrols.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wcontrols.py new file mode 100644 index 0000000..8c3c395 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wcontrols.py @@ -0,0 +1,376 @@ +import Ctl +import Controls +import Win +import Wbase +import Qd +import Evt + +class ControlWidget(Wbase.ClickableWidget): + + def __init__(self, possize, title = "Control", procID = 0, callback = None, value = 0, min = 0, max = 1): + Wbase.ClickableWidget.__init__(self, possize) + self._control = None + self._title = title + self._callback = callback + self._procID = procID + self._value = value + self._min = min + self._max = max + self._enabled = 1 + + def open(self): + self._calcbounds() + self._control = Ctl.NewControl(self._parentwindow.wid, + self._bounds, + self._title, + 1, + self._value, + self._min, + self._max, + self._procID, + 0) + self.SetPort() + Win.ValidRect(self._bounds) + self.enable(self._enabled) + + def adjust(self, oldbounds): + self.SetPort() + self._control.HideControl() + self._control.MoveControl(self._bounds[0], self._bounds[1]) + self._control.SizeControl(self._bounds[2] - self._bounds[0], self._bounds[3] - self._bounds[1]) + if self._visible: + Qd.EraseRect(self._bounds) + self._control.ShowControl() + Win.ValidRect(self._bounds) + + def close(self): + self._control.HideControl() + self._control = None + Wbase.ClickableWidget.close(self) + + def enable(self, onoff): + if self._control and self._enabled <> onoff: + self._control.HiliteControl((not onoff) and 255) + self._enabled = onoff + + def show(self, onoff): + self._visible = onoff + for w in self._widgets: + w.show(onoff) + if onoff: + self._control.ShowControl() + else: + self._control.HideControl() + + def activate(self, onoff): + self._activated = onoff + if self._enabled: + self._control.HiliteControl((not onoff) and 255) + + def draw(self, visRgn = None): + if self._visible: + self._control.Draw1Control() + + def test(self, point): + ctltype, control = Ctl.FindControl(point, self._parentwindow.wid) + if self._enabled and control == self._control: + return 1 + + def click(self, point, modifiers): + if not self._enabled: + return + part = self._control.TrackControl(point) + if part: + if self._callback: + Wbase.CallbackCall(self._callback, 0) + + def settitle(self, title): + if self._control: + self._control.SetControlTitle(title) + self._title = title + + def gettitle(self): + return self._title + +class Button(ControlWidget): + + def __init__(self, possize, title = "Button", callback = None): + procID = Controls.pushButProc | Controls.useWFont + ControlWidget.__init__(self, possize, title, procID, callback, 0, 0, 1) + self._isdefault = 0 + + def push(self): + if not self._enabled: + return + import time + self._control.HiliteControl(1) + time.sleep(0.1) + self._control.HiliteControl(0) + if self._callback: + Wbase.CallbackCall(self._callback, 0) + + def enable(self, onoff): + if self._control and self._enabled <> onoff: + self._control.HiliteControl((not onoff) and 255) + self._enabled = onoff + if self._isdefault and self._visible: + self.SetPort() + self.drawfatframe(onoff) + + def activate(self, onoff): + self._activated = onoff + if self._enabled: + self._control.HiliteControl((not onoff) and 255) + if self._isdefault and self._visible: + self.SetPort() + self.drawfatframe(onoff) + + def show(self, onoff): + ControlWidget.show(self, onoff) + if self._isdefault: + self.drawfatframe(onoff and self._enabled) + + def draw(self, visRgn = None): + if self._visible: + self._control.Draw1Control() + if self._isdefault and self._activated: + self.drawfatframe(self._enabled) + + def drawfatframe(self, onoff): + state = Qd.GetPenState() + if onoff: + Qd.PenPat(Qd.qd.black) + else: + Qd.PenPat(Qd.qd.white) + fatrect = Qd.InsetRect(self._bounds, -4, -4) + Qd.PenSize(3, 3) + Qd.FrameRoundRect(fatrect, 16, 16) + Qd.SetPenState(state) + + def _setdefault(self, onoff): + self._isdefault = onoff + if self._control: + self.SetPort() + self.drawfatframe(onoff) + + def adjust(self, oldbounds): + if self._isdefault: + old = Qd.InsetRect(oldbounds, -4, -4) + new = Qd.InsetRect(self._bounds, -4, -4) + Qd.EraseRect(old) + Win.InvalRect(old) + Win.InvalRect(new) + ControlWidget.adjust(self, oldbounds) + + +class CheckBox(ControlWidget): + + def __init__(self, possize, title = "Checkbox", callback = None, value = 0): + procID = Controls.checkBoxProc | Controls.useWFont + ControlWidget.__init__(self, possize, title, procID, callback, value, 0, 1) + + def click(self, point, modifiers): + if not self._enabled: + return + part = self._control.TrackControl(point) + if part: + self.toggle() + if self._callback: + Wbase.CallbackCall(self._callback, 0, self.get()) + + def push(self): + if not self._enabled: + return + self.toggle() + if self._callback: + Wbase.CallbackCall(self._callback, 0, self.get()) + + def toggle(self): + self.set(not self.get()) + + def set(self, value): + if self._control: + self._control.SetControlValue(value) + else: + self._value = value + + def get(self): + if self._control: + return self._control.GetControlValue() + else: + return self._value + + +class RadioButton(ControlWidget): + + def __init__(self, possize, title = "Radiobutton", thebuttons, callback = None, value = 0): + procID = Controls.radioButProc | Controls.useWFont + ControlWidget.__init__(self, possize, title, procID, callback, value, 0, 1) + self.thebuttons = thebuttons + thebuttons.append(self) + + def close(self): + self.thebuttons = None + ControlWidget.close(self) + + def click(self, point, modifiers): + if not self._enabled: + return + part = self._control.TrackControl(point) + if part: + self.set(1) + if self._callback: + Wbase.CallbackCall(self._callback, 0, 1) + + def push(self): + if not self._enabled: + return + self.set(1) + if self._callback: + Wbase.CallbackCall(self._callback, 0, 1) + + def set(self, value): + for button in self.thebuttons: + if button._control: + button._control.SetControlValue(button == self) + else: + button._value = (button == self) + + def get(self): + if self._control: + return self._control.GetControlValue() + else: + return self._value + + +class Scrollbar(ControlWidget): + + def __init__(self, possize, callback = None, value = 0, min = 0, max = 0): + procID = Controls.scrollBarProc + ControlWidget.__init__(self, possize, "", procID, callback, value, min, max) + + # interface + def set(self, value): + if self._callback: + Wbase.CallbackCall(self._callback, 1, value) + + def up(self): + if self._callback: + Wbase.CallbackCall(self._callback, 1, '+') + + def down(self): + if self._callback: + Wbase.CallbackCall(self._callback, 1, '-') + + def pageup(self): + if self._callback: + Wbase.CallbackCall(self._callback, 1, '++') + + def pagedown(self): + if self._callback: + Wbase.CallbackCall(self._callback, 1, '--') + + def setmin(self, min): + self._control.SetControlMinimum(min) + + def setmax(self, min): + self._control.SetControlMinimum(max) + + def getmin(self): + return self._control.GetControlMinimum() + + def getmax(self): + return self._control.GetControlMinimum() + + # internals + def click(self, point, modifiers): + if not self._enabled: + return + # custom TrackControl. A mousedown in a scrollbar arrow or page area should + # generate _control hits as long as the mouse is a) down, b) still in the same part + part = self._control.TestControl(point) + if Controls.inUpButton <= part <= Controls.inPageDown: + self._control.HiliteControl(part) + self._hit(part) + oldpart = part + while Evt.StillDown(): + part = self._control.TestControl(point) + if part == oldpart: + self._control.HiliteControl(part) + self._hit(part) + else: + self._control.HiliteControl(0) + self.SetPort() + point = Evt.GetMouse() + self._control.HiliteControl(0) + elif part == Controls.inThumb: + part = self._control.TrackControl(point) + if part: + self._hit(part) + + def _hit(self, part): + if part == Controls.inThumb: + value = self._control.GetControlValue() + elif part == Controls.inUpButton: + value = "+" + elif part == Controls.inDownButton: + value = "-" + elif part == Controls.inPageUp: + value = "++" + elif part == Controls.inPageDown: + value = "--" + if self._callback: + Wbase.CallbackCall(self._callback, 1, value) + + def draw(self, visRgn = None): + if self._visible: + self._control.Draw1Control() + Qd.FrameRect(self._bounds) + + def adjust(self, oldbounds): + self.SetPort() + Win.InvalRect(oldbounds) + self._control.HideControl() + self._control.MoveControl(self._bounds[0], self._bounds[1]) + self._control.SizeControl(self._bounds[2] - self._bounds[0], self._bounds[3] - self._bounds[1]) + if self._visible: + Qd.EraseRect(self._bounds) + if self._activated: + self._control.ShowControl() + else: + Qd.FrameRect(self._bounds) + Win.ValidRect(self._bounds) + + def activate(self, onoff): + self._activated = onoff + if self._visible: + if onoff: + self._control.ShowControl() + else: + self._control.HideControl() + self.draw(None) + Win.ValidRect(self._bounds) + + def set(self, value): + if self._control: + self._control.SetControlValue(value) + else: + self._value = value + + def get(self): + if self._control: + return self._control.GetControlValue() + else: + return self._value + + +def _scalebarvalue(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) - (curmax - curmin)) + return int(perc*32767) + diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wdialogs.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wdialogs.py new file mode 100644 index 0000000..b954255 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wdialogs.py @@ -0,0 +1,183 @@ +import W +from types import * +import string + +""" +import Wdialogs +testDict1 = {1:1, 2:2, 3:3} +testDict2 = {3:3,4:4, 'testDict1':testDict1, 6:6, 7:7} +testDict3 = {3:3,4:4, 'testDict2':testDict2, 'testDict1':testDict1, 6:6, 7:7} +Wdialogs.EditDictionary(testDict3) + +import Wdialogs +a = Wdialogs.Ask('xxx', 'default text', ['font', 'typografie', 'lettertonwerpen', 'huisstijl']) +""" + +def Message(text, button = "OK"): + w = W.ModalDialog((300, 100)) + w.button = W.Button((-90, -30, 80, 16), button, w.close) + w.message = W.TextBox((10, 10, -10, -40), text) + w.setdefaultbutton(w.button) + w.open() + + +def Ask(question, defaulttext = "", selections = []): + d = _Ask(question, defaulttext, selections) + return d.rv + + +class _Ask: + # selections is a list of possible for selections + + def __init__(self, question, defaulttext, selections): + self.selections = [] + for s in selections: + self.selections.append(string.lower(s)) + self.selections.sort() + self.w = W.ModalDialog((300, 120)) + self.w.button1 = W.Button((-90, -30, 80, 16), "OK", self.button1hit) + self.w.button2 = W.Button((-180, -30, 80, 16), "Cancel", self.button2hit) + self.w.question = W.TextBox((10, 10, -10, 30), question) + self.w.input = W.EditText((10, 40, -10, 20), defaulttext, self.processInput) + self.rv = None + self.w.setdefaultbutton(self.w.button1) + + self.w.bind("cmd.", self.w.button2.push) + self.w.open() + + def processInput(self, key, modifiers): # Process user input to match a selection + pos = self.w.input.getselection() + input = string.lower(self.w.input.get()[0:pos[1]]) + if len(input): + for t in self.selections: + if input == t[0:pos[0]]: + self.w.input.set(t) + self.w.input.setselection(pos[0], pos[1]) + return + self.w.input.set(input) + self.w.input.setselection(pos[1], pos[1]) + + def button1hit(self): + self.rv = self.w.input.get() + self.w.close() + + def button2hit(self): + self.w.close() + +class _AskYesNo: + + def __init__(self, question, cancelFlag= 0): + if cancelFlag: + size = 190, 80 + else: size = 150, 80 + self.w = W.ModalDialog(size) + self.w.yes = W.Button((10, -36, 50, 24), 'Yes', self.yes) + if cancelFlag: + self.w.cancel = W.Button((70, -36, -70, 24), "Cancel", self.cancel) + self.w.no = W.Button((-60, -36, -10, 24), 'No', self.no) + self.w.question = W.TextBox((10, 10, -10, 30), question) + self.rv = None + self.w.setdefaultbutton(self.w.yes) + if cancelFlag: + self.w.bind("cmd.", self.w.cancel) + else: self.w.bind("cmd.", self.w.no) + self.w.open() + + def yes(self): + self.rv = 1 + self.w.close() + + def no(self): + self.rv = 0 + self.w.close() + + def cancel(self): + self.rv = -1 + self.w.close() + +def AskYesNo(question): + d = _AskYesNo(question, 0) + return d.rv + +def AskYesCancelNo(question): + d = _AskYesNo(question, 1) + return d.rv + +class CallBackButton(W.Button): + def click(self, point, modifiers): + if not self._enabled: + return + part = self._control.TrackControl(point) + if part: + if self._callback: + self._callback(self.dict) + + def push(self): + if not self._enabled: + return + import time + self._control.HiliteControl(1) + time.sleep(0.1) + self._control.HiliteControl(0) + if self._callback: + self._callback(self.dict) + +class EditDictionary: # Auto layout editor of dictionary + def __init__(self, dictionary, title = 'Dictionary Editor'): + self.leading = 20 + self.d = dictionary + keys = self.d.keys() + windowSize = 400, len(keys) * self.leading + 100 + self.w = w = W.ModalDialog(windowSize) + y = 2 * self.leading + theFont = fontsettings = ('Geneva', 0, 10, (0,0,0)) + keys.sort() + for key in keys: + if type(key) == StringType: + label = key + else: label = `key` + if type(self.d[key]) == StringType: + value = self.d[key] + else: + value = `self.d[key]` # Just show the value + + if type(self.d[key]) == DictType: # Make a button + button = w[label] = CallBackButton((110, y, 50, 18), label, self.pushDict) + button.dict = self.d[key] + else: + w['k_' + label] = W.TextBox((10, y, 200, 18), label, fontsettings = theFont) + w[label] = W.EditText((110, y, -10, 18), value, fontsettings = theFont) + y = y + self.leading + + w._name = W.TextBox((10, 4, 100, 10), title) + w._ok = W.Button((-160, -36, 60, 24), "OK", self.ok) + w._cancel = W.Button((-80, -36, 60, 24), "Cancel", self.cancel) + w.setdefaultbutton(self.w._ok) + + self.rv = None # Return value + w.open() + + def pushDict(self, dict): + EditDictionary(dict) + + def popDict(self): + self.w.close() + + def ok(self): + self.rv = 1 + for key in self.d.keys(): + if type(key) == StringType: + label = key + else: label = `key` + if type(self.d[key]) == StringType or self.d[key] == None: + self.d[key] = self.w[label].get() + else: + try: + self.d[key] = eval(self.w[label].get()) + except: + pass + self.popDict() + + def cancel(self): + self.rv = 0 + self.popDict() diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wgrid.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wgrid.py new file mode 100644 index 0000000..efd7cb9 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wgrid.py @@ -0,0 +1,33 @@ +"""grid utility for widgets""" + +class Grid: + + def __init__(self, ncol = None, + minncol = None, + maxncol = None, + colwidth = None, + mincolwidth = None, + maxcolwidth = None, + width = None, + minwidth = None, + maxwidth = None, + vgrid = 8, + gutter = 10, + leftmargin = None, + rightmargin = None, + topmargin = None, + bottommargin = None + ): + if leftmargin == None: + leftmargin = gutter + if rightmargin == None: + rightmargin = gutter + if topmargin == None: + topmargin = vgrid + if bottommargin == None: + bottommargin = vgrid + + def getbounds(self, width, height, bounds): + xxx + + diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wlist.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wlist.py new file mode 100644 index 0000000..028e878 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wlist.py @@ -0,0 +1,425 @@ +import Wbase +import Scrap +from SpecialKeys import * +import string +import Evt +import Events +import Qd +import Win + + +class List(Wbase.SelectableWidget): + + LDEF_ID = 0 + + def __init__(self, possize, items = None, callback = None, flags = 0, cols = 1): + if items is None: + items = [] + self.items = items + Wbase.SelectableWidget.__init__(self, possize) + self._selected = 0 + self._enabled = 1 + self._list = None + self._cols = cols + self._callback = callback + self._flags = flags + self.lasttyping = "" + self.lasttime = Evt.TickCount() + self.timelimit = 30 + self.setitems(items) + self.drawingmode = 0 + + def open(self): + self.setdrawingmode(0) + self.createlist() + self.setdrawingmode(1) + + def createlist(self): + import List + self._calcbounds() + self.SetPort() + rect = self._bounds + rect = rect[0]+1, rect[1]+1, rect[2]-16, rect[3]-1 + self._list = List.LNew(rect, (0, 0, self._cols, 0), (0, 0), self.LDEF_ID, self._parentwindow.wid, + 0, 1, 0, 1) + if self.drawingmode: + self._list.LSetDrawingMode(0) + self._list.selFlags = self._flags + self.setitems(self.items) + if hasattr(self, "_sel"): + self.setselection(self._sel) + del self._sel + + def adjust(self, oldbounds): + self.SetPort() + if self._selected: + Win.InvalRect(Qd.InsetRect(oldbounds, -3, -3)) + Win.InvalRect(Qd.InsetRect(self._bounds, -3, -3)) + else: + Win.InvalRect(oldbounds) + Win.InvalRect(self._bounds) + if oldbounds[:2] == self._bounds[:2]: + # list still has the same upper/left coordinates, use LSize + l, t, r, b = self._bounds + width = r - l - 17 + height = b - t - 2 + self._list.LSize(width, height) + # now *why* deosn't the list manager recalc the cellrect??? + l, t, r, b = self._list.LRect((0,0)) + cellheight = b - t + self._list.LCellSize((width, cellheight)) + else: + # oh well, sice the list manager doesn't have a LMove call, + # we have to make the list all over again... + sel = self.getselection() + topcell = self.gettopcell() + self._list = None + self.setdrawingmode(0) + self.createlist() + self.setselection(sel) + self.settopcell(topcell) + self.setdrawingmode(1) + + def close(self): + self._list = None + self._callback = None + self.items[:] = [] + Wbase.SelectableWidget.close(self) + + def set(self, items): + self.setitems(items) + + def setitems(self, items): + self.items = items + the_list = self._list + if not self._parent or not self._list: + return + self.setdrawingmode(0) + topcell = self.gettopcell() + the_list.LDelRow(0, 1) + the_list.LAddRow(len(self.items), 0) + self_itemrepr = self.itemrepr + set_cell = the_list.LSetCell + for i in range(len(items)): + set_cell(self_itemrepr(items[i]), (0, i)) + self.settopcell(topcell) + self.setdrawingmode(1) + + def click(self, point, modifiers): + if not self._enabled: + return + isdoubleclick = self._list.LClick(point, modifiers) + if self._callback: + Wbase.CallbackCall(self._callback, 0, isdoubleclick) + return 1 + + def key(self, char, event): + (what, message, when, where, modifiers) = event + sel = self.getselection() + newselection = [] + if char == uparrowkey: + if len(sel) >= 1 and min(sel) > 0: + newselection = [min(sel) - 1] + else: + newselection = [0] + elif char == downarrowkey: + if len(sel) >= 1 and max(sel) < (len(self.items) - 1): + newselection = [max(sel) + 1] + else: + newselection = [len(self.items) - 1] + else: + modifiers = 0 + if (self.lasttime + self.timelimit) < Evt.TickCount(): + self.lasttyping = "" + self.lasttyping = self.lasttyping + string.lower(char) + self.lasttime = Evt.TickCount() + i = self.findmatch(self.lasttyping) + newselection = [i] + if modifiers & Events.shiftKey: + newselection = newselection + sel + self.setselection(newselection) + self._list.LAutoScroll() + self.click((-1, -1), 0) + + def findmatch(self, tag): + lower = string.lower + items = self.items + taglen = len(tag) + match = '\377' * 100 + match_i = -1 + for i in range(len(items)): + item = lower(str(items[i])) + if tag <= item < match: + match = item + match_i = i + if match_i >= 0: + return match_i + else: + return len(items) - 1 + + def domenu_copy(self, *args): + sel = self.getselection() + selitems = [] + for i in sel: + selitems.append(str(self.items[i])) + text = string.join(selitems, '\r') + if text: + Scrap.ZeroScrap() + Scrap.PutScrap('TEXT', text) + + def can_copy(self, *args): + return len(self.getselection()) <> 0 + + def domenu_selectall(self, *args): + self.selectall() + + def selectall(self): + self.setselection(range(len(self.items))) + self._list.LAutoScroll() + self.click((-1, -1), 0) + + def getselection(self): + if not self._parent or not self._list: + if hasattr(self, "_sel"): + return self._sel + return [] + items = [] + point = (0,0) + while 1: + ok, point = self._list.LGetSelect(1, point) + if not ok: + break + items.append(point[1]) + point = point[0], point[1]+1 + return items + + def setselection(self, selection): + if not self._parent or not self._list: + self._sel = selection + return + set_sel = self._list.LSetSelect + for i in range(len(self.items)): + if i in selection: + set_sel(1, (0, i)) + else: + set_sel(0, (0, i)) + self._list.LAutoScroll() + + def getselectedobjects(self): + sel = self.getselection() + objects = [] + for i in sel: + objects.append(self.items[i]) + return objects + + def setselectedobjects(self, objects): + sel = [] + for o in objects: + try: + sel.append(self.items.index(o)) + except: + pass + self.setselection(sel) + + def gettopcell(self): + l, t, r, b = self._bounds + t = t + 1 + cl, ct, cr, cb = self._list.LRect((0, 0)) + cellheight = cb - ct + return (t - ct) / cellheight + + def settopcell(self, topcell): + top = self.gettopcell() + diff = topcell - top + self._list.LScroll(0, diff) + + def draw(self, visRgn = None): + if self._visible: + if not visRgn: + visRgn = self._parentwindow.wid.GetWindowPort().visRgn + self._list.LUpdate(visRgn) + Qd.FrameRect(self._bounds) + if self._selected and self._activated: + self.drawselframe(1) + + def adjust(self, oldbounds): + self.SetPort() + if self._selected: + Win.InvalRect(Qd.InsetRect(oldbounds, -3, -3)) + Win.InvalRect(Qd.InsetRect(self._bounds, -3, -3)) + else: + Win.InvalRect(oldbounds) + Win.InvalRect(self._bounds) + if oldbounds[:2] == self._bounds[:2]: + # list still has the same upper/left coordinates, use LSize + l, t, r, b = self._bounds + width = r - l - 17 + height = b - t - 2 + self._list.LSize(width, height) + # now *why* deosn't the list manager recalc the cellrect??? + l, t, r, b = self._list.LRect((0,0)) + cellheight = b - t + self._list.LCellSize((width, cellheight)) + else: + # oh well, sice the list manager doesn't have a LMove call, + # we have to make the list all over again... + sel = self.getselection() + topcell = self.gettopcell() + self._list = None + self.setdrawingmode(0) + self.createlist() + self.setselection(sel) + self.settopcell(topcell) + self.setdrawingmode(1) + + def select(self, onoff, isclick = 0): + if Wbase.SelectableWidget.select(self, onoff): + return + self.SetPort() + self.drawselframe(onoff) + + def activate(self, onoff): + self._activated = onoff + if self._visible: + self._list.LActivate(onoff) + if self._selected: + self.drawselframe(onoff) + + def get(self): + return self.items + + def itemrepr(self, item): + return str(item)[:255] + + def __getitem__(self, index): + return self.items[index] + + def __setitem__(self, index, item): + if self._parent and self._list: + self._list.LSetCell(self.itemrepr(item), (0, index)) + self.items[index] = item + + def __delitem__(self, index): + if self._parent and self._list: + self._list.LDelRow(1, index) + del self.items[index] + + def __getslice__(self, a, b): + return self.items[a:b] + + def __delslice__(self, a, b): + if b-a: + if self._parent and self._list: + self._list.LDelRow(b-a, a) + del self.items[a:b] + + def __setslice__(self, a, b, items): + if self._parent and self._list: + l = len(items) + the_list = self._list + self.setdrawingmode(0) + if b-a: + if b > len(self.items): + # fix for new 1.5 "feature" where b is sys.maxint instead of len(self)... + # LDelRow doesn't like maxint. + b = len(self.items) + the_list.LDelRow(b-a, a) + the_list.LAddRow(l, a) + self_itemrepr = self.itemrepr + set_cell = the_list.LSetCell + for i in range(len(items)): + set_cell(self_itemrepr(items[i]), (0, i + a)) + self.items[a:b] = items + self.setdrawingmode(1) + else: + self.items[a:b] = items + + def __len__(self): + return len(self.items) + + def append(self, item): + if self._parent and self._list: + index = len(self.items) + self._list.LAddRow(1, index) + self._list.LSetCell(self.itemrepr(item), (0, index)) + self.items.append(item) + + def remove(self, item): + index = self.items.index(item) + self.__delitem__(index) + + def index(self, item): + return self.items.index(item) + + def insert(self, index, item): + if index < 0: + index = 0 + if self._parent and self._list: + self._list.LAddRow(1, index) + self._list.LSetCell(self.itemrepr(item), (0, index)) + self.items.insert(index, item) + + def setdrawingmode(self, onoff): + if onoff: + self.drawingmode = self.drawingmode - 1 + if self.drawingmode == 0 and self._list is not None: + self._list.LSetDrawingMode(1) + if self._visible: + bounds = l, t, r, b = Qd.InsetRect(self._bounds, 1, 1) + cl, ct, cr, cb = self._list.LRect((0, len(self.items)-1)) + if cb < b: + self.SetPort() + Qd.EraseRect((l, cb, cr, b)) + self._list.LUpdate(self._parentwindow.wid.GetWindowPort().visRgn) + Win.ValidRect(bounds) + else: + if self.drawingmode == 0 and self._list is not None: + self._list.LSetDrawingMode(0) + self.drawingmode = self.drawingmode + 1 + + +class MultiList(List): + + def setitems(self, items): + self.items = items + if not self._parent or not self._list: + return + self._list.LDelRow(0, 1) + self.setdrawingmode(0) + self._list.LAddRow(len(self.items), 0) + self_itemrepr = self.itemrepr + set_cell = self._list.LSetCell + for i in range(len(items)): + row = items[i] + for j in range(len(row)): + item = row[j] + set_cell(self_itemrepr(item), (j, i)) + self.setdrawingmode(1) + + def getselection(self): + if not self._parent or not self._list: + if hasattr(self, "_sel"): + return self._sel + return [] + items = [] + point = (0,0) + while 1: + ok, point = self._list.LGetSelect(1, point) + if not ok: + break + items.append(point[1]) + point = point[0], point[1]+1 + return items + + def setselection(self, selection): + if not self._parent or not self._list: + self._sel = selection + return + set_sel = self._list.LSetSelect + for i in range(len(self.items)): + if i in selection: + set_sel(1, (0, i)) + else: + set_sel(0, (0, i)) + #self._list.LAutoScroll() + diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wmenus.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wmenus.py new file mode 100644 index 0000000..350e036 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wmenus.py @@ -0,0 +1,182 @@ +import FrameWork +import Qd +import Wbase +from types import * +import WFrameWorkPatch + +_arrowright = Qd.GetPicture(472) +_arrowdown = Qd.GetPicture(473) + + + +class PopupWidget(Wbase.ClickableWidget): + + def __init__(self, possize, items = [], callback = None): + Wbase.Widget.__init__(self, possize) + self._items = items + self._itemsdict = {} + self._callback = callback + self._enabled = 1 + + def close(self): + Wbase.Widget.close(self) + self._items = None + self._itemsdict = {} + + def draw(self, visRgn = None): + if self._visible: + Qd.FrameRect(self._bounds) + l, t, r, b = self._bounds + l = l + 2 + t = t + 3 + pictframe = (l, t, l + 10, t + 10) + Qd.DrawPicture(_arrowright, pictframe) + + def click(self, point, modifiers): + if not self._enabled: + return + self.menu = FrameWork.Menu(self._parentwindow.parent.menubar, 'Foo', -1) + self._additems(self._items, self.menu) + + self.SetPort() + l, t, r, b = self._bounds + l, t = Qd.LocalToGlobal((l+1, t+1)) + Wbase.SetCursor("arrow") + reply = self.menu.menu.PopUpMenuSelect(t, l, 1) + if reply: + id = (reply & 0xffff0000) >> 16 + item = reply & 0xffff + self._menu_callback(id, item) + self._emptymenu() + + def set(self, items): + self._items = items + + def _additems(self, items, menu): + from FrameWork import SubMenu, MenuItem + menu_id = menu.id + for item in items: + if item == "-": + menu.addseparator() + continue + elif type(item) == ListType: + submenu = SubMenu(menu, item[0]) + self._additems(item[1:], submenu) + continue + elif type(item) == StringType: + menuitemtext = object = item + elif type(item) == TupleType and len(item) == 2: + menuitemtext, object = item + else: + raise WidgetsError, "illegal itemlist for popup menu" + + if menuitemtext[:1] == '\0': + check = ord(menuitemtext[1]) + menuitemtext = menuitemtext[2:] + else: + check = 0 + menuitem = MenuItem(menu, menuitemtext, None, None) + if check: + menuitem.check(1) + self._itemsdict[(menu_id, menuitem.item)] = object + + def _emptymenu(self): + menus = self._parentwindow.parent.menubar.menus + for id, item in self._itemsdict.keys(): + if menus.has_key(id): + self.menu = menus[id] + self.menu.delete() + self._itemsdict = {} + + def _menu_callback(self, id, item): + thing = self._itemsdict[(id, item)] + if callable(thing): + thing() + elif self._callback: + Wbase.CallbackCall(self._callback, 0, thing) + + +class PopupMenu(PopupWidget): + + def open(self): + self._calcbounds() + self.menu = WFrameWorkPatch.Menu(self._parentwindow.parent.menubar, 'Foo', -1) + self._additems(self._items, self.menu) + + def close(self): + self._emptymenu() + Wbase.Widget.close(self) + self._items = None + self._itemsdict = {} + self.menu = None + + def set(self, items): + if self._itemsdict: + self._emptymenu() + self.menu = WFrameWorkPatch.Menu(self._parentwindow.parent.menubar, 'Foo', -1) + self._items = items + self._additems(self._items, self.menu) + + def click(self, point, modifiers): + if not self._enabled: + return + self.SetPort() + l, t, r, b = self._bounds + l, t = Qd.LocalToGlobal((l+1, t+1)) + Wbase.SetCursor("arrow") + reply = self.menu.menu.PopUpMenuSelect(t, l, 1) + if reply: + id = (reply & 0xffff0000) >> 16 + item = reply & 0xffff + self._menu_callback(id, item) + + +class FontMenu(PopupMenu): + + menu = None + + def __init__(self, possize, callback): + PopupMenu.__init__(self, possize) + makefontmenu() + self._callback = callback + self._enabled = 1 + + def open(self): + self._calcbounds() + + def close(self): + pass + + def set(self): + raise Wbase.WidgetsError, "can't change font menu widget" + + def _menu_callback(self, id, item): + fontname = self.menu.menu.GetMenuItemText(item) + if self._callback: + Wbase.CallbackCall(self._callback, 0, fontname) + + def click(self, point, modifiers): + if not self._enabled: + return + makefontmenu() + return PopupMenu.click(self, point, modifiers) + + +def makefontmenu(): + if FontMenu.menu is not None: + return + import W + FontMenu.menu = WFrameWorkPatch.Menu(W.getapplication().menubar, 'Foo', -1) + W.SetCursor('watch') + for i in range(FontMenu.menu.menu.CountMItems(), 0, -1): + FontMenu.menu.menu.DeleteMenuItem(i) + FontMenu.menu.menu.AppendResMenu('FOND') + + +def _getfontlist(): + import Res + fontnames = [] + for i in range(1, Res.CountResources('FOND') + 1): + r = Res.GetIndResource('FOND', i) + fontnames.append(r.GetResInfo()[2]) + return fontnames diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wquicktime.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wquicktime.py new file mode 100644 index 0000000..adfdadb --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wquicktime.py @@ -0,0 +1,119 @@ +import os +import Qd +import Win +import Qt, QuickTime +import W +import macfs +import Evt, Events + +_moviesinitialized = 0 + +def EnterMovies(): + global _moviesinitialized + if not _moviesinitialized: + Qt.EnterMovies() + _moviesinitialized = 1 + +class Movie(W.Widget): + + def __init__(self, possize): + EnterMovies() + self.movie = None + self.running = 0 + W.Widget.__init__(self, possize) + + def adjust(self, oldbounds): + self.SetPort() + Win.InvalRect(oldbounds) + Win.InvalRect(self._bounds) + self.calcmoviebox() + + def set(self, path_or_fss, start = 0): + self.SetPort() + if self.movie: + #Win.InvalRect(self.movie.GetMovieBox()) + Qd.PaintRect(self.movie.GetMovieBox()) + if type(path_or_fss) == type(''): + path = path_or_fss + fss = macfs.FSSpec(path) + else: + path = path_or_fss.as_pathname() + fss = path_or_fss + self.movietitle = os.path.basename(path) + movieResRef = Qt.OpenMovieFile(fss, 1) + self.movie, dummy = Qt.NewMovieFromFile(movieResRef, QuickTime.newMovieActive) + self.moviebox = self.movie.GetMovieBox() + self.calcmoviebox() + Qd.ObscureCursor() # XXX does this work at all? + self.movie.GoToBeginningOfMovie() + if start: + self.movie.StartMovie() + self.running = 1 + else: + self.running = 0 + self.movie.MoviesTask(0) + + def get(self): + return self.movie + + def getmovietitle(self): + return self.movietitle + + def start(self): + if self.movie: + Qd.ObscureCursor() + self.movie.StartMovie() + self.running = 1 + + def stop(self): + if self.movie: + self.movie.StopMovie() + self.running = 0 + + def rewind(self): + if self.movie: + self.movie.GoToBeginningOfMovie() + + def calcmoviebox(self): + if not self.movie: + return + ml, mt, mr, mb = self.moviebox + wl, wt, wr, wb = widgetbox = self._bounds + mheight = mb - mt + mwidth = mr - ml + wheight = wb - wt + wwidth = wr - wl + if (mheight * 2 < wheight) and (mwidth * 2 < wwidth): + scale = 2 + elif mheight > wheight or mwidth > wwidth: + scale = min(float(wheight) / mheight, float(wwidth) / mwidth) + else: + scale = 1 + mwidth, mheight = mwidth * scale, mheight * scale + ml, mt = wl + (wwidth - mwidth) / 2, wt + (wheight - mheight) / 2 + mr, mb = ml + mwidth, mt + mheight + self.movie.SetMovieBox((ml, mt, mr, mb)) + + def idle(self, *args): + if self.movie: + if not self.movie.IsMovieDone() and self.running: + Qd.ObscureCursor() + while 1: + self.movie.MoviesTask(0) + gotone, event = Evt.EventAvail(Events.everyEvent) + if gotone or self.movie.IsMovieDone(): + break + elif self.running: + box = self.movie.GetMovieBox() + self.SetPort() + Win.InvalRect(box) + self.movie = None + self.running = 0 + + def draw(self, visRgn = None): + if self._visible: + Qd.PaintRect(self._bounds) + if self.movie: + self.movie.UpdateMovie() + self.movie.MoviesTask(0) + diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wtext.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wtext.py new file mode 100644 index 0000000..2654cc3 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wtext.py @@ -0,0 +1,882 @@ +import Qd +import TE +import Fm +import waste +import WASTEconst +import Res +import Evt +import Events +import Scrap +import string + +import Win +import Wbase +import Wcontrols +from SpecialKeys import * +import PyFontify +from types import * +import Fonts +import TextEdit + + + +class TextBox(Wbase.Widget): + + def __init__(self, possize, text = "", align = TextEdit.teJustLeft, + fontsettings = ("Monaco", 0, 9, (0, 0, 0)), + backcolor = (0xffff, 0xffff, 0xffff) + ): + + Wbase.Widget.__init__(self, possize) + self.fontsettings = fontsettings + self.text = text + self.align = align + self.backcolor = backcolor # Settings of editor added by Petr 9/7/97 + + def draw(self, visRgn = None): + if self._visible: + (font, style, size, color) = self.fontsettings + fontid = GetFNum(font) + savestate = Qd.GetPenState() + Qd.TextFont(fontid) + Qd.TextFace(style) + Qd.TextSize(size) + Qd.RGBForeColor(color) + Qd.RGBBackColor(self.backcolor) # Added by Petr 9/7/97 + TE.TETextBox(self.text, self._bounds, self.align) + Qd.RGBBackColor((0xffff, 0xffff, 0xffff)) # Reset color Added by Petr 9/7/97 + Qd.SetPenState(savestate) + + def get(self): + return self.text + + def set(self, text): + self.text = text + if self._parentwindow and self._parentwindow.wid: + self.SetPort() + self.draw() + + +class ScrollWidget: + + # to be overridden + def getscrollbarvalues(self): + return None, None + + # internal method + def updatescrollbars(self): + vx, vy = self.getscrollbarvalues() + if self._parent._barx: + if vx <> None: + self._parent._barx.enable(1) + self._parent._barx.set(vx) + else: + self._parent._barx.enable(0) + if self._parent._bary: + if vy <> None: + self._parent._bary.enable(1) + self._parent._bary.set(vy) + else: + self._parent._bary.enable(0) + + +UNDOLABELS = [ # Indexed by WEGetUndoInfo() value + None, "", "typing", "Cut", "Paste", "Clear", "Drag", "Style"] + +class EditText(Wbase.SelectableWidget, ScrollWidget): + + def __init__(self, possize, text = "", + callback = None, inset = (3, 3), + fontsettings = ("Python-Sans", 0, 9, (0, 0, 0)), + readonly = 0): + + Wbase.SelectableWidget.__init__(self, possize) + self.temptext = text + self.ted = None + self.selection = None + self._callback = callback + self.changed = 0 + self.selchanged = 0 + self._selected = 0 + self._enabled = 1 + self.wrap = 1 + self.readonly = readonly + self.fontsettings = fontsettings + if type(inset) <> TupleType: + self.inset = (inset, inset) + else: + self.inset = inset + + def open(self): + if not hasattr(self._parent, "_barx"): + self._parent._barx = None + if not hasattr(self._parent, "_bary"): + self._parent._bary = None + self._calcbounds() + self.SetPort() + viewrect, destrect = self._calctextbounds() + flags = self._getflags() + self.ted = waste.WENew(destrect, viewrect, flags) + self.ted.WEInstallTabHooks() + self.ted.WESetAlignment(WASTEconst.weFlushLeft) + self.setfontsettings(self.fontsettings) + self.ted.WEUseText(Res.Resource(self.temptext)) + self.ted.WECalText() + if self.selection: + self.setselection(self.selection[0], self.selection[1]) + self.selection = None + else: + self.selview() + self.temptext = None + self.updatescrollbars() + self.bind("pageup", self.scrollpageup) + self.bind("pagedown", self.scrollpagedown) + self.bind("top", self.scrolltop) + self.bind("bottom", self.scrollbottom) + self.selchanged = 0 + + def close(self): + self._parent._barx = None + self._parent._bary = None + self.ted = None + self.temptext = None + Wbase.SelectableWidget.close(self) + + def getfontsettings(self): + import Res + (font, style, size, color) = self.ted.WEGetRunInfo(0)[4] + font = GetFName(font) + return (font, style, size, color) + + def setfontsettings(self, (font, style, size, color)): + self.SetPort() + if type(font) <> StringType: + font = GetFName(font) + self.fontsettings = (font, style, size, color) + fontid = GetFNum(font) + readonly = self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, -1) + if readonly: + self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 0) + self.ted.WEFeatureFlag(WASTEconst.weFInhibitRecal, 1) + selstart, selend = self.ted.WEGetSelection() + self.ted.WESetSelection(0, self.ted.WEGetTextLength()) + self.ted.WESetStyle(WASTEconst.weDoFace, (0, 0, 0, (0, 0, 0))) + self.ted.WESetStyle(WASTEconst.weDoFace | + WASTEconst.weDoColor | + WASTEconst.weDoFont | + WASTEconst.weDoSize, + (fontid, style, size, color)) + self.ted.WEFeatureFlag(WASTEconst.weFInhibitRecal, 0) + self.ted.WECalText() + self.ted.WESetSelection(selstart, selend) + if readonly: + self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 1) + viewrect = self.ted.WEGetViewRect() + Qd.EraseRect(viewrect) + self.ted.WEUpdate(self._parentwindow.wid.GetWindowPort().visRgn) + self.selchanged = 1 + self.updatescrollbars() + + def adjust(self, oldbounds): + self.SetPort() + if self._selected and self._parentwindow._hasselframes: + Win.InvalRect(Qd.InsetRect(oldbounds, -3, -3)) + Win.InvalRect(Qd.InsetRect(self._bounds, -3, -3)) + else: + Win.InvalRect(oldbounds) + Win.InvalRect(self._bounds) + viewrect, destrect = self._calctextbounds() + self.ted.WESetViewRect(viewrect) + self.ted.WESetDestRect(destrect) + if self.wrap: + self.ted.WECalText() + if self.ted.WEGetDestRect()[3] < viewrect[1]: + self.selview() + self.updatescrollbars() + + # interface ----------------------- + # selection stuff + def selview(self): + self.ted.WESelView() + + def selectall(self): + self.ted.WESetSelection(0, self.ted.WEGetTextLength()) + self.selchanged = 1 + self.updatescrollbars() + + def selectline(self, lineno, charoffset = 0): + newselstart, newselend = self.ted.WEGetLineRange(lineno) + self.ted.WESetSelection(newselstart + charoffset, newselend) + self.selchanged = 1 + self.updatescrollbars() + + def getselection(self): + if self.ted: + return self.ted.WEGetSelection() + else: + return self.selection + + def setselection(self, selstart, selend): + self.selchanged = 1 + if self.ted: + self.ted.WESetSelection(selstart, selend) + self.ted.WESelView() + self.updatescrollbars() + else: + self.selection = selstart, selend + + def offsettoline(self, offset): + return self.ted.WEOffsetToLine(offset) + + def countlines(self): + return self.ted.WECountLines() + + def getselectedtext(self): + selstart, selend = self.ted.WEGetSelection() + return self.ted.WEGetText().data[selstart:selend] + + def expandselection(self): + oldselstart, oldselend = self.ted.WEGetSelection() + selstart, selend = min(oldselstart, oldselend), max(oldselstart, oldselend) + if selstart <> selend and chr(self.ted.WEGetChar(selend-1)) == '\r': + selend = selend - 1 + newselstart, dummy = self.ted.WEFindLine(selstart, 0) + dummy, newselend = self.ted.WEFindLine(selend, 0) + if oldselstart <> newselstart or oldselend <> newselend: + self.ted.WESetSelection(newselstart, newselend) + self.updatescrollbars() + self.selchanged = 1 + + def insert(self, text): + self.ted.WEInsert(text, None, None) + self.changed = 1 + self.selchanged = 1 + + def shiftleft(self): + self.expandselection() + selstart, selend = self.ted.WEGetSelection() + selstart, selend = min(selstart, selend), max(selstart, selend) + snippet = self.getselectedtext() + lines = string.split(snippet, '\r') + for i in range(len(lines)): + if lines[i][:1] == '\t': + lines[i] = lines[i][1:] + snippet = string.join(lines, '\r') + self.insert(snippet) + self.ted.WESetSelection(selstart, selstart + len(snippet)) + + def shiftright(self): + self.expandselection() + selstart, selend = self.ted.WEGetSelection() + selstart, selend = min(selstart, selend), max(selstart, selend) + snippet = self.getselectedtext() + lines = string.split(snippet, '\r') + for i in range(len(lines) - 1): + lines[i] = '\t' + lines[i] + snippet = string.join(lines, '\r') + self.insert(snippet) + self.ted.WESetSelection(selstart, selstart + len(snippet)) + + # text + def set(self, text): + if not self.ted: + self.temptext = text + else: + self.ted.WEUseText(Res.Resource(text)) + self.ted.WECalText() + self.SetPort() + viewrect, destrect = self._calctextbounds() + self.ted.WESetViewRect(viewrect) + self.ted.WESetDestRect(destrect) + rgn = Qd.NewRgn() + Qd.RectRgn(rgn, viewrect) + Qd.EraseRect(viewrect) + self.draw(rgn) + #Win.InvalRect(self.ted.WEGetViewRect()) + self.updatescrollbars() + + def get(self): + if not self._parent: + return self.temptext + else: + return self.ted.WEGetText().data + + # events + def key(self, char, event): + (what, message, when, where, modifiers) = event + if self._enabled and not modifiers & Events.cmdKey or char in arrowkeys: + self.ted.WEKey(ord(char), modifiers) + if char not in navigationkeys: + self.changed = 1 + if char not in scrollkeys: + self.selchanged = 1 + self.updatescrollbars() + if self._callback: + Wbase.CallbackCall(self._callback, 0, char, modifiers) + + def click(self, point, modifiers): + if not self._enabled: + return + self.ted.WEClick(point, modifiers, Evt.TickCount()) + self.selchanged = 1 + self.updatescrollbars() + return 1 + + def idle(self): + self.SetPort() + self.ted.WEIdle() + + def rollover(self, point, onoff): + if onoff: + Wbase.SetCursor("iBeam") + + def activate(self, onoff): + self._activated = onoff + if self._selected and self._visible: + if onoff: + self.ted.WEActivate() + else: + self.ted.WEDeactivate() + if self._selected: + self.drawselframe(onoff) + + def select(self, onoff, isclick = 0): + if Wbase.SelectableWidget.select(self, onoff): + return + self.SetPort() + if onoff: + self.ted.WEActivate() + if self._parentwindow._tabbable and not isclick: + self.selectall() + else: + self.ted.WEDeactivate() + self.drawselframe(onoff) + + def draw(self, visRgn = None): + if self._visible: + if not visRgn: + visRgn = self._parentwindow.wid.GetWindowPort().visRgn + self.ted.WEUpdate(visRgn) + if self._selected and self._activated: + self.drawselframe(1) + Qd.FrameRect(self._bounds) + + # scrolling + def scrollpageup(self): + if self._parent._bary and self._parent._bary._enabled: + self.vscroll("++") + + def scrollpagedown(self): + if self._parent._bary and self._parent._bary._enabled: + self.vscroll("--") + + def scrolltop(self): + if self._parent._bary and self._parent._bary._enabled: + self.vscroll(0) + if self._parent._barx and self._parent._barx._enabled: + self.hscroll(0) + + def scrollbottom(self): + if self._parent._bary and self._parent._bary._enabled: + self.vscroll(32767) + + # menu handlers + def domenu_copy(self, *args): + selbegin, selend = self.ted.WEGetSelection() + if selbegin == selend: + return + Scrap.ZeroScrap() + self.ted.WECopy() + self.updatescrollbars() + + def domenu_cut(self, *args): + selbegin, selend = self.ted.WEGetSelection() + if selbegin == selend: + return + Scrap.ZeroScrap() + self.ted.WECut() + self.updatescrollbars() + self.selview() + self.changed = 1 + self.selchanged = 1 + if self._callback: + Wbase.CallbackCall(self._callback, 0, "", None) + + def domenu_paste(self, *args): + if not self.ted.WECanPaste(): + return + self.selview() + self.ted.WEPaste() + self.updatescrollbars() + self.changed = 1 + self.selchanged = 1 + if self._callback: + Wbase.CallbackCall(self._callback, 0, "", None) + + def domenu_clear(self, *args): + self.ted.WEDelete() + self.selview() + self.updatescrollbars() + self.changed = 1 + self.selchanged = 1 + if self._callback: + Wbase.CallbackCall(self._callback, 0, "", None) + + def domenu_undo(self, *args): + which, redo = self.ted.WEGetUndoInfo() + if not which: + return + self.ted.WEUndo() + self.updatescrollbars() + self.changed = 1 + self.selchanged = 1 + if self._callback: + Wbase.CallbackCall(self._callback, 0, "", None) + + def can_undo(self, menuitem): + which, redo = self.ted.WEGetUndoInfo() + which = UNDOLABELS[which] + if which == None: + return None + if redo: + which = "Redo "+which + else: + which = "Undo "+which + menuitem.settext(which) + return 1 + + def domenu_selectall(self, *args): + self.selectall() + + # private + def getscrollbarvalues(self): + dr = self.ted.WEGetDestRect() + vr = self.ted.WEGetViewRect() + vx = Wcontrols._scalebarvalue(dr[0], dr[2], vr[0], vr[2]) + vy = Wcontrols._scalebarvalue(dr[1], dr[3], vr[1], vr[3]) + return vx, vy + + def vscroll(self, value): + lineheight = self.ted.WEGetHeight(0, 1) + dr = self.ted.WEGetDestRect() + vr = self.ted.WEGetViewRect() + destheight = dr[3] - dr[1] + viewheight = vr[3] - vr[1] + viewoffset = maxdelta = vr[1] - dr[1] + mindelta = vr[3] - dr[3] + if value == "+": + delta = lineheight + elif value == "-": + delta = - lineheight + elif value == "++": + delta = viewheight - lineheight + elif value == "--": + delta = lineheight - viewheight + else: # in thumb + cur = (32767 * viewoffset) / (destheight - viewheight) + delta = (cur-value)*(destheight - viewheight)/32767 + if abs(delta - viewoffset) <=2: + # compensate for irritating rounding error + delta = viewoffset + delta = min(maxdelta, delta) + delta = max(mindelta, delta) + self.ted.WEScroll(0, delta) + self.updatescrollbars() + + def hscroll(self, value): + dr = self.ted.WEGetDestRect() + vr = self.ted.WEGetViewRect() + destwidth = dr[2] - dr[0] + viewwidth = vr[2] - vr[0] + viewoffset = maxdelta = vr[0] - dr[0] + mindelta = vr[2] - dr[2] + if value == "+": + delta = 32 + elif value == "-": + delta = - 32 + elif value == "++": + delta = 0.5 * (vr[2] - vr[0]) + elif value == "--": + delta = 0.5 * (vr[0] - vr[2]) + else: # in thumb + cur = (32767 * viewoffset) / (destwidth - viewwidth) + delta = (cur-value)*(destwidth - viewwidth)/32767 + if abs(delta - viewoffset) <=2: + # compensate for irritating rounding error + delta = viewoffset + delta = min(maxdelta, delta) + delta = max(mindelta, delta) + self.ted.WEScroll(delta, 0) + self.updatescrollbars() + + # some internals + def _getflags(self): + flags = WASTEconst.weDoAutoScroll | WASTEconst.weDoMonoStyled | \ + WASTEconst.weDoUndo + if self.readonly: + flags = flags | WASTEconst.weDoReadOnly + return flags + + def _getviewrect(self): + return Qd.InsetRect(self._bounds, self.inset[0], self.inset[1]) + + def _calctextbounds(self): + viewrect = l, t, r, b = self._getviewrect() + if self.ted: + dl, dt, dr, db = self.ted.WEGetDestRect() + vl, vt, vr, vb = self.ted.WEGetViewRect() + yshift = t - vt + if (db - dt) < (b - t): + destrect = viewrect + else: + destrect = l, dt + yshift, r, db + yshift + else: + destrect = viewrect + return viewrect, destrect + + +class TextEditor(EditText): + + def __init__(self, possize, text = "", callback = None, wrap = 1, inset = (4, 4), + fontsettings = ("Python-Sans", 0, 9, (0, 0, 0)), + readonly = 0): + EditText.__init__(self, possize, text, callback, inset, fontsettings, readonly) + self.wrap = wrap + + def _getflags(self): + flags = WASTEconst.weDoAutoScroll | WASTEconst.weDoMonoStyled | \ + WASTEconst.weDoOutlineHilite + if self.readonly: + flags = flags | WASTEconst.weDoReadOnly + else: + flags = flags | WASTEconst.weDoUndo + return flags + + def _getviewrect(self): + l, t, r, b = self._bounds + return (l + 5, t + 2, r, b - 2) + + def _calctextbounds(self): + if self.wrap: + return EditText._calctextbounds(self) + else: + viewrect = l, t, r, b = self._getviewrect() + if self.ted: + dl, dt, dr, db = self.ted.WEGetDestRect() + vl, vt, vr, vb = self.ted.WEGetViewRect() + xshift = l - vl + yshift = t - vt + if (db - dt) < (b - t): + yshift = t - dt + destrect = (dl + xshift, dt + yshift, dr + xshift, db + yshift) + else: + destrect = (l, t, r + 5000, b) + return viewrect, destrect + + def draw(self, visRgn = None): + if self._visible: + if not visRgn: + visRgn = self._parentwindow.wid.GetWindowPort().visRgn + self.ted.WEUpdate(visRgn) + if self._selected and self._activated: + self.drawselframe(1) + + +class PyEditor(TextEditor): + + def __init__(self, possize, text = "", callback = None, inset = (4, 4), + fontsettings = ("Python-Sans", 0, 9, (0, 0, 0)), + readonly = 0, + debugger = None, + file = ''): + TextEditor.__init__(self, possize, text, callback, 0, inset, fontsettings, readonly) + self.bind("cmd[", self.shiftleft) + self.bind("cmd]", self.shiftright) + self.file = file # only for debugger reference + self._debugger = debugger + if debugger: + debugger.register_editor(self, self.file) + + def setfile(self, file): + self.file = file + + def set(self, text, file = ''): + oldfile = self.file + self.file = file + if self._debugger: + self._debugger.unregister_editor(self, oldfile) + self._debugger.register_editor(self, file) + TextEditor.set(self, text) + + def close(self): + if self._debugger: + self._debugger.unregister_editor(self, self.file) + self._debugger = None + TextEditor.close(self) + + def click(self, point, modifiers): + if not self._enabled: + return + if self._debugger and self.pt_in_breaks(point): + self.breakhit(point, modifiers) + elif self._debugger: + bl, bt, br, bb = self._getbreakrect() + Qd.EraseRect((bl, bt, br-1, bb)) + TextEditor.click(self, point, modifiers) + self.drawbreakpoints() + else: + TextEditor.click(self, point, modifiers) + if self.ted.WEGetClickCount() >= 3: + # select block with our indent + lines = string.split(self.get(), '\r') + selstart, selend = self.ted.WEGetSelection() + lineno = self.ted.WEOffsetToLine(selstart) + tabs = 0 + line = lines[lineno] + while line[tabs:] and line[tabs] == '\t': + tabs = tabs + 1 + tabstag = '\t' * tabs + fromline = 0 + toline = len(lines) + if tabs: + for i in range(lineno - 1, -1, -1): + line = lines[i] + if line[:tabs] <> tabstag: + fromline = i + 1 + break + for i in range(lineno + 1, toline): + line = lines[i] + if line[:tabs] <> tabstag: + toline = i - 1 + break + selstart, dummy = self.ted.WEGetLineRange(fromline) + dummy, selend = self.ted.WEGetLineRange(toline) + self.ted.WESetSelection(selstart, selend) + + def breakhit(self, point, modifiers): + if not self.file: + return + offset, edge = self.ted.WEGetOffset(point) + lineno = self.ted.WEOffsetToLine(offset) + 1 + if edge < 0: + self._debugger.clear_breaks_above(self.file, lineno) + else: + self._debugger.clear_breaks_above(self.file, self.countlines()) + self._debugger.toggle_break(self.file, lineno) + + def key(self, char, event): + (what, message, when, where, modifiers) = event + if modifiers & Events.cmdKey and not char in arrowkeys: + return + if char == '\r': + selstart, selend = self.ted.WEGetSelection() + selstart, selend = min(selstart, selend), max(selstart, selend) + lastchar = chr(self.ted.WEGetChar(selstart-1)) + if lastchar <> '\r' and selstart: + pos, dummy = self.ted.WEFindLine(selstart, 0) + lineres = Res.Resource('') + self.ted.WECopyRange(pos, selstart, lineres, None, None) + line = lineres.data + '\n' + tabcount = self.extratabs(line) + self.ted.WEKey(ord('\r'), 0) + for i in range(tabcount): + self.ted.WEKey(ord('\t'), 0) + else: + self.ted.WEKey(ord('\r'), 0) + elif char in ')]}': + self.ted.WEKey(ord(char), modifiers) + self.balanceparens(char) + else: + self.ted.WEKey(ord(char), modifiers) + if char not in navigationkeys: + self.changed = 1 + self.selchanged = 1 + self.updatescrollbars() + + def balanceparens(self, char): + if char == ')': + target = '(' + elif char == ']': + target = '[' + elif char == '}': + target = '{' + recursionlevel = 1 + selstart, selend = self.ted.WEGetSelection() + count = min(selstart, selend) - 2 + mincount = max(0, count - 2048) + lastquote = None + while count > mincount: + testchar = chr(self.ted.WEGetChar(count)) + if testchar in "\"'" and chr(self.ted.WEGetChar(count - 1)) <> '\\': + if lastquote == testchar: + recursionlevel = recursionlevel - 1 + lastquote = None + elif not lastquote: + recursionlevel = recursionlevel + 1 + lastquote = testchar + elif not lastquote and testchar == char: + recursionlevel = recursionlevel + 1 + elif not lastquote and testchar == target: + recursionlevel = recursionlevel - 1 + if recursionlevel == 0: + import time + autoscroll = self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, -1) + if autoscroll: + self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, 0) + self.ted.WESetSelection(count, count + 1) + time.sleep(0.2) + self.ted.WESetSelection(selstart, selend) + if autoscroll: + self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, 1) + break + count = count - 1 + + def extratabs(self, line): + tabcount = 0 + for c in line: + if c <> '\t': + break + tabcount = tabcount + 1 + last = 0 + cleanline = '' + tags = PyFontify.fontify(line) + # strip comments and strings + for tag, start, end, sublist in tags: + if tag in ('string', 'comment'): + cleanline = cleanline + line[last:start] + last = end + cleanline = cleanline + line[last:] + cleanline = string.strip(cleanline) + if cleanline and cleanline[-1] == ':': + tabcount = tabcount + 1 + else: + for open, close in (('(', ')'), ('[', ']'), ('{', '}')): + count = string.count(cleanline, open) + if count and count <> string.count(cleanline, close): + tabcount = tabcount + 2 + break + return tabcount + + def rollover(self, point, onoff): + if onoff: + if self._debugger and self.pt_in_breaks(point): + Wbase.SetCursor("arrow") + else: + Wbase.SetCursor("iBeam") + + def draw(self, visRgn = None): + TextEditor.draw(self, visRgn) + if self._debugger: + self.drawbreakpoints() + + def showbreakpoints(self, onoff): + if (not not self._debugger) <> onoff: + if onoff: + import PyDebugger + self._debugger = PyDebugger.getdebugger() + self._debugger.register_editor(self, self.file) + elif self._debugger: + self._debugger.unregister_editor(self, self.file) + self._debugger = None + self.adjust(self._bounds) + + def togglebreakpoints(self): + self.showbreakpoints(not self._debugger) + + def clearbreakpoints(self): + if self.file: + self._debugger.clear_all_file_breaks(self.file) + + def editbreakpoints(self): + if self._debugger: + self._debugger.edit_breaks() + self._debugger.breaksviewer.selectfile(self.file) + + def drawbreakpoints(self, eraseall = 0): + breakrect = bl, bt, br, bb = self._getbreakrect() + br = br - 1 + self.SetPort() + Qd.PenPat(Qd.qd.gray) + Qd.PaintRect((br, bt, br + 1, bb)) + Qd.PenNormal() + self._parentwindow.tempcliprect(breakrect) + Qd.RGBForeColor((0xffff, 0, 0)) + try: + lasttop = bt + self_ted = self.ted + Qd_PaintOval = Qd.PaintOval + Qd_EraseRect = Qd.EraseRect + for lineno in self._debugger.get_file_breaks(self.file): + start, end = self_ted.WEGetLineRange(lineno - 1) + if lineno <> self_ted.WEOffsetToLine(start) + 1: + # breakpoints beyond our text: erase rest, and back out + Qd_EraseRect((bl, lasttop, br, bb)) + break + (x, y), h = self_ted.WEGetPoint(start, 0) + bottom = y + h + #print y, (lasttop, bottom) + if bottom > lasttop: + Qd_EraseRect((bl, lasttop, br, y + h * eraseall)) + lasttop = bottom + redbullet = bl + 2, y + 3, bl + 8, y + 9 + Qd_PaintOval(redbullet) + else: + Qd_EraseRect((bl, lasttop, br, bb)) + Qd.RGBForeColor((0, 0, 0)) + finally: + self._parentwindow.restoreclip() + + def updatescrollbars(self): + if self._debugger: + self.drawbreakpoints(1) + TextEditor.updatescrollbars(self) + + def pt_in_breaks(self, point): + return Qd.PtInRect(point, self._getbreakrect()) + + def _getbreakrect(self): + if self._debugger: + l, t, r, b = self._bounds + return (l+1, t+1, l + 12, b-1) + else: + return (0, 0, 0, 0) + + def _getviewrect(self): + l, t, r, b = self._bounds + if self._debugger: + return (l + 17, t + 2, r, b - 2) + else: + return (l + 5, t + 2, r, b - 2) + + def _calctextbounds(self): + viewrect = l, t, r, b = self._getviewrect() + if self.ted: + dl, dt, dr, db = self.ted.WEGetDestRect() + vl, vt, vr, vb = self.ted.WEGetViewRect() + xshift = l - vl + yshift = t - vt + if (db - dt) < (b - t): + yshift = t - dt + destrect = (dl + xshift, dt + yshift, dr + xshift, db + yshift) + else: + destrect = (l, t, r + 5000, b) + return viewrect, destrect + + +def GetFNum(font): + if font <> 'Chicago': + fontid = Fm.GetFNum(font) + if fontid == 0: + fontid = Fonts.monaco + else: + fontid = 0 + return fontid + +def GetFName(fontid): + try: + res = Res.GetResource('FOND', fontid) + except Res.Error: + fontname = 'Monaco' + else: + fontname = res.GetResInfo()[2] + return fontname diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wtraceback.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wtraceback.py new file mode 100644 index 0000000..5804cd7 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wtraceback.py @@ -0,0 +1,196 @@ +import traceback +import sys +import W +import os +import types + +class TraceList(W.List): + + LDEF_ID = 468 + + def createlist(self): + import List + self._calcbounds() + self.SetPort() + rect = self._bounds + rect = rect[0]+1, rect[1]+1, rect[2]-16, rect[3]-1 + self._list = List.LNew(rect, (0, 0, 1, 0), (0, 28), self.LDEF_ID, self._parentwindow.wid, + 0, 1, 0, 1) + self.set(self.items) + + +class TraceBack: + + def __init__(self, title = "Traceback"): + app = W.getapplication() # checks if W is properly initialized + self.title = title + self.w = None + self.closed = 1 + self.start = 0 + self.lastwindowtitle = "" + self.bounds = (360, 298) + + def traceback(self, start = 0, lastwindowtitle = ""): + try: + self.lastwindowtitle = lastwindowtitle + self.start = start + self.type, self.value, self.tb = sys.exc_type, sys.exc_value, sys.exc_traceback + if self.type is not SyntaxError: + self.show() + if type(self.type) == types.ClassType: + errortext = self.type.__name__ + else: + errortext = str(self.type) + value = str(self.value) + if self.value and value: + errortext = errortext + ": " + value + self.w.text.set(errortext) + self.buildtblist() + self.w.list.set(self.textlist) + self.w.list.setselection([len(self.textlist) - 1]) + self.w.wid.SelectWindow() + self.closed = 0 + else: + self.syntaxerror() + except: + traceback.print_exc() + + def syntaxerror(self): + try: + value, (filename, lineno, charno, line) = self.value + except: + filename = "" + lineno = None + value = self.value + if not filename and self.lastwindowtitle: + filename = self.lastwindowtitle + elif not filename: + filename = "<unknown>" + if filename and os.path.exists(filename): + filename = os.path.split(filename)[1] + if lineno: + charno = charno - 1 + text = value + '\rFile: "' + str(filename) + '", line ' + str(lineno) + '\r\r' + line[:charno] + "" + line[charno:-1] + else: + text = value + '\rFile: "' + str(filename) + '"' + self.syntaxdialog = W.ModalDialog((360, 120), "Syntax Error") + self.syntaxdialog.text = W.TextBox((10, 10, -10, -40), text) + self.syntaxdialog.cancel = W.Button((-190, -32, 80, 16), "Cancel", self.syntaxclose) + self.syntaxdialog.edit = W.Button((-100, -32, 80, 16), "Edit", self.syntaxedit) + self.syntaxdialog.setdefaultbutton(self.syntaxdialog.edit) + self.syntaxdialog.bind("cmd.", self.syntaxdialog.cancel.push) + self.syntaxdialog.open() + + def syntaxclose(self): + self.syntaxdialog.close() + del self.syntaxdialog + + def syntaxedit(self): + try: + value, (filename, lineno, charno, line) = self.value + except: + filename = "" + lineno = None + if not filename and self.lastwindowtitle: + filename = self.lastwindowtitle + elif not filename: + filename = "<unknown>" + self.syntaxclose() + if lineno: + W.getapplication().openscript(filename, lineno, charno - 1) + else: + W.getapplication().openscript(filename) + + def show(self): + if self.closed: + self.setupwidgets() + self.w.open() + else: + self.w.wid.ShowWindow() + self.w.wid.SelectWindow() + + def close(self): + self.bounds = self.w.getbounds() + self.closed = 1 + self.type, self.value, self.tb = None, None, None + self.tblist = None + + def activate(self, onoff): + if onoff: + if self.closed: + self.traceback() + self.closed = 0 + self.checkbuttons() + + def setupwidgets(self): + self.w = W.Window(self.bounds, self.title, minsize = (316, 168)) + self.w.text = W.TextBox((10, 10, -10, 30)) + self.w.tbtitle = W.TextBox((10, 40, -10, 10), "Traceback (innermost last):") + self.w.list = TraceList((10, 60, -10, -40), callback = self.listhit) + + self.w.editbutton = W.Button((10, -30, 60, 16), "Edit", self.edit) + self.w.editbutton.enable(0) + + self.w.browselocalsbutton = W.Button((80, -30, 100, 16), "Browse locals", self.browselocals) + self.w.browselocalsbutton.enable(0) + + self.w.postmortembutton = W.Button((190, -30, 100, 16), "Post mortem", self.postmortem) + + self.w.setdefaultbutton(self.w.editbutton) + self.w.bind("cmdb", self.w.browselocalsbutton.push) + self.w.bind("<close>", self.close) + self.w.bind("<activate>", self.activate) + + def buildtblist(self): + tb = self.tb + for i in range(self.start): + if tb.tb_next is None: + break + tb = tb.tb_next + self.tblist = traceback.extract_tb(tb) + self.textlist = [] + for filename, lineno, func, line in self.tblist: + tbline = "" + if os.path.exists(filename): + filename = os.path.split(filename)[1] + tbline = 'File "' + filename + '", line ' + `lineno` + ', in ' + func + else: + tbline = 'File "' + filename + '", line ' + `lineno` + ', in ' + func + if line: + tbline = tbline + '\r ' + line + self.textlist.append(tbline[:255]) + + def edit(self): + sel = self.w.list.getselection() + for i in sel: + filename, lineno, func, line = self.tblist[i] + W.getapplication().openscript(filename, lineno) + + def browselocals(self): + sel = self.w.list.getselection() + for i in sel: + tb = self.tb + for j in range(i + self.start): + tb = tb.tb_next + self.browse(tb.tb_frame.f_locals) + + def browse(self, object): + import PyBrowser + PyBrowser.Browser(object) + + def postmortem(self): + import PyDebugger + PyDebugger.postmortem(self.type, self.value, self.tb) + + def listhit(self, isdbl): + if isdbl: + self.w.editbutton.push() + else: + self.checkbuttons() + + def checkbuttons(self): + havefile = len(self.w.list.getselection()) > 0 + self.w.editbutton.enable(havefile) + self.w.browselocalsbutton.enable(havefile) + self.w.setdefaultbutton(havefile and self.w.editbutton or self.w.postmortembutton) + diff --git a/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wwindows.py b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wwindows.py new file mode 100644 index 0000000..c488810 --- /dev/null +++ b/Mac/Contrib/PyIDE-src/IDELib/Widgets/Wwindows.py @@ -0,0 +1,578 @@ +import Qd +import Win +import Evt +import Fm +import FrameWork +import Windows +import Events +import Wbase +import Wlist +import Dlg +import MacOS +import Menu +import struct + +from types import * +from SpecialKeys import * + + +class Window(FrameWork.Window, Wbase.SelectableWidget): + + windowkind = Windows.documentProc + + def __init__(self, possize, title = "", minsize = None, maxsize = None, tabbable = 1, show = 1): + Wbase.SelectableWidget.__init__(self, possize) + self._globalbounds = l, t, r, b = self.getwindowbounds(possize, minsize) + self._bounds = (0, 0, r - l, b - t) + self._tabchain = [] + self._currentwidget = None + self.title = title + self._parentwindow = self + self._tabbable = tabbable + self._defaultbutton = None + self._drawwidgetbounds = 0 + self._show = show + self._lastrollover = None + if minsize: + self._hasgrowbox = 1 + self.windowkind = self.windowkind | 8 + l, t = minsize + if maxsize: + r, b = maxsize[0] + 1, maxsize[1] + 1 + else: + r, b = 32000, 32000 + self.growlimit = (l, t, r, b) + else: + self._hasgrowbox = 0 + if self.windowkind == 0 or self.windowkind >=8: + self.windowkind = self.windowkind | 4 + import W + if not W._application: + raise W.WidgetsError, 'W not properly initialized: unknown Application' + FrameWork.Window.__init__(self, W._application) + + def gettitle(self): + return self.title + + def settitle(self, title): + self.title = title + if self.wid: + self.wid.SetWTitle(title) + + def getwindowbounds(self, size, minsize = None): + return windowbounds(size, minsize) + + def getcurrentwidget(self): + return self._currentwidget + + def show(self, onoff): + if onoff: + self.wid.ShowWindow() + else: + self.wid.HideWindow() + + def isvisible(self): + return self.wid.IsWindowVisible() + + def getbounds(self): + if 0: #self.isvisible(): + self.wid.GetWindowContentRgn(scratchRegion) + self._globalbounds = GetRgnBounds(scratchRegion) + return self._globalbounds + + def select(self): + self.wid.SelectWindow() + + def open(self): + self.wid = Win.NewCWindow(self._globalbounds, self.title, self._show, + self.windowkind, -1, 1, 0) + self.SetPort() + fnum = Fm.GetFNum("Python-Sans") + if fnum == 0: + fnum = Fm.GetFNum("Geneva") + Qd.TextFont(fnum) # XXX font&size from a function? + Qd.TextSize(9) # XXX font&size from a function? + if self._bindings.has_key("<open>"): + callback = self._bindings["<open>"] + callback() + for w in self._widgets: + w.forall_frombottom("open") + self._maketabchain() + if self._tabchain: + self._tabchain[0].select(1) + if self._tabbable: + self.bind('tab', self.nextwidget) + self.bind('shifttab', self.previouswidget) + self.do_postopen() + + def close(self): + if not self.wid: + return # we are already closed + if self._bindings.has_key("<close>"): + callback = self._bindings["<close>"] + rv = callback() + if rv: + return rv + #for key in self._widgetsdict.keys(): + # self._removewidget(key) + self.forall_butself("close") + Wbase.SelectableWidget.close(self) + self._tabchain = [] + self._currentwidget = None + self.wid.HideWindow() + self.do_postclose() + + def domenu_close(self, *args): + self.close() + + def move(self, x, y = None): + """absolute move""" + if y == None: + x, y = x + self.wid.MoveWindow(x, y, 0) + + def resize(self, x, y = None): + if y == None: + x, y = x + if self._hasgrowbox: + self.SetPort() + Win.InvalRect(self.getgrowrect()) + self.wid.SizeWindow(x, y, 1) + self._calcbounds() + + def test(self, point): + return 1 + + def draw(self, visRgn = None): + if self._hasgrowbox: + self.tempcliprect(self.getgrowrect()) + self.wid.DrawGrowIcon() + self.restoreclip() + + def idle(self, *args): + self.SetPort() + point = Evt.GetMouse() + widget = self.findwidget(point, 0) + if widget is not None and hasattr(widget, "rollover"): + if 1: #self._lastrollover <> widget: + if self._lastrollover: + self._lastrollover.rollover(point, 0) + self._lastrollover = widget + self._lastrollover.rollover(point, 1) + else: + if self._lastrollover: + self._lastrollover.rollover(point, 0) + self._lastrollover = None + Wbase.SetCursor("arrow") + if self._bindings.has_key("<idle>"): + callback = self._bindings["<idle>"] + if callback(): + return + if self._currentwidget is not None and hasattr(self._currentwidget, "idle"): + if self._currentwidget._bindings.has_key("<idle>"): + callback = self._currentwidget._bindings["<idle>"] + if callback(): + return + self._currentwidget.idle() + + def xxx___select(self, widget): + if self._currentwidget == widget: + return + if self._bindings.has_key("<select>"): + callback = self._bindings["<select>"] + if callback(widget): + return + if widget is None: + if self._currentwidget is not None: + self._currentwidget.select(0) + elif type(widget) == InstanceType and widget._selectable: + widget.select(1) + elif widget == -1 or widget == 1: + if len(self._tabchain) <= 1: + return + temp = self._tabchain[(self._tabchain.index(self._currentwidget) + widget) % len(self._tabchain)] + temp.select(1) + else: + raise TypeError, "Widget is not selectable" + + def setdefaultbutton(self, newdefaultbutton = None, *keys): + if newdefaultbutton == self._defaultbutton: + return + if self._defaultbutton: + self._defaultbutton._setdefault(0) + if not newdefaultbutton: + self.bind("return", None) + self.bind("enter", None) + return + import Wcontrols + if not Wbase.HasBaseClass(newdefaultbutton, Wcontrols.Button): + raise TypeError, "widget is not a button" + self._defaultbutton = newdefaultbutton + self._defaultbutton._setdefault(1) + if not keys: + self.bind("return", self._defaultbutton.push) + self.bind("enter", self._defaultbutton.push) + else: + for key in keys: + self.bind(key, self._defaultbutton.push) + + def nextwidget(self): + self.xxx___select(1) + + def previouswidget(self): + self.xxx___select(-1) + + def drawwidgetbounds(self, onoff): + self._drawwidgetbounds = onoff + self.SetPort() + Win.InvalRect(self._bounds) + + def _drawbounds(self): + pass + + def _maketabchain(self): + # XXX This has to change, it's no good when we are adding or deleting widgets. + # XXX Perhaps we shouldn't keep a "tabchain" at all. + self._hasselframes = 0 + self._collectselectablewidgets(self._widgets) + if self._hasselframes and len(self._tabchain) > 1: + self._hasselframes = 1 + else: + self._hasselframes = 0 + + def _collectselectablewidgets(self, widgets): + for w in widgets: + if w._selectable: + self._tabchain.append(w) + if Wbase.HasBaseClass(w, Wlist.List): + self._hasselframes = 1 + self._collectselectablewidgets(w._widgets) + + def _calcbounds(self): + self._possize = self.wid.GetWindowPort().portRect[2:] + w, h = self._possize + self._bounds = (0, 0, w, h) + self.wid.GetWindowContentRgn(scratchRegion) + l, t, r, b = GetRgnBounds(scratchRegion) + self._globalbounds = l, t, l + w, t + h + for w in self._widgets: + w._calcbounds() + + # FrameWork override methods + def do_inDrag(self, partcode, window, event): + where = event[3] + self.wid.GetWindowContentRgn(scratchRegion) + was_l, was_t, r, b = GetRgnBounds(scratchRegion) + window.DragWindow(where, self.draglimit) + self.wid.GetWindowContentRgn(scratchRegion) + is_l, is_t, r, b = GetRgnBounds(scratchRegion) + self._globalbounds = Qd.OffsetRect(self._globalbounds, + is_l - was_l, is_t - was_t) + + def do_char(self, char, event): + (what, message, when, where, modifiers) = event + key = char + if keynames.has_key(key): + key = keynames[char] + if modifiers & Events.shiftKey: + key = 'shift' + key + if modifiers & Events.cmdKey: + key = 'cmd' + key + if modifiers & Events.controlKey: + key = 'control' + key + if self._bindings.has_key("<key>"): + callback = self._bindings["<key>"] + if Wbase.CallbackCall(callback, 0, char, event): + return + if self._bindings.has_key(key): + callback = self._bindings[key] + Wbase.CallbackCall(callback, 0, char, event) + elif self._currentwidget is not None: + if self._currentwidget._bindings.has_key(key): + callback = self._currentwidget._bindings[key] + Wbase.CallbackCall(callback, 0, char, event) + else: + if self._currentwidget._bindings.has_key("<key>"): + callback = self._currentwidget._bindings["<key>"] + if Wbase.CallbackCall(callback, 0, char, event): + return + self._currentwidget.key(char, event) + + def do_contentclick(self, point, modifiers, event): + widget = self.findwidget(point) + if widget is not None: + if self._bindings.has_key("<click>"): + callback = self._bindings["<click>"] + if Wbase.CallbackCall(callback, 0, point, modifiers): + return + if widget._bindings.has_key("<click>"): + callback = widget._bindings["<click>"] + if Wbase.CallbackCall(callback, 0, point, modifiers): + return + if widget._selectable: + widget.select(1, 1) + widget.click(point, modifiers) + + def do_update(self, window, event): + Qd.EraseRgn(window.GetWindowPort().visRgn) + self.forall("draw", window.GetWindowPort().visRgn) + if self._drawwidgetbounds: + self.forall("_drawbounds") + + def do_activate(self, onoff, event): + if not onoff: + if self._lastrollover: + self._lastrollover.rollover((0, 0), 0) + self._lastrollover = None + self.SetPort() + self.forall("activate", onoff) + self.draw() + + def do_postresize(self, width, height, window): + Win.InvalRect(self.getgrowrect()) + self._calcbounds() + + # utilities + def tempcliprect(self, tempcliprect): + tempclip = Qd.NewRgn() + Qd.RectRgn(tempclip, tempcliprect) + self.tempclip(tempclip) + + def tempclip(self, tempclip): + if hasattr(self, "saveclip"): + raise Wbase.WidgetsError, "already have saveclip" + self.saveclip = Qd.NewRgn() + Qd.GetClip(self.saveclip) + Qd.SectRgn(self.wid.GetWindowPort().visRgn, tempclip, tempclip) + Qd.SetClip(tempclip) + + def restoreclip(self): + Qd.SetClip(self.saveclip) + del self.saveclip + + def getgrowrect(self): + l, t, r, b = self.wid.GetWindowPort().portRect + return (r - 15, b - 15, r, b) + + def has_key(self, key): + return self._widgetsdict.has_key(key) + + def __getattr__(self, attr): + global _successcount, _failcount, _magiccount + if self._widgetsdict.has_key(attr): + _successcount = _successcount + 1 + return self._widgetsdict[attr] + if self._currentwidget is None or (attr[:7] <> 'domenu_' and + attr[:4] <> 'can_' and attr <> 'insert'): + _failcount = _failcount + 1 + raise AttributeError, attr + # special case: if a domenu_xxx, can_xxx or insert method is asked for, + # see if the active widget supports it + _magiccount = _magiccount + 1 + return getattr(self._currentwidget, attr) + +_successcount = 0 +_failcount = 0 +_magiccount = 0 + +class Dialog(Window): + + windowkind = Windows.movableDBoxProc + + # this __init__ seems redundant, but it's not: it has less args + def __init__(self, possize, title = ""): + Window.__init__(self, possize, title) + + def can_close(self, *args): + return 0 + + def getwindowbounds(self, size, minsize = None): + screenbounds = sl, st, sr, sb = Qd.qd.screenBits.bounds + w, h = size + l = sl + (sr - sl - w) / 2 + t = st + (sb - st - h) / 3 + return l, t, l + w, t + h + +class ModalDialog(Dialog): + + def __init__(self, possize, title = ""): + Dialog.__init__(self, possize, title) + if title: + self.windowkind = Windows.movableDBoxProc + else: + self.windowkind = Windows.dBoxProc + + def open(self): + import W + if not W._application: + raise W.WidgetsError, 'W not properly initialized: unknown Application' + Dialog.open(self) + self.app = W._application + self.done = 0 + Menu.HiliteMenu(0) + self.mainloop() + + def close(self): + if not self.wid: + return # we are already closed + self.done = 1 + del self.app + Dialog.close(self) + + def mainloop(self): + saveyield = MacOS.EnableAppswitch(-1) + while not self.done: + #self.do1event() + self.do1event( Events.keyDownMask + + Events.autoKeyMask + + Events.activMask + + Events.updateMask + + Events.mDownMask + + Events.mUpMask, + 10) + MacOS.EnableAppswitch(saveyield) + + def do1event(self, mask = Events.everyEvent, wait = 0): + ok, event = self.app.getevent(mask, wait) + if Dlg.IsDialogEvent(event): + if self.app.do_dialogevent(event): + return + if ok: + self.dispatch(event) + else: + self.app.idle(event) + + def do_keyDown(self, event): + self.do_key(event) + + def do_autoKey(self, event): + if not event[-1] & Events.cmdKey: + self.do_key(event) + + def do_key(self, event): + (what, message, when, where, modifiers) = event + w = Win.FrontWindow() + if w <> self.wid: + return + c = chr(message & Events.charCodeMask) + if modifiers & Events.cmdKey: + self.app.checkmenus(self) + result = Menu.MenuKey(ord(c)) + id = (result>>16) & 0xffff # Hi word + item = result & 0xffff # Lo word + if id: + self.app.do_rawmenu(id, item, None, event) + return + self.do_char(c, event) + + def do_mouseDown(self, event): + (what, message, when, where, modifiers) = event + partcode, wid = Win.FindWindow(where) + # + # Find the correct name. + # + if FrameWork.partname.has_key(partcode): + name = "do_" + FrameWork.partname[partcode] + else: + name = "do_%d" % partcode + + if name == "do_inDesk": + MacOS.HandleEvent(event) + return + if wid == self.wid: + try: + handler = getattr(self, name) + except AttributeError: + handler = self.app.do_unknownpartcode + else: + #MacOS.HandleEvent(event) + return + handler(partcode, wid, event) + + def dispatch(self, event): + (what, message, when, where, modifiers) = event + if FrameWork.eventname.has_key(what): + name = "do_" + FrameWork.eventname[what] + else: + name = "do_%d" % what + try: + handler = getattr(self, name) + except AttributeError: + try: + handler = getattr(self.app, name) + except AttributeError: + handler = self.app.do_unknownevent + handler(event) + + +def FrontWindowInsert(stuff): + if not stuff: + return + if type(stuff) <> StringType: + raise TypeError, 'string expected' + import W + app = W.getapplication() + wid = Win.FrontWindow() + if wid and app._windows.has_key(wid): + window = app._windows[wid] + if hasattr(window, "insert"): + try: + window.insert(stuff) + return + except: + pass + import EasyDialogs + if EasyDialogs.AskYesNoCancel( + "Canıt find window or widget to insert text into; copy to clipboard instead?", + 1) == 1: + import Scrap + Scrap.ZeroScrap() + Scrap.PutScrap('TEXT', stuff) + + +# not quite based on the same function in FrameWork +_windowcounter = 0 + +def getnextwindowpos(): + global _windowcounter + rows = 8 + l = 4 * (rows + 1 - (_windowcounter % rows) + _windowcounter / rows) + t = 44 + 20 * (_windowcounter % rows) + _windowcounter = _windowcounter + 1 + return l, t + +def windowbounds(preferredsize, minsize = None): + "Return sensible window bounds" + + global _windowcounter + if len(preferredsize) == 4: + bounds = l, t, r, b = preferredsize + union = Qd.UnionRect(bounds, Qd.qd.screenBits.bounds) + if union == Qd.qd.screenBits.bounds: + return bounds + else: + preferredsize = r - l, b - t + if not minsize: + minsize = preferredsize + minwidth, minheight = minsize + width, height = preferredsize + + sl, st, sr, sb = screenbounds = Qd.InsetRect(Qd.qd.screenBits.bounds, 4, 4) + l, t = getnextwindowpos() + if (l + width) > sr: + _windowcounter = 0 + l, t = getnextwindowpos() + r = l + width + b = t + height + if (t + height) > sb: + b = sb + if (b - t) < minheight: + b = t + minheight + return l, t, r, b + +scratchRegion = Qd.NewRgn() + +# util -- move somewhere convenient??? +def GetRgnBounds(the_Rgn): + (t, l, b, r) = struct.unpack("hhhh", the_Rgn.data[2:10]) + return (l, t, r, b) |