How to get in Ruby the list of templates

I did notice that, I guess that the original developers did drove them selfs in a kind of deadlock; continue with blisters and bandage or rewrite a massive piece of code. Happens often, also with Lotus Notes and Formula, they also did have to rewrite that. Maybe SU has to rewrite the events for the model engine.

Anyway, I did try this to get your idea working, but it crashes.

I did put some messageboxes in there to look at the call order. I notice that when I wait to dismiss the messagebox with ā€œbuild_menu_item - menu not loaded yet exitā€ it crashes directly after, but if I am quick I get also the to see the " build_menu_item - exit" message. But then it crashed direclty after that. My guess is that it happens because of removing the observer. If I remove that line, then it so far works, but if that is the purposeā€¦
( BTW, is there a kind of keyword like LINE or FILE but for a def or module to shoe in what for def the code is executed? )

module RvAmerongen
  module TemplateSetManager

    extend self

    NEW_FROM_TEMPLATE ||= "New ..."

    @@menu_loaded = false unless defined?(@@menu_loaded)
    @@manager_open = false unless defined?(@@manager_open)
    @@manager_menu ||= MF_ENABLED

    #{# AppObserver callbacks
    #
      def expectsStartupModelNotifications
      UI.messagebox(__FILE__ + " expectsStartupModelNotifications")
        return true
      end

      def onNewModel(model)
      UI.messagebox(__FILE__ + " onNewModel")
        build_menu_item()
      end

      def onOpenModel(model)
      UI.messagebox(__FILE__ + " onOpenModel")
        build_menu_item()
      end
    #
    #}#

    def build_menu_item
    UI.messagebox(__FILE__ + " build_menu_item")
      unless @@menu_loaded
      	UI.messagebox(__FILE__ + " build_menu_item - menu not loaded yet")
        menu = UI.menu("File")
        mItem = menu.add_item(NEW_FROM_TEMPLATE,1) { open_manager() }
        menu.set_validation_proc(mItem) { @@manager_menu }
        # Don't load the menu item again ...
        @@menu_loaded = true
        # We are now done with the AppObserver ...
        Sketchup.remove_observer(self)
        UI.messagebox(__FILE__ + "  build_menu_item - menu not loaded yet exit")
      end  #### IT CRASHES AROUND HERE
      UI.messagebox(__FILE__ + " build_menu_item - exit")
    end

    def get_templates
      # build list of templates
      # Get them ...
      UI.messagebox(__FILE__ + " get_templates")
				tdir = Sketchup.get_resource_path("Templates")
				file_list = Dir.chdir(tdir) { Dir["*.skp"] }

				# List them ...
				UI.messagebox(file_list.join("\n"), MB_MULTILINE, "Templates")

				# Current one ( full path )...
				previous = File.basename(Sketchup.template)

				# Pick one ...
				result = UI.inputbox(
  					['Choose template file '],
  					[ File.basename(previous) ],
  					[file_list.join('|')],
  					'Pick one ...'
				)
    end

    def open_manager
      @@manager_menu = MF_GRAYED
      UI.messagebox(__FILE__ + " open_manager")
      # create the WebDialog here...
      get_templates()
      @@manager_open = true
    end

    def on_close_manager
    UI.messagebox(__FILE__ + " on_close_manager")
      @@manager_open = false
      @@manager_menu = MF_ENABLED
    end

    unless @@menu_loaded
    UI.messagebox(__FILE__ + " menu_loaded not yet")
      # Always enable menu item, How ???
      # By using an AppObserver object, this module will do.
      Sketchup.add_observer(self) # (self is this module)
    end

  end
end

Yes, it is __FILE__ and __LINE__.

And from the Kernel module, the global method __method__.
You should also understand caller, and caller_locations and the Thread::Backtrace::Location class.

Do not use modal messageboxes to debug code. Open the Console and use puts calls.

Try a timer then ā€¦

UI.start_timer(1.0,false) { Sketchup.remove_observer(self) }

ā€¦ this would allow the observer callback to return before the observer itself is removed from the applicationā€™s observer queue.

About puts, I knew, but then the only way I (know) can use the console is to disable MyPlugin open the console and then enable MyPlugin, but then the load order with other pluginā€™s are different. So the ui.message is easy when directly from the start with the plugiin always enabled.

Also because of the pause, by not quickly dismissing the dialog, I notice the time needed by the observer.

Hmm, maybe there is SU.command to open the console. Bu that is for tomorrow.

The timer works, perfect thank you.

Good night

@eneroth3 has a auto console opener plugin somewhere.

Aha, this becomes bed reading :wink:

I found this from @DanRathbun (and others):

https://groups.google.com/forum/#!topic/sketchupruby/kplzdNOyclM

Yes, that is 8 years old, but it still works for all SketchUp versions ā€¦

Sketchup.send_action("showRubyPanel:")

ā€¦ whereas ā€¦

SKETCHUP_CONSOLE.show

ā€¦ will only work for SketchUp 2014 and later.

So you could use ā€¦

SKETCHUP_CONSOLE.show rescue Sketchup.send_action("showRubyPanel:")

ā€¦ to cover all possibilities.

:wink:

1 Like

Great tip, merci beaucoup. Gives extra info.

Is there a serious book about the inā€™s and outā€™s of Skechtup and Layout ( with development in mind )? Not about ruby but specific SU. I did see happily that Layout can accept plugins, but very less information or samples?

Not ā€œliveā€ plugins yet. LayOut does not have a Ruby subprocess (yet.)

We can only read and write to .layout files from within SketchUpā€™s Ruby, ā€¦ or from 3rd party C applications.

See the Books list and itā€™s ā€œSketchUp Specificā€ section of my WikiLists thread ā€¦

ā€¦ also see the official SketchUp book list ā€¦

I want to do the same for Layout. So far as I can see I can load the template names bij using a hardcoded path.

Anyway, when I do have a path to a LO template, it doesnā€™t load.
If I save a template.layout I canā€™t, read it wonā€™t, load in Layout.

This is the simplest code and copied from the docs.

doc2 = Layout::Document.new("/Users/dev/Library/Application Support/SketchUp 2018/LayOut/Templates/A1 Landscape.layout")
# doesn't work, I do get a ref pointer in the console	    

tfile = "/Users/anubis/Desktop/Untitled.layout"

puts("#{__method__} - Layout start loading")
doc = Layout::Document.open(tfile) 
# nothing get opened. I do get a ref pointer in the console
     
definitions = doc.auto_text_definitions
definitions.each { |auto_text|
puts("tag : #{auto_text.name}")
puts("name : #{auto_text.tag}")

#definitions.remove(auto_text) unless auto_text.mandatory?
}
puts("#{__method__} - Layout loading done??")

What do I wrong? I canā€™t find a doc.show command.

BTW In the mean time I use

system( "open '/Users/anubis/Desktop/Untitled.layout'")

Since I donā€™t have your files, I canā€™t say why your attempts to open it in the API donā€™t work. They work for me with my files. Maybe the problem is with what you expect from the methods #new and #open? These create a Layout::Document object instance within the current SketchUp Ruby session and provide access to it for manipulation. It is somewhat like the external SketchUp C SDK except embedded in the SketchUp Ruby API. They do not launch LayOut or open the file in LayOut itself. There is not (yet) any API method to launch LayOut and tell it to open a Document.

Just as an aside.

The following method call works on Windows to get a working path to the userā€™s LayOut templates folder.
Does it also work on Mac ?

Sketchup.find_support_file "../LayOut/Templates"
#=> C:/Users/Dan/AppData/Roaming/SketchUp/SketchUp 2016/SketchUp/../LayOut/Templates

This alos gives a working path to a Program Data distro templates folder ā€¦

Sketchup.find_support_file "../LayOut/templates/Paper"

Does it also work on Mac ?


doc2 = Layout::Document.new(
"/Users/dev/Library/Application Support/SketchUp 2018/LayOut/Templates/A1 Landscape.layout"
)

I donā€™t have a template named "A1 Landscape.layout", ā€¦ is this a custom template of yours ?


(Please use ```ruby tagline to start your code blocks.)

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.