lib/glimmer/libui/shape/composite_shape.rb
# Copyright (c) 2021-2022 Andy Maleh
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
require 'glimmer/libui/shape'
module Glimmer
module LibUI
class Shape
class CompositeShape < Glimmer::LibUI::Shape
# TODO support nested shape properties that apply to all children
parameters :x, :y
parameter_defaults 0, 0
def draw(area_draw_params)
children.each do |child|
child_fill = child.fill
child_stroke = child.stroke
child_transform = child.transform
child.fill = fill if Glimmer::LibUI.blank_color?(child.fill)
child.stroke = stroke if Glimmer::LibUI.blank_color?(child.stroke)
child.transform = transform if child.transform.nil?
child.move_by(x, y)
begin
child.draw(area_draw_params)
rescue Exception => e
raise e
ensure
# restore original child attributes
child.move_by(-x, -y)
child.transform = child_transform
child.stroke = Glimmer::LibUI.blank_color?(child_stroke) ? Glimmer::LibUI.blank_color : child_stroke
child.fill = Glimmer::LibUI.blank_color?(child_fill) ? Glimmer::LibUI.blank_color : child_fill
end
end
super
end
def transform(matrix = nil)
if matrix.nil?
@matrix
else
@matrix = matrix
end
end
def move_by(x_delta, y_delta)
self.x += x_delta
self.y += y_delta
end
def contain?(*point, outline: false, distance_tolerance: 0)
children.any? { |child| child.contain?(*point, outline: outline, distance_tolerance: distance_tolerance) }
end
def include?(*point)
children.any? { |child| child.include?(*point) }
end
def relative_x(x)
self.x + x
end
def relative_y(y)
self.y + y
end
def relative_point(*point)
[relative_x(point.first), relative_y(point.last)]
end
def perfect_shape
require 'perfect-shape'
perfect_shape_dependencies = [x, y, children.map(&:perfect_shape_dependencies)]
if perfect_shape_dependencies != @perfect_shape_dependencies
x, y, _ = @perfect_shape_dependencies = perfect_shape_dependencies
shapes = children.map(&:perfect_shape)
@perfect_shape = PerfectShape::CompositeShape.new(shapes: shapes)
end
@perfect_shape
end
end
end
end
end