Plugin Loading

The SketchApps plugin framework has several goals with respect to plugin loading. Specifically, SketchApps plugins should:

  • minimize plugin initialization overhead

  • minimize use of shared (eg, global) name spaces

  • support multiple modes of operation
    (eg, development, production, testing)

  • use shared resources (eg, directories, menus)
    in a convenient and cooperative fashion

Background

SketchUp expects plugins to be stored in a single directory. It loads the plugin files (in alphabetical order) at start-up. This approach has several drawbacks:

  • A single directory is expected to serve all users,
    allowing users' plugin-management decisions to conflict.

  • The directory's location is obscure and inconvenient;
    it may also have access-control restrictions.

  • As plugins accumulate, start-up time increases
    and name collisions (eg, classes, files) may occur.

  • No convention exists for libraries, data files, etc.

SketchApps, in contrast, allows each SketchUp user to maintain an independent tree of plugins and supporting files. A set of layout and naming conventions prevents collisions and allows code (and coders!) to find libraries, plugins, etc.

The plugin framework minimizes load time, for its own plugins, by doing very little work until the plugin is actually used.

Because SketchUp's plugins share a common name space, definitions (eg, classes, constants, globals, modules) can collide. The plugin framework minimizes its use of the global name space and ensures that each plugin has an anonymous top-level class.

Implementation

The plugin framework adds a "loader" plugin (load_sketchapps.rb) to SketchUp's plugins directory. This plugin traverses the user's SketchApps file tree, loading plugins, then sets up a sorted tree of menu items.

To make this work, however, each plugin must make explicit use of the framework. Here is some typical plugin code, taken from the "Draw Ruby 2 (ERb)" example:

$sketchapps.config[:cfcl_dr] && class Draw_Ruby_2_ERb
  attr_reader :dr2_opts

  def main(args=nil)
    $sketchapps.trace_me('Draw_Ruby_2_ERb  main') #T

    dr1_lib   = 'CFCL/Public/Plugin/Code/Draw_Ruby_1/support/lib'
    my_libs   = [ [ dr1_lib, :dr1_misc ], :dr2_erb_misc ]
    my_mods   = [            :DR1_Misc,   :DR2_ERb_Misc ]

    $sketchapps.setup_libs(self, my_libs, my_mods, __FILE__)

    setup
    @pf.log.info 'Draw_Ruby_2_ERb'
    setup_ui('dr2_erb_help.rb')
  end

  menu_path   = [ 'Plugins', 'SketchApps', 'CFCL',
                  'Toys', 'Draw Ruby 2 (ERb)' ]
  $sketchapps.register_menu(self, menu_path)
end

The code above is concise, but quite a bit is happening. So, a code walkthrough is definitely in order.

Loading

After assorted initialization tasks (eg, loading sa_config.rb, setting up logging support), load_sketchapps.rb reads and loads (ie, executes) this plugin file. A bit of Kernel.load trickery lets us avoid adding the Draw_Ruby_2_ERb class (etc) to the global namespace:

If the optional wrap parameter is true, the loaded script will be executed under an anonymous module, protecting the calling program's global namespace.

"Programming Ruby", Dave Thomas

Registration

If $sketchapps.config[:cfcl_dr] is set (by sa_config.rb), Draw_Ruby_2_ERb is defined (in an anonymous module) and registered with SketchApps. Specifically, the plugin's class definition code makes a call to register_menu, handing it the class (self) and the desired menu_path.

After all of the plugins have been loaded, load_sketchapps.rb uses the information to create organized sets of menu items and/or tools. So, for example, this plugin would appear in a sub-menu containing other CFCL toys.

Invocation

This file is simply a placeholder for the "real" plugin code, so it is small and loads very quickly. The real code (contained in dr1_misc.rb and dr2_erb_misc.rb) isn't loaded unless the user invokes the plugin (eg, by selecting its menu item).

If and when the plugin is invoked, the class is instantiated and main is run (args may be used to pass arguments from another plugin). After setting up any needed libraries and modules, main calls setup and setup_ui, which set up generic and user interface support.


This wiki page is maintained by Rich Morin, an independent consultant specializing in software design, development, and documentation. Please feel free to email comments, inquiries, suggestions, etc!

Topic revision: r8 - 21 Oct 2012, RichMorin
This site is powered by Foswiki Copyright © by the contributing authors. All material on this wiki is the property of the contributing authors.
Foswiki version v2.1.6, Release Foswiki-2.1.6, Plugin API version 2.4
Ideas, requests, problems regarding CFCL Wiki? Send us email