Notes About the Generic Saver Application By M. Asherman, 1/13/2000 Intro: The Saver application consists of a small demo program and an underlying generic class for table-driven state saving and restoration, based on use of the generic MDA Commander facility. If you invoke the saver() demo app, you will launch an instance of a Saver demo form. Additional invocations will launch additional form instances, each one having its own default state (like persistent preferences). Any changes you make to these forms, e.g. sizing, placement, zoom state, etc. will be automatically saved and restored. By creating subclasses of the foundation Saver class, you can extend this facility to handle any custom form or other type of VFP container object. The object's state is automatically restored when you add a Saver subclass as a member, and the parent object's state is saved when the Saver is destroyed. See class SaverDemo for an illustration of how this works for the saver demo form. Currently available documentation: - run saver() to see the demo (run it multiple times) - brief descriptions have been attached to all files in saver.pjx - all programs are liberally commented - see additional usage notes in comments in saver.prg and Saver.vcx - see the saver.h include file for any hard-wired constants - note that this facility depends on the generic Commandr facility Sequence Numbering Conventions Currently used in StateSave methods: Class Seq Property Saved/Restored Saver (none) (StateSave method initially deletes prior saved state) Saver 2 savrp_category (seq # macro is SV_CNCATEG) Saver 4 savrp_notes (seq # macro is SV_CNNOTES) Saver 6 savrp_title (seq # macro is SV_CNTITLE) SaverForm 10 parent.Top SaverForm 12 parent.Left SaverForm 14 parent.Width SaverForm 16 parent.Height SaverForm 18 parent.WindowState SaverForm 30 parent.AlwaysOnTop SaverForm 32 parent.ShowTips SaverFormHideable 40 parent.Visible SaverFormHideable 42 KeepHidden property (to keep Visible = .f.) SaverDemo 100 (forces parent.resize) SaverDemo 110 parent.Edit1.value SaverDemo 120 parent.BackColor Related outstanding issues and tasks (* indicates it can wait): - integrate generic error-handling facilities into Saver classes and demo E.g. maybe generic state-restoration method could trap errors and give the user the choice of Ignoring, Continuing, or Aborting (with suppression of state-saving). Also note the potential for further refinements in this area for dealing with conversion of old configs; auto-conversion logic would benefit from some sort of version numbering system, to easily distinguish old configs from the latest version. - further savrpick.scx dialog refinements - allow for restriction on categories via adjustable control - display meta-file path - optional argument for initial category restriction - ordering options: by functionid, title, category + title, etc. - support an action argument to allow for modeless operation *- maybe OK should be disabled when nothing is selected But with a non-multiselect listbox, it's not easy (if even possible) to unselect, except in the initial state, so this is minor. *- optional window caption arg, since usable in various contexts - make provisions for both automatic and manual packing of Saver meta-files Nadya requested this on 11/3. This is a little tricky because of the need to use an exclusive opening for PACK. - auto-save/prompt options, etc. Suppression of default state-saving behavior can be accomplished by setting functionid to empty value, but we may also want a separate flag to suppress saving without wiping the default functionid. Also should have an option as to whether to prompt the user whether to save state; the present logic always saves when the form is terminated, except if functionid is blank. - Close button and/or Escape support for savercfg dialog Minor, since we have the window close box. Escape support would also be nice. - savrcontconfig resizing should use two rows of buttons for very narrow layouts If too many buttons are visible. Can take space away from the Notes editbox if needed. *- compact graphics for Saver command buttons *- Saver toolbar *- additional user/developer documentation *- support a modeless flavor of the savercfg dialog Not sure how easy or tricky this may be. Wait and see if really needed. *- generic clone configuration dialog, including from/to meta-files This would use savrpick.scx to pick the source configuration. *- optional prompt for destination or auto-creation of saved state The current implementation always auto-creates the state-saving meta-file if it's missing; this logic is handled in Commander. But we may want to provide a prompting option at the Saver level. *- canned report(s) against saved configurations, tied in to saver config. dialog It may be useful to bring in Querier and Reporter facilities for this, but that may be overkill. *- savrdemo.scx really should have an editbox on page1 We only used textbox because of difficulty with special chars prior to Commander extensions that avoid this problem. *- form + Saver subclass for viewing/editing Commander meta-file records This would really be a separate application, i.e. a Saver-based Commander utility. *- sample menu and toolbar Saver subclasses would also be nice I.e. demonstrate how Saver can be applied to other types of object than forms. General guidelines and conventions: @- maintain clean copies of selected files in shared mdacomm directory For Saver, this includes saver.h/txt/vcx/vct, savercfg.scx/sct, savrpick.fxp/scx/sct. @- rebuild dependent apps after changes to shared Commander stuff @- rebuild btcrit and xformdbf after generic Saver changes Update Saver-related files in mdacomm before rebuilding. Re-create sample saved states after these changes. @- maintain thorough error and escape-handling provisions @- allow for features that would be required for Montage recursion, multiple meta-files, shared meta-files, etc. Don't lose any of the generality we've already provided for in MDA110's mc_cvs, et al. I believe that current implementation satisfies these requirements, but haven't tested all these issues thoroughly. @- maintain notes about SEQ numbering conventions used in Saver subclasses @- avoid unnecessary direct cross-app dependencies by making use of mdacomm @- all apps should avoid potential name conflicts in case moved into mdacomm E.g. avoid file names like "notes.txt" in favor of ".txt". @- avoid using the same prefix for macro name and anything else (e.g. global mvars) Remember that VFP is case-insensitive with respect to names, so use a unique prefix for macros names without regard to case. @- add comments in history of each app as to when last uploaded to BT server Change history: 990629 incorporate appropriate use of Commander's literal string assignment syntax Revised logic in SaverDemo.StateSave. This eliminates the previous restriction against use of special characters like quotes. 990920 make adjustments for move from M: to D: This entails the following steps: - adjust icon for launching VFP to start in dir on D:... and use -cd:... option - config.fpw should be ok as-is - we already eliminated hard-wired drive/path - open .pjx and tell dialog OK to move it from M: to D: - confirm that all files in project have been relocated to D:, as expected 990920 proper macro usage (CMDR_DLAS1/2) for string literal assignment syntax In state-saving logic for Saver demo form. 990920 break out generic subclass, SaverFormHideable, from underlying SaverForm class In order to allow bypassing of logic for saving and restoring form visibility, which interferes with deliberate hiding of form, e.g. in btcrit and xformdbf non-interactive modes. 990920 redefine class SaverDemo to be based on new SaverFormHideable, not SaverForm 991012 new modal saver config. dialog, savercfg.scx - prelim. 991012 new command button class, SavrCmdDialog, to launch savercfg.scx 991012 tie new savercfg.scx dialog into saver demo form via new Config... button I.e. create member of class SavrCmdDialog. Also must adjust the demo form's Resize method logic to account for this new control. 991012 add Saver properties for configuration title, category, and notes 991012 introduce a container class, SavrContConfig, for Configuration controls 991015 make saver demo form a tabbed dialog with a config page Containing an instance of the new SavrContConfig class, of course. Move other miscellaneous stuff to a separate tab. Adjust resizing and state saving logic for new locations of various controls. 991015 state saving/restoration for new Saver class properties I.e. savrp_title, savrp_category, and savrp_notes. 991015 refresh on activation of each page in savrdemo.scx 991015 redo savercfg.scx to build on underlying SavrContConfig class 991015 add logic to savercfg.init to display parent form's caption 991015 enable resizing of savercfg.scx 991015 add editbox for Notes to SavrContConfig 991015 savrdemo resizing needs to force resizing of page2.SavrContConfig1 991015 auto-resizing savercfg.scx dialog would be nice Which should be easy if we have auto-resizing class SavrContConfig. 991016 fix resizing logic of savrdemo.scx - textbox on page 1 - watch out for min pageframe height - use pageframe.pagesize/pageheight - extra initial resize in page2.Activate Needed to avoid flaky auto-sizing behavior when restoring a compact layout. 991016 finish details of auto-resizing logic for class SavrContConfig - force initial resize event for savercfg.scx - adjustment needed for height of page tabs Use pagewidth/pageheight properties of the pageframe! - drop the "Notes:" label - narrower border allowance would suffice - smaller spacing between labels and text/editboxes - tooltips, status bar prompts and prompt sequence - display meta-file path, read-only I.e. the file in which the state is to be saved and from which restored. - let width of Category textbox fill available space - watch out for minimum size limits Keep this class robust. Widths and heights must never become negative. - shortened labels for very narrow container cases Use abbreviated labels when width is less than threshold value. 991016 classes of command buttons (in saver.vcx) for Save/Restore of form's state Use these in savrdemo.scx. Compare with class SavrCmdDialog. Build these button classes on a common foundation saver button class, SavrCmd. Allow for use either as free-standing buttons and/or as buttons within class SavrContConfig. 991016 include Save/Restore commandbuttons in SavrContConfig 991017 rework the Config... button class to base it on SavrCmd foundation class 991017 refinements to class SavrContConfig: - horizontal resizing logic for new command buttons - allow for optional hiding of individual buttons To allow for moving these buttons into the parent form as free-standing buttons. - abbreviated command button captions for narrow mode - adjust editbox sizing for cases where all command buttons are hidden - add Config... button into SavrContConfig 991017 hide circular Config... button in savercfg dialog 991017 savrdemo.scx refinements - caption for page2 should be "Config" - suppress visibility of redundant command buttons on the Config page Since these have been made free-standing buttons in the main form. - abbreviated command button captions for Save/Restore - drop free-standing Config... button, since it's on the Config... page - better spacing of commandbuttons 991017 new savrpick.scx modal dialog to pick a saved configuration - take meta-file path argument and save to property savrpp_metafile - populate listbox for picking a saved configuration, by title - add form property savrpp_retval for return value - return the selected functionid, via Unload event - OK and Cancel buttons - double-click in listbox should select and return choice *- try enabling listbox itemtips (doesn't seem to work - as expected) - read-only editbox to display notes for the selected configuration Let's try binding this to savrpick.notes. Also requires refresh in listbox's When event, to keep in synch. - display functionid, category, and title columns in listbox - supply column headers - prelim. 991017 wrapper UDF, savrpick.prg, for new form savrpick.scx 991018 introduce macros (in saver.h) for elements of query used by savrpick.scx Use these macros in both SavrPick.Init and Saver.StateSave. 991018 SavrCmd button subclass, SavrCmdSwitch, to pick (i.e. switch to) another config Launches savrpick.scx modal dialog and restores the selected config, which implies changing to its functionid. Incorporate this button into class SavrContConfig. 991018 class savrcmdswitch - pass initial functionid argument - tooltip and prompt for Switch button 991018 savrpick.scx dialog refinements - use new macros (in saver.h) for construction of query - rename reserved alias used by savrpick Change to cmdrdfpick, to avoid confusion with name of the form itself. - auto-resizing logic - adjust column widths/arrangement Really should adjust column widths in resize logic, but fixed widths will do for starters, esp. if title is last. - optional arg and logic for initial selection - OK should return empty string & Notes should be blank if nothing selected - tooltips, prompts, prompt seq 991019 put savrpick.scx/sct/fxp & savercfg.scx/sct in mdacomm, since these are not in vcx Maybe should redo these as classes, so we can incorporate them into saver.vcx. But I'm not sure if/how I can launch a modal dialog from a class - open question. 991019 tie new Saver features into xformdbf 991020 support dynamic window title for savercfg.scx, using form's Refresh 991020 extra logic to force refresh(es) in Valid event of title textbox Allow for dynamic form titles that are derived from config title, e.g. in xformdbf. 991020 also need a refresh of current form for Refresh button I.e. as well as parent form refresh. See logic in Switch command. This is needed to cover savercfg cases. 991020 use wider default layouts for both savercfg and savrpick.scx 991020 trim trailing blanks in window caption for savercfg 991021 better in-progress message coverage during state saving and restoration This really belongs in the generic Saver button classes, in case of lengthy Save and Restore operations. Also applies to Switch processing. 991021 need to trim trailing blanks on title, and maybe other properties too Also check handling of categories and notes. Adjust logic in refresh methods that generate dynamic titles. Also adjust state-saving logic in Saver.StateSave to trim blanks. Check for any problems with ability to increase width via textboxes: behavior is a little unpredictable as to length limits, because they depend on variable sizing, but it's not clear this is really a problem for typical lengths; wait and see if further attention is required. 991021 introduce new method SavrContConfig.savrcm_setsaver To handle assignment of a saver + any related inits. Then we should adjust forms that use SavrContConfig (savrdemo, savercfg, and xformdbf) to invoke this method. This also seems to be a good place to force initial resizing, because it avoids need for extra resizing logic elsewhere. 991021 field width limit for functionid, if/when this is editable Try setting the maxlength property. Avoid hard-wired assumption of field width, however; pick this up from current meta-file. Requires a Commander change to add a property containing the functionid length, since we can't assume the Commander meta-file is directly accessible (it may be in another data session). 991021 New Functionid textbox in the Pick Configuration dialog This allows us to provide incremental search and validation to prevent accidental duplication of existing functionids. 991021 None command button in savrpick.scx, for clearing the functionid Allows us to avoid any need for directly editable functionid in SavrContConfig. 991022 adjust Switch To... button logic to handle special blank functionid cases 991022 disable direct editing of functionid in SavrContConfig I.e. let the functionid only be editable in the context of a Switch To... (savrpick.scx). This might make things a lot cleaner and less confusing and dangerous. Direct editing of functionid should be restricted, or must add validation/confirmation. Really should check for duplicate functionid in valid when value is altered, i.e. warn user about existing functionid, in case unintentional. 991022 disable Save/Restore buttons when functionid is blank And watch out for proper refresh after edits to functionid. This is easier to do, now that we've disabled direct edits to functionid in SavrContConfig. 991022 tie new Saver features into btcrit 991022 adjust comments in various Saver subclasses to show revised SaverForm steps I.e. for SaverBTCrit and SaverXFormDBF StateSave methods. 991022 **** UPLOADED CHANGES TO BT SERVER'S D:\REDP\APPL\SAVER\ & ...MDACOMM\ **** 991029 SET TALK OFF in savrpick.load to avoid unintended verbosity 991029 fix bug causing truncated category and title display in savrpick.scx The lenth of the first configuration's category or title seems to impose a maximum length on the display of subsequent rows of the listbox of configs to choose from. This appears to be due to a VFP bug (or at least a totally bizarre spec for VFP query behavior involving memo fields). See if use of padr() makes the problem go away. Introduce new macros to avoid hard-wired minimum widths. 991029 savrpick.scx bug fix - use SET DELETED ON to hide deleted meta-file records 991029 **** UPLOADED CHANGES TO BT SERVER'S D:\REDP\APPL\SAVER\ & ...MDACOMM\ **** 991115 introduce splitter in the Switch To... dialog (savrpick.scx) Based on generic SplitContainer class in mdacomm\splitcon.vcx. 991115 subclass of SavrCmd button, SavrCmdAbandon, for Exit Without Saving State 991115 there is no way to overwrite an existing configuration - add a way Because the Switch To... dialog deliberately prevents you from overwriting an existing configuration via its New Functionid textbox, we need to provide an alternative mechanism to accomplish this. The Copy... button solves this problem. 991115 SavrCmd button subclass to copy (i.e. clone) another configuration Launches savrpick.scx modal dialog. Preserves the initial functionid, however, instead of switching to the selected configuration. Maybe should also adjust the title to "Copy of " ..., to make this clear and avoid unintentional duplication of titles. 991115 SavrCmd button subclass for deleting the current saved configuration Let this button be disabled if there are no non-deleted records for the current functionid. This can make use of a new Commander.cmdrm_seekfunc method for doing the lookup. 991118 flaky behavior of notes editbox after moving splitter in Swtich To... dialog Maybe continuous resizing would help. Maybe we need some sort of refresh. Try more tests against configs with substantial Notes. See how it behaves as we attempt to scroll and select portions of notes. Problem seems to have been fixed by switching to continuous resizing mode. 991203 **** UPLOADED CHANGES TO BT SERVER'S D:\REDP\APPL\SAVER\ & ...MDACOMM\ ****