1
0
Fork 0
fgdata/Nasal/canvas/api/group.nas
2020-05-17 20:03:43 +01:00

148 lines
4.4 KiB
Text

#-------------------------------------------------------------------------------
# canvas.Group
#-------------------------------------------------------------------------------
# Class for a group element on a canvas
#
var Group = {
new: func(ghost) {
var obj = {
parents: [Group, Element.new(ghost)],
};
return obj;
},
# Create a child of given type with specified id.
# type can be group, text
createChild: func(type, id = nil) {
var ghost = me._createChild(type, id);
var factory = me._getFactory(type);
if (factory == nil) {
return ghost;
}
return factory(ghost);
},
# Create multiple children of given type
createChildren: func(type, count) {
var factory = me._getFactory(type);
if (factory == nil) {
return [];
}
var nodes = props._addChildren(me._node._g, [type, count, 0, 0]);
for (var i = 0; i < count; i += 1) {
nodes[i] = factory(me._getChild(nodes[i]));
}
return nodes;
},
# Create a path child drawing a (rounded) rectangle
#
# @param x Position of left border
# @param y Position of top border
# @param w Width
# @param h Height
# @param cfg Optional settings (eg. {"border-top-radius": 5})
rect: func(x, y, w, h, cfg = nil) {
return me.createChild("path").rect(x, y, w, h, cfg);
},
# Get a vector of all child elements
getChildren: func() {
var children = [];
foreach(var c; me._node.getChildren()) {
if (me._isElementNode(c)) {
append(children, me._wrapElement(c));
}
}
return children;
},
# Recursively get all children of class specified by first param
getChildrenOfType: func(type, array = nil) {
var children = array;
if (children == nil) {
children = [];
}
var my_children = me.getChildren();
if (!isvec(type)) {
type = [type];
}
foreach(var c; my_children) {
foreach(var t; type) {
if (isa(c, t)) {
append(children, c);
}
}
if (isa(c, canvas.Group)) {
c.getChildrenOfType(type, children);
}
}
return children;
},
# Set color to children of type Path and Text. It is possible to optionally
# specify which types of children should be affected by passing a vector as
# the last agrument, ie. my_group.setColor(1,1,1,[Path]);
setColor: func() {
var color = arg;
var types = [Path, Text];
var arg_c = size(color);
if (arg_c > 1 and isvec(color[-1])) {
types = color[-1];
color = subvec(color, 0, arg_c - 1);
}
var children = me.getChildrenOfType(types);
if (isvec(color)) {
var first = color[0];
if (isvec(first)) {
color = first;
}
}
foreach(var c; children) {
c.setColor(color);
}
},
# Get first child with given id (breadth-first search)
#
# @note Use with care as it can take several miliseconds (for me eg. ~2ms).
# TODO check with new C++ implementation
getElementById: func(id) {
var ghost = me._getElementById(id);
if (ghost == nil) { return nil; }
var node = props.wrapNode(ghost._node_ghost);
var factory = me._getFactory(node.getName());
if (factory == nil) { return ghost; }
return factory(ghost);
},
# Remove all children
removeAllChildren: func() {
foreach(var type; keys(me._element_factories)) {
me._node.removeChildren(type, 0);
}
return me;
},
# private:
# element nodes have type NONE and valid element names (those in the factory
# list)
_isElementNode: func(el) {
return el.getType() == "NONE" and me._element_factories[el.getName()] != nil;
},
# Create element from existing node
_wrapElement: func(node) {
var factory = me._getFactory(node.getName());
return factory(me._getChild(node._g));
},
_getFactory: func(type) {
var factory = me._element_factories[type];
if (factory == nil) {
logprint(DEV_ALERT, "canvas.Group.createChild(): unknown type ("~type~")");
}
return factory;
}
};