class Trivet::Childset

Objects of this class act like an array of the children of a node. However, unlike an array, attempts to add children result in calling Trivet::Node#allow_child? to check if the child is allowed.

Attributes

node[R]

Returns the Trivet::Node object that this object is attached to.

Public Class Methods

new(node) click to toggle source

Accepts a Trivet::Node object to which this object will be attached.

# File lib/trivet.rb, line 1109
def initialize(node)
        @node = node
        @children = []
end

Public Instance Methods

<<(new_child) click to toggle source

Shortcut for append without any options.

# File lib/trivet.rb, line 1186
def <<(new_child)
        return append(new_child)
end
append(new_child, opts={}) click to toggle source

Adds a child to the end of the array. Calls Trivet::Node#allow_child? to check if the child can be added. Does nothing if the node is already a child.

# File lib/trivet.rb, line 1181
def append(new_child, opts={})
        return add_child(new_child, 'last', opts)
end
clear() click to toggle source

Removes all children.

# File lib/trivet.rb, line 1223
def clear()
        # explicitly unlink childen
        @children.clone.each do |child|
                if child.is_a?(Trivet::Node)
                        child.unlink
                end
        end
        
        # remove all other child objects
        @children.clear
end
have_object?(potential) click to toggle source

Returns true if the @children contains the given object. This method is not quite the same as include?. This method returns true only if @children contains the actual object given, not just an object that matches ==. So, for example, the following use of have_object? would return false, even though it cohtains a string identical to the string in @children.

@children.push 'whatever'
@children.include? 'whatever'     # true
@children.have_object? 'whatever' # false
# File lib/trivet.rb, line 1339
def have_object?(potential)
        @children.each_with_index do |child, idx|
                if child.equal?(potential)
                        return idx
                end
        end
        
        return false
end
insert(index, new_child, opts={}) click to toggle source

Inserts the child at the position indicated by index. Calls Trivet::Node#allow_child? to check if the child can be added. Does nothing if the node is already a child.

# File lib/trivet.rb, line 1200
def insert(index, new_child, opts={})
        return add_child(new_child, index, opts)
end
pop() click to toggle source

Unlinks and returns the last child. Returns nil if there are no children.

# File lib/trivet.rb, line 1266
def pop()
        # remove first element
        removed = @children.pop
        
        # if a node was removed, unlink it
        if removed.is_a?(Trivet::Node)
                removed.unlink 'recurse'=>false
        end
        
        # return
        return removed
end
push(new_child, opts={}) click to toggle source

Adds a child to the end of the array. Calls Trivet::Node#allow_child? to check if the child can be added. Does nothing if the node is already a child.

# File lib/trivet.rb, line 1174
def push(new_child, opts={})
        return add_child(new_child, 'last', opts)
end
reject!() { |child| ... } click to toggle source

Acts like Array#reject!. Rejected children are unlinked.

# File lib/trivet.rb, line 1288
def reject!()
        # If no block, just return an enumerator. This mimics the behavior of
        # Array#reject!.
        if not block_given?
                return enum_for(:each)
        end
        
        # $tm.hrm
        all = @children.clone
        
        # loop through all
        all.each do |child|
                bool = yield(child)
                bool or remove_object(child)
        end
        
        # return
        return self
end
remove_object(child, opts={}) click to toggle source

Removes the given child from the array of children. Does nothing if the child isn't present.

# File lib/trivet.rb, line 1214
def remove_object(child, opts={})
        # opts = {'recurse'=>true}.merge(opts)
        
        @children.reject!() do |el|
                el.equal? child
        end
end
shift() click to toggle source

Unlinks and returns the first child. Returns nil if there are no children.

# File lib/trivet.rb, line 1244
def shift()
        # remove first element
        removed = @children.shift
        
        # if a node was removed, unlink it
        if removed.is_a?(Trivet::Node)
                removed.unlink 'recurse'=>false
        end
        
        # return
        return removed
end
to_a() click to toggle source

Returns an array of the children.

# File lib/trivet.rb, line 1317
def to_a
        return @children.clone
end
unshift(new_child, opts={}) click to toggle source

Adds a child to the beginning of the array. Calls Trivet::Node#allow_child? to check if the child can be added. Does nothing if the node is already a child.

# File lib/trivet.rb, line 1193
def unshift(new_child, opts={})
        return add_child(new_child, 'first', opts)
end

Private Instance Methods

add_child(new_child, index, opts) click to toggle source
# File lib/trivet.rb, line 1360
def add_child(new_child, index, opts)
        opts = {'recurse'=>true}.merge(opts)
        
        # check if this parent is allowed to have this child
        if not @node.allow_child?(new_child)
                if new_child.respond_to?('to_debug')
                        child_debug = new_child.to_debug
                elsif new_child.is_a?(String)
                        child_debug = new_child
                else
                        child_debug = '[unrecognized object]'
                end
                
                raise 'parent-cannot-have-this-child: ' + @node.to_debug + ' / ' + child_debug
        end
        
        # add to children if not already there
        # if dup_ok or (not @children.include?(new_child))
        if (not have_object?(new_child))
                # add to start of array
                if index == 'first'
                        @children.unshift new_child
                
                # add to end of array
                elsif index == 'last'
                        @children.push new_child
                
                # insert at specific index
                elsif index.is_a?(Integer)
                        # don't allow insert past end of array
                        if index > @children.length
                                raise 'add-child-cannot-insert-past-end'
                        end
                        
                        # insert
                        @children.insert index, new_child
                
                # else unknown index
                else
                        puts 'add-child-invalid-index: ' + index.to_s
                end
                
                # set node's parent if necessary
                if opts['recurse'] and new_child.is_a?(Trivet::Node)
                        new_child.set_parent @node, 'recurse'=>false
                end
        end
        
        # always return self
        return self
end