Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Configuration Class

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Configuration Class

    Just about every program ends up with some global variables when it gets large enough, and managing them is just one of those things which you have to take into account as you continue extending or bug fixing the program. Being someone who dislikes having to constantly run into situations where "Oh no, I need another global!", I started using a Dictionary Object with VB programs. That was fairly simple, the object didn't care what type of value you passed to it, and VB didn't care what it got from it. On the surface that is, I know there was a lot of type casting going on in the background in the compiled program, didn't care.

    In "porting" one of my programs from VB to PB, I really needed to maintain some use of that ability to manage all my configuration settings in a single place so it was not only easy to access and use, but to also be able to export and import the settings. Really critical stuff when you want to be able to permit the user of the program to adjust things to their taste, and not have to do it each time they start the program.

    So, I wrote a class which would fufill that need:
    Code:
    ' class Configuration Manager
    
    %INSERTCONSTANTS%
    
    CLASS ConfigurationClass
     %INSERTINSTANCES%
    
     CLASS METHOD CREATE()
     END METHOD
     CLASS METHOD DESTROY()
     END METHOD
    
     INTERFACE ConfigurationHandler
      INHERIT IUNKNOWN
    
      PROPERTY GET cString(BYVAL ItemIndex AS LONG) AS STRING
       LOCAL rString   AS STRING
       IF ItemIndex <= %cfgMax THEN
        SELECT CASE ItemIndex
         %INSERTGETSTRING%
        END SELECT
       END IF
       PROPERTY = rString
      END PROPERTY
    
      PROPERTY SET cString(BYVAL ItemIndex AS LONG, BYVAL ItemValue AS STRING)
       IF ItemIndex <= %cfgMax THEN
        SELECT CASE ItemIndex
         %INSERTSETSTRING%
        END SELECT
       END IF
      END PROPERTY
    
      PROPERTY GET cTitle(BYVAL ItemIndex AS LONG) AS STRING
       LOCAL rString   AS STRING
       IF ItemIndex <= %cfgMax THEN
        SELECT CASE ItemIndex
         %INSERTGETTITLE%
        END SELECT
       END IF
       PROPERTY = rString
      END PROPERTY
    
      PROPERTY GET cValue(BYVAL ItemIndex AS LONG) AS LONG
       LOCAL rValue AS LONG
       IF ItemIndex <= %cfgMax THEN
        SELECT CASE ItemIndex
         %INSERTGETVALUES%
        END SELECT
       END IF
       PROPERTY = rValue
      END PROPERTY
    
      PROPERTY SET cValue(BYVAL ItemIndex AS LONG, BYVAL ItemValue AS LONG)
       IF ItemIndex <= %cfgMax THEN
        SELECT CASE ItemIndex
         %INSERTSETVALUES%
        END SELECT
       END IF
      END PROPERTY
    
      PROPERTY GET cBoolean(BYVAL ItemIndex AS LONG) AS LONG
       LOCAL rBoolean  AS LONG
       IF ItemIndex <= %cfgMax THEN
        SELECT CASE ItemIndex
         %INSERTGETBOOLEAN%
        END SELECT
       END IF
       PROPERTY = ISTRUE rBoolean
      END PROPERTY
    
      PROPERTY SET cBoolean(BYVAL ItemIndex AS LONG, BYVAL ItemValue AS LONG)
       IF ItemIndex <= %cfgMax THEN
        ItemValue = ISTRUE ItemValue
        SELECT CASE ItemIndex
         %INSERTSETBOOLEAN%
        END SELECT
       END IF
      END PROPERTY
    
      PROPERTY GET cName(BYVAL ItemIndex AS LONG) AS STRING
       LOCAL rName  AS STRING
       IF ItemIndex <= %cfgMax THEN
        SELECT CASE ItemIndex
         %INSERTGETNAME%
        END SELECT
       END IF
       PROPERTY = rName
      END PROPERTY
    
      PROPERTY GET cIndex(BYVAL ItemName AS STRING) AS LONG
       LOCAL rIndex AS LONG
       SELECT CASE UCASE$(ItemName)
        %INSERTGETINDEX%
        CASE ELSE
         rIndex = -1
       END SELECT
       PROPERTY = rIndex
      END PROPERTY
    
      METHOD MakeConfigurationString(BYVAL ItemIndex AS LONG) AS STRING
       LOCAL cString   AS STRING
       cString = me.cName(ItemIndex) 
       IF LEN(cString) > 0 THEN
        cString = cString & "="
        SELECT CASE ItemIndex
          %INSERTCONSTRUCTORS%
        END SELECT
         END IF
       METHOD = cString
      END METHOD
    
      METHOD SetConfigurationValue(BYVAL cString AS STRING) AS LONG
       LOCAL ItemIndex  AS LONG
       LOCAL cValue  AS STRING
       LOCAL Success    AS LONG
       ItemIndex = me.cIndex(TRIM$(PARSE$(cString, "=", 1)))
       cValue = TRIM$(PARSE$(cString, "=", 2))
       Success = %TRUE
       SELECT CASE ItemIndex
        %INSERTDESTRUCTORS%
        CASE ELSE
         Success = %FALSE
       END SELECT
       METHOD = Success
      END METHOD
    
     END INTERFACE
    
    END CLASS
    That's my template, which is included in the attached zip file, it's read by the Excel VBA, also in the attached zip, and filled in to produce something which manages the various settings you need to manage your program's operation. Lets Go over all the various psuedo %variables% so you can see how I put all this together.

    %INSERTCONSTANTS%
    Code:
    %cfgActiveFolder                   = 0
    %cfgCloseGracefully                = 1
    %cfgSaveOnExit                     = 2
    %cfgScreenX                        = 3
    %cfgScreenY                        = 4
    %cfgUseLongNames                   = 5
    %cfgWindowCount                    = 6
    %cfgWorkingFolder                  = 7
    %cfgMax                            = 7
    The constants are part of being able to use the class easy, the whole idea was to make it easy to get and set values in the class without needing to remember what ID was which value, and to not use a string for lookup.


    %INSERTINSTANCES%
    Code:
        INSTANCE cfgActiveFolder            AS STRING
        INSTANCE cfgCloseGracefully         AS LONG ' Boolean
        INSTANCE cfgSaveOnExit              AS LONG ' Boolean
        INSTANCE cfgScreenX                 AS LONG
        INSTANCE cfgScreenY                 AS LONG
        INSTANCE cfgUseLongNames            AS LONG ' Boolean
        INSTANCE cfgWindowCount             AS LONG
        INSTANCE cfgWorkingFolder           AS STRING
    The compiler is not complaining about variable names being the same as the constants, and overall, it makes readability of the class easy. The class is designed to handle 3 types of values, STRING, LONG, and BOOLEAN. Seeing as PB don't have an intristic boolean value, it's a tad faked with a long.


    %INSERTGETSTRING% / %INSERTSETSTRING% (cString)
    Code:
        SELECT CASE ItemIndex
         CASE %cfgActiveFolder
           rString = cfgActiveFolder
    Code:
        SELECT CASE ItemIndex
         CASE %cfgActiveFolder
           cfgActiveFolder = ItemValue
    These two sections are for managing strings in the class, I suppose if you wanted to access values as strings, you could also include that ability into the class, however, as I constructed it, if the value you wanted was not a string, then an empty string is returned. Could probably add error management into the class so it does something if the programmer does something funky like that.


    %INSERTGETTITLE% (cTitle)
    Code:
        SELECT CASE ItemIndex
         CASE %cfgWorkingFolder
           rString = "Select Default Working Folder"
    Special purpose class item for when I throw up an Open File dialog or a Browse For Folder dialog I can get the title for the function from the class based on the value I'm permitting the user to adjust.


    %INSERTGETVALUES% / %INSERTSETVALUES% (cValue)
    Code:
        SELECT CASE ItemIndex
         CASE %cfgScreenX
           rValue = cfgScreenX
    Code:
        SELECT CASE ItemIndex
         CASE %cfgScreenX
           cfgScreenX = ItemValue
    Overall, there is no restriction on having a class like this limited to strictly Long's for values, at this point, I have no need to include other values than the three I was interesting in maintaining. It's not unfeasable to include structures into the class and use the class for managing something complex.


    %INSERTGETBOOLEAN% / %INSERTSETBOOLEAN% (cBoolean)
    Code:
        SELECT CASE ItemIndex
         CASE %cfgCloseGracefully
           rBoolean = cfgCloseGracefully
    Code:
        SELECT CASE ItemIndex
         CASE %cfgCloseGracefully
           cfgCloseGracefully = ItemValue
    You will note, from the above template, and when dealing with boolean values in the configuraton class, I explicitedly set the inbound value to being either true or false, and likewise, when returning the value from the class, by using the ISTRUE function.


    %INSERTGETNAME% (cName)
    Code:
        SELECT CASE ItemIndex
         CASE %cfgActiveFolder
           rName = "cfgActiveFolder"
    %INSERTGETINDEX% (cIndex)
    Code:
       SELECT CASE UCASE$(ItemName)
        CASE "CFGACTIVEFOLDER"
          rIndex = %cfgActiveFolder
    I suppose these two properties could of been made private to the class, it's a waffle. But they're for the next part of this class. The first one is for fetching the name of the associated configuration variable and the second is for determining the index for that name.


    %INSERTCONSTRUCTORS% (MakeConfigurationString)
    Code:
        SELECT CASE ItemIndex
          CASE %cfgActiveFolder
            cString = cString & ME.cString(ItemIndex)
          CASE %cfgCloseGracefully
            cString = cString & IIF$(ISTRUE ME.cBoolean(ItemIndex), "True", "False")
          CASE %cfgScreenX
            cString = cString & FORMAT$(ME.cValue(ItemIndex))
    %INSERTDESTRUCTORS% (SetConfigurationValue)
    Code:
       SELECT CASE ItemIndex
        CASE %cfgActiveFolder
          ME.cString(ItemIndex) = cValue
        CASE %cfgCloseGracefully
          ME.cBoolean(ItemIndex) = IIF(ucase$(cValue) = "TRUE", %TRUE, %FALSE)
        CASE %cfgScreenX
          ME.cValue(ItemIndex) = VAL(cValue)
    I suppose you could include the ability to load and save the configuration settings to a file as part of the class, I didn't include that due to the need to have "other" values written to the file, mainly a recent files list. Hence the reason that SetConfigurationValue returns either TRUE or FALSE from the operation, if FALSE, then the line from the file needs to be handled differently.
    Attached Files
    Furcadia, an interesting online MMORPG in which you can create and program your own content.
Working...
X