ki

package
v1.1.17 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2023 License: BSD-3-Clause Imports: 20 Imported by: 235

Documentation

Overview

Package ki provides the base element of GoKi Trees: Ki = Tree in Japanese, and "Key" in English -- powerful tree structures supporting scenegraphs, programs, parsing, etc.

The Node struct that implements the Ki interface, which can be used as an embedded type (or a struct field) in other structs to provide core tree functionality, including:

  • Parent / Child Tree structure -- each Node can ONLY have one parent. Node struct's can also have Node fields -- these are functionally like fixed auto-named children.

  • Paths for locating Nodes within the hierarchy -- key for many use-cases, including ability to convert pointers to/from strings for IO and robust deep copy and move functions. The path separator is / for children and . for fields.

  • Apply a function across nodes up or down a tree (natural "me first", breadth-first, depth-first) -- very flexible for tree walking.

  • Generalized I/O -- can Save and Load the Tree as JSON, XML, etc -- including pointers which are saved using paths and automatically cached-out after loading -- enums also bidirectionally convertable to strings using enum type registry in kit package.

  • Robust deep copy, clone, move of nodes, with automatic pointer updating.

  • Signal sending and receiving between Nodes (simlar to Qt Signals / Slots) -- setup connections once and then emit signals to all receivers when relevant event happens.

  • Robust state updating -- wrap updates in UpdateStart / End, and signals are blocked until the final end, at the highest affected level in the tree, at which point a single update signal is sent -- automatically gives the minimal update.

  • Properties (as a string-keyed map) with property inheritance, including type-level properties via kit type registry.

In general, the names of the children of a given node should all be unique. The following functions defined in ki package can be used:

* UniqueNameCheck(node) to check for unique names on node if uncertain. * UniqueNameCheckAll(node) to check entire tree under given node. * UniquifyNames(node) to add a suffix to name to ensure uniqueness. * UniquifyNamesAll(node) to to uniquify all names in entire tree.

The Ki interface is designed to support virtual method calling in Go and is only intended to be implemented once, by the ki.Node type (as opposed to interfaces that are used for hiding multiple different implementations of a common concept). Thus, all of the fields in ki.Node are exported (have captital names), to be accessed directly in types that embed and extend the ki.Node. The Ki interface has the "formal" name (e.g., Children) while the Node has the "nickname" (e.g., Kids). See the Naming Conventions on the GoKi Wiki for more details.

Each Node stores the Ki interface version of itself, as This() / Ths which enables full virtual function calling by calling the method on that interface instead of directly on the receiver Node itself. This requires proper initialization via Init method of the Ki 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

	// Embeds is used for methods that look for children or parents of different types.
	// Passing this argument means to look for embedded types for matches.
	Embeds = true

	// NoEmbeds is used for methods that look for children or parents of different types.
	// Passing this argument means to NOT look for embedded types for matches.
	NoEmbeds = false

	// DestroyKids is used for Delete methods to indicate that deleted children
	// should be destroyed (else can be re-used somewhere else).
	DestroyKids = true

	// NoDestroyKids is used for Delete methods to indicate that deleted children
	// should NOT be destroyed, so they can be re-used somewhere else.
	NoDestroyKids = false

	// ShallowCopy is used for Props CopyFrom functions to indicate a shallow copy of
	// Props or PropSlice within Props (points to source props)
	ShallowCopy = true

	// DeepCopy is used for Props CopyFrom functions to indicate a deep copy of
	// Props or PropSlice within Props
	DeepCopy = true

	// Inherit is used for PropInherit to indicate that inherited properties
	// from parent objects should be checked as well.  Otherwise not.
	Inherit = true

	// NoInherit is used for PropInherit to indicate that inherited properties
	// from parent objects should NOT be checked.
	NoInherit = false

	// TypeProps is used for PropInherit to indicate that properties
	// set on the type should be checked.
	TypeProps = true

	// NoTypeProps is used for PropInherit to indicate that properties
	// set on the type should NOT be checked.
	NoTypeProps = false

	// Indent is used for Write methods to indicate that indenting should be done.
	Indent = true

	// NoIndent is used for Write methods to indicate that indenting should NOT be done.
	NoIndent = false
)

Named consts for bool args

View Source
const (
	Version     = "v1.1.17"
	GitCommit   = "018e731"          // the commit JUST BEFORE the release
	VersionDate = "2023-10-05 21:52" // UTC
)
View Source
const EnumTypeFlag string = "EnumType:Flag"

EnumTypeFlag is a Props property name that indicates what enum type to use as the type for the flags field in GUI views. Its value should be of the type reflect.Type

View Source
const StartMiddle int = -1

StartMiddle indicates to start searching in the middle for slice search functions.

Variables

View Source
var DelMgr = Deleted{}

DelMgr is the manager of all deleted items

View Source
var JSONTypePrefix = []byte("{\"ki.RootType\": ")

JSONTypePrefix is the first thing output in a ki tree JSON output file, specifying the type of the root node of the ki tree -- this info appears all on one { } bracketed line at the start of the file, and can also be used to identify the file as a ki tree JSON file

View Source
var JSONTypeSuffix = []byte("}\n")

JSONTypeSuffix is just the } and \n at the end of the prefix line

View Source
var KiT_Flags = kit.Enums.AddEnum(FlagsN, kit.BitFlag, nil)
View Source
var KiT_Node = kit.Types.AddType(&Node{}, Props{EnumTypeFlag: KiT_Flags})

must register all new types so type names can be looked up by name -- also props EnumType:Flags registers KiT_Flags as type for Flags field for GUI views Nodes can also use type properties e.g., StructViewFields key with props inside that to set view properties for types, e.g., to hide or show some of these base Node flags.

View Source
var KiT_Props = kit.Types.AddType(&Props{}, PropsProps)
View Source
var KiT_Signal = kit.Types.AddType(&Signal{}, nil)
View Source
var KiType = reflect.TypeOf((*Ki)(nil)).Elem()

KiType is a Ki reflect.Type, suitable for checking for Type.Implements.

View Source
var PropsProps = Props{
	"basic-type": true,
}
View Source
var SignalTrace bool = false

SignalTrace can be set to true to automatically print out a trace of the signals as they are sent

View Source
var SignalTraceString *string

SignalTraceString can be set to a string that will then accumulate the trace of signals sent, for use in testing -- otherwise the trace just goes to stdout

View Source
var UniquifyIndexAbove = 1000

UniquifyIndexAbove is the number of children above which UniquifyNamesAddIndex is called -- that is much faster for large numbers of children. Must be < 1000

Functions

func AddNew added in v1.1.16

func AddNew[T Ki](par Ki, name string)

AddNew adds a new child of the given the type with the given name to the given parent. It is a helper function that calls [Ki.AddNewChild].

func CopyFromRaw added in v1.1.0

func CopyFromRaw(kn, frm Ki) error

CopyFromRaw performs a raw copy that just does the deep copy of the bits and doesn't do anything with pointers.

func CopyProps

func CopyProps(dest *map[string]any, src map[string]any, deepCopy bool)

CopyProps copies properties from source to destination map. If deepCopy is true, then any values that are Props or PropSlice are copied too *dest can be nil, in which case it is created.

func DecodeXMLCharData

func DecodeXMLCharData(d *xml.Decoder) (val string, err error)

DecodeXMLCharData reads char data..

func DecodeXMLCharEl

func DecodeXMLCharEl(d *xml.Decoder) (name, val string, err error)

DecodeXMLCharEl reads a start / chardata / end sequence of 3 elements, returning name, val

func DecodeXMLEndEl

func DecodeXMLEndEl(d *xml.Decoder, start xml.StartElement) error

DecodeXMLEndEl reads an end element

func DecodeXMLStartEl

func DecodeXMLStartEl(d *xml.Decoder) (start xml.StartElement, err error)

DecodeXMLStartEl reads a start element token

func Depth added in v1.1.0

func Depth(kn Ki) int

Depth returns the current depth of the node. This is only valid in a given context, not a stable property of the node (e.g., used in FuncDownBreadthFirst).

func EscapePathName added in v1.1.0

func EscapePathName(name string) string

EscapePathName returns a name that replaces any path delimiter symbols . or / with \, and \\ escaped versions.

func FieldByName added in v1.1.0

func FieldByName(kn Ki, field string) any

FieldByName returns field value by name (can be any type of field -- see KiFieldByName for Ki fields) -- returns nil if not found.

func FieldByNameTry added in v1.1.0

func FieldByNameTry(kn Ki, field string) (any, error)

FieldByNameTry returns field value by name (can be any type of field -- see KiFieldByName for Ki fields) -- returns error if not found.

func FieldTag added in v1.1.0

func FieldTag(kn Ki, field, tag string) string

FieldTag returns given field tag for that field, or empty string if not set.

func FlatFieldsValueFunc

func FlatFieldsValueFunc(stru any, fun func(stru any, typ reflect.Type, field reflect.StructField, fieldVal reflect.Value) bool) bool

FlatFieldsValueFunc is the Node version of this function from kit/embeds.go it is very slow and should be avoided at all costs!

func GenCopyFieldsFrom added in v0.9.8

func GenCopyFieldsFrom(to any, frm any)

GenCopyFieldsFrom is a general-purpose copy of primary fields of source object, recursively following anonymous embedded structs

func InitNode added in v1.1.0

func InitNode(this Ki)

InitNode initializes the node -- automatically called during Add/Insert Child -- sets the This pointer for this node as a Ki interface (pass pointer to node as this arg) -- Go cannot always access the true underlying type for structs using embedded Ki objects (when these objs are receivers to methods) so we need a This interface pointer that guarantees access to the Ki interface in a way that always reveals the underlying type (e.g., in reflect calls). Calls Init on Ki fields within struct, sets their names to the field name, and sets us as their parent.

func IsKi

func IsKi(typ reflect.Type) bool

IsKi returns true if the given type implements the Ki interface at any level of embedded structure.

func IsRoot added in v1.1.0

func IsRoot(k Ki) bool

IsRoot tests if this node is the root node -- checks Parent = nil.

func KiFieldNames added in v1.1.0

func KiFieldNames(n *Node) []string

KiFieldNames returns the field names for Ki fields of this Node. Cached for fast access.

func KiFieldOffs added in v1.1.0

func KiFieldOffs(n *Node) []uintptr

KiFieldOffs returns the uintptr offsets for Ki fields of this Node. Cached for fast access, but use HasKiFields for even faster checking.

func KiFieldsInit added in v1.1.0

func KiFieldsInit(n *Node) (foff []uintptr, fnm []string)

KiFieldsInit initializes cached data about the KiFields in this node offsets and names -- returns them

func KiHasKiFields added in v1.1.0

func KiHasKiFields(n *Node) bool

KiHasKiFields returns true if this node has Ki Node fields that are included in recursive descent traversal of the tree. This is very efficient compared to accessing the field information on the type so it should be checked first -- caches the info on the node in flags.

func KiInitKiFields added in v1.1.16

func KiInitKiFields(this Ki)

KiInitKiFields calls Init on all Ki fields within the struct, sets their names to the field name, and sets us as their parent.

func MoveToParent added in v1.1.0

func MoveToParent(kid Ki, parent Ki)

MoveToParent deletes given node from its current parent and adds it as a child of given new parent. Parents could be in different trees or not.

func NumKiFields added in v1.1.0

func NumKiFields(n *Node) int

NumKiFields returns the number of Ki Node fields on this node. This calls HasKiFields first so it is also efficient.

func ParentAllChildren added in v1.1.0

func ParentAllChildren(kn Ki)

ParentAllChildren walks the tree down from current node and call SetParent on all children -- needed after an Unmarshal.

func SetDepth added in v1.1.0

func SetDepth(kn Ki, depth int)

SetDepth sets the current depth of the node to given value.

func SetParent added in v1.1.0

func SetParent(kid Ki, parent Ki)

SetParent just sets parent of node (and inherits update count from parent, to keep consistent). Assumes not already in a tree or anything.

func SetPropStr

func SetPropStr(pr Props, key, val string)

SetPropStr is a convenience method for e.g., python wrapper that avoids need to deal directly with props interface{} type

func SetSubProps

func SetSubProps(pr Props, key string, sp Props)

SetSubProps is a convenience method for e.g., python wrapper that avoids need to deal directly with props interface{} type

func SliceDeleteAtIndex

func SliceDeleteAtIndex(sl *[]Ki, idx int) error

SliceDeleteAtIndex deletes item at index -- does not do any further management deleted item -- optimized version for avoiding memory leaks. returns error if index is invalid.

func SliceIndexByFunc

func SliceIndexByFunc(sl *[]Ki, startIdx int, match func(k Ki) bool) (int, bool)

SliceIndexByFunc finds index of item based on match function (which must return true for a find match, false for not). Returns false if not found. startIdx arg allows for optimized bidirectional find if you have an idea where it might be -- can be key speedup for large lists -- pass ki.StartMiddle to start in the middle (good default)

func SliceIndexByName

func SliceIndexByName(sl *[]Ki, name string, startIdx int) (int, bool)

SliceIndexByName returns index of first element that has given name, false if not found. See IndexOf for info on startIdx.

func SliceIndexByType

func SliceIndexByType(sl *[]Ki, t reflect.Type, embeds bool, startIdx int) (int, bool)

SliceIndexByType returns index of element that either is that type or embeds that type, false if not found. See IndexOf for info on startIdx.

func SliceIndexOf

func SliceIndexOf(sl *[]Ki, kid Ki, startIdx int) (int, bool)

SliceIndexOf returns index of element in list, false if not there. startIdx arg allows for optimized bidirectional find if you have an idea where it might be -- can be key speedup for large lists -- pass ki.StartMiddle to start in the middle (good default).

func SliceInsert

func SliceInsert(sl *[]Ki, k Ki, idx int)

SliceInsert item at index -- does not do any parent updating etc -- use Ki/Node method unless you know what you are doing.

func SliceIsValidIndex

func SliceIsValidIndex(sl *[]Ki, idx int) error

SliceIsValidIndex checks whether the given index is a valid index into slice, within range of 0..len-1. Returns error if not.

func SliceMove

func SliceMove(sl *[]Ki, frm, to int) error

SliceMove moves element from one position to another. Returns error if either index is invalid.

func SliceSwap

func SliceSwap(sl *[]Ki, i, j int) error

SliceSwap swaps elements between positions. Returns error if either index is invalid

func ThisCheck added in v1.1.0

func ThisCheck(k Ki) error

ThisCheck checks that the This pointer is set and issues a warning to log if not -- returns error if not set -- called when nodes are added and inserted.

func Type added in v1.1.0

func Type(k Ki) reflect.Type

Type returns the underlying struct type of given node

func TypeEmbeds added in v1.1.0

func TypeEmbeds(k Ki, t reflect.Type) bool

TypeEmbeds tests whether this node is of the given type, or it embeds that type at any level of anonymous embedding -- use Embed to get the embedded struct of that type from this node.

func UnescapePathName added in v1.1.0

func UnescapePathName(name string) string

UnescapePathName returns a name that replaces any escaped path delimiter symbols \, or \\ with . and / unescaped versions.

func UniqueNameCheck added in v1.1.0

func UniqueNameCheck(k Ki) bool

UniqueNameCheck checks if all the children names are unique or not. returns true if all names are unique; false if not if not unique, call UniquifyNames or take other steps to ensure uniqueness.

func UniqueNameCheckAll added in v1.1.0

func UniqueNameCheckAll(kn Ki) bool

UniqueNameCheckAll checks entire tree from given node, if all the children names are unique or not. returns true if all names are unique; false if not if not unique, call UniquifyNames or take other steps to ensure uniqueness.

func UniquifyNames added in v1.1.0

func UniquifyNames(kn Ki)

UniquifyNames makes sure that the names are unique. If number of children >= UniquifyIndexAbove, then UniquifyNamesAddIndex is called, for faster performance. Otherwise, existing names are preserved if they are unique, and only duplicates are renamed. This is a bit slower.

func UniquifyNamesAddIndex added in v1.1.0

func UniquifyNamesAddIndex(kn Ki)

UniquifyNamesAddIndex makes sure that the names are unique by automatically adding a suffix with index number, separated by underbar. Empty names get the parent name as a prefix. if there is an existing underbar, then whatever is after it is replaced with the unique index, ensuring that multiple calls are safe!

func UniquifyNamesAll added in v1.1.0

func UniquifyNamesAll(kn Ki)

UniquifyNamesAll makes sure that the names are unique for entire tree If number of children >= UniquifyIndexAbove, then UniquifyNamesAddIndex is called, for faster performance. Otherwise, existing names are preserved if they are unique, and only duplicates are renamed. This is a bit slower.

func UnmarshalPost added in v1.1.0

func UnmarshalPost(kn Ki)

UnmarshalPost must be called after an Unmarshal -- calls ParentAllChildren.

func UpdateReset added in v1.1.0

func UpdateReset(kn Ki)

UpdateReset resets Updating flag for this node and all children -- in case they are out-of-sync due to more complex tree maninpulations -- only call at a known point of non-updating.

Types

type BlankProp

type BlankProp struct{}

BlankProp is an empty property, for when there isn't any need for the value

type Deleted

type Deleted struct {
	Dels []Ki
	Mu   sync.Mutex
}

Deleted manages all the deleted Ki elements, that are destined to then be destroyed, without having an additional pointer on the Ki object

func (*Deleted) Add

func (dm *Deleted) Add(kis ...Ki)

Add the Ki elements to the deleted list

func (*Deleted) DestroyDeleted

func (dm *Deleted) DestroyDeleted()

DestroyDeleted destroys any deleted items in list

type Flags

type Flags int32

Flags are bit flags for efficient core state of nodes -- see bitflag package for using these ordinal values to manipulate bit flag field.

const (
	// IsField indicates a node is a field in its parent node, not a child in children.
	IsField Flags = iota

	// HasKiFields indicates a node has Ki Node fields that will be processed in recursive descent.
	// Use the HasFields() method to check as it will establish validity of flags on first call.
	// If neither HasFields nor HasNoFields are set, then it knows to update flags.
	HasKiFields

	// HasNoKiFields indicates a node has NO Ki Node fields that will be processed in recursive descent.
	// Use the HasFields() method to check as it will establish validity of flags on first call.
	// If neither HasFields nor HasNoFields are set, then it knows to update flags.
	HasNoKiFields

	// Updating flag is set at UpdateStart and cleared if we were the first
	// updater at UpdateEnd.
	Updating

	// OnlySelfUpdate means that the UpdateStart / End logic only applies to
	// this node in isolation, not to its children -- useful for a parent node
	// that has a different functional role than its children.
	OnlySelfUpdate

	// NodeDeleted means this node has been deleted.
	NodeDeleted

	// NodeDestroyed means this node has been destroyed -- do not trigger any
	// more update signals on it.
	NodeDestroyed

	// ChildAdded means one or more new children were added to the node.
	ChildAdded

	// ChildDeleted means one or more children were deleted from the node.
	ChildDeleted

	// ChildrenDeleted means all children were deleted.
	ChildrenDeleted

	// ValUpdated means a value was updated (Field, Prop, any kind of value)
	ValUpdated

	// FlagsN is total number of flags used by base Ki Node -- can extend from
	// here up to 64 bits.
	FlagsN

	// ChildUpdateFlagsMask is a mask for all child updates.
	ChildUpdateFlagsMask = (1 << uint32(ChildAdded)) | (1 << uint32(ChildDeleted)) | (1 << uint32(ChildrenDeleted))

	// StruUpdateFlagsMask is a mask for all structural changes update flags.
	StruUpdateFlagsMask = ChildUpdateFlagsMask | (1 << uint32(NodeDeleted))

	// ValUpdateFlagsMask is a mask for all non-structural, value-only changes update flags.
	ValUpdateFlagsMask = (1 << uint32(ValUpdated))

	// UpdateFlagsMask is a Mask for all the update flags -- destroyed is
	// excluded b/c otherwise it would get cleared.
	UpdateFlagsMask = StruUpdateFlagsMask | ValUpdateFlagsMask
)

func (Flags) Desc added in v1.1.16

func (i Flags) Desc() string

func (*Flags) FromString

func (i *Flags) FromString(s string) error

func (Flags) String

func (i Flags) String() string

type Func

type Func func(k Ki, level int, data any) bool

Func is a function to call on ki objects walking the tree -- return Break = false means don't continue processing this branch of the tree, but other branches can continue. return Continue = true continues down the tree.

type Ki

type Ki interface {
	// InitName initializes this node to given actual object as a Ki interface
	// and sets its name.  The names should be unique among children of a node.
	// This is needed for root nodes -- automatically done for other nodes
	// when they are added to the Ki tree.
	// Even though this is a method and gets the method receiver, it needs
	// an "external" version of itself passed as the first arg, from which
	// the proper Ki interface pointer will be obtained.  This is the only
	// way to get virtual functional calling to work within the Go language.
	InitName(this Ki, name string)

	// This returns the Ki interface that guarantees access to the Ki
	// interface in a way that always reveals the underlying type
	// (e.g., in reflect calls).  Returns nil if node is nil,
	// has been destroyed, or is improperly constructed.
	This() Ki

	// AsNode returns the *ki.Node base type for this node.
	AsNode() *Node

	// Embed returns the embedded struct of given type from this node (or nil
	// if it does not embed that type, or the type is not a Ki type -- see
	// kit.Embed for a generic interface{} version.
	Embed(t reflect.Type) Ki

	// BaseIface returns the base interface type for all elements
	// within this tree.  Use reflect.TypeOf((*<interface_type>)(nil)).Elem().
	// Used e.g., for determining what types of children
	// can be created (see kit.EmbedImplements for test method)
	BaseIface() reflect.Type

	// Name returns the user-defined name of the object (Node.Nm),
	// for finding elements, generating paths, IO, etc.
	Name() string

	// SetName sets the name of this node.
	// Names should generally be unique across children of each node.
	// See Unique* functions to check / fix.
	// If node requires non-unique names, add a separate Label field.
	// Does NOT wrap in UpdateStart / End.
	SetName(name string)

	// Parent returns the parent of this Ki (Node.Par) -- Ki has strict
	// one-parent, no-cycles structure -- see SetParent.
	Parent() Ki

	// IndexInParent returns our index within our parent object -- caches the
	// last value and uses that for an optimized search so subsequent calls
	// are typically quite fast.  Returns false if we don't have a parent.
	IndexInParent() (int, bool)

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

	// ParentByName finds first parent recursively up hierarchy that matches
	// given name.  Returns nil if not found.
	ParentByName(name string) Ki

	// ParentByNameTry finds first parent recursively up hierarchy that matches
	// given name -- Try version returns error on failure.
	ParentByNameTry(name string) (Ki, error)

	// ParentByType finds parent recursively up hierarchy, by type, and
	// returns nil if not found. If embeds is true, then it looks for any
	// type that embeds the given type at any level of anonymous embedding.
	ParentByType(t reflect.Type, embeds bool) Ki

	// ParentByTypeTry finds parent recursively up hierarchy, by type, and
	// returns error if not found. If embeds is true, then it looks for any
	// type that embeds the given type at any level of anonymous embedding.
	ParentByTypeTry(t reflect.Type, embeds bool) (Ki, error)

	// HasChildren tests whether this node has children (i.e., non-terminal).
	HasChildren() bool

	// NumChildren returns the number of children
	NumChildren() int

	// Children returns a pointer to the slice of children (Node.Kids) -- use
	// methods on ki.Slice for further ways to access (ByName, ByType, etc).
	// Slice can be modified, deleted directly (e.g., sort, reorder) but Add
	// method on parent node should be used to ensure proper init.
	Children() *Slice

	// Child returns the child at given index -- will panic if index is invalid.
	// See methods on ki.Slice for more ways to access.
	Child(idx int) Ki

	// ChildTry returns the child at given index -- Try version returns
	// error if index is invalid.
	// See methods on ki.Slice for more ways to access.
	ChildTry(idx int) (Ki, error)

	// ChildByName returns first element that has given name, nil if not found.
	// startIdx arg allows for optimized bidirectional find if you have
	// an idea where it might be -- can be key speedup for large lists -- pass
	// [ki.StartMiddle] to start in the middle (good default).
	ChildByName(name string, startIdx int) Ki

	// ChildByNameTry returns first element that has given name -- Try version
	// returns error message if not found.
	// startIdx arg allows for optimized bidirectional find if you have
	// an idea where it might be -- can be key speedup for large lists -- pass
	// [ki.StartMiddle] to start in the middle (good default).
	ChildByNameTry(name string, startIdx int) (Ki, error)

	// ChildByType returns first element that has given type, nil if not found.
	// If embeds is true, then it looks for any type that embeds the given type
	// at any level of anonymous embedding.
	// startIdx arg allows for optimized bidirectional find if you have
	// an idea where it might be -- can be key speedup for large lists -- pass
	// [ki.StartMiddle] to start in the middle (good default).
	ChildByType(t reflect.Type, embeds bool, startIdx int) Ki

	// ChildByTypeTry returns first element that has given name -- Try version
	// returns error message if not found.
	// If embeds is true, then it looks for any type that embeds the given type
	// at any level of anonymous embedding.
	// startIdx arg allows for optimized bidirectional find if you have
	// an idea where it might be -- can be key speedup for large lists -- pass
	// [ki.StartMiddle] to start in the middle (good default).
	ChildByTypeTry(t reflect.Type, embeds bool, startIdx int) (Ki, error)

	// Path returns path to this node from the tree root, using node Names
	// separated by / and fields by .
	// Node names escape any existing / and . characters to \\ and \,
	// Path is only valid when child names are unique (see Unique* functions)
	Path() string

	// PathFrom returns path to this node from given parent node, using
	// node Names separated by / and fields by .
	// Node names escape any existing / and . characters to \\ and \,
	// Path is only valid when child names are unique (see Unique* functions)
	PathFrom(par Ki) string

	// FindPath returns Ki object at given path, starting from this node
	// (e.g., the root).  If this node is not the root, then the path
	// to this node is subtracted from the start of the path if present there.
	// FindPath only works correctly when names are unique.
	// Path has node Names separated by / and fields by .
	// Node names escape any existing / and . characters to \\ and \,
	// There is also support for [idx] index-based access for any given path
	// element, for cases when indexes are more useful than names.
	// Returns nil if not found.
	FindPath(path string) Ki

	// FindPathTry returns Ki object at given path, starting from this node
	// (e.g., the root).  If this node is not the root, then the path
	// to this node is subtracted from the start of the path if present there.
	// FindPath only works correctly when names are unique.
	// Path has node Names separated by / and fields by .
	// Node names escape any existing / and . characters to \\ and \,
	// There is also support for [idx] index-based access for any given path
	// element, for cases when indexes are more useful than names.
	// Returns error if not found.
	FindPathTry(path string) (Ki, error)

	// 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.
	// No UpdateStart / End wrapping is done: do that externally as needed.
	// Can also call SetFlag(ki.ChildAdded) if notification is needed.
	AddChild(kid Ki) error

	// AddNewChild creates a new child of given type and
	// add at end of children list.
	// The name should be unique among children.
	// No UpdateStart / End wrapping is done: do that externally as needed.
	// Can also call SetFlag(ki.ChildAdded) if notification is needed.
	AddNewChild(typ reflect.Type, name string) Ki

	// SetChild sets child at given index to be the given item -- if name is
	// non-empty then it sets the name of the child as well -- just calls Init
	// (or InitName) on the child, and SetParent.
	// Names should be unique among children.
	// No UpdateStart / End wrapping is done: do that externally as needed.
	// Can also call SetFlag(ki.ChildAdded) if notification is needed.
	SetChild(kid Ki, idx int, name string) error

	// 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.
	// No UpdateStart / End wrapping is done: do that externally as needed.
	// Can also call SetFlag(ki.ChildAdded) if notification is needed.
	InsertChild(kid Ki, at int) error

	// InsertNewChild creates a new child of given type and
	// add at position in children list.
	// The name should be unique among children.
	// No UpdateStart / End wrapping is done: do that externally as needed.
	// Can also call SetFlag(ki.ChildAdded) if notification is needed.
	InsertNewChild(typ reflect.Type, at int, name string) Ki

	// SetNChildren ensures that there are exactly n children, deleting any
	// extra, and creating any new ones, using AddNewChild with given type and
	// naming according to nameStubX where X is the index of the child.
	//
	// IMPORTANT: returns whether any modifications were made (mods) AND if
	// that is true, the result from the corresponding UpdateStart call --
	// UpdateEnd is NOT called, allowing for further subsequent updates before
	// you call UpdateEnd(updt)
	//
	// Note that this does not ensure existing children are of given type, or
	// change their names, or call UniquifyNames -- use ConfigChildren for
	// those cases -- this function is for simpler cases where a parent uses
	// this function consistently to manage children all of the same type.
	SetNChildren(n int, typ reflect.Type, nameStub string) (mods, updt bool)

	// ConfigChildren configures children according to given list of
	// type-and-name's -- attempts to have minimal impact relative to existing
	// items that fit the type and name constraints (they are moved into the
	// corresponding positions), and any extra children are removed, and new
	// ones added, to match the specified config.
	// It is important that names are unique!
	//
	// IMPORTANT: returns whether any modifications were made (mods) AND if
	// that is true, the result from the corresponding UpdateStart call --
	// UpdateEnd is NOT called, allowing for further subsequent updates before
	// you call UpdateEnd(updt).
	ConfigChildren(config kit.TypeAndNameList) (mods, updt bool)

	// DeleteChildAtIndex deletes child at given index (returns error for
	// invalid index).
	// Wraps delete in UpdateStart / End and sets ChildDeleted flag.
	DeleteChildAtIndex(idx int, destroy bool) error

	// DeleteChild deletes child node, returning error if not found in
	// Children.
	// Wraps delete in UpdateStart / End and sets ChildDeleted flag.
	DeleteChild(child Ki, destroy bool) error

	// DeleteChildByName deletes child node by name -- returns child, error
	// if not found.
	// Wraps delete in UpdateStart / End and sets ChildDeleted flag.
	DeleteChildByName(name string, destroy bool) (Ki, error)

	// DeleteChildren deletes all children nodes -- destroy will add removed
	// children to deleted list, to be destroyed later -- otherwise children
	// remain intact but parent is nil -- could be inserted elsewhere, but you
	// better have kept a slice of them before calling this.
	DeleteChildren(destroy bool)

	// Delete deletes this node from its parent children list -- destroy will
	// add removed child to deleted list, to be destroyed later -- otherwise
	// child remains intact but parent is nil -- could be inserted elsewhere.
	Delete(destroy bool)

	// Destroy calls DisconnectAll to cut all signal connections,
	// and remove all children and their childrens-children, etc.
	Destroy()

	// Flag returns an atomically safe copy of the bit flags for this node --
	// can use bitflag package to check lags.
	// See Flags type for standard values used in Ki Node --
	// can be extended from FlagsN up to 64 bit capacity.
	// Note that we must always use atomic access as *some* things need to be atomic,
	// and with bits, that means that *all* access needs to be atomic,
	// as you cannot atomically update just a single bit.
	Flags() int64

	// HasFlag checks if flag is set
	// using atomic, safe for concurrent access
	HasFlag(flag int) bool

	// SetFlag sets the given flag(s)
	// using atomic, safe for concurrent access
	SetFlag(flag ...int)

	// SetFlagState sets the given flag(s) to given state
	// using atomic, safe for concurrent access
	SetFlagState(on bool, flag ...int)

	// SetFlagMask sets the given flags as a mask
	// using atomic, safe for concurrent access
	SetFlagMask(mask int64)

	// ClearFlag clears the given flag(s)
	// using atomic, safe for concurrent access
	ClearFlag(flag ...int)

	// ClearFlagMask clears the given flags as a bitmask
	// using atomic, safe for concurrent access
	ClearFlagMask(mask int64)

	// IsField checks if this is a field on a parent struct (via IsField
	// Flag), as opposed to a child in Children -- Ki nodes can be added as
	// fields to structs and they are automatically parented and named with
	// field name during Init function -- essentially they function as fixed
	// children of the parent struct, and are automatically included in
	// FuncDown* traversals, etc -- see also FunFields.
	IsField() bool

	// IsUpdating checks if node is currently updating.
	IsUpdating() bool

	// OnlySelfUpdate checks if this node only applies UpdateStart / End logic
	// to itself, not its children (which is the default) (via Flag of same
	// name) -- useful for a parent node that has a different function than
	// its children.
	OnlySelfUpdate() bool

	// SetChildAdded sets the ChildAdded flag -- set when notification is needed
	// for Add, Insert methods
	SetChildAdded()

	// SetValUpdated sets the ValUpdated flag -- set when notification is needed
	// for modifying a value (field, prop, etc)
	SetValUpdated()

	// IsDeleted checks if this node has just been deleted (within last update
	// cycle), indicated by the NodeDeleted flag which is set when the node is
	// deleted, and is cleared at next UpdateStart call.
	IsDeleted() bool

	// IsDestroyed checks if this node has been destroyed -- the NodeDestroyed
	// flag is set at start of Destroy function -- the Signal Emit process
	// checks for destroyed receiver nodes and removes connections to them
	// automatically -- other places where pointers to potentially destroyed
	// nodes may linger should also check this flag and reset those pointers.
	IsDestroyed() bool

	// Properties (Node.Props) tell the GoGi GUI or other frameworks operating
	// on Trees about special features of each node -- functions below support
	// inheritance up Tree -- see kit convert.go for robust convenience
	// methods for converting interface{} values to standard types.
	Properties() *Props

	// SetProp sets given property key to value val -- initializes property
	// map if nil.
	SetProp(key string, val any)

	// Prop returns property value for key that is known to exist.
	// Returns nil if it actually doesn't -- this version allows
	// direct conversion of return.  See PropTry for version with
	// error message if uncertain if property exists.
	Prop(key string) any

	// PropTry returns property value for key.  Returns error message
	// if property with that key does not exist.
	PropTry(key string) (any, error)

	// PropInherit gets property value from key with options for inheriting
	// property from parents and / or type-level properties.  If inherit, then
	// checks all parents.  If typ then checks property on type as well
	// (registered via KiT type registry).  Returns false if not set anywhere.
	PropInherit(key string, inherit, typ bool) (any, bool)

	// DeleteProp deletes property key on this node.
	DeleteProp(key string)

	// PropTag returns the name to look for in type properties, for types
	// that are valid options for values that can be set in Props.  For example
	// in GoGi, it is "style-props" which is then set for all types that can
	// be used in a style (colors, enum options, etc)
	PropTag() string

	// FuncFields calls function on all Ki fields within this node.
	FuncFields(level int, data any, fun Func)

	// FuncUp calls function on given node and all the way up to its parents,
	// and so on -- sequentially all in current go routine (generally
	// necessary for going up, which is typically quite fast anyway) -- level
	// is incremented after each step (starts at 0, goes up), and passed to
	// function -- returns false if fun aborts with false, else true.
	FuncUp(level int, data any, fun Func) bool

	// FuncUpParent calls function on parent of node and all the way up to its
	// parents, and so on -- sequentially all in current go routine (generally
	// necessary for going up, which is typically quite fast anyway) -- level
	// is incremented after each step (starts at 0, goes up), and passed to
	// function -- returns false if fun aborts with false, else true.
	FuncUpParent(level int, data any, fun Func) bool

	// FuncDownMeFirst calls function on this node (MeFirst) and then iterates
	// in a depth-first manner over all the children, including Ki Node fields,
	// which are processed first before children.
	// This uses node state information to manage the traversal and is very fast,
	// but can only be called by one thread at a time -- use a Mutex if there is
	// a chance of multiple threads running at the same time.
	// Function calls are sequential all in current go routine.
	// The level var tracks overall depth in the tree.
	// If fun returns false then any further traversal of that branch of the tree is
	// aborted, but other branches continue -- i.e., if fun on current node
	// returns false, children are not processed further.
	FuncDownMeFirst(level int, data any, fun Func)

	// FuncDownMeLast iterates in a depth-first manner over the children, calling
	// doChildTestFunc on each node to test if processing should proceed (if it returns
	// false then that branch of the tree is not further processed), and then
	// calls given fun function after all of a node's children (including fields)
	// have been iterated over ("Me Last").
	// This uses node state information to manage the traversal and is very fast,
	// but can only be called by one thread at a time -- use a Mutex if there is
	// a chance of multiple threads running at the same time.
	// Function calls are sequential all in current go routine.
	// The level var tracks overall depth in the tree.
	FuncDownMeLast(level int, data any, doChildTestFunc Func, fun Func)

	// FuncDownBreadthFirst calls function on all children in breadth-first order
	// using the standard queue strategy.  This depends on and updates the
	// Depth parameter of the node.  If fun returns false then any further
	// traversal of that branch of the tree is aborted, but other branches continue.
	FuncDownBreadthFirst(level int, data any, fun Func)

	// NodeSignal returns the main signal for this node that is used for
	// update, child signals.
	NodeSignal() *Signal

	// UpdateStart should be called when starting to modify the tree (state or
	// structure) -- returns whether this node was first to set the Updating
	// flag (if so, all children have their Updating flag set -- pass the
	// result to UpdateEnd -- automatically determines the highest level
	// updated, within the normal top-down updating sequence -- can be called
	// multiple times at multiple levels -- it is essential to ensure that all
	// such Start's have an End!  Usage:
	//
	//   updt := n.UpdateStart()
	//   ... code
	//   n.UpdateEnd(updt)
	// or
	//   updt := n.UpdateStart()
	//   defer n.UpdateEnd(updt)
	//   ... code
	UpdateStart() bool

	// UpdateEnd should be called when done updating after an UpdateStart, and
	// passed the result of the UpdateStart call -- if this is true, the
	// NodeSignalUpdated signal will be emitted and the Updating flag will be
	// cleared, and DestroyDeleted called -- otherwise it is a no-op.
	UpdateEnd(updt bool)

	// UpdateEndNoSig is just like UpdateEnd except it does not emit a
	// NodeSignalUpdated signal -- use this for situations where updating is
	// already known to be in progress and the signal would be redundant.
	UpdateEndNoSig(updt bool)

	// UpdateSig just emits a NodeSignalUpdated if the Updating flag is not
	// set -- use this to trigger an update of a given node when there aren't
	// any structural changes and you don't need to prevent any lower-level
	// updates -- much more efficient than a pair of UpdateStart /
	// UpdateEnd's.  Returns true if an update signal was sent.
	UpdateSig() bool

	// Disconnect disconnects this node, by calling DisconnectAll() on
	// any Signal fields.  Any Node that adds a Signal must define an
	// updated version of this method that calls its embedded parent's
	// version and then calls DisconnectAll() on its Signal fields.
	Disconnect()

	// DisconnectAll disconnects all the way from me down the tree.
	DisconnectAll()

	// SetField sets given field name to given value, using very robust
	// conversion routines to e.g., convert from strings to numbers, and
	// vice-versa, automatically.  Returns error if not successfully set.
	// wrapped in UpdateStart / End and sets the ValUpdated flag.
	SetField(field string, val any) error

	// CopyFrom another Ki node.  It is essential that source has Unique names!
	// The Ki copy function recreates the entire tree in the copy, duplicating
	// children etc, copying Props too.  It is very efficient by
	// using the 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 copies to same types are supported.
	// Signal connections are NOT copied.  No other Ki pointers are copied,
	// and the field tag copy:"-" can be added for any other fields that
	// should not be copied (unexported, lower-case fields are not copyable).
	CopyFrom(frm Ki) error

	// 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 Copy info).
	Clone() Ki

	// CopyFieldsFrom is the base-level copy method that any copy-intensive
	// nodes should implement directly to explicitly copy relevant fields
	// that should be copied, avoiding any internal pointers etc.
	// This is the performance bottleneck in copying -- the Node version
	// uses generic GenCopyFieldsFrom method using reflection etc
	// which is very slow.  It can be ~10x faster overall to use custom
	// method that explicitly copies each field.  When doing so, you
	// must explicitly call the CopyFieldsFrom method on any embedded
	// Ki types that you inherit from, and, critically, NONE of those
	// can rely on the generic Node-level version.  Furthermore, if the
	// actual end type itself does not define a custom version of this method
	// then the generic one will be called for everything.
	CopyFieldsFrom(frm any)

	// WriteJSON writes the tree to an io.Writer, using MarshalJSON -- also
	// saves a critical starting record that allows file to be loaded de-novo
	// and recreate the proper root type for the tree.
	WriteJSON(writer io.Writer, indent bool) error

	// SaveJSON saves the tree to a JSON-encoded file, using WriteJSON.
	SaveJSON(filename string) error

	// ReadJSON reads and unmarshals tree starting at this node, from a
	// JSON-encoded byte stream via io.Reader.  First element in the stream
	// must be of same type as this node -- see ReadNewJSON function to
	// construct a new tree.  Uses ConfigureChildren to minimize changes from
	// current tree relative to loading one -- wraps UnmarshalJSON and calls
	// UnmarshalPost to recover pointers from paths.
	ReadJSON(reader io.Reader) error

	// OpenJSON opens file over this tree from a JSON-encoded file -- see
	// ReadJSON for details, and OpenNewJSON for opening an entirely new tree.
	OpenJSON(filename string) error

	// WriteXML writes the tree to an XML-encoded byte string over io.Writer
	// using MarshalXML.
	WriteXML(writer io.Writer, indent bool) error

	// ReadXML reads the tree from an XML-encoded byte string over io.Reader, calls
	// UnmarshalPost to recover pointers from paths.
	ReadXML(reader io.Reader) error

	// OnInit is called when the node is
	// initialized (ie: through InitName).
	// 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.
	OnInit()

	// 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()

	// OnChildAdded is called when a node is added to
	// this node or any of its children. When a node is added to
	// a tree, it calls [OnAdd] and then this function on each of its parents,
	// going in order from the closest parent to the furthest parent.
	// This function does nothing by default, but it can be
	// implemented by higher-level types that want to do something.
	OnChildAdded(child Ki)
}

The Ki interface provides the core functionality for a GoKi tree. Each Ki is a node in the tree and can have child nodes, and no cycles are allowed (i.e., each node can only appear once in the tree). All the usual methods are included for accessing and managing Children, and efficiently traversing the tree and calling functions on the nodes. In addition, Ki nodes can have Fields that are also Ki nodes that are included in all the automatic tree traversal methods -- they are effectively named fixed children that are automatically present.

In general, the names of the children of a given node should all be unique. The following functions defined in ki package can be used: UniqueNameCheck(node) to check for unique names on node if uncertain. UniqueNameCheckAll(node) to check entire tree under given node. UniquifyNames(node) to add a suffix to name to ensure uniqueness. UniquifyNamesAll(node) to to uniquify all names in entire tree.

Use function MoveChild to move a node between trees or within a tree -- otherwise nodes are typically created and deleted but not moved.

The Ki interface is designed to support virtual method calling in Go and is only intended to be implemented once, by the ki.Node type (as opposed to interfaces that are used for hiding multiple different implementations of a common concept). Thus, all of the fields in ki.Node are exported (have captital names), to be accessed directly in types that embed and extend the ki.Node. The Ki interface has the "formal" name (e.g., Children) while the Node has the "nickname" (e.g., Kids). See the Naming Conventions on the GoKi Wiki for more details.

Each Node stores the Ki interface version of itself, as This() / Ths which enables full virtual function calling by calling the method on that interface instead of directly on the receiver Node itself. This requires proper initialization via Init method of the Ki interface.

Ki nodes also support the following core functionality:

  • UpdateStart() / UpdateEnd() to wrap around tree updating code, which then automatically triggers update signals at the highest level of the affected tree, resulting in efficient updating logic for arbitrary nested tree modifications.
  • Signal framework for sending messages such as the Update signals, used extensively in the GoGi GUI framework for sending event messages etc.
  • ConfigChildren system for minimally updating children to fit a given Name & Type template.
  • Automatic JSON I/O of entire tree including type information.

func FieldRoot added in v1.1.0

func FieldRoot(kn Ki) Ki

FieldRoot returns the field root object for this node -- the node that owns the branch of the tree rooted in one of its fields -- i.e., the first non-Field parent node after the first Field parent node -- can be nil if no such thing exists for this node.

func KiField added in v1.1.0

func KiField(n *Node, idx int) Ki

KiField returns the Ki Node field at given index, from KiFieldOffs list. Returns nil if index is out of range. This is generally used for generic traversal methods and thus does not have a Try version.

func KiFieldByName added in v1.1.0

func KiFieldByName(n *Node, name string) Ki

KiFieldByName returns field Ki element by name -- returns false if not found.

func NewOfType

func NewOfType(typ reflect.Type) Ki

NewOfType makes a new Ki struct of given type -- must be a Ki type -- will return nil if not.

func OpenNewJSON

func OpenNewJSON(filename string) (Ki, error)

OpenNewJSON opens a new Ki tree from a JSON-encoded file, using type information at start of file to create an object of the proper type

func ReadNewJSON

func ReadNewJSON(reader io.Reader) (Ki, error)

ReadNewJSON reads a new Ki tree from a JSON-encoded byte string, using type information at start of file to create an object of the proper type

func Root added in v1.1.0

func Root(k Ki) Ki

Root returns the root node of given ki node in tree (the node with a nil parent).

type Node

type Node struct {

	// Ki.Name() user-supplied name of this node -- can be empty or non-unique
	Nm string `copy:"-" label:"Name" desc:"Ki.Name() user-supplied name of this node -- can be empty or non-unique"`

	// [tableview: -] bit flags for internal node state
	Flag int64 `tableview:"-" copy:"-" json:"-" xml:"-" max-width:"80" height:"3" desc:"bit flags for internal node state"`

	// [tableview: -] Ki.Properties() property map for arbitrary extensible properties, including style properties
	Props Props `` /* 149-byte string literal not displayed */

	// [view: -] [tableview: -] Ki.Parent() parent of this node -- set automatically when this node is added as a child of parent
	Par Ki `` /* 168-byte string literal not displayed */

	// [tableview: -] Ki.Children() list of children of this node -- all are set to have this node as their parent -- can reorder etc but generally use Ki Node methods to Add / Delete to ensure proper usage
	Kids Slice `` /* 231-byte string literal not displayed */

	// [view: -] Ki.NodeSignal() signal for node structure / state changes -- emits NodeSignals signals -- can also extend to custom signals (see signal.go) but in general better to create a new Signal instead
	NodeSig Signal `` /* 234-byte string literal not displayed */

	// [view: -] we need a pointer to ourselves as a Ki, which can always be used to extract the true underlying type of object when Node is embedded in other structs -- function receivers do not have this ability so this is necessary.  This is set to nil when deleted.  Typically use This() convenience accessor which protects against concurrent access.
	Ths Ki `` /* 379-byte string literal not displayed */
	// contains filtered or unexported fields
}

The Node implements the Ki interface and provides the core functionality for the GoKi tree -- use the Node as an embedded struct or as a struct field -- the embedded version supports full JSON save / load.

The desc: key for fields is used by the GoGi GUI viewer for help / tooltip info -- add these to all your derived struct's fields. See relevant docs for other such tags controlling a wide range of GUI and other functionality -- Ki makes extensive use of such tags.

func (*Node) AddChild

func (n *Node) AddChild(kid Ki) error

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. No UpdateStart / End wrapping is done: do that externally as needed. Can also call SetFlag(ki.ChildAdded) if notification is needed.

func (*Node) AddNewChild

func (n *Node) AddNewChild(typ reflect.Type, name string) Ki

AddNewChild creates a new child of given type and add at end of children list. The name should be unique among children. No UpdateStart / End wrapping is done: do that externally as needed. Can also call SetChildAdded() if notification is needed.

func (*Node) AsNode added in v0.9.8

func (n *Node) AsNode() *Node

AsNode returns the *ki.Node base type for this node.

func (*Node) BaseIface

func (n *Node) BaseIface() reflect.Type

BaseIface returns the base interface type for all elements within this tree. Use reflect.TypeOf((*<interface_type>)(nil)).Elem(). Used e.g., for determining what types of children can be created (see kit.EmbedImplements for test method)

func (*Node) Child

func (n *Node) Child(idx int) Ki

Child returns the child at given index -- will panic if index is invalid. See methods on ki.Slice for more ways to access.

func (*Node) ChildByName

func (n *Node) ChildByName(name string, startIdx int) Ki

ChildByName returns first element that has given name, nil if not found. startIdx arg allows for optimized bidirectional find if you have an idea where it might be -- can be key speedup for large lists -- pass ki.StartMiddle to start in the middle (good default).

func (*Node) ChildByNameTry

func (n *Node) ChildByNameTry(name string, startIdx int) (Ki, error)

ChildByNameTry returns first element that has given name, error if not found. startIdx arg allows for optimized bidirectional find if you have an idea where it might be -- can be key speedup for large lists -- pass ki.StartMiddle to start in the middle (good default).

func (*Node) ChildByType

func (n *Node) ChildByType(t reflect.Type, embeds bool, startIdx int) Ki

ChildByType returns first element that has given type, nil if not found. If embeds is true, then it looks for any type that embeds the given type at any level of anonymous embedding. startIdx arg allows for optimized bidirectional find if you have an idea where it might be -- can be key speedup for large lists -- pass ki.StartMiddle to start in the middle (good default).

func (*Node) ChildByTypeTry

func (n *Node) ChildByTypeTry(t reflect.Type, embeds bool, startIdx int) (Ki, error)

ChildByTypeTry returns first element that has given name -- Try version returns error message if not found. If embeds is true, then it looks for any type that embeds the given type at any level of anonymous embedding. startIdx arg allows for optimized bidirectional find if you have an idea where it might be -- can be key speedup for large lists -- pass ki.StartMiddle to start in the middle (good default).

func (*Node) ChildTry

func (n *Node) ChildTry(idx int) (Ki, error)

ChildTry returns the child at given index. Try version returns error if index is invalid. See methods on ki.Slice for more ways to acces.

func (*Node) Children

func (n *Node) Children() *Slice

Children returns a pointer to the slice of children (Node.Kids) -- use methods on ki.Slice for further ways to access (ByName, ByType, etc). Slice can be modified directly (e.g., sort, reorder) but Add* / Delete* methods on parent node should be used to ensure proper tracking.

func (*Node) ClearFlag

func (n *Node) ClearFlag(flag ...int)

ClearFlag clears the given flag(s) using atomic, safe for concurrent access

func (*Node) ClearFlagMask

func (n *Node) ClearFlagMask(mask int64)

ClearFlagMask clears the given flags as a bitmask using atomic, safe for concurrent access

func (*Node) Clone

func (n *Node) Clone() Ki

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 Copy info).

func (*Node) ConfigChildren

func (n *Node) ConfigChildren(config kit.TypeAndNameList) (mods, updt bool)

ConfigChildren configures children according to given list of type-and-name's -- attempts to have minimal impact relative to existing items that fit the type and name constraints (they are moved into the corresponding positions), and any extra children are removed, and new ones added, to match the specified config. If uniqNm, then names represent UniqueNames (this results in Name == UniqueName for created children).

IMPORTANT: returns whether any modifications were made (mods) AND if that is true, the result from the corresponding UpdateStart call -- UpdateEnd is NOT called, allowing for further subsequent updates before you call UpdateEnd(updt).

func (*Node) CopyFieldsFrom

func (n *Node) CopyFieldsFrom(frm any)

CopyFieldsFrom copies from primary fields of source object, recursively following anonymous embedded structs

func (*Node) CopyFrom

func (n *Node) CopyFrom(frm Ki) error

CopyFrom another Ki node. It is essential that source has Unique names! The Ki copy function recreates the entire tree in the copy, duplicating children etc, copying Props too. It is very efficient by using the 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 copies to same types are supported. Signal connections are NOT copied. No other Ki pointers are copied, and the field tag copy:"-" can be added for any other fields that should not be copied (unexported, lower-case fields are not copyable).

func (*Node) CopyPropsFrom

func (n *Node) CopyPropsFrom(frm Ki, deep bool) error

CopyPropsFrom copies our properties from another node -- if deep then does a deep copy -- otherwise copied map just points to same values in the original map (and we don't reset our map first -- call DeleteAllProps to do that -- deep copy uses gob encode / decode -- usually not needed).

func (*Node) Delete

func (n *Node) Delete(destroy bool)

Delete deletes this node from its parent children list -- destroy will add removed child to deleted list, to be destroyed later -- otherwise child remains intact but parent is nil -- could be inserted elsewhere.

func (*Node) DeleteChild

func (n *Node) DeleteChild(child Ki, destroy bool) error

DeleteChild deletes child node, returning error if not found in Children. Wraps delete in UpdateStart / End and sets ChildDeleted flag.

func (*Node) DeleteChildAtIndex

func (n *Node) DeleteChildAtIndex(idx int, destroy bool) error

DeleteChildAtIndex deletes child at given index (returns error for invalid index). Wraps delete in UpdateStart / End and sets ChildDeleted flag.

func (*Node) DeleteChildByName

func (n *Node) DeleteChildByName(name string, destroy bool) (Ki, error)

DeleteChildByName deletes child node by name -- returns child, error if not found. Wraps delete in UpdateStart / End and sets ChildDeleted flag.

func (*Node) DeleteChildren

func (n *Node) DeleteChildren(destroy bool)

DeleteChildren deletes all children nodes -- destroy will add removed children to deleted list, to be destroyed later -- otherwise children remain intact but parent is nil -- could be inserted elsewhere, but you better have kept a slice of them before calling this.

func (*Node) DeleteProp

func (n *Node) DeleteProp(key string)

DeleteProp deletes property key on this node.

func (*Node) Destroy

func (n *Node) Destroy()

Destroy calls DisconnectAll to cut all pointers and signal connections, and remove all children and their childrens-children, etc.

func (*Node) Disconnect

func (n *Node) Disconnect()

Disconnect disconnects this node, by calling DisconnectAll() on any Signal fields. Any Node that adds a Signal must define an updated version of this method that calls its embedded parent's version and then calls DisconnectAll() on its Signal fields.

func (*Node) DisconnectAll

func (n *Node) DisconnectAll()

DisconnectAll disconnects all the way from me down the tree.

func (*Node) Embed

func (n *Node) Embed(t reflect.Type) Ki

Embed returns the embedded struct of given type from this node (or nil if it does not embed that type, or the type is not a Ki type -- see kit.Embed for a generic interface{} version.

func (*Node) FindPath added in v1.1.0

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

FindPath returns Ki object at given path, starting from this node (e.g., the root). If this node is not the root, then the path to this node is subtracted from the start of the path if present there. FindPath only works correctly when names are unique. Path has node Names separated by / and fields by . Node names escape any existing / and . characters to \\ and \, There is also support for [idx] index-based access for any given path element, for cases when indexes are more useful than names. Returns nil if not found.

func (*Node) FindPathTry added in v1.1.0

func (n *Node) FindPathTry(path string) (Ki, error)

FindPathTry returns Ki object at given path, starting from this node (e.g., the root). If this node is not the root, then the path to this node is subtracted from the start of the path if present there. FindPath only works correctly when names are unique. Path has node Names separated by / and fields by . Node names escape any existing / and . characters to \\ and \, There is also support for [idx] index-based access for any given path element, for cases when indexes are more useful than names. Returns error if not found.

func (*Node) Flags

func (n *Node) Flags() int64

Flags returns an atomically safe copy of the bit flags for this node -- can use bitflag package to check lags. See Flags type for standard values used in Ki Node -- can be extended from FlagsN up to 64 bit capacity. Note that we must always use atomic access as *some* things need to be atomic, and with bits, that means that *all* access needs to be atomic, as you cannot atomically update just a single bit.

func (*Node) FuncDownBreadthFirst

func (n *Node) FuncDownBreadthFirst(level int, data any, fun Func)

FuncDownBreadthFirst calls function on all children in breadth-first order using the standard queue strategy. This depends on and updates the Depth parameter of the node. If fun returns false then any further traversal of that branch of the tree is aborted, but other branches continue.

func (*Node) FuncDownMeFirst

func (n *Node) FuncDownMeFirst(level int, data any, fun Func)

FuncDownMeFirst calls function on this node (MeFirst) and then iterates in a depth-first manner over all the children, including Ki Node fields, which are processed first before children. The node traversal is non-recursive and uses locally-allocated state -- safe for concurrent calling (modulo conflict management in function call itself). Function calls are sequential all in current go routine. The level var tracks overall depth in the tree. If fun returns false then any further traversal of that branch of the tree is aborted, but other branches continue -- i.e., if fun on current node returns false, children are not processed further.

func (*Node) FuncDownMeLast added in v0.9.8

func (n *Node) FuncDownMeLast(level int, data any, doChildTestFunc Func, fun Func)

FuncDownMeLast iterates in a depth-first manner over the children, calling doChildTestFunc on each node to test if processing should proceed (if it returns false then that branch of the tree is not further processed), and then calls given fun function after all of a node's children (including fields) have been iterated over ("Me Last"). The node traversal is non-recursive and uses locally-allocated state -- safe for concurrent calling (modulo conflict management in function call itself). Function calls are sequential all in current go routine. The level var tracks overall depth in the tree.

func (*Node) FuncFields

func (n *Node) FuncFields(level int, data any, fun Func)

FuncFields calls function on all Ki fields within this node.

func (*Node) FuncUp

func (n *Node) FuncUp(level int, data any, fun Func) bool

FuncUp calls function on given node and all the way up to its parents, and so on -- sequentially all in current go routine (generally necessary for going up, which is typically quite fast anyway) -- level is incremented after each step (starts at 0, goes up), and passed to function -- returns false if fun aborts with false, else true.

func (*Node) FuncUpParent

func (n *Node) FuncUpParent(level int, data any, fun Func) bool

FuncUpParent calls function on parent of node and all the way up to its parents, and so on -- sequentially all in current go routine (generally necessary for going up, which is typically quite fast anyway) -- level is incremented after each step (starts at 0, goes up), and passed to function -- returns false if fun aborts with false, else true.

func (*Node) HasChildren

func (n *Node) HasChildren() bool

HasChildren tests whether this node has children (i.e., non-terminal).

func (*Node) HasFlag

func (n *Node) HasFlag(flag int) bool

HasFlag checks if flag is set using atomic, safe for concurrent access

func (*Node) IndexInParent

func (n *Node) IndexInParent() (int, bool)

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

func (*Node) InitName

func (n *Node) InitName(k Ki, name string)

InitName initializes this node to given actual object as a Ki interface and sets its name. The names should be unique among children of a node. This is needed for root nodes -- automatically done for other nodes when they are added to the Ki tree. Even though this is a method and gets the method receiver, it needs an "external" version of itself passed as the first arg, from which the proper Ki interface pointer will be obtained. This is the only way to get virtual functional calling to work within the Go framework.

func (*Node) InsertChild

func (n *Node) InsertChild(kid Ki, at int) error

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. No UpdateStart / End wrapping is done: do that externally as needed. Can also call SetChildAdded() if notification is needed.

func (*Node) InsertNewChild

func (n *Node) InsertNewChild(typ reflect.Type, at int, name string) Ki

InsertNewChild creates a new child of given type and add at position in children list. The name should be unique among children. No UpdateStart / End wrapping is done: do that externally as needed. Can also call SetChildAdded() if notification is needed.

func (*Node) IsDeleted

func (n *Node) IsDeleted() bool

IsDeleted checks if this node has just been deleted (within last update cycle), indicated by the NodeDeleted flag which is set when the node is deleted, and is cleared at next UpdateStart call.

func (*Node) IsDestroyed

func (n *Node) IsDestroyed() bool

IsDestroyed checks if this node has been destroyed -- the NodeDestroyed flag is set at start of Destroy function -- the Signal Emit process checks for destroyed receiver nodes and removes connections to them automatically -- other places where pointers to potentially destroyed nodes may linger should also check this flag and reset those pointers.

func (*Node) IsField

func (n *Node) IsField() bool

IsField checks if this is a field on a parent struct (via IsField Flag), as opposed to a child in Children -- Ki nodes can be added as fields to structs and they are automatically parented and named with field name during Init function -- essentially they function as fixed children of the parent struct, and are automatically included in FuncDown* traversals, etc -- see also FunFields.

func (*Node) IsUpdating

func (n *Node) IsUpdating() bool

IsUpdating checks if node is currently updating.

func (*Node) IsValidIndex

func (n *Node) IsValidIndex(idx int) error

IsValidIndex returns error if given index is not valid for accessing children nil otherwise.

func (*Node) Name

func (n *Node) Name() string

Name returns the user-defined name of the object (Node.Nm), for finding elements, generating paths, IO, etc.

func (*Node) NodeSignal

func (n *Node) NodeSignal() *Signal

NodeSignal returns the main signal for this node that is used for update, child signals.

func (*Node) NumChildren added in v0.9.8

func (n *Node) NumChildren() int

NumChildren returns the number of children of this node.

func (*Node) OnAdd added in v1.1.16

func (n *Node) OnAdd()

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

func (*Node) OnChildAdded added in v1.1.16

func (n *Node) OnChildAdded(child Ki)

OnChildAdded is a placeholder implementation of [Ki.OnChildAdded] that does nothing.

func (*Node) OnInit added in v1.1.16

func (n *Node) OnInit()

OnInit is a placeholder implementation of [Ki.OnInit] that does nothing.

func (*Node) OnlySelfUpdate

func (n *Node) OnlySelfUpdate() bool

OnlySelfUpdate checks if this node only applies UpdateStart / End logic to itself, not its children (which is the default) (via Flag of same name) -- useful for a parent node that has a different function than its children.

func (*Node) OpenJSON

func (n *Node) OpenJSON(filename string) error

OpenJSON opens file over this tree from a JSON-encoded file -- see ReadJSON for details, and OpenNewJSON for opening an entirely new tree.

func (*Node) Parent

func (n *Node) Parent() Ki

Parent returns the parent of this Ki (Node.Par) -- Ki has strict one-parent, no-cycles structure -- see SetParent.

func (*Node) ParentByName

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

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

func (*Node) ParentByNameTry

func (n *Node) ParentByNameTry(name string) (Ki, error)

ParentByNameTry finds first parent recursively up hierarchy that matches given name -- returns error if not found.

func (*Node) ParentByType

func (n *Node) ParentByType(t reflect.Type, embeds bool) Ki

ParentByType finds parent recursively up hierarchy, by type, and returns nil if not found. If embeds is true, then it looks for any type that embeds the given type at any level of anonymous embedding.

func (*Node) ParentByTypeTry

func (n *Node) ParentByTypeTry(t reflect.Type, embeds bool) (Ki, error)

ParentByTypeTry finds parent recursively up hierarchy, by type, and returns error if not found. If embeds is true, then it looks for any type that embeds the given type at any level of anonymous embedding.

func (*Node) ParentLevel

func (n *Node) ParentLevel(par Ki) int

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

func (*Node) Path

func (n *Node) Path() string

Path returns path to this node from the tree root, using node Names separated by / and fields by . Node names escape any existing / and . characters to \\ and \, Path is only valid when child names are unique (see Unique* functions)

func (*Node) PathFrom

func (n *Node) PathFrom(par Ki) string

PathFrom returns path to this node from given parent node, using node Names separated by / and fields by . Node names escape any existing / and . characters to \\ and \, Path is only valid for finding items when child names are unique (see Unique* functions)

func (*Node) Prop

func (n *Node) Prop(key string) any

Prop returns property value for key that is known to exist. Returns nil if it actually doesn't -- this version allows direct conversion of return. See PropTry for version with error message if uncertain if property exists.

func (*Node) PropInherit

func (n *Node) PropInherit(key string, inherit, typ bool) (any, bool)

PropInherit gets property value from key with options for inheriting property from parents and / or type-level properties. If inherit, then checks all parents. If typ then checks property on type as well (registered via KiT type registry). Returns false if not set anywhere.

func (*Node) PropTag

func (n *Node) PropTag() string

PropTag returns the name to look for in type properties, for types that are valid options for values that can be set in Props. For example in GoGi, it is "style-props" which is then set for all types that can be used in a style (colors, enum options, etc)

func (*Node) PropTry

func (n *Node) PropTry(key string) (any, error)

PropTry returns property value for key. Returns error message if property with that key does not exist.

func (*Node) Properties

func (n *Node) Properties() *Props

Properties (Node.Props) tell the GoGi GUI or other frameworks operating on Trees about special features of each node -- functions below support inheritance up Tree -- see kit convert.go for robust convenience methods for converting interface{} values to standard types.

func (*Node) ReadJSON

func (n *Node) ReadJSON(reader io.Reader) error

ReadJSON reads and unmarshals tree starting at this node, from a JSON-encoded byte stream via io.Reader. First element in the stream must be of same type as this node -- see ReadNewJSON function to construct a new tree. Uses ConfigureChildren to minimize changes from current tree relative to loading one -- wraps UnmarshalJSON and calls UnmarshalPost to recover pointers from paths.

func (*Node) ReadXML

func (n *Node) ReadXML(reader io.Reader) error

ReadXML reads the tree from an XML-encoded byte string over io.Reader, calls UnmarshalPost to recover pointers from paths.

func (*Node) SaveJSON

func (n *Node) SaveJSON(filename string) error

SaveJSON saves the tree to a JSON-encoded file, using WriteJSON.

func (*Node) SetChild

func (n *Node) SetChild(kid Ki, idx int, name string) error

SetChild sets child at given index to be the given item -- if name is non-empty then it sets the name of the child as well -- just calls Init (or InitName) on the child, and SetParent. Names should be unique among children. No UpdateStart / End wrapping is done: do that externally as needed. Can also call SetChildAdded() if notification is needed.

func (*Node) SetChildAdded added in v1.1.0

func (n *Node) SetChildAdded()

SetChildAdded sets the ChildAdded flag -- set when notification is needed for Add, Insert methods

func (*Node) SetField

func (n *Node) SetField(field string, val any) error

SetField sets given field name to given value, using very robust conversion routines to e.g., convert from strings to numbers, and vice-versa, automatically. Returns error if not successfully set. wrapped in UpdateStart / End and sets the ValUpdated flag.

func (*Node) SetFlag

func (n *Node) SetFlag(flag ...int)

SetFlag sets the given flag(s) using atomic, safe for concurrent access

func (*Node) SetFlagMask

func (n *Node) SetFlagMask(mask int64)

SetFlagMask sets the given flags as a mask using atomic, safe for concurrent access

func (*Node) SetFlagState

func (n *Node) SetFlagState(on bool, flag ...int)

SetFlagState sets the given flag(s) to given state using atomic, safe for concurrent access

func (*Node) SetNChildren

func (n *Node) SetNChildren(trgn int, typ reflect.Type, nameStub string) (mods, updt bool)

SetNChildren ensures that there are exactly n children, deleting any extra, and creating any new ones, using AddNewChild with given type and naming according to nameStubX where X is the index of the child.

IMPORTANT: returns whether any modifications were made (mods) AND if that is true, the result from the corresponding UpdateStart call -- UpdateEnd is NOT called, allowing for further subsequent updates before you call UpdateEnd(updt)

Note that this does not ensure existing children are of given type, or change their names -- use ConfigChildren for those cases. This function is for simpler cases where a parent uses this function consistently to manage children all of the same type.

func (*Node) SetName

func (n *Node) SetName(name string)

SetName sets the name of this node. Names should generally be unique across children of each node. See Unique* functions to check / fix. If node requires non-unique names, add a separate Label field. Does NOT wrap in UpdateStart / End.

func (*Node) SetOnlySelfUpdate

func (n *Node) SetOnlySelfUpdate()

SetOnlySelfUpdate sets the OnlySelfUpdate flag -- see OnlySelfUpdate method and flag.

func (*Node) SetProp

func (n *Node) SetProp(key string, val any)

SetProp sets given property key to value val. initializes property map if nil.

func (*Node) SetPropFloat64

func (n *Node) SetPropFloat64(key string, val float64)

SetPropFloat64 sets given property key to value val as a float64 (e.g., for python wrapper) Initializes property map if nil.

func (*Node) SetPropInt

func (n *Node) SetPropInt(key string, val int)

SetPropInt sets given property key to value val as an int (e.g., for python wrapper) Initializes property map if nil.

func (*Node) SetPropStr

func (n *Node) SetPropStr(key string, val string)

SetPropStr sets given property key to value val as a string (e.g., for python wrapper) Initializes property map if nil.

func (*Node) SetProps

func (n *Node) SetProps(props Props)

SetProps sets a whole set of properties

func (*Node) SetSubProps

func (n *Node) SetSubProps(key string, val Props)

SetSubProps sets given property key to sub-Props value (e.g., for python wrapper) Initializes property map if nil.

func (*Node) SetValUpdated added in v1.1.0

func (n *Node) SetValUpdated()

SetValUpdated sets the ValUpdated flag -- set when notification is needed for modifying a value (field, prop, etc)

func (*Node) String

func (n *Node) String() string

String implements the fmt.stringer interface -- returns the Path of the node

func (*Node) This

func (n *Node) This() Ki

This returns the Ki interface that guarantees access to the Ki interface in a way that always reveals the underlying type (e.g., in reflect calls). Returns nil if node is nil, has been destroyed, or is improperly constructed.

func (*Node) UpdateEnd

func (n *Node) UpdateEnd(updt bool)

UpdateEnd should be called when done updating after an UpdateStart, and passed the result of the UpdateStart call -- if this is true, the NodeSignalUpdated signal will be emitted and the Updating flag will be cleared, and DestroyDeleted called -- otherwise it is a no-op.

func (*Node) UpdateEndNoSig

func (n *Node) UpdateEndNoSig(updt bool)

UpdateEndNoSig is just like UpdateEnd except it does not emit a NodeSignalUpdated signal -- use this for situations where updating is already known to be in progress and the signal would be redundant.

func (*Node) UpdateSig

func (n *Node) UpdateSig() bool

UpdateSig just emits a NodeSignalUpdated if the Updating flag is not set -- use this to trigger an update of a given node when there aren't any structural changes and you don't need to prevent any lower-level updates -- much more efficient than a pair of UpdateStart / UpdateEnd's. Returns true if an update signal was sent.

func (*Node) UpdateStart

func (n *Node) UpdateStart() bool

UpdateStart should be called when starting to modify the tree (state or structure) -- returns whether this node was first to set the Updating flag (if so, all children have their Updating flag set -- pass the result to UpdateEnd -- automatically determines the highest level updated, within the normal top-down updating sequence -- can be called multiple times at multiple levels -- it is essential to ensure that all such Start's have an End! Usage:

updt := n.UpdateStart()
... code
n.UpdateEnd(updt)

or

updt := n.UpdateStart()
defer n.UpdateEnd(updt)
... code

func (*Node) WriteJSON

func (n *Node) WriteJSON(writer io.Writer, indent bool) error

WriteJSON writes the tree to an io.Writer, using MarshalJSON -- also saves a critical starting record that allows file to be loaded de-novo and recreate the proper root type for the tree. This calls UniquifyNamesAll because it is essential that names be unique at this point.

func (*Node) WriteXML

func (n *Node) WriteXML(writer io.Writer, indent bool) error

WriteXML writes the tree to an XML-encoded byte string over io.Writer using MarshalXML.

type NodeSignals

type NodeSignals int64

NodeSignals are signals that a Ki node sends about updates to the tree structure using the NodeSignal (convert sig int64 to NodeSignals to get the stringer name).

const (
	// NodeSignalNil is a nil signal value
	NodeSignalNil NodeSignals = iota

	// NodeSignalUpdated indicates that the node was updated -- the node Flags
	// accumulate the specific changes made since the last update signal --
	// these flags are sent in the signal data -- strongly recommend using
	// that instead of the flags, which can be subsequently updated by the
	// time a signal is processed
	NodeSignalUpdated

	// NodeSignalDeleting indicates that the node is being deleted from its
	// parent children list -- this is not blocked by Updating status and is
	// delivered immediately.  No further notifications are sent -- assume
	// it will be destroyed unless you hear from it again.
	NodeSignalDeleting

	NodeSignalsN
)

Standard signal types sent by ki.Node on its NodeSig for tree state changes

func (NodeSignals) Desc added in v1.1.16

func (i NodeSignals) Desc() string

func (*NodeSignals) FromString

func (i *NodeSignals) FromString(s string) error

func (NodeSignals) String

func (i NodeSignals) String() string

type PropSlice

type PropSlice []PropStruct

PropSlice is a slice of PropStruct, for when order is important within a subset of properties (maps do not retain order) -- can set the value of a property to a PropSlice to create an ordered list of property values.

func SliceProps

func SliceProps(pr map[string]any, key string) (PropSlice, bool)

SliceProps returns a value that contains a PropSlice, or nil and false if it doesn't exist or isn't a PropSlice

func SliceTypeProps

func SliceTypeProps(pr map[string]any, key string) (PropSlice, bool)

SliceTypeProps returns a value that contains a PropSlice, or nil and false if it doesn't exist or isn't a PropSlice -- for TypeProps, uses locking

func (*PropSlice) CopyFrom

func (dest *PropSlice) CopyFrom(src PropSlice, deepCopy bool)

CopyFrom copies properties from source to destination propslice. If deepCopy is true, then any values that are Props or PropSlice are copied too *dest can be nil, in which case it is created.

func (*PropSlice) ElemLabel added in v0.9.8

func (ps *PropSlice) ElemLabel(idx int) string

ElemLabel satisfies the gi.SliceLabeler interface to provide labels for slice elements

type PropStruct

type PropStruct struct {
	Name  string
	Value any
}

PropStruct is a struct of Name and Value, for use in a PropSlice to hold properties that require order information (maps do not retain any order)

type Props

type Props map[string]any

Props is the type used for holding generic properties -- the actual Go type is a mouthful and not very gui-friendly, and we need some special json methods

func SubProps

func SubProps(pr map[string]any, key string) (Props, bool)

SubProps returns a value that contains another props, or nil and false if it doesn't exist or isn't a Props

func SubTypeProps

func SubTypeProps(pr map[string]any, key string) (Props, bool)

SubTypeProps returns a value that contains another props, or nil and false if it doesn't exist or isn't a Props -- for TypeProps, uses locking

func (*Props) CopyFrom

func (dest *Props) CopyFrom(src map[string]any, deepCopy bool)

CopyFrom copies properties from source to receiver destination map. If deepCopy is true, then any values that are Props or PropSlice are copied too *dest can be nil, in which case it is created.

func (Props) Delete added in v1.1.3

func (pr Props) Delete(key string)

Delete deletes props value at given key

func (Props) MarshalJSON

func (p Props) MarshalJSON() ([]byte, error)

MarshalJSON saves the type information for each struct used in props, as a separate key with the __type: prefix -- this allows the Unmarshal to create actual types

func (Props) Prop added in v1.1.3

func (pr Props) Prop(key string) any

Prop returns property of given key

func (*Props) Set added in v1.1.3

func (pr *Props) Set(key string, val any)

Set sets props value -- safely creates map

func (*Props) UnmarshalJSON

func (p *Props) UnmarshalJSON(b []byte) error

UnmarshalJSON parses the type information in the map to restore actual objects -- this is super inefficient and really needs a native parser, but props are likely to be relatively small

type RecvFunc

type RecvFunc func(recv, send Ki, sig int64, data any)

RecvFunc is a receiver function type for signals -- gets the full connection information and signal, data as specified by the sender. It is good practice to avoid closures in these functions, which can be numerous and have a long lifetime, by converting the recv, send into their known types and referring to them directly

type Signal

type Signal struct {

	// [view: -] map of receivers and their functions
	Cons map[Ki]RecvFunc `view:"-" json:"-" xml:"-" desc:"map of receivers and their functions"`

	// [view: -] read-write mutex that protects Cons map access -- use RLock for all Cons reads, Lock for all writes
	Mu sync.RWMutex `` /* 132-byte string literal not displayed */
}

Signal implements general signal passing between Ki objects, like Qt's Signal / Slot system.

This design pattern separates three different factors: * when to signal that something has happened * who should receive that signal * what should the receiver do in response to the signal

Keeping these three things entirely separate greatly simplifies the overall logic.

A receiver connects in advance to a given signal on a sender to receive its signals -- these connections are typically established in an initialization step. There can be multiple different signals on a given sender, and to make more efficient use of signal connections, the sender can also send an int64 signal value that further discriminates the nature of the event, as documented in the code associated with the sender (typically an enum is used). Furthermore, arbitrary data as an interface{} can be passed as well.

The Signal uses a map indexed by the receiver pointer to hold the connections -- this means that there can only be one such connection per receiver, and the order of signal emission to different receivers will be random.

Typically an inline anonymous closure receiver function is used to keep all the relevant code in one place. Due to the typically long-standing nature of these connections, it is more efficient to avoid capturing external variables, and rely instead on appropriately interpreting the sent argument values. e.g.:

send := sender.EmbeddedStruct(KiT_SendType).(*SendType)

is guaranteed to result in a usable pointer to the sender of known type at least SendType, in a case where that sender might actually embed that SendType (otherwise if it is known to be of a given type, just directly converting as such is fine)

func (*Signal) Connect

func (s *Signal) Connect(recv Ki, fun RecvFunc)

Connect attaches a new receiver and function to the signal -- only one such connection per receiver can be made, so any existing connection to that receiver will be overwritten

func (*Signal) ConnectOnly

func (s *Signal) ConnectOnly(recv Ki, fun RecvFunc)

ConnectOnly first deletes any existing connections and then attaches a new receiver to the signal

func (*Signal) ConsFunc added in v1.0.2

func (s *Signal) ConsFunc(consFun func(recv Ki, fun RecvFunc) bool)

ConsFunc iterates over the connections with read lock and deletion of destroyed objects, calling given function on each connection -- if it returns false, then iteration is stopped, else continues. function is called with no lock in place.

func (*Signal) Disconnect

func (s *Signal) Disconnect(recv Ki)

Disconnect disconnects (deletes) the connection for a given receiver

func (*Signal) DisconnectAll

func (s *Signal) DisconnectAll()

DisconnectAll removes all connections

func (*Signal) DisconnectDestroyed added in v1.0.2

func (s *Signal) DisconnectDestroyed(recv Ki) bool

DisconnectDestroyed disconnects (deletes) the connection for a given receiver, if receiver is destroyed, assumed to be under an RLock (unlocks, relocks read lock). Returns true if was disconnected.

func (*Signal) Emit

func (s *Signal) Emit(sender Ki, sig int64, data any)

Emit sends the signal across all the connections to the receivers -- sequentially but in random order due to the randomization of map iteration

func (*Signal) EmitFiltered

func (s *Signal) EmitFiltered(sender Ki, sig int64, data any, filtFun SignalFilterFunc)

EmitFiltered calls function on each potential receiver, and only sends signal if function returns true

func (*Signal) EmitGo

func (s *Signal) EmitGo(sender Ki, sig int64, data any)

EmitGo is the concurrent version of Emit -- sends the signal across all the connections to the receivers as separate goroutines

func (*Signal) EmitGoFiltered

func (s *Signal) EmitGoFiltered(sender Ki, sig int64, data any, filtFun SignalFilterFunc)

EmitGoFiltered is the concurrent version of EmitFiltered -- calls function on each potential receiver, and only sends signal if function returns true (filtering is sequential iteration over receivers)

func (*Signal) EmitTrace

func (s *Signal) EmitTrace(sender Ki, sig int64, data any)

EmitTrace records a trace of signal being emitted

func (*Signal) SendSig

func (s *Signal) SendSig(recv, sender Ki, sig int64, data any)

SendSig sends a signal to one given receiver -- receiver must already be connected so that its receiving function is available

type SignalFilterFunc

type SignalFilterFunc func(recv Ki) bool

SignalFilterFunc is the function type for filtering signals before they are sent -- returns false to prevent sending, and true to allow sending

type Slice

type Slice []Ki

Slice is just a slice of ki elements: []Ki, providing methods for accessing elements in the slice, and JSON marshal / unmarshal with encoding of underlying types

func (*Slice) Config

func (sl *Slice) Config(n Ki, config kit.TypeAndNameList) (mods, updt bool)

Config is a major work-horse routine for minimally-destructive reshaping of a tree structure to fit a target configuration, specified in terms of a type-and-name list. If the node is != nil, then it has UpdateStart / End logic applied to it, only if necessary, as indicated by mods, updt return values.

func (*Slice) ConfigCopy added in v0.9.8

func (sl *Slice) ConfigCopy(n Ki, frm Slice)

ConfigCopy uses Config method to copy name / type config of Slice from source If n is != nil then Update etc is called properly. it is essential that child names are unique.

func (*Slice) CopyFrom added in v0.9.8

func (sl *Slice) CopyFrom(frm Slice)

CopyFrom another Slice. It is efficient by using the Config 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. it is essential that child names are unique.

func (*Slice) DeleteAtIndex

func (sl *Slice) DeleteAtIndex(idx int) error

DeleteAtIndex deletes item at index -- does not do any further management deleted item -- optimized version for avoiding memory leaks. returns error if index is invalid.

func (*Slice) Elem

func (sl *Slice) Elem(idx int) Ki

Elem returns element at index -- panics if index is invalid

func (*Slice) ElemByName

func (sl *Slice) ElemByName(name string, startIdx int) Ki

ElemByName returns first element that has given name, nil if not found. See IndexOf for info on startIdx.

func (*Slice) ElemByNameTry

func (sl *Slice) ElemByNameTry(name string, startIdx int) (Ki, error)

ElemByNameTry returns first element that has given name, error if not found. See IndexOf for info on startIdx.

func (*Slice) ElemByType

func (sl *Slice) ElemByType(t reflect.Type, embeds bool, startIdx int) Ki

ElemByType returns index of element that either is that type or embeds that type, nil if not found. See IndexOf for info on startIdx.

func (*Slice) ElemByTypeTry

func (sl *Slice) ElemByTypeTry(t reflect.Type, embeds bool, startIdx int) (Ki, error)

ElemByTypeTry returns index of element that either is that type or embeds that type, error if not found. See IndexOf for info on startIdx.

func (*Slice) ElemFromEnd

func (sl *Slice) ElemFromEnd(idx int) Ki

ElemFromEnd returns element at index from end of slice (0 = last element, 1 = 2nd to last, etc). Panics if invalid index.

func (*Slice) ElemFromEndTry

func (sl *Slice) ElemFromEndTry(idx int) (Ki, error)

ElemFromEndTry returns element at index from end of slice (0 = last element, 1 = 2nd to last, etc). Try version returns error on invalid index.

func (*Slice) ElemTry

func (sl *Slice) ElemTry(idx int) (Ki, error)

ElemTry returns element at index -- Try version returns error if index is invalid.

func (*Slice) IndexByFunc

func (sl *Slice) IndexByFunc(startIdx int, match func(k Ki) bool) (int, bool)

IndexByFunc finds index of item based on match function (which must return true for a find match, false for not). Returns false if not found. startIdx arg allows for optimized bidirectional find if you have an idea where it might be -- can be key speedup for large lists -- pass ki.StartMiddle to start in the middle (good default).

func (*Slice) IndexByName

func (sl *Slice) IndexByName(name string, startIdx int) (int, bool)

IndexByName returns index of first element that has given name, false if not found. See IndexOf for info on startIdx

func (*Slice) IndexByType

func (sl *Slice) IndexByType(t reflect.Type, embeds bool, startIdx int) (int, bool)

IndexByType returns index of element that either is that type or embeds that type, false if not found. See IndexOf for info on startIdx.

func (*Slice) IndexOf

func (sl *Slice) IndexOf(kid Ki, startIdx int) (int, bool)

IndexOf returns index of element in list, false if not there. startIdx arg allows for optimized bidirectional find if you have an idea where it might be -- can be key speedup for large lists -- pass ki.StartMiddle to start in the middle (good default).

func (*Slice) Insert

func (sl *Slice) Insert(k Ki, idx int)

Insert item at index -- does not do any parent updating etc -- use Ki/Node method unless you know what you are doing.

func (*Slice) IsValidIndex

func (sl *Slice) IsValidIndex(idx int) error

IsValidIndex checks whether the given index is a valid index into slice, within range of 0..len-1. Returns error if not.

func (Slice) MarshalJSON

func (sl Slice) MarshalJSON() ([]byte, error)

MarshalJSON saves the length and type, name information for each object in a slice, as a separate struct-like record at the start, followed by the structs for each element in the slice -- this allows the Unmarshal to first create all the elements and then load them

func (Slice) MarshalXML

func (sl Slice) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML saves the length and type information for each object in a slice, as a separate struct-like record at the start, followed by the structs for each element in the slice -- this allows the Unmarshal to first create all the elements and then load them

func (*Slice) Move

func (sl *Slice) Move(frm, to int) error

Move element from one position to another. Returns error if either index is invalid.

func (*Slice) Swap

func (sl *Slice) Swap(i, j int) error

Swap elements between positions. Returns error if either index is invalid

func (*Slice) TypeAndNames

func (sl *Slice) TypeAndNames() kit.TypeAndNameList

TypeAndNames returns a kit.TypeAndNameList of elements in the slice -- useful for Ki ConfigChildren.

func (*Slice) UnmarshalJSON

func (sl *Slice) UnmarshalJSON(b []byte) error

UnmarshalJSON parses the length and type information for each object in the slice, creates the new slice with those elements, and then loads based on the remaining bytes which represent each element

func (*Slice) UnmarshalXML

func (sl *Slice) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML parses the length and type information for each object in the slice, creates the new slice with those elements, and then loads based on the remaining bytes which represent each element

type TravIdxs added in v1.0.2

type TravIdxs struct {

	// current index of field: -1 for start
	Field int `desc:"current index of field: -1 for start"`

	// current index of children: -1 for start
	Child int `desc:"current index of children: -1 for start"`
}

TravIdxs are tree traversal indexes

type TravMap added in v1.0.2

type TravMap map[Ki]TravIdxs

TravMap is a map for recording the traversal of nodes

func (TravMap) End added in v1.0.2

func (tm TravMap) End(k Ki)

End deletes node once done at end of traversal

func (TravMap) Get added in v1.0.2

func (tm TravMap) Get(k Ki) (curField, curChild int)

Get retrieves current traversal state

func (TravMap) Set added in v1.0.2

func (tm TravMap) Set(k Ki, curField, curChild int)

Set updates traversal state

func (TravMap) Start added in v1.0.2

func (tm TravMap) Start(k Ki)

Start is called at start of traversal

Jump to

Keyboard shortcuts

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