SketchUcation Plugin Store

 

 

storing last values used in the registry?

storing last values used in the registry?

Postby tomot » Tue Mar 06, 2012 8:38 pm

I've been digging through scripts, and while doing some module script incorporation, I'm of the opinion that using the Registry provides a cleaner less error prone way of dealing with this Subject: The following code is part of the 1st menu
Code: Select all
 
reg_key = "TNT::Bookshelf"
prompts = ["Width", "Height", "Depth"]
values = [2.feet, 2.feet, 1.feet]
#---read registry values
v = Sketchup.read_default(reg_key, "values") 
  unless v.nil?
    values = eval(v)
    values[0] = values[0].to_l
    values[1] = values[1].to_l
    values[2] = values[2].to_l
  end       

Am I correct in assuming that a 2nd menu ALWAYS needs its own new Registry entry? (like the following which does work)
Code: Select all
reg_key = "TNT::Bookshelf1"
prompts = [ "No. of shelves wide ", "No. of shelves high ", "shelf thickness"]
values = [ 5, 5, 1.inch ]
#---read registry values
v = Sketchup.read_default(reg_key, "values") 
  unless v.nil?
    values = eval(v)
    values[0] = values[0].to_i
    values[1] = values[1].to_i
    values[2] = values[2].to_l
  end       

BTW: if I use only one registry entry for both menus and increment the values in the 2nd menu ie. values[4] etc. I get a console error
tomot
 
Posts: 610
Joined: Mon Apr 07, 2008 12:18 am
Operating system: Windows
SketchUp version: 8
License type: Free
SketchUp use: architecture
Level of SketchUp: Advanced

Re: storing last values used in the registry?

Postby Dan Rathbun » Tue Mar 06, 2012 9:38 pm

You are confusing terms again.

They are input dialog boxes, NOT menus.

NO. Each one of your plugins should only use ONE registry key.
  • Please begin all your keys with "Plugin_"
      Reason.. this sets them apart from all other Sketchup subkeys, but still grouped together. And it follows the convention used by the WebDialog keys, which are always (automatically,) prefixed with "WebDialog_"
  • Whitespace (and '::') in keynames should be replaced with "_"
.
like:
REGKEY = 'Plugin_'<<Module.nesting[0].name.split('::').join('_')
notice I use a constant (all caps,) because it will never change.
It would produce for your example:
'Plugin_TNT_Bookshelf'

BUT ...
Each "set" of values OR special setting has it's own ATTRIBUTE name (under the common plugin KEY.)
"RightHandDoorParams"
"LeftHandDoorParams"
User avatar
Dan Rathbun
Top SketchUcator
 
Posts: 4069
Joined: Tue Oct 06, 2009 3:06 am
Location: Florida, USA
Name: Dan Rathbun
Operating system: Windows
SketchUp version: 8
License type: Pro
SketchUp use: education
Level of SketchUp: Advanced

Re: storing last values used in the registry?

Postby Dan Rathbun » Tue Mar 06, 2012 9:59 pm

Next issue.

I gave you a couple of basic saving and loading option methods, in this thread's code sample:
viewtopic.php?f=180&t=43673&p=390107#p389920

What do you want to do differently ??

We can tweak the process.

For example.. if you still wanted to use unique @@ names, like @@lhd_width, @@lhd_height, @@lhd_style, etc., instead of @@opts[:lhd_width], etc. everywhere in your code ...
... you CAN do that and still use the @@opts hash of saving and restoring.

The trick is to collect ALL module variables (also called class variables,) into a array of var name strings, using the standard method class_variables()
then iterate that array thus:

Code: Select all
vars = class_variables()
vars.each do |var|
  eval("@@opts[#{var.gsub('@@',':')}]= #{var}")
end
# Now we can save the opts hash:
set_saved_opts()


The reverse, after calling get_saved_opts(), to distribute the saved settings back to your module variables:
Code: Select all
get_saved_opts()
@@opts.each do |attr,val|
  eval("@@#{attr.to_s} = @@opts[#{attr}]")
end
User avatar
Dan Rathbun
Top SketchUcator
 
Posts: 4069
Joined: Tue Oct 06, 2009 3:06 am
Location: Florida, USA
Name: Dan Rathbun
Operating system: Windows
SketchUp version: 8
License type: Pro
SketchUp use: education
Level of SketchUp: Advanced

Re: storing last values used in the registry?

Postby tomot » Tue Mar 06, 2012 11:18 pm

Dan Rathbun wrote:You are confusing terms again.
They are input dialog boxes, NOT menus.

yes, menus my bad!... been a long day so far, could not sleep, I started coding at 3:30 am this morning, with good intentions trying your outline, finally had to sideline that effort, it in favor of a simpler older script of mine in need of a module. Regardless this small demonstration script, is a starting point, for going forward. :) using module & registry works!..........comments welcome!
Please, register (free) to access all the attachments on the forums.
tomot
 
Posts: 610
Joined: Mon Apr 07, 2008 12:18 am
Operating system: Windows
SketchUp version: 8
License type: Free
SketchUp use: architecture
Level of SketchUp: Advanced

Re: storing last values used in the registry?

Postby Dan Rathbun » Wed Mar 07, 2012 12:01 am

OK looking at it... and making a few quick changes.

ADD: Here's version '1.1.1'
Fixed line 65: forgot to paste in the new attribute name "BookshelfDimensions" .. sorry.

TNT_1_1_1.zip



I fixed it so there is only ONE key for the plugin, and each dialog has a separate attribute beneath that key.

viz:
Plugin_TNT_Bookshelf_REGKEY.png

Also:
  • Put the plugin inside a plugin submodule: TNT::BookShelf.
  • Plugin now resides with the path "tnt/bookshelf/"
  • Added a VERSION constant.
  • Wrapped the undo operation in a begin ... rescue ... end block.
  • Moved the "BookShelf Details" dialog before the undo operation.
  • Moved the last line: file_loaded(filepath) inside the file_loaded? conditional block. (Just to be sure it only gets pushed into $loaded_files once. Although file_loaded() may test for this, there's no sense calling it if not needed to.)
  • Made note (in file header,) that on XP the REGKEY path differs from Win6+.
Please, register (free) to access all the attachments on the forums.
User avatar
Dan Rathbun
Top SketchUcator
 
Posts: 4069
Joined: Tue Oct 06, 2009 3:06 am
Location: Florida, USA
Name: Dan Rathbun
Operating system: Windows
SketchUp version: 8
License type: Pro
SketchUp use: education
Level of SketchUp: Advanced

Re: storing last values used in the registry?

Postby Dan Rathbun » Wed Mar 07, 2012 12:43 am

    Bumped: version '1.1.1'
    Fixed line 65: forgot to paste in the new attribute name "BookshelfDimensions" .. sorry.
    User avatar
    Dan Rathbun
    Top SketchUcator
     
    Posts: 4069
    Joined: Tue Oct 06, 2009 3:06 am
    Location: Florida, USA
    Name: Dan Rathbun
    Operating system: Windows
    SketchUp version: 8
    License type: Pro
    SketchUp use: education
    Level of SketchUp: Advanced

    Re: storing last values used in the registry?

    Postby tomot » Wed Mar 07, 2012 12:59 am

    Dan thanks for your patience! I'm going to digest your changes...tomorrow.
    After 12 hrs of sitting,... my ass is developing flat spots :)
    In the next stage I will be tackling how the incorporating of the rectangle.rb code
    which is used in my doortool ruby works with the module & registry stuff I have learned to implement today.
    ttyl!
    tomot
     
    Posts: 610
    Joined: Mon Apr 07, 2008 12:18 am
    Operating system: Windows
    SketchUp version: 8
    License type: Free
    SketchUp use: architecture
    Level of SketchUp: Advanced

    Re: storing last values used in the registry?

    Postby tomot » Wed Mar 07, 2012 4:20 pm

    Looks great Dan! Now unless I'm missing something, (which happens quite often), does the storing of last used dialog values in the registry not make for a more elegant solution then using the @@ approach?
    tomot
     
    Posts: 610
    Joined: Mon Apr 07, 2008 12:18 am
    Operating system: Windows
    SketchUp version: 8
    License type: Free
    SketchUp use: architecture
    Level of SketchUp: Advanced

    Re: storing last values used in the registry?

    Postby Dan Rathbun » Wed Mar 07, 2012 5:28 pm

    Firstly... the difference between @ vars and @@ vars in modules are subtle. (Save that issue for later.)

    Elegant? Well your really doing the same thing ... but dialog by dialog, instead of the plugin's whole set of saved values.

    Also you're doing it in a sort of brute force manner. You are accessing the stored values in the registry (whether you need to not,) and always saving them (without really testing if they are good values. Relying on the user to input values they wish to save.)
    Also you are creating the literal strings for the inputboxes each time the 'main' method is called.
    But that's OK for now... you can understand what's happening.

    Later on you (when you're ready to get fancier,) you might move the defaults, prompts etc out of the method into module vars. But it's not that important for a really simple single command plugin module. As your plugins get more complex and bigger, you will want to centralize common functions like loading and saving defaults into one method ... rather than have them scattered throughout your code. (Easier maintenance!)

    Ruby is multi-paradigm... "there is more that one way to skin a cat."


    The BIG lessons you have learned, is module wrapping, using variables that have namespace scope, and saving default values.
    Also take note of the operation block.



    I have noticed problems with the API's read_default() on PC when it tries to read REG_SZ strings values. We need to store quotes with the value in the registry. Using the inspect() method is a good idea, because it will escape embedded ' or " if used for unit symbols.
    If I try to read the "SnapLength" attribute in the "Preferences" key, I get nil, because it's set to 1" instead of '1"' or "1\""
    Also it cannot see any keys with spaces in their names, and just returns nil.
    User avatar
    Dan Rathbun
    Top SketchUcator
     
    Posts: 4069
    Joined: Tue Oct 06, 2009 3:06 am
    Location: Florida, USA
    Name: Dan Rathbun
    Operating system: Windows
    SketchUp version: 8
    License type: Pro
    SketchUp use: education
    Level of SketchUp: Advanced

    Re: storing last values used in the registry?

    Postby tomot » Wed Mar 07, 2012 5:53 pm

    Nice explanation! if I continue for now to go down the registry path
    How does or can values accept strings ? such as door open, or door closed?
    Please, register (free) to access all the attachments on the forums.
    tomot
     
    Posts: 610
    Joined: Mon Apr 07, 2008 12:18 am
    Operating system: Windows
    SketchUp version: 8
    License type: Free
    SketchUp use: architecture
    Level of SketchUp: Advanced

    Re: storing last values used in the registry?

    Postby Dan Rathbun » Wed Mar 07, 2012 9:11 pm

    tomot wrote:Nice explanation! if I continue for now to go down the registry path
    How does or can values accept strings ? such as door open, or door closed?


    OK just tested a bit ... the write_default and read_default have no problems if you feed a string (or most simple class types,) to them. The write stores it so it can be read OK.

    The problem arrises when there is more than one double quote char (") in sequence, AND they are not escaped.
    Because write_default always surrounds a string argument, perhaps by calling inspect() internally to the method.

    so this was wrong, on my part:
    Code: Select all
        #  set_saved_opts()
        #
        def set_saved_opts()
          @@opts.each_pair {|attr,val|
            if val.is_a?(String)
              Sketchup.write_default( REGKEY, attr.to_s, val.inspect )
            else
              Sketchup.write_default( REGKEY, attr.to_s, val )
            end
          }
        end#def set_saved_opts()


    I knew we needed to handle strings specially, but I went the opposite way. (The inspect method adds quotes.)

    We really do not want to ADD any more quotes chars...

    ... we want to either strip them off of strings, or be sure they are escaped.

    Let's go with option 2, and use the gsub method, to escape all internal double quotes, like:
    gsub(34.chr,92.chr<<34.chr)

    Code: Select all
        #  set_saved_opts()
        #
        def set_saved_opts()
          @@opts.each_pair {|attr,val|
            if val.is_a?(String)
              Sketchup.write_default( REGKEY, attr.to_s, val.gsub(34.chr,92.chr<<34.chr) )
            else
              Sketchup.write_default( REGKEY, attr.to_s, val )
            end
          }
        end#def set_saved_opts()


    In your case if you had a results array that had an embedded string:
    [1, 2, "door closed", 2.54]
    and you use inspect() on it, you get this:
    "[1, 2, "door closed", 2.54]"
    and read_default cannot eval it, so it returns nil
    Also, you cannot double inspect it, because that will result in the whole registry value delimited by 2 double quotes:
    [1, 2, "door closed", 2.54].inspect.inspect
    puts this: ""[1, 2, \"door closed\", 2.54]"" into the registry, and read_default will poop out again, (returning nil.)

    So... you need to use:
    results.inspect.gsub(34.chr,92.chr<<34.chr)

    You can try it at the console:
    Sketchup.write_default("Plugin_TNT_Bookshelf", "Array", [1,2,"door closed",2.54].inspect.gsub(34.chr,92.chr<<34.chr))
    and then to test retrieving it:
    arr = Sketchup.read_default("Plugin_TNT_Bookshelf", "Array")
    which if all goes well, should return:
    '[1,2,"door closed",2.54]' which can be eval'd back into an array.

    OK?

    However... write_default and read_default can ALSO write and read arrays directly if you DON'T inspect them.
    This is because the 'write' converts them to a string, before storing them in the registry,... and then the 'read' evals those strings back into an Array.

    But.. to confuse the issue... they do not handle hashes well. We have to resort to the .inspect.gsub(34.chr,92.chr<<34.chr) treatment for any hash arguments to write_default, and eval the return strings from read_default.



    Now.. (if your dizzy trying to absorb this,) perhaps, you'll understand why I like to write one method to get all this proper handling correct, and then reuse that method in multiple plugins. (Say via a mixin module.) Trying to remember all the quirky issues, when it comes time to write and read values, is a pain in the butt.



    You don't run into this 'nested string' in hashes and arrays problem, if all your variables are saved into individual attributes in the registry.
    (... And they are all single value types, ie, not arrays, hashes, structs, etc.)
    Code: Select all
    def save_my_vars()
      vars = instance_variables + class_variables
      vars.each{|var| eval("Sketchup.write_default(#{REGKEY}, '#{var}', #{var}")
    end

    def load_my_vars()
      vars = instance_variables + class_variables
      vars.each{|var| eval("#{var} = Sketchup.read_default(#{REGKEY}, '#{var}'")
    end

    But.. that will save ALL of your variables... even iterators, and ones you do not really need to save.

    This is why I collect only the ones I wish to save, into an @@opts hash, and then write only those values to the registry.

    Example.. at the top of your Bookshelf module, where you define your instance @ variables... you could just as easily define them AND an @@opts hash, all in one go:
    Code: Select all
    # default bookshelf values used for script development
    unless defined?(@@opts)
      @@opts = {
        :height => @height = 2.feet,
        :width  => @width = 2.feet,
        :depth  => @depth = 1.inch,
        :ny     => @ny = 5,
        :nz     => @nz = 5,
        :dist   => @dist = 1.inch
      }
    end




    Anyway... as long as the simple way works.. use it. When things get more complex... and you need to centralize your default value handling... you've got a topic thread here to mine for ideas.
    User avatar
    Dan Rathbun
    Top SketchUcator
     
    Posts: 4069
    Joined: Tue Oct 06, 2009 3:06 am
    Location: Florida, USA
    Name: Dan Rathbun
    Operating system: Windows
    SketchUp version: 8
    License type: Pro
    SketchUp use: education
    Level of SketchUp: Advanced

    Re: storing last values used in the registry?

    Postby ktkoh » Thu Mar 08, 2012 2:01 pm

    I have been following this topic as I have in the past used a file to store variables between sessions and my question is does the registry storing of variables only work on Win based computers and not on the Apple OS?

    Keith
    ktkoh
     
    Posts: 147
    Joined: Mon Mar 31, 2008 1:40 am
    Location: Bellefontaine OH
    Name: Keith Krueger
    Operating system: Windows
    SketchUp version: 8
    License type: Free
    SketchUp use: woodworking
    Level of SketchUp: Intermediate

    Re: storing last values used in the registry?

    Postby TIG » Thu Mar 08, 2012 2:40 pm

    The Sketchup.read_defaults and Sketchup.write_defaults use each PC's Sketchup 'Registry' entries OR a MAC's Sketchup 'plist' file entries... so they should work cross-platform.
    The main issue with using the Registry is storing data restructured into a format that can be recovered and then converted back into the required 'class' later - e.g. a string/float/integer/length/boolean/array/hash etc will need some 'manipulation' before writing - but if you have been using a 'file' to store such things then you've been writing them as strings already - when you reread the file you presumably convert the strings back with say string.to_f to make the value a number etc... [like an 'ini' file].
    The Registry data exists across sessions globally for Sketchup on each PC, not just the current SKP.
    So if you want SKP specific data saving then it's best to use model-attributes to save things with the SKP [you can save attributes as most common data types directly - except a hash] - the data is thereby accessible to all uses on the network when you script reads the attributes as it runs, and later updates the attributes as it closes, this can all be done independent of each PC's Registry entries.

    Horses for courses...
    TIG
    User avatar
    TIG
    Global Moderator
     
    Posts: 13949
    Joined: Mon Nov 12, 2007 7:24 pm
    Location: Northumbria UK
    Name: TIG
    Operating system: Windows
    SketchUp version: 8
    License type: Pro
    SketchUp use: architecture
    Level of SketchUp: Advanced

    SketchUcation One-Liner Adverts

    by Ad Machine » 5 minutes ago

    Artisan Organic Toolset - a set of powerful organic modeling tools.

    Premium Members get 20% discount!

    Ad Machine
    Robot
     
    Posts: 2012


    Return to Developers' Forum

    Who is online

    Users browsing this forum: No registered users and 8 guests