Module: Clevic::ActionBuilder
- Included in:
- TableView
- Defined in:
- lib/clevic/action_builder.rb,
lib/clevic/qt/action_builder.rb,
lib/clevic/swing/action_builder.rb
Overview
This module is included in a class to make the construction of collections of actions more rubyish. It must have
- an add_action method
- separator, which returns something which is_a? Separator
- create_action( &block ), which creates an Action object
- action_method_or_block( action, options, &block ) which handles events
Menus are generally made up of a collection of actions.
Once included, it’s intended to be called as follows:
def some_setup_method_or_other
build_actions do
list :edit do
#~ new_action :action_cut, 'Cu&t', :shortcut => Qt::KeySequence::Cut
action :action_copy, '&Copy', :shortcut => Qt::KeySequence::Copy, :method => :copy_current_selection
action :action_paste, '&Paste', :shortcut => Qt::KeySequence::Paste, :method => :paste
separator
action :action_ditto, '&Ditto', :shortcut => 'Ctrl+\'', :method => :ditto, :tool_tip => 'Copy same field from previous record'
action :action_ditto_right, 'Ditto R&ight', :shortcut => 'Ctrl+]', :method => :ditto_right, :tool_tip => 'Copy field one to right from previous record'
action :action_ditto_left, '&Ditto L&eft', :shortcut => 'Ctrl+[', :method => :ditto_left, :tool_tip => 'Copy field one to left from previous record'
action :action_insert_date, 'Insert Date', :shortcut => 'Ctrl+;', :method => :insert_current_date
action :action_open_editor, '&Open Editor', :shortcut => 'F4', :method => :open_editor
separator
action :action_row, 'New Ro&w', :shortcut => 'Ctrl+N', :method => :row
action :action_refresh, '&Refresh', :shortcut => 'Ctrl+R', :method => :refresh
action :action_delete_rows, 'Delete Rows', :shortcut => 'Ctrl+Delete', :method => :delete_rows
if $options[:debug]
action :action_dump, 'D&ump', :shortcut => 'Ctrl+Shift+D' do
puts model.collection[current_index.row].inspect
end
end
end
separator
end
end
Or you can pass a parameter to the block if you need access to surrounding variables:
build_actions do |ab|
ab.list :edit do
#~ new_action :action_cut, 'Cu&t', :shortcut => Qt::KeySequence::Cut
ab.action :action_copy, '&Copy', :shortcut => Qt::KeySequence::Copy, :method => :copy_current_selection
end
end
If the including class defines a method called action_triggered( &block ), it can be used to wrap the code triggered by actions. That way, the including class can catch exceptions and things like that.
def action_triggered( &block )
catch :something_happened do
yield
end
end
If this method is not defined, it will be created in the including class as an empty wrapper.
Class Method Summary collapse
-
.included(including_module) ⇒ Object
raise a RuntimeError if the including class/module does not define add_action.
Instance Method Summary collapse
-
#action(name_or_action, text = nil, options = {}, &block) ⇒ Object
Create a new Action and 1.
-
#action_method_or_block(action, options, &block) ⇒ Object
set up the code to be executed when an action is triggered,.
-
#build_actions(&block) ⇒ Object
Outer block for the build process.
- #create_action(&block) ⇒ Object
-
#create_key_sequence(sequence) ⇒ Object
TODO move this into Action, like the swing adapter.
- #group_names ⇒ Object
-
#list(group_name) {|_self| ... } ⇒ Object
Create and return a list of actions.
-
#separator ⇒ Object
Create a new separator and add a new separator.
Class Method Details
.included(including_module) ⇒ Object
raise a RuntimeError if the including class/module does not define add_action
61 62 63 64 65 66 67 68 |
# File 'lib/clevic/action_builder.rb', line 61 def self.included( including_module ) shortlist = including_module.instance_methods.grep /action/i # add_action is actually an method_missing lookup for addAction, so # search for both. unless shortlist.any? {|x| %w{add_action addAction}.include?( x )} raise NotImplementedError, "#{including_module.class.name} must have an add_action method" end end |
Instance Method Details
#action(name_or_action, text = nil, options = {}, &block) ⇒ Object
Create a new Action and
-
pass it to add_action
-
add it to the collect_actions collection.
The block takes predence over options, which is a method on self to be called. Option keys can be any method in Action, ie :tool_tip, :shortcut, :status_tip etc. A value for :shortcut is automatically passed to create_key_sequence
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/clevic/action_builder.rb', line 114 def action( name_or_action, text = nil, = {}, &block ) if name_or_action.is_a? Action add_action( name_or_action ) else name = name_or_action if .has_key?( :method ) && !block.nil? raise "you can't specify both :method and a block" end create_action do |action| action.name = name.to_s action.text = text .each do |k,v| next if k == :method if k == :shortcut action.shortcut = v else action.send( "#{k.to_s}=", v ) end end # add action add_action action # add actions for list. Yes, it's a side-effect. # TODO is there a better way to do this? collect_actions << action action_method_or_block( action, , &block ) end end end |
#action_method_or_block(action, options, &block) ⇒ Object
set up the code to be executed when an action is triggered,
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/clevic/qt/action_builder.rb', line 23 def action_method_or_block( qt_action, , &block ) signal_name = "triggered(#{.has_key?( :checkable ) ? 'bool' : ''})" # connect the action to some code if .has_key?( :method ) qt_action.connect SIGNAL( signal_name ) do |active| action_triggered do send_args = [ [:method], .has_key?( :checkable ) ? active : nil ].compact send( *send_args ) end end else unless block.nil? action_triggered do qt_action.connect SIGNAL( signal_name ) do |active| # need this rescue here because otherwise Qt # doesn't catch it and the whole app comes down begin yield( active ) rescue # TODO how to display this in the UI? puts $!. puts $!.backtrace end end end end end end |
#build_actions(&block) ⇒ Object
Outer block for the build process.
71 72 73 74 75 76 77 78 |
# File 'lib/clevic/action_builder.rb', line 71 def build_actions( &block ) raise 'a block must be present' if block.nil? if block.arity == -1 instance_eval &block else yield self end end |
#create_action(&block) ⇒ Object
13 14 15 |
# File 'lib/clevic/qt/action_builder.rb', line 13 def create_action( &block ) Qt::Action.new( parent, &block ) end |
#create_key_sequence(sequence) ⇒ Object
TODO move this into Action, like the swing adapter
18 19 20 |
# File 'lib/clevic/qt/action_builder.rb', line 18 def create_key_sequence( sequence ) Qt::KeySequence.new( sequence ) end |
#group_names ⇒ Object
80 81 82 |
# File 'lib/clevic/action_builder.rb', line 80 def group_names @group_names ||= [] end |
#list(group_name) {|_self| ... } ⇒ Object
Create and return a list of actions. The actions are grouped together, ie live together on the menu with a separator between groups. A method called “#group_name_actions” will be added to self, which will return the set of framework-specific Action instances created in the block.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/clevic/action_builder.rb', line 88 def list( group_name, &block ) @group_name = group_name group_names << group_name unless respond_to?( "#{group_name.to_s}_actions" ) self.class.send( :define_method, "#{group_name.to_s}_actions" ) do eval "@#{group_name.to_s}_actions" end end self.collect_actions = [] yield( self ) # copy actions to the right instance variable eval "@#{group_name.to_s}_actions = collect_actions" # reset these, just for cleanliness @group_name = nil self.collect_actions = [] end |