Save and restore properties 
Author Message
 Save and restore properties

    Just curious to know how others are handling this. I name the properties
I need to save DATA_<etc...> or STATIC_<etc...> , parse an amembers() array
and save/restore the stuff I need to a memo field. Other options...?

--
-Lew S



Mon, 20 Jun 2005 11:57:47 GMT  
 Save and restore properties


    Just curious to know how others are handling this. I name the properties
I need to save DATA_<etc...> or STATIC_<etc...> , parse an amembers() array
and save/restore the stuff I need to a memo field. Other options...?

---Lew S

Hi Lew,

In my startuproutine a central Class, having my main settings, is initiated from the registry like:
=readkey("DatasetLastUsed","oVar.gnDatasetLastUsed")
...
on leaving the settings are saved in the registry like:
=wrightkey("DatasetLastUsed","N"+"oVar.gnDatasetLastUsed")
*!* "N" = Numeric, "C"=Character,...

Hopes it helps,
Chris

Happy New Year!

FUNCTION readkey
 LPARAMETER cVeld,cWaarde
 cRetVal=""

 * ? cVeld,cRetVal
 IF lnError=0
  IF LEFT(cRetVal,1)="C"
   &cWaarde=SUBSTR(cRetVal,2)
  ENDIF
  IF LEFT(cRetVal,1)="N"
   &cWaarde=VAL(SUBSTR(cRetVal,2))
  ENDIF
  IF LEFT(cRetVal,1)="L"
   IF UPPER(SUBSTR(cRetVal,2))="T"
    &cWaarde=.T.
   ELSE
    &cWaarde=.F.
   ENDIF
  ENDIF
  *!*  ELSE
  *!*   cRetVal=""
 ENDIF
 RETURN && cRetVal

FUNCTION wrightkey
 LPARAMETER cVeld,cWaarde

 RETURN



Mon, 20 Jun 2005 19:21:49 GMT  
 Save and restore properties
These aren't startup settings. They're for any object, any time, and for any
reason. Thanks.

--
-Lew S



Mon, 20 Jun 2005 21:24:26 GMT  
 Save and restore properties


Quote:
>These aren't startup settings. They're for any object, any time, and for any
>reason. Thanks.

If it helps, here is the code I use to persist user settings in forms.
The class is designed to be dropped in any container for which you
want settings saved. It's designed, also, to let you choose which
properties you want to save. Containers can register objects that
should _not_ be persisted. The code below is a simple example. Run it,
change the form size and label caption and text box value. Close the
form and run it again. You should see your previous choices, and a
reset button, also.

PUBLIC oform1

oform1=NEWOBJECT("form1")
oform1.Show
RETURN

DEFINE CLASS form1 AS form

        Top = 0
        Left = 0
        Height = 229
        Width = 309
        DoCreate = .T.
        Caption = "Form1"
        Visible = .T.
        Name = "Form1"

        ADD OBJECT text1 AS textbox WITH ;
                Value = "Try resizing the form", ;
                Height = 23, ;
                Left = 55, ;
                StatusBarText = "This value won't be persisted.", ;
                ToolTipText = "This value won't be persisted.", ;
                Top = 81, ;
                Width = 193, ;
                Name = "Text1"

        ADD OBJECT label1 AS label WITH ;
                AutoSize = .T., ;
                Caption = "Label1", ;
                Height = 17, ;
                Left = 55, ;
                Top = 65, ;
                Width = 40, ;
                Name = "Label1"

        ADD OBJECT command1 AS commandbutton WITH ;
                Top = 112, ;
                Left = 55, ;
                Height = 27, ;
                Width = 193, ;
                Caption = "Change label caption", ;
                Name = "Command1"

        ADD OBJECT persist AS persist WITH ;
                Top = 15, ;
                Left = 134, ;
                Height = 17, ;
                Width = 21, ;
                Name = "Persist"

        ADD OBJECT command2 AS commandbutton WITH ;
                Top = 198, ;
                Left = 56, ;
                Height = 27, ;
                Width = 193, ;
                Caption = "Reset defaults (requires restart)", ;
                Name = "Command2"

        PROCEDURE Init
                THIS.Persist.Exceptions[1] = 'Text1'
        ENDPROC

        PROCEDURE command1.Click
                THISFORM.label1.CAPTION = INPUTBOX('Change label
caption',THISFORM.label1.CAPTION)
        ENDPROC

        PROCEDURE command2.Init
                THIS.VISIBLE = FILE(THISFORM.persist.savetofile)
        ENDPROC

        PROCEDURE command2.Click
                THISFORM.Persist.Kill = .T.
                THIS.ENABLED = .F.
        ENDPROC

ENDDEFINE
*
*-- EndDefine: form1
**************************************************

DEFINE CLASS persist AS custom

        *-- Name of the file to save the preferences in.
  *-- Default is the parent object's name.
        savetofile = ""
        *-- Where to save the preferences.
  *-- Default is user's temporary directory. This means that
        *-- preferences are automatically saved for the user logged
        *-- into to the OS.
        PROTECTED savetofiledir
        savetofiledir = (ADDBS(GETENV('TEMP')))
        *-- File extension for the settings. For example, ".FPW"
        PROTECTED savetofileext
        savetofileext = ".FPW"
        *-- Use a prefix that denotes the application. Optional.
        PROTECTED savetofileprefix
        savetofileprefix = "_RB"
        *-- The version of the application the object was last saved in.
        *-- This is so that when new EXE's are delivered, the object's
        *-- default properties are used, since they may have changed in the
        *-- new EXE.
        PROTECTED version
        version = ""
        *-- What was the last saved version of the object?
        PROTECTED restoreversion
        restoreversion = ""
        Name = "persist"

        *-- Set to .T. to reset the default properties. Requires reload.
        kill = .F.

        *-- Array of properties for which we save preferences.
        PROTECTED properties[1]

        *-- Array of Object.Property.Settings
        PROTECTED settings[1,2]

        *-- Register the names of any controls that shouldn't be persisted.
        *-- The container that owns the persistance object will populate
        *-- this array.
        DIMENSION exceptions[1]

        *-- Save properties for all the members of an object.
        PROCEDURE save
                LPARAMETERS toObject
                *!* Save the object Version
                THIS.SaveVersion()

                *!* Save all the member objects properties
                LOCAL lnMembers, laMembers[1], lcMember, lni
                lnMembers = AMEMBERS(laMembers, toObject, 2)
                FOR lni = 1 TO lnMembers
                        IF ASCAN( THIS.Exceptions, laMembers[lni] ) > 0
                                LOOP
                        ENDIF
                        lcMember = "toObject." + laMembers[lni]
                        THIS.SAVE(&lcMember)
                NEXT lni

                *!* Then save the object's properties.
                THIS.SaveProperties(toObject)
        ENDPROC

        *-- Restore preferences for all the members of an object.
        PROTECTED PROCEDURE restore
                LPARAMETERS toObject
                LOCAL lnMembers, laMembers[1], lcMember, lni

                *!* Loop thru any member objects to save their properties.
                lnMembers = AMEMBERS(laMembers, toObject, 2)
                FOR lni = 1 TO lnMembers
                        IF ASCAN( THIS.Exceptions, laMembers[lni] ) > 0
                                LOOP
                        ENDIF
                        lcMember = "toObject." + laMembers[lni]
                        THIS.RESTORE(&lcMember)
                NEXT lni
                *!* Then save the object's properties.
                THIS.RestoreProperties(toObject)
        ENDPROC

        *-- Save properties for an object.
        PROTECTED PROCEDURE saveproperties
                LPARAMETERS toObject
                *!* Save the properties that are likely to change for objects.
                *!* Most obviously are layout and value. This could be abstracted.
                LOCAL lcObject, lni, lcProperty
                lcObject = toObject.NAME
                FOR lni = 1 TO ALEN(THIS.Properties)
                        lcProperty = THIS.Properties[lni]
                        STRTOFILE( SYS(1272,toObject) + "." + lcProperty + CHR(9) + ;
                                TRANSFORM(EVALUATE("toObject." + lcProperty ) ) + CHR(13), ;
                                THIS.SaveToFile, .T. )
                NEXT lni
        ENDPROC

        *-- Restore preferences for an object.
        PROTECTED PROCEDURE restoreproperties
                LPARAMETERS toObject
                LOCAL lcObject, lni, lcProperty, lnj, lcSetExact, ;
                                        lcSetting, lcValue
                lcSetExact = SET('EXACT')
                lcObject = toObject.NAME
                SET EXACT OFF
                FOR lni = 1 TO ALEN(THIS.Properties)
                        lcProperty =  THIS.Properties[lni]
                        lnj = ASCAN( THIS.Settings, SYS(1272,toObject) + "." + ;
                                                lcProperty + CHR(9) )
                        IF lnj > 0
                                lcSetting = THIS.Settings[lnj]
                                lcValue = RTRIM(SUBSTR(lcSetting,AT(CHR(9),lcSetting)+1 ))
                                IF TYPE(lcValue) = "U"
                                        lcValue = "[" + lcValue + "]"
                                ENDIF
                                STORE EVALUATE(lcValue) TO toObject.&lcProperty
                        ENDIF
                NEXT lni
                SET EXACT &lcSetExact
        ENDPROC

        PROTECTED PROCEDURE reset
                 IF FILE(THIS.SaveToFile)
                        DELETE FILE (THIS.SaveToFile) RECYCLE
                 ENDIF
        ENDPROC

        *-- Method that saves the object version.
        PROTECTED PROCEDURE saveversion
                STRTOFILE( "Version" + CHR(9) + ;
                        THIS.VERSION + CHR(13), ;
                        THIS.SaveToFile, .T. )
        ENDPROC

        *-- There is a difference if we're testing in development
        *-- or runtime.
        PROTECTED PROCEDURE version_access
                LOCAL lcVersion, lcProgram, laVersion[1]
                lcProgram = SYS(16,0)
                IF AGETFILEVERSION(laVersion, lcProgram) > 0
                        lcVersion = laVersion[4]
                ELSE
                        lcVersion = "0"
                ENDIF
                RETURN lcVersion
        ENDPROC

        *-- Load the settings, if there are any, for the object and its
        *-- members.
        PROTECTED PROCEDURE loadsettings
                *!* First find the persistent file, if it exists
                IF !FILE(THIS.SaveToFile)
                        RETURN .F.
                ENDIF
                RETURN ALINES(THIS.Settings,FILETOSTR(THIS.SaveToFile)) > 0
        ENDPROC

        PROTECTED PROCEDURE restoreversion_access
                LOCAL lcExact, lcVersion, lni
                lcExact = SET('EXACT')
                SET EXACT OFF
                lni = ASCAN( this.Settings, "Version" )
                lcVersion = STRTRAN( THIS.SETTINGS[lni], 'Version' + CHR(9))
                SET EXACT &lcExact
                RETURN  lcVersion
        ENDPROC

        PROCEDURE Init
                THIS.Exceptions[1] = ""

                THIS.SaveToFile = ;
                        THIS.SaveToFileDir + ;
                        THIS.SaveToFilePrefix + ;
                        THIS.PARENT.NAME + ;
                        THIS.SaveToFileExt

                DIMENSION THIS.Properties[11]
                THIS.Properties[1]  = "Caption"
                THIS.Properties[2]  = "BackColor"
                THIS.Properties[3]  = "ForeColor"
                THIS.Properties[4]  = "FontSize"
                THIS.Properties[5]  = "Enabled"
                THIS.Properties[6]  = "Value"
                THIS.Properties[7]  = "Height"
                THIS.Properties[8]  = "Left"
                THIS.Properties[9]  = "Top"
                THIS.Properties[10] = "ToolTipText"
                THIS.Properties[11] = "Width"

                #IF VERSION(2) = 2
                        _CLIPTEXT = THIS.SaveToFile
                #ENDIF

                IF THIS.loadSettings()
                        IF THIS.RestoreVersion = THIS.VERSION
                                THIS.RESTORE(THIS.PARENT)
                        ENDIF
                ENDIF
        ENDPROC

        PROCEDURE Destroy
                IF TYPE( "this.parent" ) = "O" .AND. !ISNULL( THIS.PARENT )

                  *!* Prepare to save the current settings
                  THIS.RESET()

                  *!* 01/02/03 09:59:37 AM nf 1: Added ability to just kill the
                        *!* saved settings so the next time the parent is loaded, the
                        *!* default settings will be used.
                  IF !THIS.Kill
                    THIS.SAVE(THIS.PARENT)
                  ENDIF

                ENDIF
        ENDPROC

        PROCEDURE Error
                LPARAMETERS nError, cMethod, nLine
                IF INLIST(nError, 1732, 1743, 1757, 1734, 1559)
                        *!* 1734 Property "name" is not found.
                        *!* 1757 Property "name" is protected.
                        *!* 1743 Property "name" is read-only.
                        *!* 1559 Property is not found.
                        *!* 1732 Data type is invalid for this property.
                        *!* Ignore
                        RETURN
                ELSE
                        SET ASSERTS ON
                        ASSERT .F. MESSAGE MESSAGE()
                        IF .F.
                                RETRY
                                RETURN
                        ENDIF
                ENDIF
        ENDPROC

ENDDEFINE

------------------------
Nancy Folsom--FoxPro MVP
Author of _Debugging_Visual_FoxPro_Applications_
http://www.hentzenwerke.com/catalogavailability/debugvfp.htm

Download VFP 8.0 Beta (http://msdn.microsoft.com/vfoxpro/)

The Ed Leafe Fox Forum http://msdn.microsoft.com/vfoxpro/



Tue, 21 Jun 2005 02:31:18 GMT  
 Save and restore properties
    Thanks, Nancy! A very complete solution. I especially like the
versioning idea.
    As I've been working through this problem, I think the main issue is
encapsulation: which objects know what about what gets save and what doesn't
(if that makes any sense). In your solution, even though the saver object
can be dropped onto the savee container, the savee must still anticipate
through its exceptions list. The only way I see to get around this, for user
defined properties anyway (I think this is a Steve Black idea), is to target
properties via a naming convention like STATIC_property or DATA_ etc...
    Also, were there any implementation issues about saving to a file as
opposed to a memo field?
--
-Lew S


Thu, 23 Jun 2005 00:27:32 GMT  
 Save and restore properties
Hi, Lew-

Quote:
>    Thanks, Nancy! A very complete solution. I especially like the
>versioning idea.

I wish I could say I anticipated it, but I realized this would be a
problem once I'd changed the layout of a form, and kept getting the
old layout! In addition, my client wanted to except one of the
controls but they didn't know it until after they'd used the prototype
for a while.

Quote:
>    As I've been working through this problem, I think the main issue is
>encapsulation: which objects know what about what gets save and what doesn't
>(if that makes any sense). In your solution, even though the saver object
>can be dropped onto the savee container, the savee must still anticipate
>through its exceptions list.

This is how I framed the problem to myself. I wanted to be able to
save prefences for some objects without the objects knowing anything
about whether or how they are being persisted. This meant that I
didn't want to have to change any of my base classes to accomodate the
new functionality. One of my mottos is implement new funtionality with
minimal if any impact to the existing architecture. This design, IMO,
best meets my conditions. The _only_ coupling between objects is in
the registration of excepted objects by the container. In OOP,
containers can "know" about and address their contained objects.

I considered several solutions to the problem of excepting objects and
discussed a couple of alternatives with an experience OOP developer,
so this solution meets my needs. However, I can see where it wouldn't
be the best solution given different requirements. For example, if
there is a lot of variation between how objects are persisted. In that
case I would consider hooking subclassed persistance objects on to
baseclasses (textboxes, etc.).

Theoretically it should be possible to use my design and create more
specialized persistance classes for, say, layout, value, position, and
what not. Then drop as many of the persistence objects as one needs in
a container.

Quote:
>The only way I see to get around this, for user
>defined properties anyway (I think this is a Steve Black idea), is to target
>properties via a naming convention like STATIC_property or DATA_ etc...

I'm not a fan of this. It is an artificial solution, and I try to
avoid those. By artificial I mean that it requires changing the
structure of baseclasses to accomodate a convention used by another
class. That's tight coupling, IMHO.

Quote:
>    Also, were there any implementation issues about saving to a file as
>opposed to a memo field?

Storing settings in a table is a reasonable choice, and in this case
I'd say it was primarily personal preference. In this case, since the
goal is to develop a system to save user settings (form location,
resize, etc) the settings need to be established for specific users.
So, (keeping with motto above), I looked at what I already have
available in the system for knowing about an individual user, and
concluded using the Windows user temporary directory was a simple
solution. It saves programming more table access and storing code. So,
again, minimal coding necessary.

The problem with my choice that you wouldn't have with a table is that
users won't see their preferences if they move from machine to
machine. IOW, it's not based on logging in to the application, but
logging into Windows.

------------------------
Author of _Debugging_Visual_FoxPro_Applications_
http://www.hentzenwerke.com/catalogavailability/debugvfp.htm

What's new?
-----------
The Ed Leafe Fox Forum http://leafe.com/forum/



Thu, 23 Jun 2005 01:56:58 GMT  
 Save and restore properties
My solution used a table, because I wanted to persist the entire application UI state and then rebuild it later.
For speed I copied properties to an array (attribute/value pairs) and then used SAVE ... LIKE to very quickly copy that array to a memo field.
I was handling 300 objects per save, so speed was important.
Restoring from a save was the reverse process.
Yes, as the objects changed I had to version them (and the saves) so I could tell if a previous save could be restored to the current version.
I considered making it leave default values for new properties that weren't saved in an old version, but decided that could break the application. So I just made it abort and issue an error.
I also abused that idea to clone a set of objects.

I think the save design pattern is "dismantling your car to put in the garage (in cardboard boxes)" and restore is "putting in all back together with no bits left over".



Sat, 25 Jun 2005 18:55:30 GMT  
 Save and restore properties

Quote:

>I think the save design pattern is "dismantling your car to put in the garage (in cardboard boxes)" and restore is "putting in all back together with no bits left over".

My save pattern was for a multi-driver family. "Dismantle the parts that are
likely to be changed by the next driver, but leave the rest as the default."
IOW, Junior doesn't get a choice of swapping out a V8 for the 4-cyl. :)

------------------------
Author of _Debugging_Visual_FoxPro_Applications_
http://www.hentzenwerke.com/catalogavailability/debugvfp.htm

What's new?
-----------
The Ed Leafe Fox Forum http://leafe.com/forum/



Sun, 26 Jun 2005 00:11:16 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. How to save and restore table layout?

2. Need to save/restore FoxPro environment.

3. SAVE WINDOWS, RESTORE WINDOWS commands

4. Saving and restoring printed reports ?

5. How to save/restore screen color?

6. Save and Restore REPROCESS setting

7. Save/Restore and object???

8. Help: Strict Date and save/restore filters

9. restoring user customized screen and form properties when they restart an app

10. Clearing (restoring default values) to properties

11. Losing Changes Since Last Save when clicking Save

12. save in paint and auto saved into table

 

 
Powered by phpBB® Forum Software