tree

package
v0.3.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 10, 2024 License: BSD-3-Clause Imports: 21 Imported by: 89

README

Tree

The Tree is one of the most flexible, widely used data structures in programming, including the DOM structure at the core of a web browser, scene graphs for 3D and 2D graphics systems, JSON, XML, SVG, file systems, programs themselves, etc. This is because trees can capture most relevant forms of structure (hierarchical groupings, categories, relationships, etc) and are most powerful when they are fully generative -- arbitrary new types can be inserted flexibly.

Cogent Core provides a general-purpose tree container type, that can support all of these applications, by embedding and extending the NodeBase struct type that implements the Node interface. Unlike many cases in Go, the need to be able to arbitrarily extend the type space of nodes in the tree within a consistent API, means that the more traditional object-oriented model works best here, with a single common base type, and derived types that handle diverse cases (e.g., different types of widgets in a GUI). Cogent Core stores a Node interface of each node, enabling correct virtual function calling on these derived types.

In addition, Cogent Core provides functions that traverse the tree in the usual relevant ways and take a func function argument, so you can easily apply a common operation across the whole tree in a transparent and self-contained manner, like this:

func (mn *MyNode) DoSomethingOnMyTree() {
	mn.WalkDown(func(n tree.Node) bool {
		DoSomething(n)
		// ...
		return tree.Continue // return value determines whether tree traversal continues or not
	})
}

Many operations are naturally expressed in terms of these traversal algorithms.

Making a Plan for the Tree

The tree package implements an efficient mechanism for dynamically updating the tree contents, based on creating a tree.Plan that specifies the desired elements of the tree, and functions to make and initialize new nodes when they are needed. The base/plan package implements the Update function that performs the minimal additions and deletions to update the current state of the tree to match the specified Plan.

The NodeBase contains a set of Makers functions that are called to create the Plan and define its functions, as well as a set of Updaters that are called for all elements when Update is called. Together, these allow significant flexibility in creating efficient, dynamically updatable trees.

In the Cogent Core GUI context, this infrastructure provides a more efficient and effective alternative to the declarative paradigm used in many other GUI frameworks, where the entire new desired state of the GUI is constructed at every update, and then a generic "diff"-like algorithm compares that state with the current and drives the necessary updates. This is typically extremely wasteful in terms of unnecessary memory and processing churn, and also creates problems tracking the current active state of elements.

By contrast, the Plan-based mechanism does the diff only on unique names of each element in the tree, and calls closure functions to configure and update any new elements as needed, instead of running such functions for every single element even when unnecessary.

Fast finding in a slice

Several tree methods take an optional startIndex argument that is used by the generic base/slicesx Search algorithm to search for the item starting at that index, looking up and down from that starting point. Thus, if you have any idea where the item might be in the list, it can save (considerable for large lists) time finding it.

The IndexInParent() method uses this trick, using the cached NodeBase.index value, so it is very fast in general, while also robust to dynamically changing trees.

Documentation

Overview

Package tree provides a powerful and extensible tree system, centered on the core Node interface.

Index

Constants

View Source
const (
	// Continue = true can be returned from tree iteration functions to continue
	// processing down the tree, as compared to Break = false which stops this branch.
	Continue = true

	// Break = false can be returned from tree iteration functions to stop processing
	// this branch of the tree.
	Break = false
)

Variables

This section is empty.

Functions

func Add added in v0.2.0

func Add[T NodeValue](p *Plan, init func(w *T))

Add adds a new PlanItem to the given Plan for a Node with the given function to initialize the node. The node is guaranteed to be added to its parent before the init function is called. The name of the node is automatically generated based on the file and line number of the calling function.

func AddAt added in v0.2.0

func AddAt[T NodeValue](p *Plan, name string, init func(w *T))

AddAt adds a new PlanItem to the given Plan for a Node with the given name and function to initialize the node. The node is guaranteed to be added to its parent before the init function is called.

func AddChild added in v0.2.0

func AddChild[T NodeValue](parent Node, init func(w *T))

AddChild adds a new NodeBase.Maker to the the given parent Node that adds a PlanItem with the given init function using Add. In other words, this adds a maker that will add a child to the given parent.

func AddChildAt added in v0.2.0

func AddChildAt[T NodeValue](parent Node, name string, init func(w *T))

AddChildAt adds a new NodeBase.Maker to the the given parent Node that adds a PlanItem with the given name and init function using AddAt. In other words, this adds a maker that will add a child to the given parent.

func AddChildInit added in v0.2.0

func AddChildInit[T NodeValue](parent Node, name string, init func(w *T))

AddChildInit adds a new NodeBase.Maker to the the given parent Node that adds a new function for initializing the node with the given name in the given Plan. The node must already exist in the plan; this is for extending an existing PlanItem, not adding a new one. The node is guaranteed to be added to its parent before the init function is called. The init functions are called in sequential ascending order.

func AddInit added in v0.2.0

func AddInit[T NodeValue](p *Plan, name string, init func(w *T))

AddInit adds a new function for initializing the Node with the given name in the given Plan. The node must already exist in the plan; this is for extending an existing PlanItem, not adding a new one. The node is guaranteed to be added to its parent before the init function is called. The init functions are called in sequential ascending order.

func AddNew added in v0.2.0

func AddNew[T Node](p *Plan, name string, new func() T, init func(w T))

AddNew adds a new PlanItem to the given Plan for a Node with the given name, function for constructing the node, and function for initializing the node. The node is guaranteed to be added to its parent before the init function is called. It should only be called instead of Add and AddAt when the node must be made new, like when using cogentcore.org/core/core.NewValue.

func AutoPlanName added in v0.2.1

func AutoPlanName(level int) string

AutoPlanName returns the dir-filename of runtime.Caller(level), with all / . replaced to -, which is suitable as a unique name for a [PlanItem.Name].

func ChildByType

func ChildByType[T Node](n Node, startIndex ...int) T

ChildByType returns the first child of the given node that is of the given type, if any such node exists.

func EscapePathName

func EscapePathName(name string) string

EscapePathName returns a name that replaces any / with \\

func IndexByName added in v0.2.0

func IndexByName(slice []Node, name string, startIndex ...int) int

IndexByName returns the index of the first element in the given slice that has the given name, or -1 if none is found. See IndexOf for info on startIndex.

func IndexOf added in v0.2.0

func IndexOf(slice []Node, child Node, startIndex ...int) int

IndexOf returns the index of the given node in the given slice, or -1 if it is not found. The optional startIndex argument allows for optimized bidirectional searching if you have a guess at where the node might be, which can be a key speedup for large slices. If no value is specified for startIndex, it starts in the middle, which is a good default.

func InitNode added in v0.2.1

func InitNode(n Node)

InitNode initializes the node. It should not be called by end-user code. It must be exported since it is referenced in generic functions included in yaegi.

func IsNode

func IsNode(typ reflect.Type) bool

IsNode returns whether the given type or a pointer to it implements the Node interface.

func IsRoot

func IsRoot(n Node) bool

IsRoot returns whether the given node is the root node in its tree.

func MoveToParent

func MoveToParent(child Node, parent Node)

MoveToParent removes the given node from its current parent and adds it as a child of the given new parent. The old and new parents can be in different trees (or not).

func New

func New[T NodeValue](parent ...Node) *T

New returns a new node of the given type with the given optional parent. If the name is unspecified, it defaults to the ID (kebab-case) name of the type, plus the [Node.NumLifetimeChildren] of the parent.

func ParentByType

func ParentByType[T Node](n Node) T

ParentByType returns the first parent of the given node that is of the given type, if any such node exists.

func SetParent

func SetParent(child Node, parent Node)

SetParent sets the parent of the given node to the given parent node. This is only for nodes with no existing parent; see MoveToParent to move nodes that already have a parent. It does not add the node to the parent's list of children; see [Node.AddChild] for a version that does. It automatically gets the [Node.This] of the parent.

func SetUniqueName added in v0.1.1

func SetUniqueName(n Node)

SetUniqueName sets the name of the node to be unique, using the number of lifetime children of the parent node as a unique identifier. If the node already has a name, it adds the unique id to it. Otherwise, it uses the type name of the node plus the unique id.

func UnescapePathName

func UnescapePathName(name string) string

UnescapePathName returns a name that replaces any \\ with /

func Update added in v0.2.0

func Update(n Node, p TypePlan) bool

Update ensures that the children of the given Node contain the elements according to the TypePlan, specified by unique element names. It returns whether any changes were made.

func UpdateSlice added in v0.2.0

func UpdateSlice(slice *[]Node, parent Node, p TypePlan) bool

UpdateSlice ensures that the given slice contains the elements according to the TypePlan, specified by unique element names. The given Node is set as the parent of the created nodes. It returns whether any changes were made.

Types

type Node

type Node interface {

	// AsTree returns the [NodeBase] of this Node. Most core
	// tree functionality is implemented on [NodeBase].
	AsTree() *NodeBase

	// Init is called when the node is first initialized.
	// It is called before the node is added to the tree,
	// so it will not have any parents or siblings.
	// It will be called only once in the lifetime of the node.
	// It does nothing by default, but it can be implemented
	// by higher-level types that want to do something.
	// It is the main place that initialization steps should
	// be done, like adding Stylers, Makers, and event handlers
	// to widgets in Cogent Core.
	Init()

	// OnAdd is called when the node is added to a parent.
	// It will be called only once in the lifetime of the node,
	// unless the node is moved. It will not be called on root
	// nodes, as they are never added to a parent.
	// It does nothing by default, but it can be implemented
	// by higher-level types that want to do something.
	OnAdd()

	// Destroy recursively deletes and destroys the node, all of its children,
	// and all of its children's children, etc. Node types can implement this
	// to do additional necessary destruction; if they do, they should call
	// [NodeBase.Destroy] at the end of their implementation.
	Destroy()

	// NodeWalkDown is a method that nodes can implement to traverse additional nodes
	// like widget parts during [NodeBase.WalkDown]. It is called with the function passed
	// to [Node.WalkDown] after the function is called with the node itself.
	NodeWalkDown(fun func(n Node) bool)

	// CopyFieldsFrom copies the fields of the node from the given node.
	// By default, it is [NodeBase.CopyFieldsFrom], which automatically does
	// a deep copy of all of the fields of the node that do not a have a
	// `copier:"-"` struct tag. Node types should only implement a custom
	// CopyFieldsFrom method when they have fields that need special copying
	// logic that can not be automatically handled. All custom CopyFieldsFrom
	// methods should call [NodeBase.CopyFieldsFrom] first and then only do manual
	// handling of specific fields that can not be automatically copied. See
	// [cogentcore.org/core/core.WidgetBase.CopyFieldsFrom] for an example of a
	// custom CopyFieldsFrom method.
	CopyFieldsFrom(from Node)

	// This is necessary for tree planning to work.
	plan.Namer
}

Node is an interface that all tree nodes satisfy. The core functionality of a tree node is defined on NodeBase, and all higher-level tree types must embed it. This interface only contains the tree functionality that higher-level tree types may need to override. You can call [Node.AsTree] to get the NodeBase of a Node and access the core tree functionality. All values that implement Node are pointer values; see NodeValue for an interface for non-pointer values.

func Last

func Last(n Node) Node

Last returns the last node in the tree.

func NewOfType

func NewOfType(typ *types.Type, parent ...Node) Node

NewOfType returns a new node of the given types.Type with the given optional parent. If the name is unspecified, it defaults to the ID (kebab-case) name of the type, plus the [Node.NumLifetimeChildren] of the parent.

func Next

func Next(n Node) Node

Next returns next node in the tree, or nil if this is the last node.

func NextSibling

func NextSibling(n Node) Node

NextSibling returns the next sibling of this node, or nil if it has none.

func Previous

func Previous(n Node) Node

Previous returns the previous node in the tree, or nil if this is the root node.

func Root

func Root(n Node) Node

Root returns the root node of the given node's tree.

func UnmarshalRootJSON added in v0.2.0

func UnmarshalRootJSON(b []byte) (Node, error)

UnmarshalRootJSON loads the given JSON to produce a new root node of the correct type with all properties and children loaded. If you have a root node that you know is already of the correct type, you can just call NodeBase.UnmarshalJSON on it instead.

type NodeBase

type NodeBase struct {

	// Name is the name of this node, which is typically unique relative to other children of
	// the same parent. It can be used for finding and serializing nodes. If not otherwise set,
	// it defaults to the ID (kebab-case) name of the node type combined with the total number
	// of children that have ever been added to the node's parent.
	Name string `copier:"-"`

	// This is the value of this Node as its true underlying type. This allows methods
	// defined on base types to call methods defined on higher-level types, which
	// is necessary for various parts of tree and widget functionality. This is set
	// to nil when the node is deleted.
	This Node `copier:"-" json:"-" xml:"-" display:"-" set:"-"`

	// Parent is the parent of this node, which is set automatically when this node is
	// added as a child of a parent. To change the parent of a node, use [MoveToParent];
	// you should typically not set this field directly. Nodes can only have one parent
	// at a time.
	Parent Node `copier:"-" json:"-" xml:"-" display:"-" set:"-"`

	// Children is the list of children of this node. All of them are set to have this node
	// as their parent. You can directly modify this list, but you should typically use the
	// various NodeBase child helper functions when applicable so that everything is updated
	// properly, such as when deleting children.
	Children []Node `table:"-" copier:"-" set:"-" json:",omitempty"`

	// Properties is a property map for arbitrary key-value properties.
	// When possible, use typed fields on a new type embedding NodeBase instead of this.
	// You should typically use the [NodeBase.SetProperty], [NodeBase.Property], and
	// [NodeBase.DeleteProperty] methods for modifying and accessing properties.
	Properties map[string]any `table:"-" xml:"-" copier:"-" set:"-" json:",omitempty"`

	// Updaters is a tiered set of functions called in sequential descending (reverse) order
	// in [NodeBase.RunUpdaters] to update the node. You can use [NodeBase.Updater],
	// [NodeBase.FirstUpdater], or [NodeBase.FinalUpdater] to add one. This typically
	// typically contains [NodeBase.UpdateFromMake] at the start of the normal list.
	Updaters tiered.Tiered[[]func()] `copier:"-" json:"-" xml:"-" set:"-" edit:"-" display:"add-fields"`

	// Makers is a tiered set of functions called in sequential ascending order
	// in [NodeBase.Make] to make the plan for how the node's children should
	// be configured. You can use [NodeBase.Maker], [NodeBase.FirstMaker], or
	// [NodeBase.FinalMaker] to add one.
	Makers tiered.Tiered[[]func(p *Plan)] `copier:"-" json:"-" xml:"-" set:"-" edit:"-" display:"add-fields"`

	// OnChildAdded is called when a node is added as a direct child of this node.
	// When a node is added to a parent, it calls [Node.OnAdd] on itself and then
	// this function on its parent if it is non-nil.
	OnChildAdded func(n Node) `copier:"-" json:"-" xml:"-" edit:"-"`
	// contains filtered or unexported fields
}

NodeBase implements the Node interface and provides the core functionality for the Cogent Core tree system. You must use NodeBase as an embedded struct in all higher-level tree types.

All nodes must be properly initialized by using one of New, NodeBase.NewChild, NodeBase.AddChild, NodeBase.InsertChild, NodeBase.Clone, Update, or Plan. This ensures that the [NodeBase.This] field is set correctly and the [Node.Init] method is called.

All nodes support JSON marshalling and unmarshalling through the standard encoding/json interfaces, so you can use the standard functions for loading and saving trees. However, if you want to load a root node of the correct type from JSON, you need to use the UnmarshalRootJSON function.

All node types must be added to the Cogent Core type registry via typegen, so you must add a go:generate line that runs `core generate` to any packages you write that have new node types defined.

func NewNodeBase

func NewNodeBase(parent ...Node) *NodeBase

NewNodeBase returns a new NodeBase with the given optional parent: NodeBase implements the Node interface and provides the core functionality for the Cogent Core tree system. You must use NodeBase as an embedded struct in all higher-level tree types.

All nodes must be properly initialized by using one of New, NodeBase.NewChild, NodeBase.AddChild, NodeBase.InsertChild, NodeBase.Clone, Update, or Plan. This ensures that the [NodeBase.This] field is set correctly and the [Node.Init] method is called.

All nodes support JSON marshalling and unmarshalling through the standard encoding/json interfaces, so you can use the standard functions for loading and saving trees. However, if you want to load a root node of the correct type from JSON, you need to use the UnmarshalRootJSON function.

All node types must be added to the Cogent Core type registry via typegen, so you must add a go:generate line that runs `core generate` to any packages you write that have new node types defined.

func (*NodeBase) AddChild

func (n *NodeBase) AddChild(kid Node)

AddChild adds given child at end of children list. The kid node is assumed to not be on another tree (see MoveToParent) and the existing name should be unique among children.

func (*NodeBase) AsTree added in v0.2.0

func (n *NodeBase) AsTree() *NodeBase

AsTree returns the NodeBase for this Node.

func (*NodeBase) Child

func (n *NodeBase) Child(i int) Node

Child returns the child of this node at the given index and returns nil if the index is out of range.

func (*NodeBase) ChildByName

func (n *NodeBase) ChildByName(name string, startIndex ...int) Node

ChildByName returns the first child that has the given name, and nil if no such element is found. startIndex arg allows for optimized bidirectional find if you have an idea where it might be, which can be a key speedup for large lists. If no value is specified for startIndex, it starts in the middle, which is a good default.

func (*NodeBase) Clone

func (n *NodeBase) Clone() Node

Clone creates and returns a deep copy of the tree from this node down. Any pointers within the cloned tree will correctly point within the new cloned tree (see [Node.CopyFrom] for more information).

func (*NodeBase) CopyFieldsFrom

func (n *NodeBase) CopyFieldsFrom(from Node)

CopyFieldsFrom copies the fields of the node from the given node. By default, it is NodeBase.CopyFieldsFrom, which automatically does a deep copy of all of the fields of the node that do not a have a `copier:"-"` struct tag. Node types should only implement a custom CopyFieldsFrom method when they have fields that need special copying logic that can not be automatically handled. All custom CopyFieldsFrom methods should call NodeBase.CopyFieldsFrom first and then only do manual handling of specific fields that can not be automatically copied. See cogentcore.org/core/core.WidgetBase.CopyFieldsFrom for an example of a custom CopyFieldsFrom method.

func (*NodeBase) CopyFrom

func (n *NodeBase) CopyFrom(from Node)

CopyFrom copies the data and children of the given node to this node. It is essential that the source node has unique names. It is very efficient by using the [Node.ConfigChildren] method which attempts to preserve any existing nodes in the destination if they have the same name and type, so a copy from a source to a target that only differ minimally will be minimally destructive. Only copying to the same type is supported. The struct field tag copier:"-" can be added for any fields that should not be copied. Also, unexported fields are not copied. See [Node.CopyFieldsFrom] for more information on field copying.

func (*NodeBase) Delete

func (n *NodeBase) Delete()

Delete deletes this node from its parent's children list and then destroys itself.

func (*NodeBase) DeleteChild

func (n *NodeBase) DeleteChild(child Node) bool

DeleteChild deletes the given child node, returning false if it can not find it.

func (*NodeBase) DeleteChildAt added in v0.2.0

func (n *NodeBase) DeleteChildAt(index int) bool

DeleteChildAt deletes child at the given index. It returns false if there is no child at the given index.

func (*NodeBase) DeleteChildByName

func (n *NodeBase) DeleteChildByName(name string) bool

DeleteChildByName deletes child node by name, returning false if it can not find it.

func (*NodeBase) DeleteChildren

func (n *NodeBase) DeleteChildren()

DeleteChildren deletes all children nodes.

func (*NodeBase) DeleteProperty

func (n *NodeBase) DeleteProperty(key string)

DeleteProperty deletes the property with the given key.

func (*NodeBase) Destroy

func (n *NodeBase) Destroy()

Destroy recursively deletes and destroys the node, all of its children, and all of its children's children, etc.

func (*NodeBase) FinalMaker added in v0.2.0

func (nb *NodeBase) FinalMaker(maker func(p *Plan))

FinalMaker adds a new function to [NodeBase.Makers.Final], which are called in sequential ascending order in NodeBase.Make to make the plan for how the node's children should be configured.

func (*NodeBase) FinalUpdater added in v0.2.0

func (nb *NodeBase) FinalUpdater(updater func())

FinalUpdater adds a new function to [NodeBase.Updaters.Final], which are called in sequential descending (reverse) order in NodeBase.RunUpdaters to update the node.

func (*NodeBase) FindPath

func (n *NodeBase) FindPath(path string) Node

FindPath returns the node at the given path from this node. FindPath only works correctly when names are unique. The given path must be consistent with the format produced by NodeBase.PathFrom. There is also support for index-based access (ie: [0] for the first child) for cases where indexes are more useful than names. It returns nil if no node is found at the given path.

func (*NodeBase) FirstMaker added in v0.2.0

func (nb *NodeBase) FirstMaker(maker func(p *Plan))

FirstMaker adds a new function to [NodeBase.Makers.First], which are called in sequential ascending order in NodeBase.Make to make the plan for how the node's children should be configured.

func (*NodeBase) FirstUpdater added in v0.2.0

func (nb *NodeBase) FirstUpdater(updater func())

FirstUpdater adds a new function to [NodeBase.Updaters.First], which are called in sequential descending (reverse) order in NodeBase.RunUpdaters to update the node.

func (*NodeBase) HasChildren

func (n *NodeBase) HasChildren() bool

HasChildren returns whether this node has any children.

func (*NodeBase) IndexInParent

func (n *NodeBase) IndexInParent() int

IndexInParent returns our index within our parent node. It caches the last value and uses that for an optimized search so subsequent calls are typically quite fast. Returns -1 if we don't have a parent.

func (*NodeBase) Init added in v0.2.0

func (n *NodeBase) Init()

Init is a placeholder implementation of [Node.Init] that does nothing.

func (*NodeBase) InsertChild

func (n *NodeBase) InsertChild(kid Node, index int)

InsertChild adds given child at position in children list. The kid node is assumed to not be on another tree (see MoveToParent) and the existing name should be unique among children.

func (*NodeBase) Make added in v0.2.0

func (nb *NodeBase) Make(p *Plan)

Make makes a plan for how the node's children should be structured. It does this by running [NodeBase.Makers] in sequential ascending order.

func (*NodeBase) Maker added in v0.2.0

func (nb *NodeBase) Maker(maker func(p *Plan))

Maker adds a new function to [NodeBase.Makers.Normal], which are called in sequential ascending order in NodeBase.Make to make the plan for how the node's children should be configured.

func (*NodeBase) MarshalJSON added in v0.2.0

func (n *NodeBase) MarshalJSON() ([]byte, error)

MarshalJSON marshals the node by injecting the [Node.NodeType] as a nodeType field and the NodeBase.NumChildren as a numChildren field at the start of the standard JSON encoding output.

func (*NodeBase) NewChild

func (n *NodeBase) NewChild(typ *types.Type) Node

NewChild creates a new child of the given type and adds it at the end of the list of children. The name defaults to the ID (kebab-case) name of the type, plus the [Node.NumLifetimeChildren] of the parent.

func (*NodeBase) NewInstance added in v0.2.1

func (n *NodeBase) NewInstance() Node

NewInstance returns a new instance of this node type.

func (*NodeBase) NodeType

func (n *NodeBase) NodeType() *types.Type

NodeType returns the types.Type of this node. If there is no types.Type registered for this node already, it registers one and then returns it.

func (NodeBase) NodeValue added in v0.2.1

func (nb NodeBase) NodeValue()

NodeValue implements NodeValue. It should not be called.

func (*NodeBase) NodeWalkDown

func (n *NodeBase) NodeWalkDown(fun func(n Node) bool)

NodeWalkDown is a placeholder implementation of [Node.NodeWalkDown] that does nothing.

func (*NodeBase) NumChildren

func (n *NodeBase) NumChildren() int

NumChildren returns the number of children this node has.

func (*NodeBase) OnAdd

func (n *NodeBase) OnAdd()

OnAdd is a placeholder implementation of [Node.OnAdd] that does nothing.

func (*NodeBase) ParentByName

func (n *NodeBase) ParentByName(name string) Node

ParentByName finds first parent recursively up hierarchy that matches the given name. It returns nil if not found.

func (*NodeBase) ParentLevel

func (n *NodeBase) ParentLevel(parent Node) int

ParentLevel finds a given potential parent node recursively up the hierarchy, returning the level above the current node that the parent was found, and -1 if not found.

func (*NodeBase) Path

func (n *NodeBase) Path() string

Path returns the path to this node from the tree root, using [Node.Name]s separated by / delimeters. Any existing / characters in names are escaped to \\

func (*NodeBase) PathFrom

func (n *NodeBase) PathFrom(parent Node) string

PathFrom returns the path to this node from the given parent node, using [Node.Name]s separated by / delimeters. Any existing / characters in names are escaped to \\

The paths that it returns exclude the name of the parent and the leading slash; for example, in the tree a/b/c/d/e, the result of d.PathFrom(b) would be c/d. PathFrom automatically gets the [NodeBase.This] version of the given parent, so a base type can be passed in without manually accessing [NodeBase.This].

func (*NodeBase) PlanName added in v0.2.0

func (n *NodeBase) PlanName() string

PlanName implements plan.Namer.

func (*NodeBase) Property

func (n *NodeBase) Property(key string) any

Property returns the property value for the given key. It returns nil if it doesn't exist.

func (*NodeBase) RunUpdaters added in v0.2.0

func (nb *NodeBase) RunUpdaters()

RunUpdaters runs the [NodeBase.Updaters] in sequential descending (reverse) order. It is called in cogentcore.org/core/core.WidgetBase.UpdateWidget and other places such as in xyz to update the node.

func (*NodeBase) SetName

func (t *NodeBase) SetName(v string) *NodeBase

SetName sets the [NodeBase.Name]: Name is the name of this node, which is typically unique relative to other children of the same parent. It can be used for finding and serializing nodes. If not otherwise set, it defaults to the ID (kebab-case) name of the node type combined with the total number of children that have ever been added to the node's parent.

func (*NodeBase) SetOnChildAdded added in v0.3.0

func (t *NodeBase) SetOnChildAdded(v func(n Node)) *NodeBase

SetOnChildAdded sets the [NodeBase.OnChildAdded]: OnChildAdded is called when a node is added as a direct child of this node. When a node is added to a parent, it calls [Node.OnAdd] on itself and then this function on its parent if it is non-nil.

func (*NodeBase) SetProperty

func (n *NodeBase) SetProperty(key string, value any)

SetProperty sets given the given property to the given value.

func (*NodeBase) String

func (n *NodeBase) String() string

String implements the fmt.Stringer interface by returning the path of the node.

func (*NodeBase) UnmarshalJSON added in v0.2.0

func (n *NodeBase) UnmarshalJSON(b []byte) error

UnmarshalJSON unmarshals the node by extracting the nodeType and numChildren fields added by NodeBase.MarshalJSON and then updating the node to the correct type and creating the correct number of children. Note that this method can not update the type of the node if it has no parent; to load a root node from JSON and have it be of the correct type, see the UnmarshalRootJSON function. If the type of the node is changed by this function, the node pointer will no longer be valid, and the node must be fetched again through the children of its parent. You do not need to call UnmarshalRootJSON or worry about pointers changing if this node is already of the correct type.

func (*NodeBase) UpdateFromMake added in v0.2.0

func (nb *NodeBase) UpdateFromMake()

UpdateFromMake updates the node using NodeBase.Make.

func (*NodeBase) Updater added in v0.2.0

func (nb *NodeBase) Updater(updater func())

Updater adds a new function to [NodeBase.Updaters.Normal], which are called in sequential descending (reverse) order in NodeBase.RunUpdaters to update the node.

func (*NodeBase) WalkDown

func (n *NodeBase) WalkDown(fun func(n Node) bool)

WalkDown calls the given function on the node and all of its children in a depth-first manner over all of the children, sequentially in the current goroutine. It stops walking the current branch of the tree if the function returns Break and keeps walking if it returns Continue. It is non-recursive and safe for concurrent calling. The [Node.NodeWalkDown] method is called for every node after the given function, which enables nodes to also traverse additional nodes, like widget parts.

func (*NodeBase) WalkDownBreadth

func (n *NodeBase) WalkDownBreadth(fun func(n Node) bool)

WalkDownBreadth calls the given function on the node and all of its children in breadth-first order. It stops walking the current branch of the tree if the function returns Break and keeps walking if it returns Continue. It is non-recursive, but not safe for concurrent calling.

func (*NodeBase) WalkDownPost

func (n *NodeBase) WalkDownPost(shouldContinue func(n Node) bool, fun func(n Node) bool)

WalkDownPost iterates in a depth-first manner over the children, calling shouldContinue on each node to test if processing should proceed (if it returns Break then that branch of the tree is not further processed), and then calls the given function after all of a node's children have been iterated over. In effect, this means that the given function is called for deeper nodes first. This uses node state information to manage the traversal and is very fast, but can only be called by one goroutine at a time, so you should use a Mutex if there is a chance of multiple threads running at the same time. The nodes are processed in the current goroutine.

func (*NodeBase) WalkUp

func (n *NodeBase) WalkUp(fun func(n Node) bool) bool

WalkUp calls the given function on the node and all of its parents, sequentially in the current goroutine (generally necessary for going up, which is typically quite fast anyway). It stops walking if the function returns Break and keeps walking if it returns Continue. It returns whether walking was finished (false if it was aborted with Break).

func (*NodeBase) WalkUpParent

func (n *NodeBase) WalkUpParent(fun func(n Node) bool) bool

WalkUpParent calls the given function on all of the node's parents (but not the node itself), sequentially in the current goroutine (generally necessary for going up, which is typically quite fast anyway). It stops walking if the function returns Break and keeps walking if it returns Continue. It returns whether walking was finished (false if it was aborted with Break).

type NodeValue added in v0.2.1

type NodeValue interface {

	// NodeValue should only be implemented by [NodeBase],
	// and it should not be called. It must be exported due
	// to a nuance with the way that [reflect.StructOf] works,
	// which results in panics with embedded structs that have
	// unexported non-pointer methods.
	NodeValue()
}

NodeValue is an interface that all non-pointer tree nodes satisfy. Pointer tree nodes satisfy Node, not NodeValue. NodeValue and Node are mutually exclusive; a Node cannot be a NodeValue and vice versa. However, a pointer to a NodeValue type is guaranteed to be a Node, and a non-pointer version of a Node type is guaranteed to be a NodeValue.

type Plan added in v0.2.0

type Plan struct {

	// Children are the [PlanItem]s for the children.
	Children []*PlanItem

	// EnforceEmpty is whether an empty plan results in the removal
	// of all children of the parent. If there are [NodeBase.Makers]
	// defined then this is true by default; otherwise it is false.
	EnforceEmpty bool
}

Plan represents a plan for how the children of a Node should be configured. A Plan instance is passed to [NodeBase.Makers], which are responsible for configuring it. To add a child item to a plan, use Add, AddAt, or AddNew. To add a child item maker to a Node, use AddChild or AddChildAt. To extend an existing child item, use AddInit or AddChildInit.

func (*Plan) Add added in v0.2.0

func (p *Plan) Add(name string, new func() Node, init func(w Node))

Add adds a new PlanItem with the given name and functions to the Plan. It should typically not be called by end-user code; see the generic Add, AddAt, AddNew, AddChild, AddChildAt, AddInit, and AddChildInit functions instead.

func (*Plan) Update added in v0.2.0

func (p *Plan) Update(n Node)

Update updates the children of the given Node in accordance with the Plan.

type PlanItem added in v0.2.0

type PlanItem struct {

	// Name is the name of the planned node.
	Name string

	// New returns a new node of the correct type for this child.
	New func() Node

	// Init is a slice of functions that are called once in sequential ascending order
	// after [PlanItem.New] to initialize the node for the first time.
	Init []func(n Node)
}

PlanItem represents a plan for how a child Node should be constructed and initialized. See Plan for more information.

type TypePlan added in v0.2.0

type TypePlan []TypePlanItem

TypePlan is a plan for the organization of a list of tree nodes, specified by the Type of element at a given index, with a given name. It is used in Update and UpdateSlice to actually update the items according to the plan.

func (*TypePlan) Add added in v0.2.0

func (t *TypePlan) Add(typ *types.Type, name string)

Add adds a new TypePlanItem with the given type and name.

type TypePlanItem added in v0.2.0

type TypePlanItem struct {
	Type *types.Type
	Name string
}

TypePlanItem holds a type and a name, for specifying the TypePlan.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL