Module: Sevgi::Graphics::Mixtures::Core
- Extended by:
- Forwardable
- Defined in:
- lib/sevgi/graphics/mixtures/core.rb
Overview
Core SVG tree and attribute DSL helpers.
Instance Method Summary collapse
-
#<<(element) ⇒ Sevgi::Graphics::Element
Appends an element as a child.
-
#Adopt(new_parent = nil, index: -1)) ⇒ Sevgi::Graphics::Element
Moves this element under a new parent.
-
#AdoptFirst(new_parent = nil) ⇒ Sevgi::Graphics::Element
Moves this element to the beginning of a parent.
-
#Append(*elements) ⇒ Sevgi::Graphics::Element
Appends distinct existing elements as children in argument order.
-
#Classify(*classes) ⇒ Sevgi::Graphics::Element
Adds CSS classes without duplicating existing values.
-
#Defaults(**attributes) ⇒ Sevgi::Graphics::Element
Assigns default attributes only when they are absent.
-
#Element(tag, *contents, **attributes) { ... } ⇒ Sevgi::Graphics::Element
Builds a child element with an explicit tag name.
-
#Forward(receiver, method, *args, **kwargs) ⇒ Object
Forwards this element as the first argument to another receiver.
-
#Is?(name) ⇒ Boolean
Reports whether this element has the given SVG name.
-
#Orphan ⇒ Sevgi::Graphics::Element?
Removes this element from its parent and makes it a detached subtree root.
-
#Prepend(*elements) ⇒ Sevgi::Graphics::Element
Prepends distinct existing elements as children in argument order.
-
#Root ⇒ Sevgi::Graphics::Element
Returns the topmost element in this tree.
-
#Root? ⇒ Boolean
Reports whether this element is the root document element.
-
#Stay(value) ⇒ Sevgi::Graphics::Mixtures::Stop
Wraps a traversal return value as a stop token.
-
#Traverse(depth = 0, leave = nil) {|element, depth| ... } ⇒ Sevgi::Graphics::Element, Object
Traverses the subtree depth-first.
-
#TraverseUp(height = 0) {|element, height| ... } ⇒ Object?
Traverses ancestors from this element to the root.
-
#With(*args, receiver: self, **kwargs) {|*args, **kwargs| ... } ⇒ Sevgi::Graphics::Element
Evaluates a block in the parent element context.
-
#Within(*args, receiver: self, **kwargs) {|*args, **kwargs| ... } ⇒ Sevgi::Graphics::Element
Evaluates a block in this element context.
Instance Method Details
#<<(element) ⇒ Sevgi::Graphics::Element
Appends an element as a child.
287 288 289 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 287 def <<(element) Append(element) end |
#Adopt(new_parent = nil, index: -1)) ⇒ Sevgi::Graphics::Element
Moves this element under a new parent.
59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 59 def Adopt(new_parent = nil, index: -1) tap do new_parent ||= parent Adoption.validate(self, new_parent) insertion = Adoption.index_for(self, new_parent, index) self.Orphan() Element.send(:attach, self, new_parent, index: insertion) end end |
#AdoptFirst(new_parent = nil) ⇒ Sevgi::Graphics::Element
77 78 79 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 77 def AdoptFirst(*) Adopt(*, index: 0) end |
#Append(*elements) ⇒ Sevgi::Graphics::Element
Appends distinct existing elements as children in argument order. Each element transfers from its current parent. The complete batch is validated before any element moves.
92 93 94 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 92 def Append(*elements) tap { Adoption.batch(elements, self, front: false) } end |
#Classify(*classes) ⇒ Sevgi::Graphics::Element
Adds CSS classes without duplicating existing values.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 99 def Classify(*classes) tap do tokens = proc do |value| case value when nil [] when ::Array value.flat_map { tokens.call(it) } else value.to_s.split end end self[:class] = [*tokens.call(self[:class]), *tokens.call(classes)].uniq end end |
#Defaults(**attributes) ⇒ Sevgi::Graphics::Element
Assigns default attributes only when they are absent.
119 120 121 122 123 124 125 126 127 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 119 def Defaults(**attributes) tap do attributes.each do |key, value| next if has?(key) self[key] = value end end end |
#Element(tag, *contents, **attributes) { ... } ⇒ Sevgi::Graphics::Element
Builds a child element with an explicit tag name.
137 138 139 140 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 137 def Element(tag, *contents, **attributes, &block) contents.map! { it.is_a?(Content) ? it : Content.encoded(it) } self.class.send(:new, tag, contents:, attributes:, parent: self, &block) end |
#Forward(receiver, method, *args, **kwargs) ⇒ Object
Forwards this element as the first argument to another receiver.
149 150 151 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 149 def Forward(receiver, method, ...) receiver.public_send(method, self, ...) end |
#Is?(name) ⇒ Boolean
Reports whether this element has the given SVG name.
156 157 158 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 156 def Is?(name) self.name() == name.to_sym end |
#Orphan ⇒ Sevgi::Graphics::Element?
Removes this element from its parent and makes it a detached subtree root.
162 163 164 165 166 167 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 162 def Orphan return if Root?() Element.send(:detach, self) self end |
#Prepend(*elements) ⇒ Sevgi::Graphics::Element
Prepends distinct existing elements as children in argument order. Each element transfers from its current parent. The complete batch is validated before any element moves.
174 175 176 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 174 def Prepend(*elements) tap { Adoption.batch(elements, self, front: true) } end |
#Root ⇒ Sevgi::Graphics::Element
Returns the topmost element in this tree. A detached subtree returns its detached topmost element; use #Root? to distinguish a document root.
181 182 183 184 185 186 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 181 def Root element = self element = element.parent while element.parent element end |
#Root? ⇒ Boolean
Reports whether this element is the root document element.
190 191 192 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 190 def Root? Element.root?(self) end |
#Stay(value) ⇒ Sevgi::Graphics::Mixtures::Stop
198 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 198 def Stay(...) = Stop.send(:new, ...) |
#Traverse(depth = 0, leave = nil) {|element, depth| ... } ⇒ Sevgi::Graphics::Element, Object
Traverses the subtree depth-first.
213 214 215 216 217 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 213 def Traverse(depth = 0, leave = nil, &block) ArgumentError.("Block required") unless block Traversal.call(self, depth, leave, &block) end |
#TraverseUp(height = 0) {|element, height| ... } ⇒ Object?
Traverses ancestors from this element to the root.
227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 227 def TraverseUp(height = 0, &block) ArgumentError.("Block required") unless block element = self loop do yield(element, height).tap { return it.value if it.is_a?(Stop) } break unless element.parent element = element.parent height += 1 end end |
#With(*args, receiver: self, **kwargs) {|*args, **kwargs| ... } ⇒ Sevgi::Graphics::Element
Evaluates a block in the parent element context.
255 256 257 258 259 260 261 262 263 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 255 def With(*args, receiver: self, **kwargs, &block) ArgumentError.("Block required") unless block ArgumentError.("Receiver must be an element") unless receiver.is_a?(Element) parent = receiver.parent ArgumentError.("Receiver has no parent") unless parent tap { parent.instance_exec(*args, **kwargs, &block) } end |
#Within(*args, receiver: self, **kwargs) {|*args, **kwargs| ... } ⇒ Sevgi::Graphics::Element
Evaluates a block in this element context.
277 278 279 280 281 |
# File 'lib/sevgi/graphics/mixtures/core.rb', line 277 def Within(*args, receiver: self, **kwargs, &block) ArgumentError.("Block required") unless block tap { receiver.instance_exec(*args, **kwargs, &block) } end |