SketchUp插件开发(二十)完整的插件——更好的工具管理

在我们的工具管理类ToolManager中,创建工具条的代码有很多是重复的。每一个工具条的按钮的创建都经过了下面几个步骤

  1. 加载工具类
  2. 创建工具对象
  3. 创建工具激活命令对象
  4. 添加工具激活命令到工具条中

其中的创建工具激活命令对象,可以很复杂,例如设置图标、提示文本、状态栏文本等。

如果对这些操作进行简单分类,可以把创建工具激活命令对象提取出来放到每个工具中来做,包括创建命令对象、设置图标等。因为每个工具应该知道自己应该表现成什么样的按钮,这属于“个体”内容。工具管理对象则不需要关注这些,它只处理创建几个什么名字的工具条,工具应该添加到哪个工具条的什么位置就可以了,这属于“群体”内容。因此,我们可以把工具类和工具管理类改造一下,使我们添加工具可以更方便灵活。

工具类

工具类的改造主要涉及两部分内容:

  1. 创建工具激活命令对象
  2. 个性化图标和提示文本

工具管理类中应该只关注工具创建的命令对象,为了统一处理,我们应该在工具中添加一个共同的接口来获取工具的命令对象,这可以通过ruby的混入模块或类继承来实现,为了灵活,我们这里使用混入模块的方式。首先,需要定义一个工具命令的模块,模块中实现一个方法用于创建工具激活命令对象。

# 工具命令模块
module ToolCommand
  # 获取SketchUp命令
  def command
    cmd = UI::Command.new('工具名称') do
      Sketchup.active_model.select_tool(self)
    end
  end
end

然后在每个工具中混入该模块使每个工具都有command方法来创建激活自身的命令

require 'free_wall/tool/tool_command'
class DrawWallTool
  include ToolCommand
...

对于一个完整的插件来说,工具应该都自己的图标、提示文本等个性化的信息,所以我们应该在创建命令的时候把这些信息都设置好,而这些信息则应该在每个工具中来定义。

class DrawWallTool
  include ToolCommand

  def initialize
    @menu_text = '画墙工具'
    @large_icon = File.join(File.dirname(__dir__), 'resource/img/draw_wall_tool.jpg')
    @small_icon = File.join(File.dirname(__dir__), 'resource/img/draw_wall_tool.jpg')
    @status_bar_text = '画墙工具'
    @tooltip = '绘制线生成一堵墙'
  end
...

然后在创建命令时统一应用这些信息

def command
  menu_text = @menu_text ? @menu_text : '未命名工具'
  cmd = UI::Command.new(menu_text) do
    Sketchup.active_model.select_tool(self)
  end
  cmd.large_icon = @large_icon if @large_icon
  cmd.small_icon = @small_icon if @small_icon
  cmd.status_bar_text = @status_bar_text if @status_bar_text
  cmd.tooltip = @tooltip if @tooltip
  cmd
end

这样,我们就可以创建出针对工具的个性化的命令,在添加到工具条时就可以看到不同的工具有不同的显示效果。

工具管理类

加载定义

工具管理类中首先要加载工具类的定义,由于我们的工具都定义在tool目录下,所以实际上我们可以遍历该目录来加载所有的ruby文件。

tool_dir = File.join(__dir__, 'tool')
Dir.entries(tool_dir).each { |file|
  file_path = File.join(tool_dir, file)
  next unless File.file?(file_path)
  require(file_path)
}

之后,我们应该定义出创建的工具条名称以及工具条中应该如何布局具体的工具,这实际可以通过一个哈希表来定义

TOOLBAR_LIST = { '墙工具条' => [DrawWallTool, CreateHoleTool] }.freeze

key为工具条名称,value为工具列表。这样就可以通过一次遍历,创建出所有的工具。
其中的工具列表中还可以添加特殊元素来标记为分隔符,比如在以上两个工具之间添加一个nil元素,在遍历创建工具按钮时,如果遇到nil元素,则创建分隔符。

# 创建工具条
def create_toolbar
  TOOLBAR_LIST.each { |name, tools_klass|
    tool_bar = UI::Toolbar.new(name)
    tools_klass.each { |tool_klass|
      if tool_klass
        tool = tool_klass.new
        tool_bar.add_item(tool.command)
      else
        tool_bar.add_separator
      end
    }
  }
end

如果想要在创建工具条时,对点击按钮的行为进行控制,还可以把创建工具时激活工具的命令替换成对块的执行,在创建工具条获取工具命令的时候再添加具体的行为

...
cmd = UI::Command.new(menu_text) do
  yield
end
...

...
cmd = tool.command {
  Sketchup.active_model.select_tool(tool)
}
...

经过这样的改造,在添加新工具时,只需要把新工具的类定义添加到TOOLBAR_LIST中特定工具条的特定位置即可。而且即使是同一个工具,我们也可以添加到不同的工具条中,在每个工具条中的行为都可以进行控制。

你可能感兴趣的:(SketchUp插件开发)