Module: Glimmer::LibUI::CustomShape

Includes:
DataBinding::ObservableModel, SuperModule
Defined in:
lib/glimmer/libui/custom_shape.rb

Defined Under Namespace

Modules: GlimmerSupersedable

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



186
187
188
# File 'lib/glimmer/libui/custom_shape.rb', line 186

def args
  @args
end

#body_rootObject (readonly)

Returns the value of attribute body_root.



186
187
188
# File 'lib/glimmer/libui/custom_shape.rb', line 186

def body_root
  @body_root
end

#content(*args, &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 shape



236
237
238
# File 'lib/glimmer/libui/custom_shape.rb', line 236

def content
  @content
end

#keywordObject (readonly)

Returns the value of attribute keyword.



186
187
188
# File 'lib/glimmer/libui/custom_shape.rb', line 186

def keyword
  @keyword
end

#optionsObject (readonly)

Returns the value of attribute options.



186
187
188
# File 'lib/glimmer/libui/custom_shape.rb', line 186

def options
  @options
end

#parentObject (readonly)

Returns the value of attribute parent.



186
187
188
# File 'lib/glimmer/libui/custom_shape.rb', line 186

def parent
  @parent
end

#parent_proxyObject (readonly)

Returns the value of attribute parent_proxy.



186
187
188
# File 'lib/glimmer/libui/custom_shape.rb', line 186

def parent_proxy
  @parent_proxy
end

Class Method Details

.add_custom_shape_namespaces_for(klass) ⇒ Object



113
114
115
116
117
# File 'lib/glimmer/libui/custom_shape.rb', line 113

def add_custom_shape_namespaces_for(klass)
  Glimmer::LibUI::CustomShape.namespaces_for_class(klass).drop(1).each do |namespace|
    Glimmer::LibUI::CustomShape.custom_shape_namespaces << namespace
  end
end

.after_body(&block) ⇒ Object



181
182
183
# File 'lib/glimmer/libui/custom_shape.rb', line 181

def after_body(&block)
  @after_body_block = block
end

.before_body(&block) ⇒ Object



173
174
175
# File 'lib/glimmer/libui/custom_shape.rb', line 173

def before_body(&block)
  @before_body_block = block
end

.body(&block) ⇒ Object



177
178
179
# File 'lib/glimmer/libui/custom_shape.rb', line 177

def body(&block)
  @body_block = block
end

.custom_shape_namespacesObject



127
128
129
# File 'lib/glimmer/libui/custom_shape.rb', line 127

def custom_shape_namespaces
  @custom_shape_namespaces ||= reset_custom_shape_namespaces
end

.def_option_attr_accessors(new_options) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/glimmer/libui/custom_shape.rb', line 159

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_shape_classesObject

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



99
100
101
# File 'lib/glimmer/libui/custom_shape.rb', line 99

def flyweight_custom_shape_classes
  @flyweight_custom_shape_classes ||= {}
end

.for(keyword) ⇒ Object



65
66
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
# File 'lib/glimmer/libui/custom_shape.rb', line 65

def for(keyword)
  unless flyweight_custom_shape_classes.keys.include?(keyword)
    begin
      extracted_namespaces = keyword.
        to_s.
        split(/__/).map do |namespace|
          namespace.camelcase(:upper)
        end
      custom_shape_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_shape_classes[keyword] = constant = result.const_get(namespace)
            return constant if constant.ancestors.include?(Glimmer::LibUI::CustomShape)
            flyweight_custom_shape_classes[keyword] = constant
          rescue => e
            # Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
            flyweight_custom_shape_classes[keyword] = result
          end
        end
      end
      raise "#{keyword} has no custom shape class!"
    rescue => e
      Glimmer::Config.logger.debug {e.message}
      Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
      flyweight_custom_shape_classes[keyword] = nil
    end
  end
  flyweight_custom_shape_classes[keyword]
end

.keywordObject

Returns keyword to use for this custom shape



104
105
106
# File 'lib/glimmer/libui/custom_shape.rb', line 104

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

.namespaces_for_class(m) ⇒ Object



119
120
121
122
123
124
125
# File 'lib/glimmer/libui/custom_shape.rb', line 119

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



152
153
154
155
156
157
# File 'lib/glimmer/libui/custom_shape.rb', line 152

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



141
142
143
144
145
146
147
148
149
150
# File 'lib/glimmer/libui/custom_shape.rb', line 141

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_shape_namespacesObject



131
132
133
# File 'lib/glimmer/libui/custom_shape.rb', line 131

def reset_custom_shape_namespaces
  @custom_shape_namespaces = Set[Object, Glimmer::LibUI]
end

.shortcut_keywordObject

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



109
110
111
# File 'lib/glimmer/libui/custom_shape.rb', line 109

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

Instance Method Details

#can_handle_listener?(listener) ⇒ Boolean

Returns:

  • (Boolean)


217
218
219
# File 'lib/glimmer/libui/custom_shape.rb', line 217

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

#handle_listener(listener, &block) ⇒ Object



221
222
223
# File 'lib/glimmer/libui/custom_shape.rb', line 221

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)


226
227
228
229
230
231
232
# File 'lib/glimmer/libui/custom_shape.rb', line 226

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/shape.rb')
end

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

Raises:

  • (Glimmer::Error)


188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/glimmer/libui/custom_shape.rb', line 188

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 shape for having no body! Please define body block!' if body_block.nil?
  @body_root = instance_exec(&body_block)
  raise Glimmer::Error, 'Invalid custom shape for having an empty body! Please fill body block!' if @body_root.nil?
  execute_hook('after_body')
  # TODO deregister all observer_registrations on destroy of the shape 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



213
214
215
# File 'lib/glimmer/libui/custom_shape.rb', line 213

def observer_registrations
  @observer_registrations ||= []
end

#post_add_contentObject



209
210
211
# File 'lib/glimmer/libui/custom_shape.rb', line 209

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



205
206
207
# File 'lib/glimmer/libui/custom_shape.rb', line 205

def post_initialize_child(child)
  # No Op by default
end