1 from Carbon
import Dlg
, Evt
, Events
, Fm
2 from Carbon
import Menu
, Qd
, Win
, Windows
8 from types
import InstanceType
, StringType
10 if hasattr(Win
, "FrontNonFloatingWindow"):
11 MyFrontWindow
= Win
.FrontNonFloatingWindow
13 MyFrontWindow
= Win
.FrontWindow
16 class Window(FrameWork
.Window
, Wbase
.SelectableWidget
):
18 windowkind
= Windows
.documentProc
20 def __init__(self
, possize
, title
="", minsize
=None, maxsize
=None,
21 tabbable
=1, show
=1, fontsettings
=None):
23 if fontsettings
is None:
24 fontsettings
= W
.getdefaultfont()
25 self
._fontsettings
= fontsettings
26 W
.SelectableWidget
.__init
__(self
, possize
)
27 self
._globalbounds
= l
, t
, r
, b
= self
.getwindowbounds(possize
, minsize
)
28 self
._bounds
= (0, 0, r
- l
, b
- t
)
30 self
._currentwidget
= None
32 self
._parentwindow
= self
33 self
._tabbable
= tabbable
34 self
._defaultbutton
= None
35 self
._drawwidgetbounds
= 0
37 self
._lastrollover
= None
39 # XXX the following is not really compatible with the
40 # new (system >= 7.5) window procs.
43 self
.windowkind
= self
.windowkind |
8
46 r
, b
= maxsize
[0] + 1, maxsize
[1] + 1
49 self
.growlimit
= (l
, t
, r
, b
)
52 if (self
.windowkind
== 0 or self
.windowkind
>= 8) and self
.windowkind
< 1000:
53 self
.windowkind
= self
.windowkind |
4
54 FrameWork
.Window
.__init
__(self
, W
.getapplication())
59 def settitle(self
, title
):
62 self
.wid
.SetWTitle(title
)
64 def getwindowbounds(self
, size
, minsize
= None):
65 return windowbounds(size
, minsize
)
67 def getcurrentwidget(self
):
68 return self
._currentwidget
70 def show(self
, onoff
):
77 return self
.wid
.IsWindowVisible()
80 self
.wid
.SelectWindow()
81 # not sure if this is the best place, I need it when
82 # an editor gets selected, and immediately scrolled
83 # to a certain line, waste scroll assumes everything
85 self
.do_rawupdate(self
.wid
, "DummyEvent")
88 self
.wid
= Win
.NewCWindow(self
._globalbounds
, self
.title
, self
._show
,
89 self
.windowkind
, -1, self
.hasclosebox
, 0)
91 fontname
, fontstyle
, fontsize
, fontcolor
= self
._fontsettings
92 fnum
= Fm
.GetFNum(fontname
)
94 fnum
= Fm
.GetFNum("Geneva")
96 Qd
.TextFace(fontstyle
)
98 if self
._bindings
.has_key("<open>"):
99 callback
= self
._bindings
["<open>"]
101 for w
in self
._widgets
:
102 w
.forall_frombottom("open")
105 self
.bind('tab', self
.nextwidget
)
106 self
.bind('shifttab', self
.previouswidget
)
108 self
._hasselframes
= 0
110 self
._tabchain
[0].select(1)
115 return # we are already closed
116 if self
._bindings
.has_key("<close>"):
117 callback
= self
._bindings
["<close>"]
121 print 'error in <close> callback'
122 traceback
.print_exc()
126 #for key in self._widgetsdict.keys():
127 # self._removewidget(key)
128 self
.forall_butself("close")
129 Wbase
.SelectableWidget
.close(self
)
131 self
._currentwidget
= None
132 self
.wid
.HideWindow()
135 def domenu_close(self
, *args
):
139 return self
._globalbounds
141 def setbounds(self
, bounds
):
144 self
.resize(r
-l
, b
-t
)
146 def move(self
, x
, y
= None):
150 self
.wid
.MoveWindow(x
, y
, 0)
152 def resize(self
, x
, y
= None):
153 if not self
._hasgrowbox
:
158 self
.GetWindow().InvalWindowRect(self
.getgrowrect())
159 self
.wid
.SizeWindow(x
, y
, 1)
162 def test(self
, point
):
165 def draw(self
, visRgn
= None):
167 self
.tempcliprect(self
.getgrowrect())
168 self
.wid
.DrawGrowIcon()
171 def idle(self
, *args
):
173 point
= Evt
.GetMouse()
174 widget
= self
.findwidget(point
, 0)
175 if self
._bindings
.has_key("<idle>"):
176 callback
= self
._bindings
["<idle>"]
179 if self
._currentwidget
is not None and hasattr(self
._currentwidget
, "idle"):
180 if self
._currentwidget
._bindings
.has_key("<idle>"):
181 callback
= self
._currentwidget
._bindings
["<idle>"]
184 if self
._currentwidget
.idle():
186 if widget
is not None and hasattr(widget
, "rollover"):
187 if 1: #self._lastrollover <> widget:
188 if self
._lastrollover
:
189 self
._lastrollover
.rollover(point
, 0)
190 self
._lastrollover
= widget
191 self
._lastrollover
.rollover(point
, 1)
193 if self
._lastrollover
:
194 self
._lastrollover
.rollover(point
, 0)
195 self
._lastrollover
= None
196 Wbase
.SetCursor("arrow")
198 def xxx___select(self
, widget
):
199 if self
._currentwidget
== widget
:
201 if self
._bindings
.has_key("<select>"):
202 callback
= self
._bindings
["<select>"]
206 if self
._currentwidget
is not None:
207 self
._currentwidget
.select(0)
208 elif type(widget
) == InstanceType
and widget
._selectable
:
210 elif widget
== -1 or widget
== 1:
211 if len(self
._tabchain
) <= 1:
213 temp
= self
._tabchain
[(self
._tabchain
.index(self
._currentwidget
) + widget
) % len(self
._tabchain
)]
216 raise TypeError, "Widget is not selectable"
218 def setdefaultbutton(self
, newdefaultbutton
= None, *keys
):
219 if newdefaultbutton
== self
._defaultbutton
:
221 if self
._defaultbutton
:
222 self
._defaultbutton
._setdefault
(0)
223 if not newdefaultbutton
:
224 self
.bind("return", None)
225 self
.bind("enter", None)
228 if not isinstance(newdefaultbutton
, Wcontrols
.Button
):
229 raise TypeError, "widget is not a button"
230 self
._defaultbutton
= newdefaultbutton
231 self
._defaultbutton
._setdefault
(1)
233 self
.bind("return", self
._defaultbutton
.push
)
234 self
.bind("enter", self
._defaultbutton
.push
)
237 self
.bind(key
, self
._defaultbutton
.push
)
239 def nextwidget(self
):
242 def previouswidget(self
):
243 self
.xxx___select(-1)
245 def drawwidgetbounds(self
, onoff
):
246 self
._drawwidgetbounds
= onoff
248 self
.GetWindow().InvalWindowRect(self
._bounds
)
250 def _drawbounds(self
):
253 def _maketabchain(self
):
254 # XXX This has to change, it's no good when we are adding or deleting widgets.
255 # XXX Perhaps we shouldn't keep a "tabchain" at all.
256 self
._hasselframes
= 0
257 self
._collectselectablewidgets
(self
._widgets
)
258 if self
._hasselframes
and len(self
._tabchain
) > 1:
259 self
._hasselframes
= 1
261 self
._hasselframes
= 0
263 def _collectselectablewidgets(self
, widgets
):
267 self
._tabchain
.append(w
)
268 if isinstance(w
, W
.List
):
269 self
._hasselframes
= 1
270 self
._collectselectablewidgets
(w
._widgets
)
272 def _calcbounds(self
):
273 self
._possize
= self
.wid
.GetWindowPort().GetPortBounds()[2:]
275 self
._bounds
= (0, 0, w
, h
)
276 self
.wid
.GetWindowContentRgn(scratchRegion
)
277 l
, t
, r
, b
= GetRgnBounds(scratchRegion
)
278 self
._globalbounds
= l
, t
, l
+ w
, t
+ h
279 for w
in self
._widgets
:
282 # FrameWork override methods
283 def do_inDrag(self
, partcode
, window
, event
):
285 self
.wid
.GetWindowContentRgn(scratchRegion
)
286 was_l
, was_t
, r
, b
= GetRgnBounds(scratchRegion
)
287 window
.DragWindow(where
, self
.draglimit
)
288 self
.wid
.GetWindowContentRgn(scratchRegion
)
289 is_l
, is_t
, r
, b
= GetRgnBounds(scratchRegion
)
290 self
._globalbounds
= Qd
.OffsetRect(self
._globalbounds
,
291 is_l
- was_l
, is_t
- was_t
)
293 def do_char(self
, char
, event
):
295 (what
, message
, when
, where
, modifiers
) = event
297 if Wkeys
.keynames
.has_key(key
):
298 key
= Wkeys
.keynames
[key
]
299 if modifiers
& Events
.shiftKey
:
301 if modifiers
& Events
.cmdKey
:
303 if modifiers
& Events
.controlKey
:
304 key
= 'control' + key
305 if self
._bindings
.has_key("<key>"):
306 callback
= self
._bindings
["<key>"]
307 if Wbase
.CallbackCall(callback
, 0, char
, event
):
309 if self
._bindings
.has_key(key
):
310 callback
= self
._bindings
[key
]
311 Wbase
.CallbackCall(callback
, 0, char
, event
)
312 elif self
._currentwidget
is not None:
313 if self
._currentwidget
._bindings
.has_key(key
):
314 callback
= self
._currentwidget
._bindings
[key
]
315 Wbase
.CallbackCall(callback
, 0, char
, event
)
317 if self
._currentwidget
._bindings
.has_key("<key>"):
318 callback
= self
._currentwidget
._bindings
["<key>"]
319 if Wbase
.CallbackCall(callback
, 0, char
, event
):
321 self
._currentwidget
.key(char
, event
)
323 def do_contentclick(self
, point
, modifiers
, event
):
324 widget
= self
.findwidget(point
)
325 if widget
is not None:
326 if self
._bindings
.has_key("<click>"):
327 callback
= self
._bindings
["<click>"]
328 if Wbase
.CallbackCall(callback
, 0, point
, modifiers
):
330 if widget
._bindings
.has_key("<click>"):
331 callback
= widget
._bindings
["<click>"]
332 if Wbase
.CallbackCall(callback
, 0, point
, modifiers
):
334 if widget
._selectable
:
336 widget
.click(point
, modifiers
)
338 def do_update(self
, window
, event
):
339 Qd
.EraseRgn(window
.GetWindowPort().visRgn
)
340 self
.forall_frombottom("draw", window
.GetWindowPort().visRgn
)
341 if self
._drawwidgetbounds
:
342 self
.forall_frombottom("_drawbounds")
344 def do_activate(self
, onoff
, event
):
346 if self
._lastrollover
:
347 self
._lastrollover
.rollover((0, 0), 0)
348 self
._lastrollover
= None
350 self
.forall("activate", onoff
)
353 def do_postresize(self
, width
, height
, window
):
354 self
.GetWindow().InvalWindowRect(self
.getgrowrect())
357 def do_inGoAway(self
, partcode
, window
, event
):
359 closeall
= event
[4] & Events
.optionKey
360 if window
.TrackGoAway(where
):
364 for window
in self
.parent
._windows
.values():
370 def tempcliprect(self
, tempcliprect
):
371 tempclip
= Qd
.NewRgn()
372 Qd
.RectRgn(tempclip
, tempcliprect
)
373 self
.tempclip(tempclip
)
374 Qd
.DisposeRgn(tempclip
)
376 def tempclip(self
, tempclip
):
377 if not hasattr(self
, "saveclip"):
379 saveclip
= Qd
.NewRgn()
381 self
.saveclip
.append(saveclip
)
384 def restoreclip(self
):
385 Qd
.SetClip(self
.saveclip
[-1])
386 Qd
.DisposeRgn(self
.saveclip
[-1])
387 del self
.saveclip
[-1]
389 def getgrowrect(self
):
390 l
, t
, r
, b
= self
.wid
.GetWindowPort().GetPortBounds()
391 return (r
- 15, b
- 15, r
, b
)
393 def has_key(self
, key
):
394 return self
._widgetsdict
.has_key(key
)
396 def __getattr__(self
, attr
):
397 global _successcount
, _failcount
, _magiccount
398 if self
._widgetsdict
.has_key(attr
):
399 _successcount
= _successcount
+ 1
400 return self
._widgetsdict
[attr
]
401 if self
._currentwidget
is None or (attr
[:7] <> 'domenu_' and
402 attr
[:4] <> 'can_' and attr
<> 'insert'):
403 _failcount
= _failcount
+ 1
404 raise AttributeError, attr
405 # special case: if a domenu_xxx, can_xxx or insert method is asked for,
406 # see if the active widget supports it
407 _magiccount
= _magiccount
+ 1
408 return getattr(self
._currentwidget
, attr
)
414 class Dialog(Window
):
416 windowkind
= Windows
.movableDBoxProc
418 # this __init__ seems redundant, but it's not: it has less args
419 def __init__(self
, possize
, title
= ""):
420 Window
.__init
__(self
, possize
, title
)
422 def can_close(self
, *args
):
425 def getwindowbounds(self
, size
, minsize
= None):
426 screenbounds
= sl
, st
, sr
, sb
= Qd
.GetQDGlobalsScreenBits().bounds
428 l
= sl
+ (sr
- sl
- w
) / 2
429 t
= st
+ (sb
- st
- h
) / 3
430 return l
, t
, l
+ w
, t
+ h
433 class ModalDialog(Dialog
):
435 def __init__(self
, possize
, title
= ""):
436 Dialog
.__init
__(self
, possize
, title
)
438 self
.windowkind
= Windows
.movableDBoxProc
440 self
.windowkind
= Windows
.dBoxProc
445 self
.app
= W
.getapplication()
457 return # we are already closed
463 if hasattr(MacOS
, 'EnableAppswitch'):
464 saveyield
= MacOS
.EnableAppswitch(-1)
467 self
.do1event( Events
.keyDownMask
+
474 if hasattr(MacOS
, 'EnableAppswitch'):
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 if hasattr(MacOS
, "HandleEvent"):
523 MacOS
.HandleEvent(event
)
525 print 'Unexpected inDesk event:', event
529 handler
= getattr(self
, name
)
530 except AttributeError:
531 handler
= self
.app
.do_unknownpartcode
533 #MacOS.HandleEvent(event)
534 if name
== 'do_inMenuBar':
535 handler
= getattr(self
.parent
, name
)
538 handler(partcode
, wid
, event
)
540 def dispatch(self
, event
):
541 (what
, message
, when
, where
, modifiers
) = event
542 if FrameWork
.eventname
.has_key(what
):
543 name
= "do_" + FrameWork
.eventname
[what
]
545 name
= "do_%d" % what
547 handler
= getattr(self
, name
)
548 except AttributeError:
550 handler
= getattr(self
.app
, name
)
551 except AttributeError:
552 handler
= self
.app
.do_unknownevent
556 def FrontWindowInsert(stuff
):
559 if type(stuff
) <> StringType
:
560 raise TypeError, 'string expected'
562 app
= W
.getapplication()
563 wid
= MyFrontWindow()
564 if wid
and app
._windows
.has_key(wid
):
565 window
= app
._windows
[wid
]
566 if hasattr(window
, "insert"):
573 if EasyDialogs
.AskYesNoCancel(
574 "Can't find window or widget to insert text into; copy to clipboard instead?",
576 from Carbon
import Scrap
577 if hasattr(Scrap
, 'PutScrap'):
579 Scrap
.PutScrap('TEXT', stuff
)
581 Scrap
.ClearCurrentScrap()
582 sc
= Scrap
.GetCurrentScrap()
583 sc
.PutScrapFlavor('TEXT', 0, stuff
)
586 # not quite based on the same function in FrameWork
589 def getnextwindowpos():
590 global _windowcounter
592 l
= 4 * (rows
+ 1 - (_windowcounter
% rows
) + _windowcounter
/ rows
)
593 t
= 44 + 20 * (_windowcounter
% rows
)
594 _windowcounter
= _windowcounter
+ 1
597 def windowbounds(preferredsize
, minsize
=None):
598 "Return sensible window bounds"
600 global _windowcounter
601 if len(preferredsize
) == 4:
602 bounds
= l
, t
, r
, b
= preferredsize
603 desktopRgn
= Win
.GetGrayRgn()
604 tempRgn
= Qd
.NewRgn()
605 Qd
.RectRgn(tempRgn
, bounds
)
606 union
= Qd
.UnionRgn(tempRgn
, desktopRgn
, tempRgn
)
607 equal
= Qd
.EqualRgn(tempRgn
, desktopRgn
)
608 Qd
.DisposeRgn(tempRgn
)
612 preferredsize
= r
- l
, b
- t
614 minsize
= preferredsize
615 minwidth
, minheight
= minsize
616 width
, height
= preferredsize
618 sl
, st
, sr
, sb
= screenbounds
= Qd
.InsetRect(Qd
.GetQDGlobalsScreenBits().bounds
, 4, 4)
619 l
, t
= getnextwindowpos()
622 l
, t
= getnextwindowpos()
625 if (t
+ height
) > sb
:
627 if (b
- t
) < minheight
:
631 scratchRegion
= Qd
.NewRgn()
633 # util -- move somewhere convenient???
634 def GetRgnBounds(the_Rgn
):
635 (t
, l
, b
, r
) = struct
.unpack("hhhh", the_Rgn
.data
[2:10])