Module: Ruber::GuiStatesHandler
- Included in:
- MainWindow, OutputWidget
- Defined in:
- lib/ruber/gui_states_handler.rb
Overview
Module which provides a mechanism to enable/disable actions basing on whether some ‘states’ are true or false. This functionality is similar to that provided by the KDE XML GUI framework, but much more flexible.
A state is simply a string to which a true or false value is associated. For example, the value associated with a state called “current_document_modified” should be set to true whenever the current document becomes modified and to false when it’s saved. Through the rest of this documentation, the expression the value of the state will mean the true or false value associated with the state.
The system works this way: an action is registered using the register_action_handler method. To do so, a block (called a handler) and a list of states the action depends on are supplied.
The value of a state is modified using the change_state method. That method will call the handlers of every action depending on the changed state, passing it a list of all known states, and enables or disable them according to the value returned by the block.
Whenever this module is included in a class derived from Qt::Object, it will define a signal with the following signature ui_state_changed(QString, bool), which will be emitted from the state_changed method. The signal won’t be defined if the module extends an object (even if it is Qt::Object).
Note: before using any of the functionality provided by this module, you must call the initialize_states_handler method. This is usually done in the initialize method of the including class.
Defined Under Namespace
Classes: Data
Class Method Summary (collapse)
-
+ (Object) included(other)
Override of Module#included which is called whenever the module is included in another module or class.
Instance Method Summary (collapse)
-
- (Object) change_state(state, value)
(also: #set_state)
Sets the value associated with the state state to value, then calls the handlers of all actions depending on state and enables or disables them according to the returned value.
-
- (Object) initialize_states_handler
private
Initializes the instance variables used by the module.
-
- (Object) register_action_handler(action, states, options = {:check => true}, &blk)
Makes an action known to the system, telling it on which states it depends and which handler should be used to decide whether the action should be enabled or not.
-
- (Object) remove_action_handler_for(action, extra_id = nil)
Remove the existing handlers for actions matching action and extra_id.
-
- (Object) state(name)
(also: #gui_state)
Returns the value associated with the state name.
Class Method Details
+ (Object) included(other)
Override of Module#included which is called whenever the module is included in another module or class.
If other is a class derived from Qt::Object, it defines the ui_state_changed(QString, bool) signal.
67 68 69 |
# File 'lib/ruber/gui_states_handler.rb', line 67 def self.included other other.send :signals, 'ui_state_changed(QString, bool)' if other.ancestors.include?(Qt::Object) end |
Instance Method Details
- (Object) change_state(state, value) Also known as: set_state
Sets the value associated with the state state to value, then calls the handlers of all actions depending on state and enables or disables them according to the returned value. If self is an instance of Qt::Object, it also emits the ui_state_changed(QString, bool) signal, passing state and value (converted to bool) as arguments.
state can be either a string or symbol (in this case, it’ll be converted to string). value can be any value. It will be converted to true or false according to the usual ruby rules before being used.
198 199 200 201 202 203 204 205 206 |
# File 'lib/ruber/gui_states_handler.rb', line 198 def change_state state, value state = state.to_s value = value.to_bool @gui_state_handler_states[state] = value @gui_state_handler_handlers[state].each do |d| d.action.enabled = d.handler.call @gui_state_handler_states end emit ui_state_changed state, value if self.is_a?(Qt::Object) end |
- (Object) initialize_states_handler (private)
Initializes the instance variables used by the module. It must be called before any other method in the module is used.
224 225 226 227 |
# File 'lib/ruber/gui_states_handler.rb', line 224 def initialize_states_handler @gui_state_handler_states = {} @gui_state_handler_handlers = Hash.new{|h, k| h[k] = []} end |
- (Object) register_action_handler(action, states, options = {:check => true}, &blk)
Makes an action known to the system, telling it on which states it depends and which handler should be used to decide whether the action should be enabled or not.
action is a Qt::Action or derived object. states is an array of strings and/or symbols or a single string or symbol. Each string/symbol represents the name of a state action depends on (that is, a state whose value concurs in deciding whether action should be enabled or not).
blk is the handler associated with action. It takes a single argument, which will be a hash having the names of the states as keys and their values as values, and returns a true value if, basing on the values of the states, action should be enabled and a false value if it shouldn’t.
option contains some options. One is :check: if true, the handler will be called (and the action enabled or disabled) immediately after registering it; if it’s false, nothing will be done until one of the states in states changes. The other option is :extra_id. If not nil, it is an extra value used to identify the action (see remove_action_handler_for for more information).
If the block is not given and states is a string, a symbol or an array with only one element, then a default handler is generated (if states is an array with more than one element, ArgumentError is raised). The default handler returns the same value as the state value. If the only state starts with a !, instead, the leading exclamation mark is removed from the name of the state and the generated handler returns the opposite of the state value (that is, returns true if the state is false and vice versa).
Note: even if states can be specified as symbols, they’re actually always converted to strings.
====Examples
In all the following examples, action_handler is an instance of a class which includes this module.
This registers an handler for an action which depends on the two states ‘a’ and ‘b’. The action should be enabled when ‘a’ is true and ‘b’ is false or when ‘a’ is false, regardless of ‘b’.
action_handler.register_action_handler KDE::Action.new(nil), [‘a’, ‘b’] do |states| if states[‘a’] and !states[‘b’] then true elsif !states[‘a’] then true else false end endThis registers an action depending only on the state ‘a’ which should be enabled when ‘a’ is true and disabled when ‘a’ is false.
action_handler.register_action_handler KDE::Action.new(nil), [‘a’] do |states| states[‘a’] endHere we could also have passed simply the string ‘a’ as second argument. Even easier, we could have omitted the block, relying on the default handler that would have been generated: action_handler.register_action_handler KDE::Action.new(nil), ‘a’
Here, still using the default handler, register an handler for an action which depends only on the state ‘a’ but needs to be enabled when ‘a’ is false and disabled when it’s true. action_handler.register_action_handler KDE::Action.new(nil), ‘!a’
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/ruber/gui_states_handler.rb', line 136 def register_action_handler action, states, = {:check => true}, &blk states = Array(states) states = states.map &:to_s if !blk and states.size > 1 raise ArgumentError, "If more than one state is supplied, a block is needed" elsif !blk if states[0].start_with? '!' states[0] = states[0][1..-1] blk = Proc.new{|s| !s[states[0]]} else blk = Proc.new{|s| s[states[0]]} end end data = Data.new(action, blk, [:extra_id]) states.each{|s| @gui_state_handler_handlers[s.to_s] << data} if [:check] action.enabled = blk.call @gui_state_handler_states end end |
- (Object) remove_action_handler_for(action, extra_id = nil)
Remove the existing handlers for actions matching action and extra_id.
action may be either a Qt::Action or a string. If it is a Qt::Action, then only the handlers for that object will be removed (actually, there usually is only one handler).
If action is a string, all handlers for actions whose object_name is action will be removed. In this case, the extra_id parameter can be used narrow the list of actions to remove (for example, if there are more than one action with the same name but different extra_ids). If extra_id isn’t nil, then only actions whose object_name is action and which were given an extra_id equal to extra_id will be removed.
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/ruber/gui_states_handler.rb', line 170 def remove_action_handler_for action, extra_id = nil if action.is_a? KDE::Action @gui_state_handler_handlers.each_value do |v| v.delete_if{|d| d.action.same? action} end elsif extra_id @gui_state_handler_handlers.each_value do |v| v.delete_if{|d| d.action.object_name == action and d.extra_id == extra_id} end else @gui_state_handler_handlers.each_value do |v| v.delete_if{|d| d.action.object_name == action} end end @gui_state_handler_handlers.delete_if{|k, v| v.empty?} end |
- (Object) state(name) Also known as: gui_state
Returns the value associated with the state name_. If the value of the state has never been set using changestate, nil will be returned.
213 214 215 |
# File 'lib/ruber/gui_states_handler.rb', line 213 def state name @gui_state_handler_states[name.to_s] end |