Skip to content

Adding items to the Redcar menus

Delisa Mason edited this page Aug 29, 2011 · 1 revision

If you want to add a menu item into the Redcar menu you can use the following API:

  • Use ‘group’ to logically group a set of items together and add some default properties to them. This has no visible effect on the final menu, it’s purely an aide for coders. The most obvious use for this is applying a :priority to many items/sub_menus at once, but it can be used with any :symbol option. For instance, you could use a group to apply a common :command or :type to a group of menu items.
  • Use ‘sub_menu’ to add a submenu. This works with hierarchies, that is if there’s a sub_menu inside another sub_menu, it will create a nested menu.
  • Use ‘item’ to add an item to the submenu. The API call is:
   item <name>, :command => <command handler>, :priority => <priority>, :type => [:check|:radio], :active => [true|false],
     :value => <options of command handler>

All symbol parameters are optional.

  • :command provides the command to run. You must provide either a :command or a block to execute.
  • :priority provides a method to order menus from different plugins. This value is an integer, or one of the symbols :first or :last. There is no practical upper or lower bound to priorities, other than what JRuby enforces. The lower the value, the higher the priority, and hence the higher in the menu the item appears. :first and :last allow you to force an item or group to the top or bottom of a menu. If more than one item shares a priority, they will be ordered in the same order they are defined. This is useful for using the group construct inside a single plugin, but shouldn’t be relied on between modules.
  • :type will create either Push item (regular item in the menu), Check item (checkbox selection) or Radio item (selection in the group). A submenu is automatically used as a group for Radio items.
  • :active will set the created item as active according to its type.
  • :value can be used to send something to the command handler.

In the following example we are going to create a new submenu, All Themes, that will allow us selecting a new theme from the list in the menu instead of the theme selection dialog. To do that, and following Contribution-Guidelines, we first create a new plugin, all_themes. In our plugin we’re going to add a submenu for all themes in Appearance submenu. So, go into the plugins/ folder, and create a new plugin:

 mkdir -p all_themes/lib/
 cd all_themes;
 redcar plugin.rb

Now, we first update our plugin.rb:
 Plugin.define do
   name    "all_themes"
   version "1.0"
   file    "lib", "all_themes"
   object  "Redcar::AllThemes"
   dependencies "textmate",  ">0"
 end

Now, let’s create the plugin itself:
 cd lib;
 redcar all_themes.rb

Enter the following:

module Redcar
  class AllThemes
  end
end

So first, we create a hook into the global menus. The hook is provided by implementing the self.menus call. So we add the following:
 def self.menus
      Menu::Builder.build do
      end
 end

Menu::Builder.build already provides the global menus, so all we need to do is to attach our submenu to the end of an existing Appearance menu:

 def self.menus
      Menu::Builder.build do
        sub_menu "View" do
          sub_menu "Appearance" do
            sub_menu "All Themes", :priority => :last do
            end
          end
        end
      end
  end

Now, create the menu items:

          EditView.themes.sort.each do |theme|
            item theme, :command => AllThemes::ShowTheme, :value => theme, :type => :radio, :active => (theme == EditView.theme)
          end

In the example above, you can see the following:

  • First, EditView.themes.sort.each creates an alphabetically sorted list of all theme bundles that come with Redcar.
  • Second, for each element of list, an item is created. In that item, ShowTheme is the command handler, :value is the theme name, type is “Radio” (we only need one theme visually selected in the list), and :active will get true only when the theme name will match current theme. This will automatically select the current theme in the menu during the menu creation.

Now that we have created the menu, we need to take care the AllThemes::ShowTheme handler. So, create the following class for handling the menu selection:

 class ShowTheme < Command
    def execute(options)
      if options[:value]
        Redcar::EditView.theme=options[:value]
      end
    end
 end

In this class we have the following:
  • execute is being called by the Redcar when the menu item is clicked in our submenu.
  • execute is capable of receiving optional parameters.
  • if parameter is a hash with existing :value key (the one that is sent from created menu item), then we set the theme according to the hash value:
     Redcar::EditView.theme=options[:value]

So, our complete file is:

module Redcar
  class AllThemes

    def self.menus
      Menu::Builder.build do
        sub_menu "View" do
          sub_menu "Appearance" do
            sub_menu "All Themes", :priority => :last do
              group :command => AllThemes::ShowTheme, :type => :radio do
                EditView.themes.sort.each do |theme|
                  item theme, :value => theme, :active => (theme == EditView.theme)
                end
              end
            end
          end
        end
      end
    end

    class ShowTheme < Command
      def execute(options)
        if options[:value]
          Redcar::EditView.theme=options[:value]
        end
      end
    end

  end
end

That is all. Save all the files and run the redcar again.

Here’s the screenshot of the result: images/AllThemes.png

The code is available at http://github.com/alourie/redcar/tree/themes_menu