Version 1.0
Copyright (C) 1999 AbiSource, Inc., All Rights Reserved.
AbiSource, Inc.
AbiWord makes use of a
Before adding a dialog, the following questions must be answered:
[1] Is the dialog application-specific (ie. AbiWord vs AbiCalc) or is it application-independent (theoretically usable by any application). The File-Open dialog on most systems, for example.
[2] What is the persistence nature of the information in the dialog? That is, what information (either user-entered or system-supplied) that is shown in one invocation of the dialog should be remembered and shown the next time that the dialog is raised (assuming nothing in the application needs to override it).
The Dialog Framework defines 3 levels of persistence:
[a] no-persistence (think of a yes/no message box)
[b] frame (window) persistence
[c] application (global) persistence
The file abi/src/xap/xp/xap_Dialog.h gives the class hierarchy of the Dialog Framework:
Dialog
NonPersistent [*]
Persistent
FramePersistent [*]
AppPersistent [*]
From the ones marked with [*] we then derive a dialog-specific subclass (for FileOpenSaveAs, MessageBox, FontChooser, etc.). From these, we then derive platform-specific versions. For example:
Dialog
NonPersistent [*]
MessageBox [**]
UnixMessageBox [***]
WinMessageBox [***]
Persistent
FramePersistent [*]
AppPersistent [*]
FileOpenSaveAs [**]
UnixFileOpenSaveAs [***]
WinFileOpenSaveAs [***]
The
Needless to say, the [**] classes define a MINI-API for each type of dialog using absolute and virtual methods, so that the business logic can just work with the [**] classes. For example, the MessageBox dialog defines the following methods and data types (in abi/src/xap/xp/xap_Dlg_MessageBox.h):
After requesting an instance of the MessageBox dialog from the Dialog Factory, application logic can simply use the dialog by doing something like the following:
In a similar fashion each type of dialog defines (in cross-platform code) the set of verbs that it requires.
The Dialog Framework contains a Dialog Factory that is contained in the {xap,ap}_{Frame,App} code The Dialog Factory deals with the specific class construction and persistence, such that application logic can just request a dialog by ID and let the Dialog Factory take care of the details.
The following code shows an example of how to request a MessageBox dialog from the Dialog Factory:
This code snippet was taken from code in abi/src/wp/ap/xp/ap_EditMethods.cpp.
To add a new type of dialog, we need to do the following:
If you are creating an application-independent dialog:
[1] Define XAP_DIALOG_ID_foo for it in abi/src/xap/xp/xap_Dialog_Id.h.
[2] Create a [**] class for it in abi/src/xap/xp/xap_Dialog_Foo.{h,cpp} -- completely define the MINI-API for this dialog.
[3] Create [***] classes for each platform (abi/src/xap/{unix,win}/xap_{Unix,Win}Dialog_Foo.{h,cpp} -- create both sets even if you only "speak" one platform (stub in the other platform so it will at least compile).
[4] Update the Makefiles in abi/src/xap/{Makefile,{unix,win}/Makefile}.
If an application-dependent dialog, do steps [1-4] above but in abi/src/wp/ap/ instead of abi/src/xap/.
For either type of dialog:
[5] Add declarations for the dialog in abi/src/wp/ap/{unix,win}/ap_{Unix,Win}Dialog_All.h -- there are 2 sections in this file, add something to both.
[6] On win32, if not using a common dialog, add a resource ID to abi/src/wp/ap/win/ap_Win32Resources.rc2 and create a dialog template in abi/src/wp/ap/win/ap_Win32Resources_DialogFoo.rc2.
With some luck (and hopefully I haven't left anything out) you should have it.
[a] For some related dialogs (like file-open and save-as) we use the same code for both -- but with 2 unique ID's -- the association is made in the DeclareDialog() statements in the .../...Dialog_All.h files.
[b] All dialogs run as modal dialogs (hence the runModal call in the base class :-) We do not (at present time) have need to modeless dialogs.
[c] All persistent dialogs are instantiated once (per-frame or per-application) and re-used between screen invocations. The Dialog Factory takes care of instantiation and final destruction. This allows you to store anything in the class that you want to persist between appearances on screen. The useStart() and useEnd() methods are called by the Dialog Factory before and after your application logic uses the dialog (during the call to requestDialog() and during the releaseDialog() call, respectively), so your dialog can do any per-use initialization/cleanup.
[d] At this point we haven't dealt with localization issues, so (for now) we've just hard-coded English text in the dialogs. We'll deal with that later.