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 if 0: #self.isvisible():
83 self
.wid
.GetWindowContentRgn(scratchRegion
)
84 self
._globalbounds
= GetRgnBounds(scratchRegion
)
85 return self
._globalbounds
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
93 self
.do_rawupdate(self
.wid
, "DummyEvent")
96 self
.wid
= Win
.NewCWindow(self
._globalbounds
, self
.title
, self
._show
,
97 self
.windowkind
, -1, self
.hasclosebox
, 0)
99 fontname
, fontstyle
, fontsize
, fontcolor
= self
._fontsettings
100 fnum
= Fm
.GetFNum(fontname
)
102 fnum
= Fm
.GetFNum("Geneva")
104 Qd
.TextFace(fontstyle
)
105 Qd
.TextSize(fontsize
)
106 if self
._bindings
.has_key("<open>"):
107 callback
= self
._bindings
["<open>"]
109 for w
in self
._widgets
:
110 w
.forall_frombottom("open")
113 self
.bind('tab', self
.nextwidget
)
114 self
.bind('shifttab', self
.previouswidget
)
116 self
._hasselframes
= 0
118 self
._tabchain
[0].select(1)
123 return # we are already closed
124 if self
._bindings
.has_key("<close>"):
125 callback
= self
._bindings
["<close>"]
129 print 'error in <close> callback'
130 traceback
.print_exc()
134 #for key in self._widgetsdict.keys():
135 # self._removewidget(key)
136 self
.forall_butself("close")
137 Wbase
.SelectableWidget
.close(self
)
139 self
._currentwidget
= None
140 self
.wid
.HideWindow()
143 def domenu_close(self
, *args
):
146 def move(self
, x
, y
= None):
150 self
.wid
.MoveWindow(x
, y
, 0)
152 def resize(self
, x
, y
= None):
157 Win
.InvalRect(self
.getgrowrect())
158 self
.wid
.SizeWindow(x
, y
, 1)
161 def test(self
, point
):
164 def draw(self
, visRgn
= None):
166 self
.tempcliprect(self
.getgrowrect())
167 self
.wid
.DrawGrowIcon()
170 def idle(self
, *args
):
172 point
= Evt
.GetMouse()
173 widget
= self
.findwidget(point
, 0)
174 if self
._bindings
.has_key("<idle>"):
175 callback
= self
._bindings
["<idle>"]
178 if self
._currentwidget
is not None and hasattr(self
._currentwidget
, "idle"):
179 if self
._currentwidget
._bindings
.has_key("<idle>"):
180 callback
= self
._currentwidget
._bindings
["<idle>"]
183 if self
._currentwidget
.idle():
185 if widget
is not None and hasattr(widget
, "rollover"):
186 if 1: #self._lastrollover <> widget:
187 if self
._lastrollover
:
188 self
._lastrollover
.rollover(point
, 0)
189 self
._lastrollover
= widget
190 self
._lastrollover
.rollover(point
, 1)
192 if self
._lastrollover
:
193 self
._lastrollover
.rollover(point
, 0)
194 self
._lastrollover
= None
195 Wbase
.SetCursor("arrow")
197 def xxx___select(self
, widget
):
198 if self
._currentwidget
== widget
:
200 if self
._bindings
.has_key("<select>"):
201 callback
= self
._bindings
["<select>"]
205 if self
._currentwidget
is not None:
206 self
._currentwidget
.select(0)
207 elif type(widget
) == InstanceType
and widget
._selectable
:
209 elif widget
== -1 or widget
== 1:
210 if len(self
._tabchain
) <= 1:
212 temp
= self
._tabchain
[(self
._tabchain
.index(self
._currentwidget
) + widget
) % len(self
._tabchain
)]
215 raise TypeError, "Widget is not selectable"
217 def setdefaultbutton(self
, newdefaultbutton
= None, *keys
):
218 if newdefaultbutton
== self
._defaultbutton
:
220 if self
._defaultbutton
:
221 self
._defaultbutton
._setdefault
(0)
222 if not newdefaultbutton
:
223 self
.bind("return", None)
224 self
.bind("enter", None)
227 if not isinstance(newdefaultbutton
, Wcontrols
.Button
):
228 raise TypeError, "widget is not a button"
229 self
._defaultbutton
= newdefaultbutton
230 self
._defaultbutton
._setdefault
(1)
232 self
.bind("return", self
._defaultbutton
.push
)
233 self
.bind("enter", self
._defaultbutton
.push
)
236 self
.bind(key
, self
._defaultbutton
.push
)
238 def nextwidget(self
):
241 def previouswidget(self
):
242 self
.xxx___select(-1)
244 def drawwidgetbounds(self
, onoff
):
245 self
._drawwidgetbounds
= onoff
247 Win
.InvalRect(self
._bounds
)
249 def _drawbounds(self
):
252 def _maketabchain(self
):
253 # XXX This has to change, it's no good when we are adding or deleting widgets.
254 # XXX Perhaps we shouldn't keep a "tabchain" at all.
255 self
._hasselframes
= 0
256 self
._collectselectablewidgets
(self
._widgets
)
257 if self
._hasselframes
and len(self
._tabchain
) > 1:
258 self
._hasselframes
= 1
260 self
._hasselframes
= 0
262 def _collectselectablewidgets(self
, widgets
):
266 self
._tabchain
.append(w
)
267 if isinstance(w
, W
.List
):
268 self
._hasselframes
= 1
269 self
._collectselectablewidgets
(w
._widgets
)
271 def _calcbounds(self
):
272 self
._possize
= self
.wid
.GetWindowPort().portRect
[2:]
274 self
._bounds
= (0, 0, w
, h
)
275 self
.wid
.GetWindowContentRgn(scratchRegion
)
276 l
, t
, r
, b
= GetRgnBounds(scratchRegion
)
277 self
._globalbounds
= l
, t
, l
+ w
, t
+ h
278 for w
in self
._widgets
:
281 # FrameWork override methods
282 def do_inDrag(self
, partcode
, window
, event
):
284 self
.wid
.GetWindowContentRgn(scratchRegion
)
285 was_l
, was_t
, r
, b
= GetRgnBounds(scratchRegion
)
286 window
.DragWindow(where
, self
.draglimit
)
287 self
.wid
.GetWindowContentRgn(scratchRegion
)
288 is_l
, is_t
, r
, b
= GetRgnBounds(scratchRegion
)
289 self
._globalbounds
= Qd
.OffsetRect(self
._globalbounds
,
290 is_l
- was_l
, is_t
- was_t
)
292 def do_char(self
, char
, event
):
294 (what
, message
, when
, where
, modifiers
) = event
296 if Wkeys
.keynames
.has_key(key
):
297 key
= Wkeys
.keynames
[key
]
298 if modifiers
& Events
.shiftKey
:
300 if modifiers
& Events
.cmdKey
:
302 if modifiers
& Events
.controlKey
:
303 key
= 'control' + key
304 if self
._bindings
.has_key("<key>"):
305 callback
= self
._bindings
["<key>"]
306 if Wbase
.CallbackCall(callback
, 0, char
, event
):
308 if self
._bindings
.has_key(key
):
309 callback
= self
._bindings
[key
]
310 Wbase
.CallbackCall(callback
, 0, char
, event
)
311 elif self
._currentwidget
is not None:
312 if self
._currentwidget
._bindings
.has_key(key
):
313 callback
= self
._currentwidget
._bindings
[key
]
314 Wbase
.CallbackCall(callback
, 0, char
, event
)
316 if self
._currentwidget
._bindings
.has_key("<key>"):
317 callback
= self
._currentwidget
._bindings
["<key>"]
318 if Wbase
.CallbackCall(callback
, 0, char
, event
):
320 self
._currentwidget
.key(char
, event
)
322 def do_contentclick(self
, point
, modifiers
, event
):
323 widget
= self
.findwidget(point
)
324 if widget
is not None:
325 if self
._bindings
.has_key("<click>"):
326 callback
= self
._bindings
["<click>"]
327 if Wbase
.CallbackCall(callback
, 0, point
, modifiers
):
329 if widget
._bindings
.has_key("<click>"):
330 callback
= widget
._bindings
["<click>"]
331 if Wbase
.CallbackCall(callback
, 0, point
, modifiers
):
333 if widget
._selectable
:
335 widget
.click(point
, modifiers
)
337 def do_update(self
, window
, event
):
338 Qd
.EraseRgn(window
.GetWindowPort().visRgn
)
339 self
.forall_frombottom("draw", window
.GetWindowPort().visRgn
)
340 if self
._drawwidgetbounds
:
341 self
.forall_frombottom("_drawbounds")
343 def do_activate(self
, onoff
, event
):
345 if self
._lastrollover
:
346 self
._lastrollover
.rollover((0, 0), 0)
347 self
._lastrollover
= None
349 self
.forall("activate", onoff
)
352 def do_postresize(self
, width
, height
, window
):
353 Win
.InvalRect(self
.getgrowrect())
356 def do_inGoAway(self
, partcode
, window
, event
):
358 closeall
= event
[4] & Events
.optionKey
359 if window
.TrackGoAway(where
):
363 for window
in self
.parent
._windows
.values():
369 def tempcliprect(self
, tempcliprect
):
370 tempclip
= Qd
.NewRgn()
371 Qd
.RectRgn(tempclip
, tempcliprect
)
372 self
.tempclip(tempclip
)
373 Qd
.DisposeRgn(tempclip
)
375 def tempclip(self
, tempclip
):
376 if not hasattr(self
, "saveclip"):
378 saveclip
= Qd
.NewRgn()
380 self
.saveclip
.append(saveclip
)
383 def restoreclip(self
):
384 Qd
.SetClip(self
.saveclip
[-1])
385 Qd
.DisposeRgn(self
.saveclip
[-1])
386 del self
.saveclip
[-1]
388 def getgrowrect(self
):
389 l
, t
, r
, b
= self
.wid
.GetWindowPort().portRect
390 return (r
- 15, b
- 15, r
, b
)
392 def has_key(self
, key
):
393 return self
._widgetsdict
.has_key(key
)
395 def __getattr__(self
, attr
):
396 global _successcount
, _failcount
, _magiccount
397 if self
._widgetsdict
.has_key(attr
):
398 _successcount
= _successcount
+ 1
399 return self
._widgetsdict
[attr
]
400 if self
._currentwidget
is None or (attr
[:7] <> 'domenu_' and
401 attr
[:4] <> 'can_' and attr
<> 'insert'):
402 _failcount
= _failcount
+ 1
403 raise AttributeError, attr
404 # special case: if a domenu_xxx, can_xxx or insert method is asked for,
405 # see if the active widget supports it
406 _magiccount
= _magiccount
+ 1
407 return getattr(self
._currentwidget
, attr
)
413 class Dialog(Window
):
415 windowkind
= Windows
.movableDBoxProc
417 # this __init__ seems redundant, but it's not: it has less args
418 def __init__(self
, possize
, title
= ""):
419 Window
.__init
__(self
, possize
, title
)
421 def can_close(self
, *args
):
424 def getwindowbounds(self
, size
, minsize
= None):
425 screenbounds
= sl
, st
, sr
, sb
= Qd
.qd
.screenBits
.bounds
427 l
= sl
+ (sr
- sl
- w
) / 2
428 t
= st
+ (sb
- st
- h
) / 3
429 return l
, t
, l
+ w
, t
+ h
432 class ModalDialog(Dialog
):
434 def __init__(self
, possize
, title
= ""):
435 Dialog
.__init
__(self
, possize
, title
)
437 self
.windowkind
= Windows
.movableDBoxProc
439 self
.windowkind
= Windows
.dBoxProc
444 self
.app
= W
.getapplication()
456 return # we are already closed
462 saveyield
= MacOS
.EnableAppswitch(-1)
465 self
.do1event( Events
.keyDownMask
+
472 MacOS
.EnableAppswitch(saveyield
)
474 def do1event(self
, mask
= Events
.everyEvent
, wait
= 0):
475 ok
, event
= self
.app
.getevent(mask
, wait
)
476 if Dlg
.IsDialogEvent(event
):
477 if self
.app
.do_dialogevent(event
):
484 def do_keyDown(self
, event
):
487 def do_autoKey(self
, event
):
488 if not event
[-1] & Events
.cmdKey
:
491 def do_key(self
, event
):
492 (what
, message
, when
, where
, modifiers
) = event
493 w
= Win
.FrontWindow()
496 c
= chr(message
& Events
.charCodeMask
)
497 if modifiers
& Events
.cmdKey
:
498 self
.app
.checkmenus(self
)
499 result
= Menu
.MenuKey(ord(c
))
500 id = (result
>>16) & 0xffff # Hi word
501 item
= result
& 0xffff # Lo word
503 self
.app
.do_rawmenu(id, item
, None, event
)
505 self
.do_char(c
, event
)
507 def do_mouseDown(self
, event
):
508 (what
, message
, when
, where
, modifiers
) = event
509 partcode
, wid
= Win
.FindWindow(where
)
511 # Find the correct name.
513 if FrameWork
.partname
.has_key(partcode
):
514 name
= "do_" + FrameWork
.partname
[partcode
]
516 name
= "do_%d" % partcode
518 if name
== "do_inDesk":
519 MacOS
.HandleEvent(event
)
523 handler
= getattr(self
, name
)
524 except AttributeError:
525 handler
= self
.app
.do_unknownpartcode
527 #MacOS.HandleEvent(event)
528 if name
== 'do_inMenuBar':
529 handler
= getattr(self
.parent
, name
)
532 handler(partcode
, wid
, event
)
534 def dispatch(self
, event
):
535 (what
, message
, when
, where
, modifiers
) = event
536 if FrameWork
.eventname
.has_key(what
):
537 name
= "do_" + FrameWork
.eventname
[what
]
539 name
= "do_%d" % what
541 handler
= getattr(self
, name
)
542 except AttributeError:
544 handler
= getattr(self
.app
, name
)
545 except AttributeError:
546 handler
= self
.app
.do_unknownevent
550 def FrontWindowInsert(stuff
):
553 if type(stuff
) <> StringType
:
554 raise TypeError, 'string expected'
556 app
= W
.getapplication()
557 wid
= Win
.FrontWindow()
558 if wid
and app
._windows
.has_key(wid
):
559 window
= app
._windows
[wid
]
560 if hasattr(window
, "insert"):
567 if EasyDialogs
.AskYesNoCancel(
568 "CanĀ¹t find window or widget to insert text into; copy to clipboard instead?",
572 Scrap
.PutScrap('TEXT', stuff
)
575 # not quite based on the same function in FrameWork
578 def getnextwindowpos():
579 global _windowcounter
581 l
= 4 * (rows
+ 1 - (_windowcounter
% rows
) + _windowcounter
/ rows
)
582 t
= 44 + 20 * (_windowcounter
% rows
)
583 _windowcounter
= _windowcounter
+ 1
586 def windowbounds(preferredsize
, minsize
=None):
587 "Return sensible window bounds"
589 global _windowcounter
590 if len(preferredsize
) == 4:
591 bounds
= l
, t
, r
, b
= preferredsize
592 desktopRgn
= Win
.GetGrayRgn()
593 tempRgn
= Qd
.NewRgn()
594 Qd
.RectRgn(tempRgn
, bounds
)
595 union
= Qd
.UnionRgn(tempRgn
, desktopRgn
, tempRgn
)
596 equal
= Qd
.EqualRgn(tempRgn
, desktopRgn
)
597 Qd
.DisposeRgn(tempRgn
)
601 preferredsize
= r
- l
, b
- t
603 minsize
= preferredsize
604 minwidth
, minheight
= minsize
605 width
, height
= preferredsize
607 sl
, st
, sr
, sb
= screenbounds
= Qd
.InsetRect(Qd
.qd
.screenBits
.bounds
, 4, 4)
608 l
, t
= getnextwindowpos()
611 l
, t
= getnextwindowpos()
614 if (t
+ height
) > sb
:
616 if (b
- t
) < minheight
:
620 scratchRegion
= Qd
.NewRgn()
622 # util -- move somewhere convenient???
623 def GetRgnBounds(the_Rgn
):
624 (t
, l
, b
, r
) = struct
.unpack("hhhh", the_Rgn
.data
[2:10])