[code] Passing a webdialog reference into an observer

Example:

Passing a webdialog reference into an observer, and
using that dialog reference to control the dialog’s visibility.

There is an issue that I left in, to show those learning the API. When the selection is changed from one item to another, it goes through an empty state, and the onBulkChange() callback gets called twice.

PassWebDialogRefToObserver.rb (4.4 KB)

# encoding: UTF-8
#
# Example: Passing a webdialog reference into an observer, and
# using that dialog reference to control the dialog's visibility.

module Author
  module SomePlugin

    extend self

    @@dialog = nil unless defined?(@@dialog)
    @@selection_spy = nil unless defined?(@@selection_spy)

    @@opts = {
      :dialog_title => "SelectionSwitch",
      :preferences_key => Module.nesting[0].name.split('::').join('_')<<"_SelectionSwitch",
      :scrollable => false,
      :resizable  => true,
      :width  => 150,
      :height => 150,
      :left   => 500,
      :top    => 500,
      :min_width  => 150,
      :min_height => 130,
      :max_width  => 200,
      :max_height => 200
    } unless defined?(@@opts)

    class SelectionSpy < Sketchup::SelectionObserver

      # Local constants:
      WIN =( Sketchup.platform == :platform_win rescue RUBY_PLATFORM !~ /darwin/i )

      def initialize(webdialog)
        # This method is called in the newly instantiated instance,
        # automatically by Ruby, just after the ::new() constructor
        # has created the instance object. Ruby passes in along
        # arguments that were given to the ::new() constructor.
        # It does not matter what this method returns, the ::new()
        # constructor always returns a reference to the new instance.
        @webdialog = webdialog
        # Initialize other instance variables here:
      end ###

      def show_my_dialog()
        if @webdialog.visible?
          @webdialog.bring_to_front
        else
          WIN ? @webdialog.show : @webdialog.show_modal
        end
      end ###

      def my_dialog_is_open?()
        if @webdialog.visible?
          UI.messagebox("The Webdialog is visible.")
          return true
        else
          UI.messagebox("The Webdialog is not open!")
          return false
        end
      end ###

      ### CALLBACK METHODS

      def onSelectionBulkChange(selection)
        if selection.size > 0
          show_my_dialog() if ! my_dialog_is_open?
        elsif selection.empty?
          @webdialog.close() if my_dialog_is_open?
        end
      end ###

      def onSelectionCleared(selection)
        @webdialog.close()
      end ###

    end # class SelectionSpy

    def dialog_init()
      #
      if @@dialog.nil? || ! @@dialog.is_a?(UI::WebDialog)

        @@dialog = UI::WebDialog.new(@@opts)

        @@dialog.add_action_callback("add_selection_spy") {

          if @@selection_spy.is_a?(SelectionSpy)
            Sketchup.active_model.selection.remove_observer(@@selection_spy)
          else
            @@selection_spy = SelectionSpy.new(@@dialog)
          end
          Sketchup.active_model.selection.add_observer(@@selection_spy)

        }

        @@dialog.add_action_callback("remove_selection_spy") {

          if !@@selection_spy.nil?
            if @@selection_spy.is_a?(SelectionSpy)
              Sketchup.active_model.selection.remove_observer(@@selection_spy)
            end
            @@selection_spy = nil
          end
        }

        @@dialog.set_html %q[
          <!DOCTYPE html>
          <html>
            <head>
              <meta name="MSThemeCompatible" content="yes">
              <script>
                function watch_selection() {
                  window.location.href="skp:add_selection_spy@"
                }
                function ignore_selection() {
                  window.location.href="skp:remove_selection_spy@"
                }
              </script>
              <style>
                body {
                  margin:  0px;
                  border:  0px;
                  padding: 0px;
                  margin-top:   16px;
                  margin-left:  16px;
                  margin-right: 16px;
                }
                div { width: 100%; margin-bottom: 16px; }
                input { width: 100% }
              </style>
            </head>
            <body>
              <div>
                <input type="button" onclick="watch_selection();"  value=" Watch Selection ">
              </div>
              <div>
                <input type="button" onclick="ignore_selection();" value=" Ignore Selection ">
              </div>
            </body>
          </html>
        ]

      end # if dialog init block
      #
      return @@dialog
      #
    end ### dialog_init()

    def get_dialog()
      @@dialog
    end ###

    # Call the dialog init method:
    dialog_init().show()

  end # this plugin module
end # toplevel namespace module