|
|
|
|
||
|
DEFINITION MODULE DMWindows; (******************************************************************* Module DMWindows ('Dialog Machine' DM_V3.0) Copyright (c) 1985-2006 by Andreas Fischlin, Alex Itten and ETH Zurich. Purpose Manages windows on behalf of a 'Dialog Machine' program. Remarks Windows give the user a particular view onto any type of objects the application program creates or manages, such as a portion of a graph or a text. Multiple windows may coexist on the same screen. They may overlap and can be moved, resized, rearranged in their sequence by bringing a partially overlapped window to the front (= window activation) implies the simultaneous removing of the previously frontmost window from the front (= window deactivation). A window's content can be scrolled, so that other parts of the displayedobject may become visible. Method: Windows may be created, repositioned, activated, or removed under program control exerted by the application. However, typically an application only creates windows (procedure DMWindows.CreateWindow) and specifies its properties. Once created, the window management is left to module DMMaster, i.e. clicking the mouse button in the content region or the close box of a window results in an automatical call to the corresponding window management procedure. Except for the window creation, all window management functions can be left to the 'Dialog Machine' and must not be dealt with by the application program. An exception to this is the updating of the window content necessary after an event causing a previously covered window portion to become visible again. The client program has to provide a so-called re- store procedure (DMWindows.RestoreProc) which redraws the whole window content. The calling of this procedure and the restriction of the drawing area to window areas currently really visible (not covered by other windows) are automatically provided by the 'Dialog Machine' and the restore procedure need not to be concerned with this problem. This module belongs to the 'Dialog Machine'. Programming o Design Andreas Fischlin 16/12/1985 o Implementation Andreas Fischlin 16/12/1985 Alex Itten 22/12/1986 ETH Zurich Systems Ecology CHN E 35.1 Universitaetstrasse 16 8092 Zurich SWITZERLAND URLs: <mailto:RAMSES@env.ethz.ch> <http://www.sysecol.ethz.ch> <http://www.sysecol.ethz.ch/SimSoftware/RAMSES> Last revision of definition: 05/08/1991 AF *******************************************************************) FROM SYSTEM IMPORT ADDRESS; TYPE Window; (* Variables of this type are needed to identify particular windows. Always(!) declare such variables on a global level, since the window management routines attempt to update your variables. E.g. when closing a window by clicking the close box contained in the window title bar, the "Dialog Machine" assigns to your window variable the value nonexistent. *) (* types of application windows (document windows with a title bar except for FixedLocation) are distinguished as follows: *) WindowKind = (GrowOrShrinkOrDrag, (*resizing and dragging permitted*) FixedSize, (*no resizing, dragging permitted*) FixedLocation, (*no resizing, no dragging. no title bar*) FixedLocTitleBar); (*no resizing, no dragging*) ModalWindowKind = (DoubleFrame, SingleFrameShadowed); ScrollBars = (WithVerticalScrollBar, WithHorizontalScrollBar, WithBothScrollBars, WithoutScrollBars); CloseAttr = (WithCloseBox, WithoutCloseBox); ZoomAttr = (WithZoomBox, WithoutZoomBox); (*only meaningful on >= Mac+*) RectArea = RECORD x,y,w,h: INTEGER END; (*Rectangular area with lower left corner (x,y) and width w and height h*) WindowFrame = RectArea; (*Determines size and position of a window relative to the background coordinates. It frames just the working area in which output takes place, i.e. the title bar or any scrollbars are excluded. Note, when you create a window, that these areas are added on the outside of the WindowFrame.*) WFFixPoint = (bottomLeft, topLeft); (* Fixpoint on the window frame (corner) relative to which the window content is positioned after a redefinition of the window size (redefine event). *) RestoreProc = PROCEDURE (Window); (* Procedure to redraw the whole content of a window. A procedure of this type is called by the "Dialog Machine" after a portion of a window's content region becomes uncovered (for instance if the window becomes the frontmost window after having been partially overlapped by other windows). Its purpose is to simply redraw the whole content of the window. Typically this is done without being concerned about the visibility of the window's content region or other similar issues; the "Dialog Machine's" window management takes care of that. Given the current arrangement of windows, only the visible portions of the drawing will be displayed. *) CloseProc = PROCEDURE (Window, VAR BOOLEAN); (* Procedure called if the window is about to be closed by the user when clicking into the close box, just before it is actually closed. This happens before any eventually installed window handlers (see below WindowHandlers) and before the global MouseHandler for closing events from DMMaster are called. This is the right moment to save objects associated with the closing window or eventually to suppress the closing of the window by returning FALSE. Typically the latter case is used if it has not been possible to complete successfully the handling procedure, for instance if errors have been detected in the entry of an edit field maintained by module DMEditFields requesting from the user a value necessary for any further meaningful use of the program. If FALSE is returned the global MouseHandler CloseWindow is not called and the window remains open as it was before the user attempted to close it. The default close procedure returns always TRUE. (see also SetCloseProc (this module) and DMWindows.CloseHandler). Note that RemoveWindow will not call such a close procedure, assuming that the programmer calls the procedure only after having done any houskeeping. In case you need to receive a message when RemoveWindow is called, installed a WindowHandler closed. *) WindowProc = PROCEDURE (Window); (* Type of an action procedure to be performed with a window (s.a. procedures DoForAllWindows, AddWindowHandler, and RemoveWindowHandler). *) WindowHandlers = (clickedInContent, broughtToFront, removedFromFront, redefined, onlyMoved, disappeared, reappeared, closing); (* Possible window related events. Some of these events may be produced by the user via mouse or keyboard (user event) or also by the running program (software event). The events are: Event type description ----------------------------------------------------------- clickedInContent mouse, user User clicked into the content region of the window (controls and edit fields excluded) broughtToFront mouse, user, The window has been brought software to the front, i.e. it has just become the frontmost window. removedFromFront mouse, user, the opposite of broughtToFront software redefined mouse, user, The window size or position has software been changed onlyMoved mouse, user, The window's position has been software changed but not its size disappeared software The window has been made invisible reappeared software the opposite of disappeared closing mouse, user, The window is to be closed, software i.e. completely removed from the screen. Note, that this event is handled specially: This handler is called before the denoted action has actually taken place (hence named closing not closed). Note also, that it is called after the CloseProc of the involved window and before the global MouseHandler (CloseWindow). When called you may safely assume that the window still exists. Note also, that this is the only closing events related handler which is callable via software, i.e. by a call to RemoveWindow or RemoveAllWindows. Window handlers are owned by a single window and are only called by the Dialog Machine if an event of the corresponding class involves the particular window. See the procedures AddWindowHandler and RemoveWindowHandler. IMPORTANT NOTE: A closing window handler MUST NOT call RemoveWindow nor RemoveAllWindows, since it is called by these procedures (otherwise you will obtain an infinite loop)! IMPORTANT RECOMMENDATION: It is highly recommended and a safe programming practice to set your window variable (not the actual argument passed to your closing handler, which is only a value parameter) to the value notExistingValue within the body of your closing handler routine. Example code of a GOOD closing handler which you have added to window myWindow: PROCEDURE GoodClosingHandler(u: Window); BEGIN (* do cleaning up of objects associated with myWindow *) myWindow := notExistingWindow; END GoodClosingHandler; Note, the value argument passed to your closing handler by the 'Dialog Machine', i.e. u, always points properly at the window object, which still exists, since the 'Dialog Machine' will only really discard the instantiation of this object after the last closing handler had a chance to properly handle its closing task. This technique allows to associate as many handlers as you wish to the particular instantiation of a particular window object. Each closing handler should then find the same preconditions, i.e. the existence of the object while handling its closing task. Hence, you can program every handler as if it would be alone and set your opaque window variable to notExistingWindow (as an important side effect of your closing handler) and leave the rest to the 'Dialog Machine'. This programing technique makes it less likely that you have dangling pointers to no longer existing objects. The only situation in which you have to be more cautios is the case where you have several handlers which all operate on the same master instantiation of the variable of type Window (instead of keeping a separate copy). Once a handler (the first one), has set this variable to notExistingWindow, the closing handlers subsequently called by the Dialog Machine will of course no longer have proper access to this variable, since the first handler which set it to notExistingWindow has cleared it. In this case you need to be aware of the coesticence of these handlers and you have to program them such, that the first one leaves the opaque variable intact and that only the last one does actually assign notExistingWindow. Alternatively you can use the actual argument passed to you by the 'Dialog Machine' to access the object and perform the specific cleaning up task and simply assign notExistingWindow to the master variable (regardless of any sequence). In the latter case it is NOT a safer programing practice to test within the closing handler whether the actual argument and your window variable (which you consider to be the same) are equal. Example code of a BAD closing handler in a multiple handler situation operating on the same window: PROCEDURE BadClosingHandler(u: Window); BEGIN IF u=myWindow THEN (* do cleaning up of objects associated with myWindow *) myWindow := notExistingWindow; ELSE (* do nothing *) END(*IF*); END BadClosingHandler; Since the test u=myWindow is likely to fail in a multiple handler situation. However it is perfectly ok to do the following: PROCEDURE AnotherGoodClosingHandler(u: Window); BEGIN myWindow := u; (* do cleaning up of objects associated with myWindow *) myWindow := notExistingWindow; END AnotherGoodClosingHandler; NOTE: In case there is also a global handler (DMMaster.MouseHandler) installed for the particular event, that a window handler is normally called before the global handler. Note also that these window handlers are always called, regardless whether the event was caused by a user or software. This behavior is different from that of the global handlers, which are only called if the event is caused by a user event. Howeve, the use of global handlers via DMMaster is discouraged, since it runs contrary to information hiding. *) VAR notExistingWindow: Window; (* read only var! *) (* Read only variable which may be used for variables of type Window to denote that the associated window is actually not existing, i.e. not displayed on the screen. It is a good programming practice to assign this value to all window variables during the initialization phase of the "Dialog Machine", i.e. before calling procedure DMMaster.RunDialogMachine. *) background: Window; (* This is a predefined window covering the whole screen except for the menu bar. It is always provided automatically by the "Dialog Machine" and cannot be removed, dragged, put on top, nor resized. The origin of its pixel coordinate system cannot be moved and is at the lower left corner of the screen. The background window has no title bar and it's content is by default filled with the DMWindIO. GreyContent grey. The background resembles the desktop; however, it is different in the following respect: It is possible to make output in the background like in any other ordinary window maintained by the "Dialog Machine". To better support the new operating systems on the Macintosh, the background is initially no longer visible unless you call ReshowBackground. *) WindowsDone: BOOLEAN; (*indicates success of a window management procedure*) PROCEDURE NoBackground; (* Call this procedure if your application does not need the background window (is initially default). *) PROCEDURE ReshowBackground; (* Call this procedure if your application needs the background again, e.g. after NoBackground. *) PROCEDURE OuterWindowFrame(innerf: WindowFrame; wk: WindowKind; s: ScrollBars; VAR outerf: RectArea); (* Calculates from the working area f within a window the outer frame of the window of kind wk and with scrollbars s (reverse of procedure InnerWindowFrame). Typically this procedure is called before calling CreateWindow in order to determine the exact position of the window relative to the background. This routine does not work on a modal window. A modal window of kind DoubleFrame which has no scroll bars has an outer frame of 7 pixels larger than the innerf. *) PROCEDURE InnerWindowFrame(outerf: WindowFrame; wk: WindowKind; s: ScrollBars; VAR innerf: RectArea); (* Calculates from the outer window frame outerf from a window of kind wk and with scrollbars s the inner working area innerf (reverse of procedure OuterWindowFrame). Typically this procedure is called before calling CreateWindow in order to determine the parameter f of type WindowFrame used in parameter list of CreateWindow given a particular outer size of the window. This routine does not work on a modal window. *) PROCEDURE CreateWindow(VAR u: Window; wk: WindowKind; s: ScrollBars; c: CloseAttr; z: ZoomAttr; fixPoint: WFFixPoint; f: WindowFrame; title: ARRAY OF CHAR; Repaint: RestoreProc); (* Creates and opens a window of kind wk, titlestring title, with its lower left corner at position (f.x,f.y) and with width f.w and height f.h. Attribute wk specifies whether the window may be resized or has to keep its size always, plus whether it may be dragged or has to stay at the same screen location for its whole existence. Attribute s determines the type of ScrollBars of the window, i.e. vertical and/or horizontal scroll bars. Attribute c specifies whether the window may be closed via a close box shown in the upper left corner of a window's title bar. Windows of type "GrowORShrinkOrDrag" may have a so called zoom box in the upper right corner of the window's title bar. By clicking inside this zoom box, the window will be enlarged to the entier screen size or (with a second click) resized to it's original size before the zooming. fixPoint denotes the point of the window content, which will stay at it's position if the window grows or shrinks. By default it specifies the origin (0,0) of the local window coordinate system. A window identifier u is returned for future references. Procedure Repaint will be invoked in case the window has to be restored, i.e. its whole content has to be redrawn. *) PROCEDURE CreateModalWindow(VAR u: Window; wk: ModalWindowKind; s: ScrollBars; f: WindowFrame; Repaint: RestoreProc); (* Creates and opens a window of kind wk with its lower left corner at position (f.x,f.y) and with width f.w and height f.h. In case f.x or f.y define a point outside the main screen the window will be automatically centered in the middle of the screen. Attribute wk specifies whether the window will have a double frame (recommended standard type for modal dialogs) or will have a simple frame and a shadow. Modal windows are typically used for modal dialogs (see procedure UseWindowModally), i.e. during a modal dialog such a window can't be dragged, nor zoomed, nor closed via clicking into the close box. Attribute s determines the type of ScrollBars of the window, i.e. vertical and/or horizontal scroll bars. The origin (0,0) of the local window coordinate system is always at the lower left corner. A window identifier u is returned for future references. Procedure Repaint will be invoked in case the window has to be restored, i.e. its whole content has to be redrawn. *) PROCEDURE UsePredefinedWindow(VAR u: Window; fileName: ARRAY OF CHAR; windowID: INTEGER; fixPoint: WFFixPoint; Repaint : RestoreProc); (* Creates a predefined window read from a Macintosh resource of the type "WIND" with ID = windowID contained in the resource fork of the file fileName. In case that the fileName passed is empty, the default search strategy to find the resource is followed. For the other parameters see procedure CreateWindow. The following rules apply when mapping Macintosh procIDs with the type WindowKind from DMWindows (see also Inside Macintosh I-273, Fig.4): procID WindowKind Resize drag title ------ ---------- ------ ---- ----- documentProc (0) GrowOrShrinkOrDrag yes yes yes noGrowDocProc (4) FixedSize no yes yes plainDBox† (2) FixedLocation† no no no - (not available) FixedLocTitleBar no no yes ModalWindowKind --------------- dBoxProc° (1) DoubleFrame° no no no altDBoxProc (3) SingleFrameShadowed no no no † This type is used by the Dialog Machine for modal entry forms (see DMEntryForms) ° This type is used by the Dialog Machine for the modal alerts (see DMAlerts) procID values different from any of those values given above (i.e. 0..4) are interpreted to code for WindowKind FixedLocTitleBar. *) CONST DoubleFrameTitled = 3; PROCEDURE CreateTitledModalWindow(VAR u: Window; title: ARRAY OF CHAR; f: WindowFrame); (* Creates a double framed but titled and movable modal dialog window. This function is only available under system 7.0. The value for argument wk (see GetWindowCharacteristics) returned is DoubleFrameTitled. *) PROCEDURE AttachWindowObject(u: Window; obj: ADDRESS); PROCEDURE WindowObject(u: Window): ADDRESS; (* Attaches to the window u an object in memory at address obj. The attach allows the calling program to associate its own objects, e.g. a data structure with a window for reference to that object. Typically a mouse handler (see DMMaster) may profit from this mechanism, since it returns the window in which the user event has taken place, which allows the programer to access directly the associated object by calling procedure WindowObject from within the mouse handler procedure without having frist to search the object. Attach NIL to detach an object. *) PROCEDURE RedefineWindow(u: Window; f: WindowFrame); (* Change size or position of window *) PROCEDURE RedrawTitle(u: Window; title: ARRAY OF CHAR); PROCEDURE MakeWindowInvisible(u: Window); PROCEDURE MakeWindowVisible (u: Window); PROCEDURE IsNowVisible (u: Window): BOOLEAN; PROCEDURE WindowLevel(u: Window): CARDINAL; (* Returns the level of the sub-program on which the window u has been created. If the window does not exist it returns DMSystem.startUpLevel-1, i.e. 0. *) PROCEDURE GetWindowCharacteristics(u: Window; VAR wk: INTEGER; VAR modalKind: BOOLEAN; VAR s: ScrollBars; VAR c: CloseAttr; VAR z: ZoomAttr; VAR fixPoint: WFFixPoint; VAR f: WindowFrame; VAR title: ARRAY OF CHAR); (* Returns the characteristics of the window u. Note that wk either holds the ORD(WindowKind) or ORD(ModalWindowKind) value, depending whether the window is an ordinary window (modalKind = FALSE) or a modal window (modalKind = TRUE). *) (********************************************************************* Window Updating: If a part of a window becomes visible again after beeing covered by another window or Desk Acessory, this part of the window content must be restored. The best way to do this is to pack all drawing procedures (offered by DMWindIO) into a procedure of type RestoreProc (see above) and to pass it eigther by procedure CreateWindow or SetRestoreProc to the Dialog Machine. In this case the Dialog Machine cares about the entier restoring of a window in the way that only the just discovered part(s) of the window will actually been drawn (necessary for drawing with mode invert). On the other hand this module offers an automatic restore mechanism, wich will maintain a copy in memory (bit map) of all drawings into the specified window. This mechanism is very fast but needs quit a lot of memory (default on Mac Plus and Mac SE apr. 22 kBytes and on Mac II 36 kBytes). This update mechanism may only restore in one single color, mainly in the last assigned window color by DMWindIO.SetColor. This procedure should be used in case the recalculation of the window content takes a long time and would slow down execution speed dramatically or in simple programs to minimize devellopement expense. The automatic restore mechanism my be used in two different ways: 1. By simple assigning the procedure AutoRestoreProc to the Dialog Machine by procedure CreateWindow or SetRestoreProc default hidden bit map size is used which is as large as the maximum possible window size ( Size = (ScreenHeight - MenuBarHeigth) * ScreenWidth ). This guarantees that the whole window content may automatically be restored if the window content will never be scrolled. 2. With the procedure StartAutoRestoring you may assign a rectangle area to the auto restore mechanism in which the mechanism will maintain any restoring. This is very usefull in the case of very large video displays or if multiple video displays are used simultaneously. Then you may combine the auto update mechanism inside this RectArea together with your own (written) restore procedure for the rest of the window. To do this you FIRST assign your update procedure which itself calls the procedure AutoRstoreProc to the Dialog Machine and SECOND you define the rect area to be maintained by calling the procedure StartAutoRestring (which will not change the assigned RestoreProc but will allocate the hidden bit map). The restore procedure may be changed any time but this will cause the loss of the content in the hidden bit map. *********************************************************************) PROCEDURE DummyRestoreProc(u: Window); (*using this restore procedure results in no updating at all*) PROCEDURE AutoRestoreProc(u: Window); (* Assigning this restore procedure directly to the Dialog Machine results in an automatic updating, i.e. no application provided restore procedure is called. Note, that this update mechanism uses memory space, since for every window updated, a bitmap accommodating the maximum window size has to be provided (on older Macintosh with built in screens (e.g. Mac Plus) approximately 22KBytes). NOTE: This procedure is not capable to restore the window content if it contained different colors! *) PROCEDURE SetRestoreProc(u: Window; r: RestoreProc); (* Sets r as the new restore procedure. If r is equal the AutoRestoreProc a hidden bit map is allocated and if r is different to AutoRestoreProc an eventually allocated hidden bit map is removed. NOTE: Calling this procedure will result in an eventual reinitialization, hence clearing of the hidden bit map if it has been used previously. r is called once immediately after the installation. *) PROCEDURE GetRestoreProc(u: Window; VAR r: RestoreProc); (* Returns the current used Restore procedure of the window u. *) PROCEDURE StartAutoRestoring(u: Window; r: RectArea); (* It is possible to maintain the rectangle area r by the auto restore mechanism, while restoring the rest of the window by your own restore procedure previously assigned by SetRestoreProc. If there is enough memory available, the rect area r may be set equal to the content size of your document and the auto scroll mechanism (see DMWindIO) may be used together with the auto restoring. If you dynamically change the size of r with this procedure the previous content of the hidden bit map is destroyed. *) PROCEDURE StopAutoRestoring(u: Window); (* stops the autorestore mechanism for this window u and deallocates the used hidden bit map. *) PROCEDURE AutoRestoring(u: Window): BOOLEAN; (* returns TRUE if current restore mechanism of window u is performed by procedure DMWindows.AutoRestoreProc *) PROCEDURE GetHiddenBitMapSize(u: Window; VAR r: RectArea); (* Returns the current Size of the used hidden bit map. *) PROCEDURE UpdateWindow(u: Window); (* This procedure forces the update of the window u. The standard update mechanism is used which guarantees that only an eventually newly become discovered part of the window will actually beeing drawn. NOTE: The usage of this procedure is ONLY necessary if you want a window beeing updated earlier than the 'Dialog Machine' would do it. In the Batch 'Dialog Machine' this routine does flush the standard output and standard error if you use the 'background' for the actual argument. *) PROCEDURE InvalidateContent(u: Window); (* In contrast to the procedure UpdateWindow, this procedure declares the entier window content as invalid, just like it would have got visible after beeing totally covered by another window. It does not call the window update procedure directly, but the Dialog Machine will, when it handles the update event, call the window specific update procedure. Then the entire content will be redrawn. This procedure is very useful in case the information visible in a window should be changed. Then all drawing routines may be packed into a own written update procedure, which will update the information on screen. *) PROCEDURE UpdateAllWindows; (*only used by the "Dialog Machine"*) PROCEDURE RedrawBackground; (*only used by the "Dialog Machine"*) PROCEDURE SetCloseProc(u: Window; cp: CloseProc); PROCEDURE GetCloseProc(u: Window; VAR cp: CloseProc); (* Sets or gets cp as the close procedure for window u. Note that a close procedure asks the user for confirmation before actually closing the window. *) PROCEDURE AddWindowHandler(u: Window; wh: WindowHandlers; wp: WindowProc; priority: INTEGER); PROCEDURE RemoveWindowHandler(u: Window; wh: WindowHandlers; wp: WindowProc); (* Adds or removes a so-called window handler to a particular window. Each handler handles only a particular class of events; for a description of the events see above comment for type WindowHandlers. Each time the Dialog Machine detects an event involving a window, it checks whether any handlers are installed for that window. In case it finds one for the given class of event, it calls it by passing the involved window u as the actual argument. Multiple handlers can be installed, even for the same class of events. In case of the latter situation, the priority decides which handler will be called first (0 = highest priority). In case there should still be a conflict (same event class, same priority), the handler installed last will be called first (LIFO-queue). To remove a handler, you must be the "owner" of the window procedure; i.e. only if exactly the same wp is passed as actual argument during removal as was used when installing it, RemoveWindowHandler will succesfully remove the handler. *) PROCEDURE GetWFFixPoint(u: Window; VAR loc: WFFixPoint); (* Returns loc as the fixpoint on the window frame relative to which the window content is positioned during all subsequent redefinitions of the window size (redefine event). This point is by default equal the origin (0,0) of the local window coordinate system. *) PROCEDURE DoForAllWindows(action: WindowProc); (* Execute procedure action for all windows *) PROCEDURE GetWindowFrame(u: Window; VAR f: WindowFrame); PROCEDURE PutOnTop(u: Window); (* Put window u in front of all other windows and make it the active window by deactivating the previously frontmost window *) PROCEDURE UseWindowModally(u: Window; VAR terminateModalDialog, cancelModalDialog: BOOLEAN); (* Use the window u for a modal dialog which implies the following action taken by the Dialog Machine: In case u is a draggable window it will be placed in the centre of the main screen, put on top of all windows, terminateModalDialog and cancelModalDialog will be set to FALSE. Then all user events other than mouse clicks in the content of u or in the close box of u (if it has one), or keyboard events, are not accepted. In particular user events such as dragging, menu selection, clicking in another window etc. are ignored and the Dialog Machine will sound a beep instead. This behavior is typical for a modal dialog, i.e. such a dialog does not allow the user to proceed with anything than what is allowed in the modal dialog. Hence, try to avoid modal dialogs, use so-called modeless dialogs instead. The latter allow the user to divert his attention away from the dialog and complete first another task before resuming the original dialog. This may be quite important, for instance if the user wishes to look up a number before he makes an entry etc. On the other hand, experience shows that reasonably used, modal dialogs can be very effective and simple to comprehend, not only for the programmer but also for the user! It is important to ensure that the window contains an appropriate push buttons, or content handlers which are capable of setting either terminateModalDialog or cancelModalDialog to TRUE. This is because the "Dialog Machine" allows to terminate the modal dialog only if one of the following conditions is satisfied: o the calling program sets terminateModalDialog to TRUE (e.g. via a push button). Note that installing a so-called default push button (see module DMEditFields procedure UseAsDefaultButton) allows to select that button also via the keyboard, i.e. by typing Return (in case no text field is currently selected) or via the Enter key, or o the calling program sets cancelModalDialog to TRUE (e.g. via a push button), or o the user presses the Command-key simultaneously with the period "." ("Dialog Machine" sets cancelModalDialog to TRUE), or o the user types Escape ("Dialog Machine" sets cancelModalDialog to TRUE), or o if the window has a close box the user closes it via its close box ("Dialog Machine" sets cancelModalDialog to TRUE). Note that in the first two cases the client program is causing the dialog termination, in the latter cases the "Dialog Machine" will assign a value to the variable cancelModalDialog without any intervention by the client program. Otherwise the "Dialog Machine" won't have any effect on the values of terminateModalDialog or cancelModalDialog. This allows the calling program to detect always how the dialog has been terminated. In order to avoid user confusion you can apply such modal dialogs only to windows which have been created by calling CreateModalWindow or then to a window of one of the following tyes: - FixedSize and WithoutZoomBox - FixedLocation - FixedLocTitleBar and WithoutZoomBox If you call this procedure with a window different from any of the types listed the procedure will immediately return and have no effect except that it sets dialogAborted to TRUE. It is recommended not to run modal dialogs on windows with a close box. Here a sample program text demonstrating the use of procedure UseWindowModally by implementing an entry form (see module DMEntryForms) containing one integer field: VAR myEntryForm: DMWindows.Window; wf: DMWindows.WindowFrame; acceptIt, cancelled, entryFormOk: BOOLEAN; theInt1, origInt1, theInt2, origInt2: INTEGER; intF1, intF2, okBut, cancelBut: DMEditFields.EditItem; ... PROCEDURE DoOk; BEGIN acceptIt := DMEditFields.IsInteger(intF1, theInt1) AND DMEditFields.IsInteger(intF2, theInt2); END DoOk; PROCEDURE DoCancel; BEGIN cancelled:=TRUE; theInt1:=origInt1; theInt2:=origInt2; END DoCancel; ... origInt1:=theInt1; origInt2:=theInt2; wf.w:=360; wf.h:=120; wf.x := (DMWindIO.BackgroundWidth()-wf.w) DIV 2; wf.y := (DMWindIO.BackgroundHeight()-wf.h) DIV 2; DMWindows.CreateModalWindow(myEntryForm, DMWindows.SingleFrameShadowed, DMWindows.WithoutScrollBars, wf, DMWindows.AutoRestoreProc); DMWindIO.SetWindowFont(DMWindIO.Chicago, 12, DMWindIO.FontStyle{}); DMEditFields.MakeIntField(myEntryForm, intF1, (wf.w-6*DMWindIO.CellWidth()) DIV 2, 88, 6, theInt1, MIN(INTEGER), MAX(INTEGER)); DMEditFields.MakeIntField(myEntryForm, intF2, (wf.w-6*DMWindIO.CellWidth()) DIV 2, 66, 6, theInt2, MIN(INTEGER), MAX(INTEGER)); DMEditFields.MakePushButton(myEntryForm, okBut, wf.w-75-14, 22, 75 DIV DMWindIO.CellWidth(), DMLanguage.okButtonText, DoOk); DMEditFields.UseAsDefaultButton(okBut); DMEditFields.MakePushButton(myEntryForm, cancelBut, 14, 22, 75 DIV DMWindIO.CellWidth(), DMLanguage.cancelButtonText, DoCancel); DMEditFields.SelectField(intF1); DMWindows.UseWindowModally(myEntryForm, acceptIt, cancelled); DMWindows.RemoveWindow(myEntryForm); entryFormOk := NOT cancelled; Above code is equivalent to: VAR ef: DMEntryForms.FormFrame; entryFormOk: BOOLEAN; theInt1,theInt2: INTEGER; ... DMEntryForms.IntField(2, 20, 7, theInt1, useAsDeflt, MIN(INTEGER), MAX(INTEGER)); DMEntryForms.IntField(3, 20, 7, theInt2, useAsDeflt, MIN(INTEGER),MAX(INTEGER)); ef.x:=0; ef.y:=-1; ef.lines:=5; ef.columns:=45; DMEntryForms.UseEntryForm(ef, entryFormOk); *) PROCEDURE FrontWindow(): Window; (* returns currently frontmost window *) PROCEDURE WindowExists(u: Window): BOOLEAN; (*tests whether window u currently exists*) PROCEDURE RemoveWindow(VAR u: Window); (*upon returning u = nonexistent*) PROCEDURE RemoveAllWindows; END DMWindows.
|
||
|
|
|