home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Mac / Tools / IDE / Wwindows.py < prev    next >
Encoding:
Python Source  |  2000-06-23  |  16.0 KB  |  619 lines

  1. import Qd
  2. import Win
  3. import Evt
  4. import Fm
  5. import FrameWork
  6. import Windows
  7. import Events
  8. import Wbase
  9. import Dlg
  10. import MacOS
  11. import Menu
  12. import struct
  13. import traceback
  14.  
  15. from types import *
  16.  
  17.  
  18. class Window(FrameWork.Window, Wbase.SelectableWidget):
  19.     
  20.     windowkind = Windows.documentProc
  21.     
  22.     def __init__(self, possize, title="", minsize=None, maxsize=None, 
  23.             tabbable=1, show=1, fontsettings=None):
  24.         import W
  25.         if fontsettings is None:
  26.             fontsettings = W.getdefaultfont()
  27.         self._fontsettings = fontsettings
  28.         W.SelectableWidget.__init__(self, possize)
  29.         self._globalbounds = l, t, r, b = self.getwindowbounds(possize, minsize)
  30.         self._bounds = (0, 0, r - l, b - t)
  31.         self._tabchain = []
  32.         self._currentwidget = None
  33.         self.title = title
  34.         self._parentwindow = self
  35.         self._tabbable = tabbable
  36.         self._defaultbutton = None
  37.         self._drawwidgetbounds = 0
  38.         self._show = show
  39.         self._lastrollover = None
  40.         self.hasclosebox = 1
  41.         # XXX the following is not really compatible with the
  42.         #  new (system >= 7.5) window procs. 
  43.         if minsize:
  44.             self._hasgrowbox = 1
  45.             self.windowkind = self.windowkind | 8
  46.             l, t = minsize
  47.             if maxsize:
  48.                 r, b = maxsize[0] + 1, maxsize[1] + 1
  49.             else:
  50.                 r, b = 32000, 32000
  51.             self.growlimit = (l, t, r, b)
  52.         else:
  53.             self._hasgrowbox = 0
  54.             if (self.windowkind == 0 or self.windowkind >= 8) and self.windowkind < 1000:
  55.                 self.windowkind = self.windowkind | 4
  56.         FrameWork.Window.__init__(self, W.getapplication())
  57.     
  58.     def gettitle(self):
  59.         return self.title
  60.     
  61.     def settitle(self, title):
  62.         self.title = title
  63.         if self.wid:
  64.             self.wid.SetWTitle(title)
  65.     
  66.     def getwindowbounds(self, size, minsize = None):
  67.         return windowbounds(size, minsize)    
  68.     
  69.     def getcurrentwidget(self):
  70.         return self._currentwidget
  71.     
  72.     def show(self, onoff):
  73.         if onoff:
  74.             self.wid.ShowWindow()
  75.         else:
  76.             self.wid.HideWindow()
  77.     
  78.     def isvisible(self):
  79.         return self.wid.IsWindowVisible()
  80.     
  81.     def getbounds(self):
  82.         if 0:    #self.isvisible():
  83.             self.wid.GetWindowContentRgn(scratchRegion)
  84.             self._globalbounds = GetRgnBounds(scratchRegion)
  85.         return self._globalbounds
  86.         
  87.     def select(self):
  88.         self.wid.SelectWindow()
  89.         # not sure if this is the best place, I need it when
  90.         # an editor gets selected, and immediately scrolled
  91.         # to a certain line, waste scroll assumes everything 
  92.         # to be in tact.
  93.         self.do_rawupdate(self.wid, "DummyEvent")
  94.     
  95.     def open(self):
  96.         self.wid = Win.NewCWindow(self._globalbounds, self.title, self._show,
  97.             self.windowkind, -1, self.hasclosebox, 0)
  98.         self.SetPort()
  99.         fontname, fontstyle, fontsize, fontcolor = self._fontsettings
  100.         fnum = Fm.GetFNum(fontname)
  101.         if fnum == 0:
  102.             fnum = Fm.GetFNum("Geneva")
  103.         Qd.TextFont(fnum)
  104.         Qd.TextFace(fontstyle)
  105.         Qd.TextSize(fontsize)
  106.         if self._bindings.has_key("<open>"):
  107.             callback = self._bindings["<open>"]
  108.             callback()
  109.         for w in self._widgets:
  110.             w.forall_frombottom("open")
  111.         self._maketabchain()
  112.         if self._tabchain:
  113.             self._tabchain[0].select(1)
  114.         if self._tabbable:
  115.             self.bind('tab', self.nextwidget)
  116.             self.bind('shifttab', self.previouswidget)
  117.         self.do_postopen()
  118.     
  119.     def close(self):
  120.         if not self.wid:
  121.             return    # we are already closed
  122.         if self._bindings.has_key("<close>"):
  123.             callback = self._bindings["<close>"]
  124.             try:
  125.                 rv = callback()
  126.             except:
  127.                 print 'error in <close> callback'
  128.                 traceback.print_exc()
  129.             else:
  130.                 if rv:
  131.                     return rv
  132.         #for key in self._widgetsdict.keys():
  133.         #    self._removewidget(key)
  134.         self.forall_butself("close")
  135.         Wbase.SelectableWidget.close(self)
  136.         self._tabchain = []
  137.         self._currentwidget = None
  138.         self.wid.HideWindow()
  139.         self.do_postclose()
  140.     
  141.     def domenu_close(self, *args):
  142.         self.close()
  143.     
  144.     def move(self, x, y = None):
  145.         """absolute move"""
  146.         if y == None:
  147.             x, y = x
  148.         self.wid.MoveWindow(x, y, 0)
  149.     
  150.     def resize(self, x, y = None):
  151.         if y == None:
  152.             x, y = x
  153.         if self._hasgrowbox:
  154.             self.SetPort()
  155.             Win.InvalRect(self.getgrowrect())
  156.         self.wid.SizeWindow(x, y, 1)
  157.         self._calcbounds()
  158.     
  159.     def test(self, point):
  160.         return 1
  161.     
  162.     def draw(self, visRgn = None):
  163.         if self._hasgrowbox:
  164.             self.tempcliprect(self.getgrowrect())
  165.             self.wid.DrawGrowIcon()
  166.             self.restoreclip()
  167.     
  168.     def idle(self, *args):
  169.         self.SetPort()
  170.         point = Evt.GetMouse()
  171.         widget = self.findwidget(point, 0)
  172.         if self._bindings.has_key("<idle>"):
  173.             callback = self._bindings["<idle>"]
  174.             if callback():
  175.                 return
  176.         if self._currentwidget is not None and hasattr(self._currentwidget, "idle"):
  177.             if self._currentwidget._bindings.has_key("<idle>"):
  178.                 callback = self._currentwidget._bindings["<idle>"]
  179.                 if callback():
  180.                     return
  181.             if self._currentwidget.idle():
  182.                 return
  183.         if widget is not None and hasattr(widget, "rollover"):
  184.             if 1:    #self._lastrollover <> widget:
  185.                 if self._lastrollover:
  186.                     self._lastrollover.rollover(point, 0)
  187.                 self._lastrollover = widget
  188.                 self._lastrollover.rollover(point, 1)
  189.         else:
  190.             if self._lastrollover:
  191.                 self._lastrollover.rollover(point, 0)
  192.             self._lastrollover = None
  193.             Wbase.SetCursor("arrow")
  194.  
  195.     def xxx___select(self, widget):
  196.         if self._currentwidget == widget:
  197.             return
  198.         if self._bindings.has_key("<select>"):
  199.             callback = self._bindings["<select>"]
  200.             if callback(widget):
  201.                 return
  202.         if widget is None:
  203.             if self._currentwidget is not None:
  204.                 self._currentwidget.select(0)
  205.         elif type(widget) == InstanceType and widget._selectable:
  206.             widget.select(1)
  207.         elif widget == -1 or widget == 1:
  208.             if len(self._tabchain) <= 1:
  209.                 return
  210.             temp = self._tabchain[(self._tabchain.index(self._currentwidget) + widget) % len(self._tabchain)]
  211.             temp.select(1)
  212.         else:
  213.             raise TypeError, "Widget is not selectable"
  214.     
  215.     def setdefaultbutton(self, newdefaultbutton = None, *keys):
  216.         if newdefaultbutton == self._defaultbutton:
  217.             return
  218.         if self._defaultbutton:
  219.             self._defaultbutton._setdefault(0)
  220.         if not newdefaultbutton:
  221.             self.bind("return", None)
  222.             self.bind("enter", None)
  223.             return
  224.         import Wcontrols
  225.         if not isinstance(newdefaultbutton, Wcontrols.Button):
  226.             raise TypeError, "widget is not a button"
  227.         self._defaultbutton = newdefaultbutton
  228.         self._defaultbutton._setdefault(1)
  229.         if not keys:
  230.             self.bind("return", self._defaultbutton.push)
  231.             self.bind("enter", self._defaultbutton.push)
  232.         else:
  233.             for key in keys:
  234.                 self.bind(key, self._defaultbutton.push)
  235.     
  236.     def nextwidget(self):
  237.         self.xxx___select(1)
  238.     
  239.     def previouswidget(self):
  240.         self.xxx___select(-1)
  241.     
  242.     def drawwidgetbounds(self, onoff):
  243.         self._drawwidgetbounds = onoff
  244.         self.SetPort()
  245.         Win.InvalRect(self._bounds)
  246.     
  247.     def _drawbounds(self):
  248.         pass
  249.  
  250.     def _maketabchain(self):
  251.         # XXX This has to change, it's no good when we are adding or deleting widgets.
  252.         # XXX Perhaps we shouldn't keep a "tabchain" at all.
  253.         self._hasselframes = 0
  254.         self._collectselectablewidgets(self._widgets)
  255.         if self._hasselframes and len(self._tabchain) > 1:
  256.             self._hasselframes = 1
  257.         else:
  258.             self._hasselframes = 0
  259.     
  260.     def _collectselectablewidgets(self, widgets):
  261.         import W
  262.         for w in widgets:
  263.             if w._selectable:
  264.                 self._tabchain.append(w)
  265.                 if isinstance(w, W.List):
  266.                     self._hasselframes = 1
  267.             self._collectselectablewidgets(w._widgets)
  268.     
  269.     def _calcbounds(self):
  270.         self._possize = self.wid.GetWindowPort().portRect[2:]
  271.         w, h = self._possize
  272.         self._bounds = (0, 0, w, h)
  273.         self.wid.GetWindowContentRgn(scratchRegion)
  274.         l, t, r, b = GetRgnBounds(scratchRegion)
  275.         self._globalbounds = l, t, l + w, t + h
  276.         for w in self._widgets:
  277.             w._calcbounds()
  278.     
  279.     # FrameWork override methods
  280.     def do_inDrag(self, partcode, window, event):
  281.         where = event[3]
  282.         self.wid.GetWindowContentRgn(scratchRegion)
  283.         was_l, was_t, r, b = GetRgnBounds(scratchRegion)
  284.         window.DragWindow(where, self.draglimit)
  285.         self.wid.GetWindowContentRgn(scratchRegion)
  286.         is_l, is_t, r, b = GetRgnBounds(scratchRegion)
  287.         self._globalbounds = Qd.OffsetRect(self._globalbounds, 
  288.                     is_l - was_l, is_t - was_t)
  289.     
  290.     def do_char(self, char, event):
  291.         import Wkeys
  292.         (what, message, when, where, modifiers) = event
  293.         key = char
  294.         if Wkeys.keynames.has_key(key):
  295.             key = Wkeys.keynames[key]
  296.         if modifiers & Events.shiftKey:
  297.             key = 'shift' + key
  298.         if modifiers & Events.cmdKey:
  299.             key = 'cmd' + key
  300.         if modifiers & Events.controlKey:
  301.             key = 'control' + key
  302.         if self._bindings.has_key("<key>"):
  303.             callback = self._bindings["<key>"]
  304.             if Wbase.CallbackCall(callback, 0, char, event):
  305.                 return
  306.         if self._bindings.has_key(key):
  307.             callback = self._bindings[key]
  308.             Wbase.CallbackCall(callback, 0, char, event)
  309.         elif self._currentwidget is not None:
  310.             if self._currentwidget._bindings.has_key(key):
  311.                 callback = self._currentwidget._bindings[key]
  312.                 Wbase.CallbackCall(callback, 0, char, event)
  313.             else:
  314.                 if self._currentwidget._bindings.has_key("<key>"):
  315.                     callback = self._currentwidget._bindings["<key>"]
  316.                     if Wbase.CallbackCall(callback, 0, char, event):
  317.                         return
  318.                 self._currentwidget.key(char, event)
  319.     
  320.     def do_contentclick(self, point, modifiers, event):
  321.         widget = self.findwidget(point)
  322.         if widget is not None:
  323.             if self._bindings.has_key("<click>"):
  324.                 callback = self._bindings["<click>"]
  325.                 if Wbase.CallbackCall(callback, 0, point, modifiers):
  326.                     return
  327.             if widget._bindings.has_key("<click>"):
  328.                 callback = widget._bindings["<click>"]
  329.                 if Wbase.CallbackCall(callback, 0, point, modifiers):
  330.                     return
  331.             if widget._selectable:
  332.                 widget.select(1, 1)
  333.             widget.click(point, modifiers)
  334.     
  335.     def do_update(self, window, event):
  336.         Qd.EraseRgn(window.GetWindowPort().visRgn)
  337.         self.forall_frombottom("draw", window.GetWindowPort().visRgn)
  338.         if self._drawwidgetbounds:
  339.             self.forall_frombottom("_drawbounds")
  340.     
  341.     def do_activate(self, onoff, event):
  342.         if not onoff:
  343.             if self._lastrollover:
  344.                 self._lastrollover.rollover((0, 0), 0)
  345.                 self._lastrollover = None
  346.         self.SetPort()
  347.         self.forall("activate", onoff)
  348.         self.draw()
  349.     
  350.     def do_postresize(self, width, height, window):
  351.         Win.InvalRect(self.getgrowrect())
  352.         self._calcbounds()
  353.     
  354.     def do_inGoAway(self, partcode, window, event):
  355.         where = event[3]
  356.         closeall = event[4] & Events.optionKey
  357.         if window.TrackGoAway(where):
  358.             if not closeall:
  359.                 self.close()
  360.             else:
  361.                 for window in self.parent._windows.values():
  362.                     rv = window.close()
  363.                     if rv and rv > 0:
  364.                         return
  365.     
  366.     # utilities
  367.     def tempcliprect(self, tempcliprect):
  368.         tempclip = Qd.NewRgn()
  369.         Qd.RectRgn(tempclip, tempcliprect)
  370.         self.tempclip(tempclip)
  371.         Qd.DisposeRgn(tempclip)
  372.     
  373.     def tempclip(self, tempclip):
  374.         if not hasattr(self, "saveclip"):
  375.             self.saveclip = []
  376.         saveclip = Qd.NewRgn()
  377.         Qd.GetClip(saveclip)
  378.         self.saveclip.append(saveclip)
  379.         Qd.SetClip(tempclip)
  380.     
  381.     def restoreclip(self):
  382.         Qd.SetClip(self.saveclip[-1])
  383.         Qd.DisposeRgn(self.saveclip[-1])
  384.         del self.saveclip[-1]
  385.     
  386.     def getgrowrect(self):
  387.         l, t, r, b = self.wid.GetWindowPort().portRect
  388.         return (r - 15, b - 15, r, b)
  389.     
  390.     def has_key(self, key):
  391.         return self._widgetsdict.has_key(key)
  392.     
  393.     def __getattr__(self, attr):
  394.         global _successcount, _failcount, _magiccount
  395.         if self._widgetsdict.has_key(attr):
  396.             _successcount = _successcount + 1
  397.             return self._widgetsdict[attr]
  398.         if self._currentwidget is None or (attr[:7] <> 'domenu_' and 
  399.                 attr[:4] <> 'can_' and attr <> 'insert'):
  400.             _failcount = _failcount + 1
  401.             raise AttributeError, attr
  402.         # special case: if a domenu_xxx, can_xxx or insert method is asked for, 
  403.         # see if the active widget supports it
  404.         _magiccount = _magiccount + 1
  405.         return getattr(self._currentwidget, attr)
  406.  
  407. _successcount = 0
  408. _failcount = 0
  409. _magiccount = 0
  410.  
  411. class Dialog(Window):
  412.     
  413.     windowkind = Windows.movableDBoxProc
  414.     
  415.     # this __init__ seems redundant, but it's not: it has less args
  416.     def __init__(self, possize, title = ""):
  417.         Window.__init__(self, possize, title)
  418.     
  419.     def can_close(self, *args):
  420.         return 0
  421.     
  422.     def getwindowbounds(self, size, minsize = None):
  423.         screenbounds = sl, st, sr, sb = Qd.qd.screenBits.bounds
  424.         w, h = size
  425.         l = sl + (sr - sl - w) / 2
  426.         t = st + (sb - st - h) / 3
  427.         return l, t, l + w, t + h
  428.  
  429.  
  430. class ModalDialog(Dialog):
  431.     
  432.     def __init__(self, possize, title = ""):
  433.         Dialog.__init__(self, possize, title)
  434.         if title:
  435.             self.windowkind = Windows.movableDBoxProc
  436.         else:
  437.             self.windowkind = Windows.dBoxProc
  438.     
  439.     def open(self):
  440.         import W
  441.         Dialog.open(self)
  442.         self.app = W.getapplication()
  443.         self.done = 0
  444.         Menu.HiliteMenu(0)
  445.         app = self.parent
  446.         app.enablemenubar(0)
  447.         try:
  448.             self.mainloop()
  449.         finally:
  450.             app.enablemenubar(1)
  451.     
  452.     def close(self):
  453.         if not self.wid:
  454.             return    # we are already closed
  455.         self.done = 1
  456.         del self.app
  457.         Dialog.close(self)
  458.     
  459.     def mainloop(self):
  460.         saveyield = MacOS.EnableAppswitch(-1)
  461.         while not self.done:
  462.             #self.do1event()
  463.             self.do1event(    Events.keyDownMask + 
  464.                         Events.autoKeyMask + 
  465.                         Events.activMask + 
  466.                         Events.updateMask + 
  467.                         Events.mDownMask +
  468.                         Events.mUpMask, 
  469.                         10)
  470.         MacOS.EnableAppswitch(saveyield)
  471.     
  472.     def do1event(self, mask = Events.everyEvent, wait = 0):
  473.         ok, event = self.app.getevent(mask, wait)
  474.         if Dlg.IsDialogEvent(event):
  475.             if self.app.do_dialogevent(event):
  476.                 return
  477.         if ok:
  478.             self.dispatch(event)
  479.         else:
  480.             self.app.idle(event)
  481.     
  482.     def do_keyDown(self, event):
  483.         self.do_key(event)
  484.     
  485.     def do_autoKey(self, event):
  486.         if not event[-1] & Events.cmdKey:
  487.             self.do_key(event)
  488.     
  489.     def do_key(self, event):
  490.         (what, message, when, where, modifiers) = event
  491.         w = Win.FrontWindow()
  492.         if w <> self.wid:
  493.             return
  494.         c = chr(message & Events.charCodeMask)
  495.         if modifiers & Events.cmdKey:
  496.             self.app.checkmenus(self)
  497.             result = Menu.MenuKey(ord(c))
  498.             id = (result>>16) & 0xffff    # Hi word
  499.             item = result & 0xffff        # Lo word
  500.             if id:
  501.                 self.app.do_rawmenu(id, item, None, event)
  502.                 return
  503.         self.do_char(c, event)
  504.     
  505.     def do_mouseDown(self, event):
  506.         (what, message, when, where, modifiers) = event
  507.         partcode, wid = Win.FindWindow(where)
  508.         #
  509.         # Find the correct name.
  510.         #
  511.         if FrameWork.partname.has_key(partcode):
  512.             name = "do_" + FrameWork.partname[partcode]
  513.         else:
  514.             name = "do_%d" % partcode
  515.         
  516.         if name == "do_inDesk":
  517.             MacOS.HandleEvent(event)
  518.             return
  519.         if wid == self.wid:
  520.             try:
  521.                 handler = getattr(self, name)
  522.             except AttributeError:
  523.                 handler = self.app.do_unknownpartcode
  524.         else:
  525.             #MacOS.HandleEvent(event)
  526.             if name == 'do_inMenuBar':
  527.                 handler = getattr(self.parent, name)
  528.             else:
  529.                 return        
  530.         handler(partcode, wid, event)
  531.     
  532.     def dispatch(self, event):
  533.         (what, message, when, where, modifiers) = event
  534.         if FrameWork.eventname.has_key(what):
  535.             name = "do_" + FrameWork.eventname[what]
  536.         else:
  537.             name = "do_%d" % what
  538.         try:
  539.             handler = getattr(self, name)
  540.         except AttributeError:
  541.             try:
  542.                 handler = getattr(self.app, name)
  543.             except AttributeError:
  544.                 handler = self.app.do_unknownevent
  545.         handler(event)
  546.     
  547.  
  548. def FrontWindowInsert(stuff):
  549.     if not stuff:
  550.         return
  551.     if type(stuff) <> StringType:
  552.         raise TypeError, 'string expected'
  553.     import W
  554.     app = W.getapplication()
  555.     wid = Win.FrontWindow()
  556.     if wid and app._windows.has_key(wid):
  557.         window = app._windows[wid]
  558.         if hasattr(window, "insert"):
  559.             try:
  560.                 window.insert(stuff)
  561.                 return
  562.             except:
  563.                 pass
  564.     import EasyDialogs
  565.     if EasyDialogs.AskYesNoCancel(
  566.             "Can’t find window or widget to insert text into; copy to clipboard instead?", 
  567.             1) == 1:
  568.         import Scrap
  569.         Scrap.ZeroScrap()
  570.         Scrap.PutScrap('TEXT', stuff)
  571.  
  572.  
  573. # not quite based on the same function in FrameWork    
  574. _windowcounter = 0
  575.  
  576. def getnextwindowpos():
  577.     global _windowcounter
  578.     rows = 8
  579.     l = 4 * (rows + 1 - (_windowcounter % rows) + _windowcounter / rows)
  580.     t = 44 + 20 * (_windowcounter % rows)
  581.     _windowcounter = _windowcounter + 1
  582.     return l, t
  583.  
  584. def windowbounds(preferredsize, minsize = None):
  585.     "Return sensible window bounds"
  586.     
  587.     global _windowcounter
  588.     if len(preferredsize) == 4:
  589.         bounds = l, t, r, b = preferredsize
  590.         union = Qd.UnionRect(bounds, Qd.qd.screenBits.bounds)
  591.         if union == Qd.qd.screenBits.bounds:
  592.             return bounds
  593.         else:
  594.             preferredsize = r - l, b - t
  595.     if not minsize:
  596.         minsize = preferredsize
  597.     minwidth, minheight = minsize
  598.     width, height = preferredsize
  599.     
  600.     sl, st, sr, sb = screenbounds = Qd.InsetRect(Qd.qd.screenBits.bounds, 4, 4)
  601.     l, t = getnextwindowpos()
  602.     if (l + width) > sr:
  603.         _windowcounter = 0
  604.         l, t = getnextwindowpos()
  605.     r = l + width
  606.     b = t + height
  607.     if (t + height) > sb:
  608.         b = sb
  609.         if (b - t) < minheight:
  610.             b = t + minheight
  611.     return l, t, r, b
  612.  
  613. scratchRegion = Qd.NewRgn()
  614.  
  615. # util -- move somewhere convenient???
  616. def GetRgnBounds(the_Rgn):
  617.     (t, l, b, r) = struct.unpack("hhhh", the_Rgn.data[2:10])
  618.     return (l, t, r, b)
  619.