Class: Glimmer::LibUI::Shape

Inherits:
Object
  • Object
show all
Includes:
DataBindable, Parent, PerfectShaped
Defined in:
lib/glimmer/libui/shape.rb,
lib/glimmer/libui/shape/arc.rb,
lib/glimmer/libui/shape/line.rb,
lib/glimmer/libui/shape/bezier.rb,
lib/glimmer/libui/shape/circle.rb,
lib/glimmer/libui/shape/figure.rb,
lib/glimmer/libui/shape/square.rb,
lib/glimmer/libui/shape/polygon.rb,
lib/glimmer/libui/shape/polyline.rb,
lib/glimmer/libui/shape/rectangle.rb,
lib/glimmer/libui/shape/polybezier.rb,
lib/glimmer/libui/shape/composite_shape.rb

Overview

Represents LibUI lightweight shape objects nested under path (e.g. line, rectangle, arc, bezier)

Defined Under Namespace

Classes: Arc, Bezier, Circle, CompositeShape, Figure, Line, Polybezier, Polygon, Polyline, Rectangle, Square

Constant Summary collapse

KEYWORD_ALIASES =
{
  'shape' => 'composite_shape',
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from DataBindable

#data_bind, #data_bind_read, #data_bind_write, #data_binding_model_attribute_observer_registrations

Methods included from PerfectShaped

#bounding_box, #contain?, #include?, #move, #move_by, #perfect_shape, #perfect_shape_dependencies

Methods included from Parent

#children

Constructor Details

#initialize(keyword, parent, args, &block) ⇒ Shape

Returns a new instance of Shape.



83
84
85
86
87
88
89
90
91
92
# File 'lib/glimmer/libui/shape.rb', line 83

def initialize(keyword, parent, args, &block)
  keyword = KEYWORD_ALIASES[keyword] || keyword
  @keyword = keyword
  @parent = parent
  @args = args
  @block = block
  set_parameter_defaults
  build_control if implicit_path?
  post_add_content if @block.nil?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &block) ⇒ Object



299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/glimmer/libui/shape.rb', line 299

def method_missing(method_name, *args, &block)
  method_name_parameter = method_name.to_s.sub(/=$/, '').sub(/^set_/, '').to_sym
  if self.class.parameters.include?(method_name_parameter)
    method_name = method_name.to_s
    parameter_index = self.class.parameters.index(method_name_parameter)
    if method_name.start_with?('set_') || method_name.end_with?('=') || !args.empty?
      args = [args] if args.size > 1
      if args.first != @args[parameter_index]
        @args[parameter_index] = args.first
        request_auto_redraw
      end
    else
      @args[parameter_index]
    end
  else # TODO consider if there is a need to redirect anything to path proxy or delete this TODO
    super
  end
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



80
81
82
# File 'lib/glimmer/libui/shape.rb', line 80

def args
  @args
end

#blockObject (readonly)

Returns the value of attribute block.



80
81
82
# File 'lib/glimmer/libui/shape.rb', line 80

def block
  @block
end

#content_addedObject (readonly) Also known as: content_added?

Returns the value of attribute content_added.



80
81
82
# File 'lib/glimmer/libui/shape.rb', line 80

def content_added
  @content_added
end

#keywordObject (readonly)

Returns the value of attribute keyword.



80
81
82
# File 'lib/glimmer/libui/shape.rb', line 80

def keyword
  @keyword
end

#parentObject (readonly)

Returns the value of attribute parent.



80
81
82
# File 'lib/glimmer/libui/shape.rb', line 80

def parent
  @parent
end

Class Method Details

.constant_symbol(keyword) ⇒ Object



66
67
68
69
# File 'lib/glimmer/libui/shape.rb', line 66

def constant_symbol(keyword)
  keyword = KEYWORD_ALIASES[keyword] || keyword
  "#{keyword.camelcase(:upper)}".to_sym
end

.create(keyword, parent, args, &block) ⇒ Object



40
41
42
43
# File 'lib/glimmer/libui/shape.rb', line 40

def create(keyword, parent, args, &block)
  keyword = KEYWORD_ALIASES[keyword] || keyword
  shape_class(keyword).new(keyword, parent, args, &block)
end

.exists?(keyword) ⇒ Boolean

Returns:

  • (Boolean)


33
34
35
36
37
38
# File 'lib/glimmer/libui/shape.rb', line 33

def exists?(keyword)
  keyword = KEYWORD_ALIASES[keyword] || keyword
  Shape.constants.include?(constant_symbol(keyword)) and
    shape_class(keyword).respond_to?(:ancestors) and
    shape_class(keyword).ancestors.include?(Shape)
end

.parameter_defaults(*defaults) ⇒ Object



58
59
60
61
62
63
64
# File 'lib/glimmer/libui/shape.rb', line 58

def parameter_defaults(*defaults)
  if defaults.empty?
    @parameter_defaults
  else
    @parameter_defaults = defaults
  end
end

.parameters(*params) ⇒ Object



50
51
52
53
54
55
56
# File 'lib/glimmer/libui/shape.rb', line 50

def parameters(*params)
  if params.empty?
    @parameters
  else
    @parameters = params
  end
end

.shape_class(keyword) ⇒ Object



45
46
47
48
# File 'lib/glimmer/libui/shape.rb', line 45

def shape_class(keyword)
  keyword = KEYWORD_ALIASES[keyword] || keyword
  Shape.const_get(constant_symbol(keyword))
end

Instance Method Details

#absolute_c1_xObject



218
219
220
221
222
223
224
225
226
227
# File 'lib/glimmer/libui/shape.rb', line 218

def absolute_c1_x
  # TODO Consider moving this method into a module mixed into all shapes having c1_x
  return unless respond_to?(:c1_x)
  
  if composite_shape
    composite_shape.relative_x(c1_x)
  else
    c1_x
  end
end

#absolute_c1_yObject



229
230
231
232
233
234
235
236
237
238
# File 'lib/glimmer/libui/shape.rb', line 229

def absolute_c1_y
  # TODO Consider moving this method into a module mixed into all shapes having c1_y
  return unless respond_to?(:c1_y)
  
  if composite_shape
    composite_shape.relative_x(c1_y)
  else
    c1_y
  end
end

#absolute_c2_xObject



240
241
242
243
244
245
246
247
248
249
# File 'lib/glimmer/libui/shape.rb', line 240

def absolute_c2_x
  # TODO Consider moving this method into a module mixed into all shapes having c2_x
  return unless respond_to?(:c2_x)
  
  if composite_shape
    composite_shape.relative_x(c2_x)
  else
    c2_x
  end
end

#absolute_c2_yObject



251
252
253
254
255
256
257
258
259
260
# File 'lib/glimmer/libui/shape.rb', line 251

def absolute_c2_y
  # TODO Consider moving this method into a module mixed into all shapes having c2_y
  return unless respond_to?(:c2_y)
  
  if composite_shape
    composite_shape.relative_x(c2_y)
  else
    c2_y
  end
end

#absolute_end_xObject



262
263
264
265
266
267
268
269
270
271
# File 'lib/glimmer/libui/shape.rb', line 262

def absolute_end_x
  # TODO Consider moving this method into a module mixed into all shapes having end_x
  return unless respond_to?(:end_x)
  
  if composite_shape
    composite_shape.relative_x(end_x)
  else
    end_x
  end
end

#absolute_end_yObject



273
274
275
276
277
278
279
280
281
282
# File 'lib/glimmer/libui/shape.rb', line 273

def absolute_end_y
  # TODO Consider moving this method into a module mixed into all shapes having end_y
  return unless respond_to?(:end_y)
  
  if composite_shape
    composite_shape.relative_x(end_y)
  else
    end_y
  end
end

#absolute_point_arrayObject



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/glimmer/libui/shape.rb', line 180

def absolute_point_array
  # TODO Consider moving this method into a module mixed into all shapes having point_array
  return unless respond_to?(:point_array)
  
  point_array = self.point_array || []
  require 'perfect-shape'
  point_array = PerfectShape::MultiPoint.normalize_point_array(point_array)
  point_array.map do |point|
    if composite_shape
      composite_shape.relative_point(*point)
    else
      point
    end
  end
end

#absolute_xObject



164
165
166
167
168
169
170
# File 'lib/glimmer/libui/shape.rb', line 164

def absolute_x
  if composite_shape
    composite_shape.relative_x(x)
  else
    x
  end
end

#absolute_x_centerObject



196
197
198
199
200
201
202
203
204
205
# File 'lib/glimmer/libui/shape.rb', line 196

def absolute_x_center
  # TODO Consider moving this method into a module mixed into all shapes having x_center
  return unless respond_to?(:x_center)
  
  if composite_shape
    composite_shape.relative_x(x_center)
  else
    x_center
  end
end

#absolute_yObject



172
173
174
175
176
177
178
# File 'lib/glimmer/libui/shape.rb', line 172

def absolute_y
  if composite_shape
    composite_shape.relative_y(y)
  else
    y
  end
end

#absolute_y_centerObject



207
208
209
210
211
212
213
214
215
216
# File 'lib/glimmer/libui/shape.rb', line 207

def absolute_y_center
  # TODO Consider moving this method into a module mixed into all shapes having y_center
  return unless respond_to?(:y_center)
  
  if composite_shape
    composite_shape.relative_y(y_center)
  else
    y_center
  end
end

#area_proxyObject



134
135
136
# File 'lib/glimmer/libui/shape.rb', line 134

def area_proxy
  find_parent_in_ancestors { |parent| parent.nil? || parent.is_a?(ControlProxy::AreaProxy) }
end

#can_handle_listener?(listener_name) ⇒ Boolean

Returns:

  • (Boolean)


284
285
286
# File 'lib/glimmer/libui/shape.rb', line 284

def can_handle_listener?(listener_name)
  area_proxy&.can_handle_listener?(listener_name)
end

#composite_shapeObject



142
143
144
# File 'lib/glimmer/libui/shape.rb', line 142

def composite_shape
  find_parent_in_ancestors { |parent| parent.nil? || parent.is_a?(CompositeShape) }
end

#content(&block) ⇒ Object



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

def content(&block)
  Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Libui::ShapeExpression.new, @keyword, {post_add_content: @content_added}, &block)
  request_auto_redraw
end

#destroyObject



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

def destroy
  return if ControlProxy.main_window_proxy&.destroying?
  @parent.children.delete(self)
end

#draw(area_draw_params) ⇒ Object

Subclasses must override to perform draw work and call super afterwards to ensure calling destroy when semi-declarative in an on_draw method



117
118
119
# File 'lib/glimmer/libui/shape.rb', line 117

def draw(area_draw_params)
  destroy if area_proxy.nil?
end

#fill(*args) ⇒ Object Also known as: fill=, set_fill



146
147
148
# File 'lib/glimmer/libui/shape.rb', line 146

def fill(*args)
  path_proxy.fill(*args)
end

#handle_listener(listener_name, &listener) ⇒ Object



288
289
290
291
292
# File 'lib/glimmer/libui/shape.rb', line 288

def handle_listener(listener_name, &listener)
  area_proxy&.handle_listener(listener_name) do |event|
    listener.call(event) if include?(event[:x], event[:y])
  end
end

#implicit_path?Boolean

indicates if nested directly under area or on_draw event (having an implicit path not an explicit path parent)

Returns:

  • (Boolean)


319
320
321
322
323
324
325
# File 'lib/glimmer/libui/shape.rb', line 319

def implicit_path?
  @implicit_path ||= !!(
    @parent.is_a?(Glimmer::LibUI::ControlProxy::AreaProxy) ||
    @parent.is_a?(Glimmer::LibUI::Shape::CompositeShape) ||
    (@parent.nil? && Glimmer::LibUI::ControlProxy::AreaProxy.current_area_draw_params)
  )
end

#path_proxyObject



138
139
140
# File 'lib/glimmer/libui/shape.rb', line 138

def path_proxy
  find_parent_in_ancestors { |parent| parent.nil? || parent.is_a?(ControlProxy::PathProxy) }
end

#post_add_contentObject

Subclasses may override to perform post add_content work (normally must call super)



95
96
97
98
99
100
101
# File 'lib/glimmer/libui/shape.rb', line 95

def post_add_content
  unless @content_added
    @parent&.post_initialize_child(self)
    @parent.post_add_content if implicit_path? && dynamic?
    @content_added = true
  end
end

#post_initialize_child(child, add_child: true) ⇒ Object



103
104
105
106
107
108
109
# File 'lib/glimmer/libui/shape.rb', line 103

def post_initialize_child(child, add_child: true)
  if child.is_a?(ControlProxy::MatrixProxy)
    path_proxy.post_initialize_child(child, add_child: add_child)
  else
    super(child, add_child: add_child)
  end
end

#redrawObject



121
122
123
# File 'lib/glimmer/libui/shape.rb', line 121

def redraw
  area_proxy&.redraw
end

#request_auto_redrawObject



125
126
127
# File 'lib/glimmer/libui/shape.rb', line 125

def request_auto_redraw
  area_proxy&.request_auto_redraw
end

#respond_to?(method_name, *args, &block) ⇒ Boolean

Returns:

  • (Boolean)


294
295
296
297
# File 'lib/glimmer/libui/shape.rb', line 294

def respond_to?(method_name, *args, &block)
  self.class.parameters.include?(method_name.to_s.sub(/=$/, '').sub(/^set_/, '').to_sym) or
    super(method_name, true)
end

#stroke(*args) ⇒ Object Also known as: stroke=, set_stroke



152
153
154
# File 'lib/glimmer/libui/shape.rb', line 152

def stroke(*args)
  path_proxy.stroke(*args)
end

#transform(matrix = nil) ⇒ Object Also known as: transform=, set_transform



158
159
160
# File 'lib/glimmer/libui/shape.rb', line 158

def transform(matrix = nil)
  path_proxy.transform(matrix)
end