blob: c665fb70018a2994703a553b328da7bd4cd63ca7 [file] [log] [blame]
Georg Brandl116aa622007-08-15 14:28:22 +00001
2:mod:`FrameWork` --- Interactive application framework
3======================================================
4
5.. module:: FrameWork
6 :platform: Mac
7 :synopsis: Interactive application framework.
8
9
10The :mod:`FrameWork` module contains classes that together provide a framework
11for an interactive Macintosh application. The programmer builds an application
12by creating subclasses that override various methods of the bases classes,
13thereby implementing the functionality wanted. Overriding functionality can
14often be done on various different levels, i.e. to handle clicks in a single
15dialog window in a non-standard way it is not necessary to override the complete
16event handling.
17
18Work on the :mod:`FrameWork` has pretty much stopped, now that :mod:`PyObjC` is
19available for full Cocoa access from Python, and the documentation describes
20only the most important functionality, and not in the most logical manner at
21that. Examine the source or the examples for more details. The following are
22some comments posted on the MacPython newsgroup about the strengths and
23limitations of :mod:`FrameWork`:
24
25
26.. epigraph::
27
28 The strong point of :mod:`FrameWork` is that it allows you to break into the
29 control-flow at many different places. :mod:`W`, for instance, uses a different
30 way to enable/disable menus and that plugs right in leaving the rest intact.
31 The weak points of :mod:`FrameWork` are that it has no abstract command
32 interface (but that shouldn't be difficult), that its dialog support is minimal
33 and that its control/toolbar support is non-existent.
34
35The :mod:`FrameWork` module defines the following functions:
36
37
38.. function:: Application()
39
40 An object representing the complete application. See below for a description of
41 the methods. The default :meth:`__init__` routine creates an empty window
42 dictionary and a menu bar with an apple menu.
43
44
45.. function:: MenuBar()
46
47 An object representing the menubar. This object is usually not created by the
48 user.
49
50
51.. function:: Menu(bar, title[, after])
52
53 An object representing a menu. Upon creation you pass the ``MenuBar`` the menu
54 appears in, the *title* string and a position (1-based) *after* where the menu
55 should appear (default: at the end).
56
57
58.. function:: MenuItem(menu, title[, shortcut, callback])
59
60 Create a menu item object. The arguments are the menu to create, the item title
61 string and optionally the keyboard shortcut and a callback routine. The callback
62 is called with the arguments menu-id, item number within menu (1-based), current
63 front window and the event record.
64
65 Instead of a callable object the callback can also be a string. In this case
66 menu selection causes the lookup of a method in the topmost window and the
67 application. The method name is the callback string with ``'domenu_'``
68 prepended.
69
70 Calling the ``MenuBar`` :meth:`fixmenudimstate` method sets the correct dimming
71 for all menu items based on the current front window.
72
73
74.. function:: Separator(menu)
75
76 Add a separator to the end of a menu.
77
78
79.. function:: SubMenu(menu, label)
80
81 Create a submenu named *label* under menu *menu*. The menu object is returned.
82
83
84.. function:: Window(parent)
85
86 Creates a (modeless) window. *Parent* is the application object to which the
87 window belongs. The window is not displayed until later.
88
89
90.. function:: DialogWindow(parent)
91
92 Creates a modeless dialog window.
93
94
95.. function:: windowbounds(width, height)
96
97 Return a ``(left, top, right, bottom)`` tuple suitable for creation of a window
98 of given width and height. The window will be staggered with respect to previous
99 windows, and an attempt is made to keep the whole window on-screen. However, the
100 window will however always be the exact size given, so parts may be offscreen.
101
102
103.. function:: setwatchcursor()
104
105 Set the mouse cursor to a watch.
106
107
108.. function:: setarrowcursor()
109
110 Set the mouse cursor to an arrow.
111
112
113.. _application-objects:
114
115Application Objects
116-------------------
117
118Application objects have the following methods, among others:
119
120
121.. method:: Application.makeusermenus()
122
123 Override this method if you need menus in your application. Append the menus to
124 the attribute :attr:`menubar`.
125
126
127.. method:: Application.getabouttext()
128
129 Override this method to return a text string describing your application.
130 Alternatively, override the :meth:`do_about` method for more elaborate "about"
131 messages.
132
133
134.. method:: Application.mainloop([mask[, wait]])
135
136 This routine is the main event loop, call it to set your application rolling.
137 *Mask* is the mask of events you want to handle, *wait* is the number of ticks
138 you want to leave to other concurrent application (default 0, which is probably
139 not a good idea). While raising *self* to exit the mainloop is still supported
140 it is not recommended: call ``self._quit()`` instead.
141
142 The event loop is split into many small parts, each of which can be overridden.
143 The default methods take care of dispatching events to windows and dialogs,
144 handling drags and resizes, Apple Events, events for non-FrameWork windows, etc.
145
146 In general, all event handlers should return ``1`` if the event is fully handled
147 and ``0`` otherwise (because the front window was not a FrameWork window, for
148 instance). This is needed so that update events and such can be passed on to
149 other windows like the Sioux console window. Calling :func:`MacOS.HandleEvent`
150 is not allowed within *our_dispatch* or its callees, since this may result in an
151 infinite loop if the code is called through the Python inner-loop event handler.
152
153
154.. method:: Application.asyncevents(onoff)
155
156 Call this method with a nonzero parameter to enable asynchronous event handling.
157 This will tell the inner interpreter loop to call the application event handler
158 *async_dispatch* whenever events are available. This will cause FrameWork window
159 updates and the user interface to remain working during long computations, but
160 will slow the interpreter down and may cause surprising results in non-reentrant
161 code (such as FrameWork itself). By default *async_dispatch* will immediately
162 call *our_dispatch* but you may override this to handle only certain events
163 asynchronously. Events you do not handle will be passed to Sioux and such.
164
165 The old on/off value is returned.
166
167
168.. method:: Application._quit()
169
170 Terminate the running :meth:`mainloop` call at the next convenient moment.
171
172
173.. method:: Application.do_char(c, event)
174
175 The user typed character *c*. The complete details of the event can be found in
176 the *event* structure. This method can also be provided in a ``Window`` object,
177 which overrides the application-wide handler if the window is frontmost.
178
179
180.. method:: Application.do_dialogevent(event)
181
182 Called early in the event loop to handle modeless dialog events. The default
183 method simply dispatches the event to the relevant dialog (not through the
184 ``DialogWindow`` object involved). Override if you need special handling of
185 dialog events (keyboard shortcuts, etc).
186
187
188.. method:: Application.idle(event)
189
190 Called by the main event loop when no events are available. The null-event is
191 passed (so you can look at mouse position, etc).
192
193
194.. _window-objects:
195
196Window Objects
197--------------
198
199Window objects have the following methods, among others:
200
201
202.. method:: Window.open()
203
204 Override this method to open a window. Store the MacOS window-id in
205 :attr:`self.wid` and call the :meth:`do_postopen` method to register the window
206 with the parent application.
207
208
209.. method:: Window.close()
210
211 Override this method to do any special processing on window close. Call the
212 :meth:`do_postclose` method to cleanup the parent state.
213
214
215.. method:: Window.do_postresize(width, height, macoswindowid)
216
217 Called after the window is resized. Override if more needs to be done than
218 calling ``InvalRect``.
219
220
221.. method:: Window.do_contentclick(local, modifiers, event)
222
223 The user clicked in the content part of a window. The arguments are the
224 coordinates (window-relative), the key modifiers and the raw event.
225
226
227.. method:: Window.do_update(macoswindowid, event)
228
229 An update event for the window was received. Redraw the window.
230
231
232.. method:: Window.do_activate(activate, event)
233
234 The window was activated (``activate == 1``) or deactivated (``activate == 0``).
235 Handle things like focus highlighting, etc.
236
237
238.. _controlswindow-object:
239
240ControlsWindow Object
241---------------------
242
243ControlsWindow objects have the following methods besides those of ``Window``
244objects:
245
246
247.. method:: ControlsWindow.do_controlhit(window, control, pcode, event)
248
249 Part *pcode* of control *control* was hit by the user. Tracking and such has
250 already been taken care of.
251
252
253.. _scrolledwindow-object:
254
255ScrolledWindow Object
256---------------------
257
258ScrolledWindow objects are ControlsWindow objects with the following extra
259methods:
260
261
262.. method:: ScrolledWindow.scrollbars([wantx[, wanty]])
263
264 Create (or destroy) horizontal and vertical scrollbars. The arguments specify
265 which you want (default: both). The scrollbars always have minimum ``0`` and
266 maximum ``32767``.
267
268
269.. method:: ScrolledWindow.getscrollbarvalues()
270
271 You must supply this method. It should return a tuple ``(x, y)`` giving the
272 current position of the scrollbars (between ``0`` and ``32767``). You can return
273 ``None`` for either to indicate the whole document is visible in that direction.
274
275
276.. method:: ScrolledWindow.updatescrollbars()
277
278 Call this method when the document has changed. It will call
279 :meth:`getscrollbarvalues` and update the scrollbars.
280
281
282.. method:: ScrolledWindow.scrollbar_callback(which, what, value)
283
284 Supplied by you and called after user interaction. *which* will be ``'x'`` or
285 ``'y'``, *what* will be ``'-'``, ``'--'``, ``'set'``, ``'++'`` or ``'+'``. For
286 ``'set'``, *value* will contain the new scrollbar position.
287
288
289.. method:: ScrolledWindow.scalebarvalues(absmin, absmax, curmin, curmax)
290
291 Auxiliary method to help you calculate values to return from
292 :meth:`getscrollbarvalues`. You pass document minimum and maximum value and
293 topmost (leftmost) and bottommost (rightmost) visible values and it returns the
294 correct number or ``None``.
295
296
297.. method:: ScrolledWindow.do_activate(onoff, event)
298
299 Takes care of dimming/highlighting scrollbars when a window becomes frontmost.
300 If you override this method, call this one at the end of your method.
301
302
303.. method:: ScrolledWindow.do_postresize(width, height, window)
304
305 Moves scrollbars to the correct position. Call this method initially if you
306 override it.
307
308
309.. method:: ScrolledWindow.do_controlhit(window, control, pcode, event)
310
311 Handles scrollbar interaction. If you override it call this method first, a
312 nonzero return value indicates the hit was in the scrollbars and has been
313 handled.
314
315
316.. _dialogwindow-objects:
317
318DialogWindow Objects
319--------------------
320
321DialogWindow objects have the following methods besides those of ``Window``
322objects:
323
324
325.. method:: DialogWindow.open(resid)
326
327 Create the dialog window, from the DLOG resource with id *resid*. The dialog
328 object is stored in :attr:`self.wid`.
329
330
331.. method:: DialogWindow.do_itemhit(item, event)
332
333 Item number *item* was hit. You are responsible for redrawing toggle buttons,
334 etc.
335