Module: Glimmer::LibUI::CustomControl

Includes:
DataBinding::ObservableModel, SuperModule
Included in:
CodeArea, RefinedTable, CustomWindow
Defined in:
lib/glimmer/libui/custom_control.rb,
lib/glimmer/libui/custom_control/code_area.rb,
lib/glimmer/libui/custom_control/refined_table.rb

Defined Under Namespace

Modules: GlimmerSupersedable Classes: CodeArea, RefinedTable

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



188
189
190
# File 'lib/glimmer/libui/custom_control.rb', line 188

def args
  @args
end

#body_rootObject (readonly)

Returns the value of attribute body_root.



188
189
190
# File 'lib/glimmer/libui/custom_control.rb', line 188

def body_root
  @body_root
end

#content(&block) ⇒ Object (readonly)

Returns content block if used as an attribute reader (no args) Otherwise, if a block is passed, it adds it as content to this custom control



239
240
241
# File 'lib/glimmer/libui/custom_control.rb', line 239

def content
  @content
end

#keywordObject (readonly)

Returns the value of attribute keyword.



188
189
190
# File 'lib/glimmer/libui/custom_control.rb', line 188

def keyword
  @keyword
end

#libuiObject (readonly)

Returns the value of attribute libui.



188
189
190
# File 'lib/glimmer/libui/custom_control.rb', line 188

def libui
  @libui
end

#optionsObject (readonly)

Returns the value of attribute options.



188
189
190
# File 'lib/glimmer/libui/custom_control.rb', line 188

def options
  @options
end

#parentObject (readonly)

Returns the value of attribute parent.



188
189
190
# File 'lib/glimmer/libui/custom_control.rb', line 188

def parent
  @parent
end

#parent_proxyObject (readonly)

Returns the value of attribute parent_proxy.



188
189
190
# File 'lib/glimmer/libui/custom_control.rb', line 188

def parent_proxy
  @parent_proxy
end

Class Method Details

.add_custom_control_namespaces_for(klass) ⇒ Object



115
116
117
118
119
# File 'lib/glimmer/libui/custom_control.rb', line 115

def add_custom_control_namespaces_for(klass)
  Glimmer::LibUI::CustomControl.namespaces_for_class(klass).drop(1).each do |namespace|
    Glimmer::LibUI::CustomControl.custom_control_namespaces << namespace
  end
end

.after_body(&block) ⇒ Object



183
184
185
# File 'lib/glimmer/libui/custom_control.rb', line 183

def after_body(&block)
  @after_body_block = block
end

.before_body(&block) ⇒ Object



175
176
177
# File 'lib/glimmer/libui/custom_control.rb', line 175

def before_body(&block)
  @before_body_block = block
end

.body(&block) ⇒ Object



179
180
181
# File 'lib/glimmer/libui/custom_control.rb', line 179

def body(&block)
  @body_block = block
end

.custom_control_namespacesObject



129
130
131
# File 'lib/glimmer/libui/custom_control.rb', line 129

def custom_control_namespaces
  @custom_control_namespaces ||= reset_custom_control_namespaces
end

.def_option_attr_accessors(new_options) ⇒ Object



161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/glimmer/libui/custom_control.rb', line 161

def def_option_attr_accessors(new_options)
  new_options.each do |option, default|
    class_eval <<-end_eval, __FILE__, __LINE__
      def #{option}
        options[:#{option}]
      end
      
      def #{option}=(option_value)
        self.options[:#{option}] = option_value
      end
    end_eval
  end
end

.flyweight_custom_control_classesObject

Flyweight Design Pattern memoization cache. Can be cleared if memory is needed.



101
102
103
# File 'lib/glimmer/libui/custom_control.rb', line 101

def flyweight_custom_control_classes
  @flyweight_custom_control_classes ||= {}
end

.for(keyword) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/glimmer/libui/custom_control.rb', line 67

def for(keyword)
  unless flyweight_custom_control_classes.keys.include?(keyword)
    begin
      extracted_namespaces = keyword.
        to_s.
        split(/__/).map do |namespace|
          namespace.camelcase(:upper)
        end
      custom_control_namespaces.each do |base|
        extracted_namespaces.reduce(base) do |result, namespace|
          if !result.constants.include?(namespace)
            namespace = result.constants.detect {|c| c.to_s.upcase == namespace.to_s.upcase } || namespace
          end
          begin
            flyweight_custom_control_classes[keyword] = constant = result.const_get(namespace)
            return constant if constant.ancestors.include?(Glimmer::LibUI::CustomControl)
            flyweight_custom_control_classes[keyword] = constant
          rescue => e
            # Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
            flyweight_custom_control_classes[keyword] = result
          end
        end
      end
      raise "#{keyword} has no custom control class!"
    rescue => e
      Glimmer::Config.logger.debug {e.message}
      Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
      flyweight_custom_control_classes[keyword] = nil
    end
  end
  flyweight_custom_control_classes[keyword]
end

.keywordObject

Returns keyword to use for this custom control



106
107
108
# File 'lib/glimmer/libui/custom_control.rb', line 106

def keyword
  self.name.underscore.gsub('::', '__')
end

.namespaces_for_class(m) ⇒ Object



121
122
123
124
125
126
127
# File 'lib/glimmer/libui/custom_control.rb', line 121

def namespaces_for_class(m)
  return [m] if m.name.nil?
  namespace_constants = m.name.split(/::/).map(&:to_sym)
  namespace_constants.reduce([Object]) do |output, namespace_constant|
    output += [output.last.const_get(namespace_constant)]
  end[1..-1].uniq.reverse
end

.option(new_option, default: nil) ⇒ Object



154
155
156
157
158
159
# File 'lib/glimmer/libui/custom_control.rb', line 154

def option(new_option, default: nil)
  new_option = new_option.to_s.to_sym
  new_options = {new_option => default}
  @options = options.merge(new_options)
  def_option_attr_accessors(new_options)
end

.options(*new_options) ⇒ Object

Allows defining convenience option accessors for an array of option names Example: ‘options :color1, :color2` defines `#color1` and `#color2` where they return the instance values `options` and `options` respectively. Can be called multiple times to set more options additively. When passed no arguments, it returns list of all option names captured so far



143
144
145
146
147
148
149
150
151
152
# File 'lib/glimmer/libui/custom_control.rb', line 143

def options(*new_options)
  new_options = new_options.compact.map(&:to_s).map(&:to_sym)
  if new_options.empty?
    @options ||= {} # maps options to defaults
  else
    new_options = new_options.reduce({}) {|new_options_hash, new_option| new_options_hash.merge(new_option => nil)}
    @options = options.merge(new_options)
    def_option_attr_accessors(new_options)
  end
end

.reset_custom_control_namespacesObject



133
134
135
# File 'lib/glimmer/libui/custom_control.rb', line 133

def reset_custom_control_namespaces
  @custom_control_namespaces = Set[Object, Glimmer::LibUI]
end

.shortcut_keywordObject

Returns shortcut keyword to use for this custom control (keyword minus namespace)



111
112
113
# File 'lib/glimmer/libui/custom_control.rb', line 111

def shortcut_keyword
  self.name.underscore.gsub('::', '__').split('__').last
end

Instance Method Details

#can_handle_listener?(listener) ⇒ Boolean

Returns:

  • (Boolean)


220
221
222
# File 'lib/glimmer/libui/custom_control.rb', line 220

def can_handle_listener?(listener)
  body_root&.can_handle_listener?(listener.to_s)
end

#handle_listener(listener, &block) ⇒ Object



224
225
226
# File 'lib/glimmer/libui/custom_control.rb', line 224

def handle_listener(listener, &block)
  body_root.handle_listener(listener.to_s, &block)
end

#has_instance_method?(method_name) ⇒ Boolean

This method ensures it has an instance method not coming from Glimmer DSL

Returns:

  • (Boolean)


229
230
231
232
233
234
235
# File 'lib/glimmer/libui/custom_control.rb', line 229

def has_instance_method?(method_name)
  respond_to?(method_name) and
    !@body_root.respond_to_libui?(method_name) and
    (method(method_name) rescue nil) and
    !method(method_name)&.source_location&.first&.include?('glimmer/dsl/engine.rb') and
    !method(method_name)&.source_location&.first&.include?('glimmer/libui/control_proxy.rb')
end

#initialize(keyword, parent, args, options, &content) ⇒ Object

Raises:

  • (Glimmer::Error)


190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/glimmer/libui/custom_control.rb', line 190

def initialize(keyword, parent, args, options, &content)
  @parent_proxy = @parent = parent
  options ||= {}
  @options = self.class.options.merge(options)
  @content = ProcTracker.new(content) if content
  execute_hook('before_body')
  body_block = self.class.instance_variable_get("@body_block")
  raise Glimmer::Error, 'Invalid custom control for having no body! Please define body block!' if body_block.nil?
  @body_root = instance_exec(&body_block)
  raise Glimmer::Error, 'Invalid custom control for having an empty body! Please fill body block!' if @body_root.nil?
  @libui = @body_root.libui
  execute_hook('after_body')
  # TODO deregister all observer_registrations on destroy of the control once that listener is supported
  # (on_destroy) unless it is the last window closing, in which case exit faster
  post_add_content if content.nil?
end

#observer_registrationsObject



216
217
218
# File 'lib/glimmer/libui/custom_control.rb', line 216

def observer_registrations
  @observer_registrations ||= []
end

#post_add_contentObject



212
213
214
# File 'lib/glimmer/libui/custom_control.rb', line 212

def post_add_content
  # No Op by default
end

#post_initialize_child(child) ⇒ Object

Subclasses may override to perform post initialization work on an added child



208
209
210
# File 'lib/glimmer/libui/custom_control.rb', line 208

def post_initialize_child(child)
  # No Op by default
end