18 class Window(FrameWork
.Window
, Wbase
.SelectableWidget
):
20 windowkind
= Windows
.documentProc
22 def __init__(self
, possize
, title
="", minsize
=None, maxsize
=None,
23 tabbable
=1, show
=1, fontsettings
=None):
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
)
32 self
._currentwidget
= None
34 self
._parentwindow
= self
35 self
._tabbable
= tabbable
36 self
._defaultbutton
= None
37 self
._drawwidgetbounds
= 0
39 self
._lastrollover
= None
41 # XXX the following is not really compatible with the
42 # new (system >= 7.5) window procs.
45 self
.windowkind
= self
.windowkind |
8
48 r
, b
= maxsize
[0] + 1, maxsize
[1] + 1
51 self
.growlimit
= (l
, t
, r
, b
)
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())
61 def settitle(self
, title
):
64 self
.wid
.SetWTitle(title
)
66 def getwindowbounds(self
, size
, minsize
= None):
67 return windowbounds(size
, minsize
)
69 def getcurrentwidget(self
):
70 return self
._currentwidget
72 def show(self
, onoff
):
79 return self
.wid
.IsWindowVisible()
82 self
.wid
.SelectWindow()
83 # not sure if this is the best place, I need it when
84 # an editor gets selected, and immediately scrolled
85 # to a certain line, waste scroll assumes everything
87 self
.do_rawupdate(self
.wid
, "DummyEvent")
90 self
.wid
= Win
.NewCWindow(self
._globalbounds
, self
.title
, self
._show
,
91 self
.windowkind
, -1, self
.hasclosebox
, 0)
93 fontname
, fontstyle
, fontsize
, fontcolor
= self
._fontsettings
94 fnum
= Fm
.GetFNum(fontname
)
96 fnum
= Fm
.GetFNum("Geneva")
98 Qd
.TextFace(fontstyle
)
100 if self
._bindings
.has_key("<open>"):
101 callback
= self
._bindings
["<open>"]
103 for w
in self
._widgets
:
104 w
.forall_frombottom("open")
107 self
.bind('tab', self
.nextwidget
)
108 self
.bind('shifttab', self
.previouswidget
)
110 self
._hasselframes
= 0
112 self
._tabchain
[0].select(1)
117 return # we are already closed
118 if self
._bindings
.has_key("<close>"):
119 callback
= self
._bindings
["<close>"]
123 print 'error in <close> callback'
124 traceback
.print_exc()
128 #for key in self._widgetsdict.keys():
129 # self._removewidget(key)
130 self
.forall_butself("close")
131 Wbase
.SelectableWidget
.close(self
)
133 self
._currentwidget
= None
134 self
.wid
.HideWindow()
137 def domenu_close(self
, *args
):
141 return self
._globalbounds
143 def setbounds(self
, bounds
):
146 self
.resize(r
-l
, b
-t
)
148 def move(self
, x
, y
= None):
152 self
.wid
.MoveWindow(x
, y
, 0)
154 def resize(self
, x
, y
= None):
155 if not self
._hasgrowbox
:
160 self
.GetWindow().InvalWindowRect(self
.getgrowrect())
161 self
.wid
.SizeWindow(x
, y
, 1)
164 def test(self
, point
):
167 def draw(self
, visRgn
= None):
169 self
.tempcliprect(self
.getgrowrect())
170 self
.wid
.DrawGrowIcon()
173 def idle(self
, *args
):
175 point
= Evt
.GetMouse()
176 widget
= self
.findwidget(point
, 0)
177 if self
._bindings
.has_key("<idle>"):
178 callback
= self
._bindings
["<idle>"]
181 if self
._currentwidget
is not None and hasattr(self
._currentwidget
, "idle"):
182 if self
._currentwidget
._bindings
.has_key("<idle>"):
183 callback
= self
._currentwidget
._bindings
["<idle>"]
186 if self
._currentwidget
.idle():
188 if widget
is not None and hasattr(widget
, "rollover"):
189 if 1: #self._lastrollover <> widget:
190 if self
._lastrollover
:
191 self
._lastrollover
.rollover(point
, 0)
192 self
._lastrollover
= widget
193 self
._lastrollover
.rollover(point
, 1)
195 if self
._lastrollover
:
196 self
._lastrollover
.rollover(point
, 0)
197 self
._lastrollover
= None
198 Wbase
.SetCursor("arrow")
200 def xxx___select(self
, widget
):
201 if self
._currentwidget
== widget
:
203 if self
._bindings
.has_key("<select>"):
204 callback
= self
._bindings
["<select>"]
208 if self
._currentwidget
is not None:
209 self
._currentwidget
.select(0)
210 elif type(widget
) == InstanceType
and widget
._selectable
:
212 elif widget
== -1 or widget
== 1:
213 if len(self
._tabchain
) <= 1:
215 temp
= self
._tabchain
[(self
._tabchain
.index(self
._currentwidget
) + widget
) % len(self
._tabchain
)]
218 raise TypeError, "Widget is not selectable"
220 def setdefaultbutton(self
, newdefaultbutton
= None, *keys
):
221 if newdefaultbutton
== self
._defaultbutton
:
223 if self
._defaultbutton
:
224 self
._defaultbutton
._setdefault
(0)
225 if not newdefaultbutton
:
226 self
.bind("return", None)
227 self
.bind("enter", None)
230 if not isinstance(newdefaultbutton
, Wcontrols
.Button
):
231 raise TypeError, "widget is not a button"
232 self
._defaultbutton
= newdefaultbutton
233 self
._defaultbutton
._setdefault
(1)
235 self
.bind("return", self
._defaultbutton
.push
)
236 self
.bind("enter", self
._defaultbutton
.push
)
239 self
.bind(key
, self
._defaultbutton
.push
)
241 def nextwidget(self
):
244 def previouswidget(self
):
245 self
.xxx___select(-1)
247 def drawwidgetbounds(self
, onoff
):
248 self
._drawwidgetbounds
= onoff
250 self
.GetWindow().InvalWindowRect(self
._bounds
)
252 def _drawbounds(self
):
255 def _maketabchain(self
):
256 # XXX This has to change, it's no good when we are adding or deleting widgets.
257 # XXX Perhaps we shouldn't keep a "tabchain" at all.
258 self
._hasselframes
= 0
259 self
._collectselectablewidgets
(self
._widgets
)
260 if self
._hasselframes
and len(self
._tabchain
) > 1:
261 self
._hasselframes
= 1
263 self
._hasselframes
= 0
265 def _collectselectablewidgets(self
, widgets
):
269 self
._tabchain
.append(w
)
270 if isinstance(w
, W
.List
):
271 self
._hasselframes
= 1
272 self
._collectselectablewidgets
(w
._widgets
)
274 def _calcbounds(self
):
275 self
._possize
= self
.wid
.GetWindowPort().portRect
[2:]
277 self
._bounds
= (0, 0, w
, h
)
278 self
.wid
.GetWindowContentRgn(scratchRegion
)
279 l
, t
, r
, b
= GetRgnBounds(scratchRegion
)
280 self
._globalbounds
= l
, t
, l
+ w
, t
+ h
281 for w
in self
._widgets
:
284 # FrameWork override methods
285 def do_inDrag(self
, partcode
, window
, event
):
287 self
.wid
.GetWindowContentRgn(scratchRegion
)
288 was_l
, was_t
, r
, b
= GetRgnBounds(scratchRegion
)
289 window
.DragWindow(where
, self
.draglimit
)
290 self
.wid
.GetWindowContentRgn(scratchRegion
)
291 is_l
, is_t
, r
, b
= GetRgnBounds(scratchRegion
)
292 self
._globalbounds
= Qd
.OffsetRect(self
._globalbounds
,
293 is_l
- was_l
, is_t
- was_t
)
295 def do_char(self
, char
, event
):
297 (what
, message
, when
, where
, modifiers
) = event
299 if Wkeys
.keynames
.has_key(key
):
300 key
= Wkeys
.keynames
[key
]
301 if modifiers
& Events
.shiftKey
:
303 if modifiers
& Events
.cmdKey
:
305 if modifiers
& Events
.controlKey
:
306 key
= 'control' + key
307 if self
._bindings
.has_key("<key>"):
308 callback
= self
._bindings
["<key>"]
309 if Wbase
.CallbackCall(callback
, 0, char
, event
):
311 if self
._bindings
.has_key(key
):
312 callback
= self
._bindings
[key
]
313 Wbase
.CallbackCall(callback
, 0, char
, event
)
314 elif self
._currentwidget
is not None:
315 if self
._currentwidget
._bindings
.has_key(key
):
316 callback
= self
._currentwidget
._bindings
[key
]
317 Wbase
.CallbackCall(callback
, 0, char
, event
)
319 if self
._currentwidget
._bindings
.has_key("<key>"):
320 callback
= self
._currentwidget
._bindings
["<key>"]
321 if Wbase
.CallbackCall(callback
, 0, char
, event
):
323 self
._currentwidget
.key(char
, event
)
325 def do_contentclick(self
, point
, modifiers
, event
):
326 widget
= self
.findwidget(point
)
327 if widget
is not None:
328 if self
._bindings
.has_key("<click>"):
329 callback
= self
._bindings
["<click>"]
330 if Wbase
.CallbackCall(callback
, 0, point
, modifiers
):
332 if widget
._bindings
.has_key("<click>"):
333 callback
= widget
._bindings
["<click>"]
334 if Wbase
.CallbackCall(callback
, 0, point
, modifiers
):
336 if widget
._selectable
:
338 widget
.click(point
, modifiers
)
340 def do_update(self
, window
, event
):
341 Qd
.EraseRgn(window
.GetWindowPort().visRgn
)
342 self
.forall_frombottom("draw", window
.GetWindowPort().visRgn
)
343 if self
._drawwidgetbounds
:
344 self
.forall_frombottom("_drawbounds")
346 def do_activate(self
, onoff
, event
):
348 if self
._lastrollover
:
349 self
._lastrollover
.rollover((0, 0), 0)
350 self
._lastrollover
= None
352 self
.forall("activate", onoff
)
355 def do_postresize(self
, width
, height
, window
):
356 self
.GetWindow().InvalWindowRect(self
.getgrowrect())
359 def do_inGoAway(self
, partcode
, window
, event
):
361 closeall
= event
[4] & Events
.optionKey
362 if window
.TrackGoAway(where
):
366 for window
in self
.parent
._windows
.values():
372 def tempcliprect(self
, tempcliprect
):
373 tempclip
= Qd
.NewRgn()
374 Qd
.RectRgn(tempclip
, tempcliprect
)
375 self
.tempclip(tempclip
)
376 Qd
.DisposeRgn(tempclip
)
378 def tempclip(self
, tempclip
):
379 if not hasattr(self
, "saveclip"):
381 saveclip
= Qd
.NewRgn()
383 self
.saveclip
.append(saveclip
)
386 def restoreclip(self
):
387 Qd
.SetClip(self
.saveclip
[-1])
388 Qd
.DisposeRgn(self
.saveclip
[-1])
389 del self
.saveclip
[-1]
391 def getgrowrect(self
):
392 l
, t
, r
, b
= self
.wid
.GetWindowPort().portRect
393 return (r
- 15, b
- 15, r
, b
)
395 def has_key(self
, key
):
396 return self
._widgetsdict
.has_key(key
)
398 def __getattr__(self
, attr
):
399 global _successcount
, _failcount
, _magiccount
400 if self
._widgetsdict
.has_key(attr
):
401 _successcount
= _successcount
+ 1
402 return self
._widgetsdict
[attr
]
403 if self
._currentwidget
is None or (attr
[:7] <> 'domenu_' and
404 attr
[:4] <> 'can_' and attr
<> 'insert'):
405 _failcount
= _failcount
+ 1
406 raise AttributeError, attr
407 # special case: if a domenu_xxx, can_xxx or insert method is asked for,
408 # see if the active widget supports it
409 _magiccount
= _magiccount
+ 1
410 return getattr(self
._currentwidget
, attr
)
416 class Dialog(Window
):
418 windowkind
= Windows
.movableDBoxProc
420 # this __init__ seems redundant, but it's not: it has less args
421 def __init__(self
, possize
, title
= ""):
422 Window
.__init
__(self
, possize
, title
)
424 def can_close(self
, *args
):
427 def getwindowbounds(self
, size
, minsize
= None):
428 screenbounds
= sl
, st
, sr
, sb
= Qd
.qd
.screenBits
.bounds
430 l
= sl
+ (sr
- sl
- w
) / 2
431 t
= st
+ (sb
- st
- h
) / 3
432 return l
, t
, l
+ w
, t
+ h
435 class ModalDialog(Dialog
):
437 def __init__(self
, possize
, title
= ""):
438 Dialog
.__init
__(self
, possize
, title
)
440 self
.windowkind
= Windows
.movableDBoxProc
442 self
.windowkind
= Windows
.dBoxProc
447 self
.app
= W
.getapplication()
459 return # we are already closed
465 saveyield
= MacOS
.EnableAppswitch(-1)
468 self
.do1event( Events
.keyDownMask
+
475 MacOS
.EnableAppswitch(saveyield
)
477 def do1event(self
, mask
= Events
.everyEvent
, wait
= 0):
478 ok
, event
= self
.app
.getevent(mask
, wait
)
479 if Dlg
.IsDialogEvent(event
):
480 if self
.app
.do_dialogevent(event
):
487 def do_keyDown(self
, event
):
490 def do_autoKey(self
, event
):
491 if not event
[-1] & Events
.cmdKey
:
494 def do_key(self
, event
):
495 (what
, message
, when
, where
, modifiers
) = event
496 w
= Win
.FrontWindow()
499 c
= chr(message
& Events
.charCodeMask
)
500 if modifiers
& Events
.cmdKey
:
501 self
.app
.checkmenus(self
)
502 result
= Menu
.MenuKey(ord(c
))
503 id = (result
>>16) & 0xffff # Hi word
504 item
= result
& 0xffff # Lo word
506 self
.app
.do_rawmenu(id, item
, None, event
)
508 self
.do_char(c
, event
)
510 def do_mouseDown(self
, event
):
511 (what
, message
, when
, where
, modifiers
) = event
512 partcode
, wid
= Win
.FindWindow(where
)
514 # Find the correct name.
516 if FrameWork
.partname
.has_key(partcode
):
517 name
= "do_" + FrameWork
.partname
[partcode
]
519 name
= "do_%d" % partcode
521 if name
== "do_inDesk":
522 MacOS
.HandleEvent(event
)
526 handler
= getattr(self
, name
)
527 except AttributeError:
528 handler
= self
.app
.do_unknownpartcode
530 #MacOS.HandleEvent(event)
531 if name
== 'do_inMenuBar':
532 handler
= getattr(self
.parent
, name
)
535 handler(partcode
, wid
, event
)
537 def dispatch(self
, event
):
538 (what
, message
, when
, where
, modifiers
) = event
539 if FrameWork
.eventname
.has_key(what
):
540 name
= "do_" + FrameWork
.eventname
[what
]
542 name
= "do_%d" % what
544 handler
= getattr(self
, name
)
545 except AttributeError:
547 handler
= getattr(self
.app
, name
)
548 except AttributeError:
549 handler
= self
.app
.do_unknownevent
553 def FrontWindowInsert(stuff
):
556 if type(stuff
) <> StringType
:
557 raise TypeError, 'string expected'
559 app
= W
.getapplication()
560 wid
= Win
.FrontWindow()
561 if wid
and app
._windows
.has_key(wid
):
562 window
= app
._windows
[wid
]
563 if hasattr(window
, "insert"):
570 if EasyDialogs
.AskYesNoCancel(
571 "Can't find window or widget to insert text into; copy to clipboard instead?",
575 Scrap
.PutScrap('TEXT', stuff
)
578 # not quite based on the same function in FrameWork
581 def getnextwindowpos():
582 global _windowcounter
584 l
= 4 * (rows
+ 1 - (_windowcounter
% rows
) + _windowcounter
/ rows
)
585 t
= 44 + 20 * (_windowcounter
% rows
)
586 _windowcounter
= _windowcounter
+ 1
589 def windowbounds(preferredsize
, minsize
=None):
590 "Return sensible window bounds"
592 global _windowcounter
593 if len(preferredsize
) == 4:
594 bounds
= l
, t
, r
, b
= preferredsize
595 desktopRgn
= Win
.GetGrayRgn()
596 tempRgn
= Qd
.NewRgn()
597 Qd
.RectRgn(tempRgn
, bounds
)
598 union
= Qd
.UnionRgn(tempRgn
, desktopRgn
, tempRgn
)
599 equal
= Qd
.EqualRgn(tempRgn
, desktopRgn
)
600 Qd
.DisposeRgn(tempRgn
)
604 preferredsize
= r
- l
, b
- t
606 minsize
= preferredsize
607 minwidth
, minheight
= minsize
608 width
, height
= preferredsize
610 sl
, st
, sr
, sb
= screenbounds
= Qd
.InsetRect(Qd
.qd
.screenBits
.bounds
, 4, 4)
611 l
, t
= getnextwindowpos()
614 l
, t
= getnextwindowpos()
617 if (t
+ height
) > sb
:
619 if (b
- t
) < minheight
:
623 scratchRegion
= Qd
.NewRgn()
625 # util -- move somewhere convenient???
626 def GetRgnBounds(the_Rgn
):
627 (t
, l
, b
, r
) = struct
.unpack("hhhh", the_Rgn
.data
[2:10])