github.com/goki/ki@v1.1.17/ki/ki.go (about)

     1  // Copyright (c) 2018, The GoKi Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ki
     6  
     7  import (
     8  	"io"
     9  	"log"
    10  	"reflect"
    11  
    12  	"github.com/goki/ki/kit"
    13  )
    14  
    15  // The Ki interface provides the core functionality for a GoKi tree.
    16  // Each Ki is a node in the tree and can have child nodes, and no cycles
    17  // are allowed (i.e., each node can only appear once in the tree).
    18  // All the usual methods are included for accessing and managing Children,
    19  // and efficiently traversing the tree and calling functions on the nodes.
    20  // In addition, Ki nodes can have Fields that are also Ki nodes that
    21  // are included in all the automatic tree traversal methods -- they are
    22  // effectively named fixed children that are automatically present.
    23  //
    24  // In general, the names of the children of a given node should all be unique.
    25  // The following functions defined in ki package can be used:
    26  // UniqueNameCheck(node) to check for unique names on node if uncertain.
    27  // UniqueNameCheckAll(node) to check entire tree under given node.
    28  // UniquifyNames(node) to add a suffix to name to ensure uniqueness.
    29  // UniquifyNamesAll(node) to to uniquify all names in entire tree.
    30  //
    31  // Use function MoveChild to move a node between trees or within a tree --
    32  // otherwise nodes are typically created and deleted but not moved.
    33  //
    34  // The Ki interface is designed to support virtual method calling in Go
    35  // and is only intended to be implemented once, by the ki.Node type
    36  // (as opposed to interfaces that are used for hiding multiple different
    37  // implementations of a common concept).  Thus, all of the fields in ki.Node
    38  // are exported (have captital names), to be accessed directly in types
    39  // that embed and extend the ki.Node. The Ki interface has the "formal" name
    40  // (e.g., Children) while the Node has the "nickname" (e.g., Kids).  See the
    41  // Naming Conventions on the GoKi Wiki for more details.
    42  //
    43  // Each Node stores the Ki interface version of itself, as This() / Ths
    44  // which enables full virtual function calling by calling the method
    45  // on that interface instead of directly on the receiver Node itself.
    46  // This requires proper initialization via Init method of the Ki interface.
    47  //
    48  // Ki nodes also support the following core functionality:
    49  //   - UpdateStart() / UpdateEnd() to wrap around tree updating code, which then
    50  //     automatically triggers update signals at the highest level of the
    51  //     affected tree, resulting in efficient updating logic for arbitrary
    52  //     nested tree modifications.
    53  //   - Signal framework for sending messages such as the Update signals, used
    54  //     extensively in the GoGi GUI framework for sending event messages etc.
    55  //   - ConfigChildren system for minimally updating children to fit a given
    56  //     Name & Type template.
    57  //   - Automatic JSON I/O of entire tree including type information.
    58  type Ki interface {
    59  	// InitName initializes this node to given actual object as a Ki interface
    60  	// and sets its name.  The names should be unique among children of a node.
    61  	// This is needed for root nodes -- automatically done for other nodes
    62  	// when they are added to the Ki tree.
    63  	// Even though this is a method and gets the method receiver, it needs
    64  	// an "external" version of itself passed as the first arg, from which
    65  	// the proper Ki interface pointer will be obtained.  This is the only
    66  	// way to get virtual functional calling to work within the Go language.
    67  	InitName(this Ki, name string)
    68  
    69  	// This returns the Ki interface that guarantees access to the Ki
    70  	// interface in a way that always reveals the underlying type
    71  	// (e.g., in reflect calls).  Returns nil if node is nil,
    72  	// has been destroyed, or is improperly constructed.
    73  	This() Ki
    74  
    75  	// AsNode returns the *ki.Node base type for this node.
    76  	AsNode() *Node
    77  
    78  	// Embed returns the embedded struct of given type from this node (or nil
    79  	// if it does not embed that type, or the type is not a Ki type -- see
    80  	// kit.Embed for a generic interface{} version.
    81  	Embed(t reflect.Type) Ki
    82  
    83  	// BaseIface returns the base interface type for all elements
    84  	// within this tree.  Use reflect.TypeOf((*<interface_type>)(nil)).Elem().
    85  	// Used e.g., for determining what types of children
    86  	// can be created (see kit.EmbedImplements for test method)
    87  	BaseIface() reflect.Type
    88  
    89  	// Name returns the user-defined name of the object (Node.Nm),
    90  	// for finding elements, generating paths, IO, etc.
    91  	Name() string
    92  
    93  	// SetName sets the name of this node.
    94  	// Names should generally be unique across children of each node.
    95  	// See Unique* functions to check / fix.
    96  	// If node requires non-unique names, add a separate Label field.
    97  	// Does NOT wrap in UpdateStart / End.
    98  	SetName(name string)
    99  
   100  	//////////////////////////////////////////////////////////////////////////
   101  	//  Parents
   102  
   103  	// Parent returns the parent of this Ki (Node.Par) -- Ki has strict
   104  	// one-parent, no-cycles structure -- see SetParent.
   105  	Parent() Ki
   106  
   107  	// IndexInParent returns our index within our parent object -- caches the
   108  	// last value and uses that for an optimized search so subsequent calls
   109  	// are typically quite fast.  Returns false if we don't have a parent.
   110  	IndexInParent() (int, bool)
   111  
   112  	// ParentLevel finds a given potential parent node recursively up the
   113  	// hierarchy, returning level above current node that the parent was
   114  	// found, and -1 if not found.
   115  	ParentLevel(par Ki) int
   116  
   117  	// ParentByName finds first parent recursively up hierarchy that matches
   118  	// given name.  Returns nil if not found.
   119  	ParentByName(name string) Ki
   120  
   121  	// ParentByNameTry finds first parent recursively up hierarchy that matches
   122  	// given name -- Try version returns error on failure.
   123  	ParentByNameTry(name string) (Ki, error)
   124  
   125  	// ParentByType finds parent recursively up hierarchy, by type, and
   126  	// returns nil if not found. If embeds is true, then it looks for any
   127  	// type that embeds the given type at any level of anonymous embedding.
   128  	ParentByType(t reflect.Type, embeds bool) Ki
   129  
   130  	// ParentByTypeTry finds parent recursively up hierarchy, by type, and
   131  	// returns error if not found. If embeds is true, then it looks for any
   132  	// type that embeds the given type at any level of anonymous embedding.
   133  	ParentByTypeTry(t reflect.Type, embeds bool) (Ki, error)
   134  
   135  	//////////////////////////////////////////////////////////////////////////
   136  	//  Children
   137  
   138  	// HasChildren tests whether this node has children (i.e., non-terminal).
   139  	HasChildren() bool
   140  
   141  	// NumChildren returns the number of children
   142  	NumChildren() int
   143  
   144  	// Children returns a pointer to the slice of children (Node.Kids) -- use
   145  	// methods on ki.Slice for further ways to access (ByName, ByType, etc).
   146  	// Slice can be modified, deleted directly (e.g., sort, reorder) but Add
   147  	// method on parent node should be used to ensure proper init.
   148  	Children() *Slice
   149  
   150  	// Child returns the child at given index -- will panic if index is invalid.
   151  	// See methods on ki.Slice for more ways to access.
   152  	Child(idx int) Ki
   153  
   154  	// ChildTry returns the child at given index -- Try version returns
   155  	// error if index is invalid.
   156  	// See methods on ki.Slice for more ways to access.
   157  	ChildTry(idx int) (Ki, error)
   158  
   159  	// ChildByName returns first element that has given name, nil if not found.
   160  	// startIdx arg allows for optimized bidirectional find if you have
   161  	// an idea where it might be -- can be key speedup for large lists -- pass
   162  	// [ki.StartMiddle] to start in the middle (good default).
   163  	ChildByName(name string, startIdx int) Ki
   164  
   165  	// ChildByNameTry returns first element that has given name -- Try version
   166  	// returns error message if not found.
   167  	// startIdx arg allows for optimized bidirectional find if you have
   168  	// an idea where it might be -- can be key speedup for large lists -- pass
   169  	// [ki.StartMiddle] to start in the middle (good default).
   170  	ChildByNameTry(name string, startIdx int) (Ki, error)
   171  
   172  	// ChildByType returns first element that has given type, nil if not found.
   173  	// If embeds is true, then it looks for any type that embeds the given type
   174  	// at any level of anonymous embedding.
   175  	// startIdx arg allows for optimized bidirectional find if you have
   176  	// an idea where it might be -- can be key speedup for large lists -- pass
   177  	// [ki.StartMiddle] to start in the middle (good default).
   178  	ChildByType(t reflect.Type, embeds bool, startIdx int) Ki
   179  
   180  	// ChildByTypeTry returns first element that has given name -- Try version
   181  	// returns error message if not found.
   182  	// If embeds is true, then it looks for any type that embeds the given type
   183  	// at any level of anonymous embedding.
   184  	// startIdx arg allows for optimized bidirectional find if you have
   185  	// an idea where it might be -- can be key speedup for large lists -- pass
   186  	// [ki.StartMiddle] to start in the middle (good default).
   187  	ChildByTypeTry(t reflect.Type, embeds bool, startIdx int) (Ki, error)
   188  
   189  	//////////////////////////////////////////////////////////////////////////
   190  	//  Paths
   191  
   192  	// Path returns path to this node from the tree root, using node Names
   193  	// separated by / and fields by .
   194  	// Node names escape any existing / and . characters to \\ and \,
   195  	// Path is only valid when child names are unique (see Unique* functions)
   196  	Path() string
   197  
   198  	// PathFrom returns path to this node from given parent node, using
   199  	// node Names separated by / and fields by .
   200  	// Node names escape any existing / and . characters to \\ and \,
   201  	// Path is only valid when child names are unique (see Unique* functions)
   202  	PathFrom(par Ki) string
   203  
   204  	// FindPath returns Ki object at given path, starting from this node
   205  	// (e.g., the root).  If this node is not the root, then the path
   206  	// to this node is subtracted from the start of the path if present there.
   207  	// FindPath only works correctly when names are unique.
   208  	// Path has node Names separated by / and fields by .
   209  	// Node names escape any existing / and . characters to \\ and \,
   210  	// There is also support for [idx] index-based access for any given path
   211  	// element, for cases when indexes are more useful than names.
   212  	// Returns nil if not found.
   213  	FindPath(path string) Ki
   214  
   215  	// FindPathTry returns Ki object at given path, starting from this node
   216  	// (e.g., the root).  If this node is not the root, then the path
   217  	// to this node is subtracted from the start of the path if present there.
   218  	// FindPath only works correctly when names are unique.
   219  	// Path has node Names separated by / and fields by .
   220  	// Node names escape any existing / and . characters to \\ and \,
   221  	// There is also support for [idx] index-based access for any given path
   222  	// element, for cases when indexes are more useful than names.
   223  	// Returns error if not found.
   224  	FindPathTry(path string) (Ki, error)
   225  
   226  	//////////////////////////////////////////////////////////////////////////
   227  	//  Adding, Inserting Children
   228  
   229  	// AddChild adds given child at end of children list.
   230  	// The kid node is assumed to not be on another tree (see MoveToParent)
   231  	// and the existing name should be unique among children.
   232  	// No UpdateStart / End wrapping is done: do that externally as needed.
   233  	// Can also call SetFlag(ki.ChildAdded) if notification is needed.
   234  	AddChild(kid Ki) error
   235  
   236  	// AddNewChild creates a new child of given type and
   237  	// add at end of children list.
   238  	// The name should be unique among children.
   239  	// No UpdateStart / End wrapping is done: do that externally as needed.
   240  	// Can also call SetFlag(ki.ChildAdded) if notification is needed.
   241  	AddNewChild(typ reflect.Type, name string) Ki
   242  
   243  	// SetChild sets child at given index to be the given item -- if name is
   244  	// non-empty then it sets the name of the child as well -- just calls Init
   245  	// (or InitName) on the child, and SetParent.
   246  	// Names should be unique among children.
   247  	// No UpdateStart / End wrapping is done: do that externally as needed.
   248  	// Can also call SetFlag(ki.ChildAdded) if notification is needed.
   249  	SetChild(kid Ki, idx int, name string) error
   250  
   251  	// InsertChild adds given child at position in children list.
   252  	// The kid node is assumed to not be on another tree (see MoveToParent)
   253  	// and the existing name should be unique among children.
   254  	// No UpdateStart / End wrapping is done: do that externally as needed.
   255  	// Can also call SetFlag(ki.ChildAdded) if notification is needed.
   256  	InsertChild(kid Ki, at int) error
   257  
   258  	// InsertNewChild creates a new child of given type and
   259  	// add at position in children list.
   260  	// The name should be unique among children.
   261  	// No UpdateStart / End wrapping is done: do that externally as needed.
   262  	// Can also call SetFlag(ki.ChildAdded) if notification is needed.
   263  	InsertNewChild(typ reflect.Type, at int, name string) Ki
   264  
   265  	// SetNChildren ensures that there are exactly n children, deleting any
   266  	// extra, and creating any new ones, using AddNewChild with given type and
   267  	// naming according to nameStubX where X is the index of the child.
   268  	//
   269  	// IMPORTANT: returns whether any modifications were made (mods) AND if
   270  	// that is true, the result from the corresponding UpdateStart call --
   271  	// UpdateEnd is NOT called, allowing for further subsequent updates before
   272  	// you call UpdateEnd(updt)
   273  	//
   274  	// Note that this does not ensure existing children are of given type, or
   275  	// change their names, or call UniquifyNames -- use ConfigChildren for
   276  	// those cases -- this function is for simpler cases where a parent uses
   277  	// this function consistently to manage children all of the same type.
   278  	SetNChildren(n int, typ reflect.Type, nameStub string) (mods, updt bool)
   279  
   280  	// ConfigChildren configures children according to given list of
   281  	// type-and-name's -- attempts to have minimal impact relative to existing
   282  	// items that fit the type and name constraints (they are moved into the
   283  	// corresponding positions), and any extra children are removed, and new
   284  	// ones added, to match the specified config.
   285  	// It is important that names are unique!
   286  	//
   287  	// IMPORTANT: returns whether any modifications were made (mods) AND if
   288  	// that is true, the result from the corresponding UpdateStart call --
   289  	// UpdateEnd is NOT called, allowing for further subsequent updates before
   290  	// you call UpdateEnd(updt).
   291  	ConfigChildren(config kit.TypeAndNameList) (mods, updt bool)
   292  
   293  	//////////////////////////////////////////////////////////////////////////
   294  	//  Deleting Children
   295  
   296  	// DeleteChildAtIndex deletes child at given index (returns error for
   297  	// invalid index).
   298  	// Wraps delete in UpdateStart / End and sets ChildDeleted flag.
   299  	DeleteChildAtIndex(idx int, destroy bool) error
   300  
   301  	// DeleteChild deletes child node, returning error if not found in
   302  	// Children.
   303  	// Wraps delete in UpdateStart / End and sets ChildDeleted flag.
   304  	DeleteChild(child Ki, destroy bool) error
   305  
   306  	// DeleteChildByName deletes child node by name -- returns child, error
   307  	// if not found.
   308  	// Wraps delete in UpdateStart / End and sets ChildDeleted flag.
   309  	DeleteChildByName(name string, destroy bool) (Ki, error)
   310  
   311  	// DeleteChildren deletes all children nodes -- destroy will add removed
   312  	// children to deleted list, to be destroyed later -- otherwise children
   313  	// remain intact but parent is nil -- could be inserted elsewhere, but you
   314  	// better have kept a slice of them before calling this.
   315  	DeleteChildren(destroy bool)
   316  
   317  	// Delete deletes this node from its parent children list -- destroy will
   318  	// add removed child to deleted list, to be destroyed later -- otherwise
   319  	// child remains intact but parent is nil -- could be inserted elsewhere.
   320  	Delete(destroy bool)
   321  
   322  	// Destroy calls DisconnectAll to cut all signal connections,
   323  	// and remove all children and their childrens-children, etc.
   324  	Destroy()
   325  
   326  	//////////////////////////////////////////////////////////////////////////
   327  	//  Flags
   328  
   329  	// Flag returns an atomically safe copy of the bit flags for this node --
   330  	// can use bitflag package to check lags.
   331  	// See Flags type for standard values used in Ki Node --
   332  	// can be extended from FlagsN up to 64 bit capacity.
   333  	// Note that we must always use atomic access as *some* things need to be atomic,
   334  	// and with bits, that means that *all* access needs to be atomic,
   335  	// as you cannot atomically update just a single bit.
   336  	Flags() int64
   337  
   338  	// HasFlag checks if flag is set
   339  	// using atomic, safe for concurrent access
   340  	HasFlag(flag int) bool
   341  
   342  	// SetFlag sets the given flag(s)
   343  	// using atomic, safe for concurrent access
   344  	SetFlag(flag ...int)
   345  
   346  	// SetFlagState sets the given flag(s) to given state
   347  	// using atomic, safe for concurrent access
   348  	SetFlagState(on bool, flag ...int)
   349  
   350  	// SetFlagMask sets the given flags as a mask
   351  	// using atomic, safe for concurrent access
   352  	SetFlagMask(mask int64)
   353  
   354  	// ClearFlag clears the given flag(s)
   355  	// using atomic, safe for concurrent access
   356  	ClearFlag(flag ...int)
   357  
   358  	// ClearFlagMask clears the given flags as a bitmask
   359  	// using atomic, safe for concurrent access
   360  	ClearFlagMask(mask int64)
   361  
   362  	// IsField checks if this is a field on a parent struct (via IsField
   363  	// Flag), as opposed to a child in Children -- Ki nodes can be added as
   364  	// fields to structs and they are automatically parented and named with
   365  	// field name during Init function -- essentially they function as fixed
   366  	// children of the parent struct, and are automatically included in
   367  	// FuncDown* traversals, etc -- see also FunFields.
   368  	IsField() bool
   369  
   370  	// IsUpdating checks if node is currently updating.
   371  	IsUpdating() bool
   372  
   373  	// OnlySelfUpdate checks if this node only applies UpdateStart / End logic
   374  	// to itself, not its children (which is the default) (via Flag of same
   375  	// name) -- useful for a parent node that has a different function than
   376  	// its children.
   377  	OnlySelfUpdate() bool
   378  
   379  	// SetChildAdded sets the ChildAdded flag -- set when notification is needed
   380  	// for Add, Insert methods
   381  	SetChildAdded()
   382  
   383  	// SetValUpdated sets the ValUpdated flag -- set when notification is needed
   384  	// for modifying a value (field, prop, etc)
   385  	SetValUpdated()
   386  
   387  	// IsDeleted checks if this node has just been deleted (within last update
   388  	// cycle), indicated by the NodeDeleted flag which is set when the node is
   389  	// deleted, and is cleared at next UpdateStart call.
   390  	IsDeleted() bool
   391  
   392  	// IsDestroyed checks if this node has been destroyed -- the NodeDestroyed
   393  	// flag is set at start of Destroy function -- the Signal Emit process
   394  	// checks for destroyed receiver nodes and removes connections to them
   395  	// automatically -- other places where pointers to potentially destroyed
   396  	// nodes may linger should also check this flag and reset those pointers.
   397  	IsDestroyed() bool
   398  
   399  	//////////////////////////////////////////////////////////////////////////
   400  	//  Property interface with inheritance -- nodes can inherit props from parents
   401  
   402  	// Properties (Node.Props) tell the GoGi GUI or other frameworks operating
   403  	// on Trees about special features of each node -- functions below support
   404  	// inheritance up Tree -- see kit convert.go for robust convenience
   405  	// methods for converting interface{} values to standard types.
   406  	Properties() *Props
   407  
   408  	// SetProp sets given property key to value val -- initializes property
   409  	// map if nil.
   410  	SetProp(key string, val any)
   411  
   412  	// Prop returns property value for key that is known to exist.
   413  	// Returns nil if it actually doesn't -- this version allows
   414  	// direct conversion of return.  See PropTry for version with
   415  	// error message if uncertain if property exists.
   416  	Prop(key string) any
   417  
   418  	// PropTry returns property value for key.  Returns error message
   419  	// if property with that key does not exist.
   420  	PropTry(key string) (any, error)
   421  
   422  	// PropInherit gets property value from key with options for inheriting
   423  	// property from parents and / or type-level properties.  If inherit, then
   424  	// checks all parents.  If typ then checks property on type as well
   425  	// (registered via KiT type registry).  Returns false if not set anywhere.
   426  	PropInherit(key string, inherit, typ bool) (any, bool)
   427  
   428  	// DeleteProp deletes property key on this node.
   429  	DeleteProp(key string)
   430  
   431  	// PropTag returns the name to look for in type properties, for types
   432  	// that are valid options for values that can be set in Props.  For example
   433  	// in GoGi, it is "style-props" which is then set for all types that can
   434  	// be used in a style (colors, enum options, etc)
   435  	PropTag() string
   436  
   437  	//////////////////////////////////////////////////////////////////////////
   438  	//  Tree walking and Paths
   439  	//   note: always put function args last -- looks better for inline functions
   440  
   441  	// FuncFields calls function on all Ki fields within this node.
   442  	FuncFields(level int, data any, fun Func)
   443  
   444  	// FuncUp calls function on given node and all the way up to its parents,
   445  	// and so on -- sequentially all in current go routine (generally
   446  	// necessary for going up, which is typically quite fast anyway) -- level
   447  	// is incremented after each step (starts at 0, goes up), and passed to
   448  	// function -- returns false if fun aborts with false, else true.
   449  	FuncUp(level int, data any, fun Func) bool
   450  
   451  	// FuncUpParent calls function on parent of node and all the way up to its
   452  	// parents, and so on -- sequentially all in current go routine (generally
   453  	// necessary for going up, which is typically quite fast anyway) -- level
   454  	// is incremented after each step (starts at 0, goes up), and passed to
   455  	// function -- returns false if fun aborts with false, else true.
   456  	FuncUpParent(level int, data any, fun Func) bool
   457  
   458  	// FuncDownMeFirst calls function on this node (MeFirst) and then iterates
   459  	// in a depth-first manner over all the children, including Ki Node fields,
   460  	// which are processed first before children.
   461  	// This uses node state information to manage the traversal and is very fast,
   462  	// but can only be called by one thread at a time -- use a Mutex if there is
   463  	// a chance of multiple threads running at the same time.
   464  	// Function calls are sequential all in current go routine.
   465  	// The level var tracks overall depth in the tree.
   466  	// If fun returns false then any further traversal of that branch of the tree is
   467  	// aborted, but other branches continue -- i.e., if fun on current node
   468  	// returns false, children are not processed further.
   469  	FuncDownMeFirst(level int, data any, fun Func)
   470  
   471  	// FuncDownMeLast iterates in a depth-first manner over the children, calling
   472  	// doChildTestFunc on each node to test if processing should proceed (if it returns
   473  	// false then that branch of the tree is not further processed), and then
   474  	// calls given fun function after all of a node's children (including fields)
   475  	// have been iterated over ("Me Last").
   476  	// This uses node state information to manage the traversal and is very fast,
   477  	// but can only be called by one thread at a time -- use a Mutex if there is
   478  	// a chance of multiple threads running at the same time.
   479  	// Function calls are sequential all in current go routine.
   480  	// The level var tracks overall depth in the tree.
   481  	FuncDownMeLast(level int, data any, doChildTestFunc Func, fun Func)
   482  
   483  	// FuncDownBreadthFirst calls function on all children in breadth-first order
   484  	// using the standard queue strategy.  This depends on and updates the
   485  	// Depth parameter of the node.  If fun returns false then any further
   486  	// traversal of that branch of the tree is aborted, but other branches continue.
   487  	FuncDownBreadthFirst(level int, data any, fun Func)
   488  
   489  	//////////////////////////////////////////////////////////////////////////
   490  	//  State update signaling -- automatically consolidates all changes across
   491  	//   levels so there is only one update at end (optionally per node or only
   492  	//   at highest level)
   493  	//   All modification starts with UpdateStart() and ends with UpdateEnd()
   494  
   495  	// NodeSignal returns the main signal for this node that is used for
   496  	// update, child signals.
   497  	NodeSignal() *Signal
   498  
   499  	// UpdateStart should be called when starting to modify the tree (state or
   500  	// structure) -- returns whether this node was first to set the Updating
   501  	// flag (if so, all children have their Updating flag set -- pass the
   502  	// result to UpdateEnd -- automatically determines the highest level
   503  	// updated, within the normal top-down updating sequence -- can be called
   504  	// multiple times at multiple levels -- it is essential to ensure that all
   505  	// such Start's have an End!  Usage:
   506  	//
   507  	//   updt := n.UpdateStart()
   508  	//   ... code
   509  	//   n.UpdateEnd(updt)
   510  	// or
   511  	//   updt := n.UpdateStart()
   512  	//   defer n.UpdateEnd(updt)
   513  	//   ... code
   514  	UpdateStart() bool
   515  
   516  	// UpdateEnd should be called when done updating after an UpdateStart, and
   517  	// passed the result of the UpdateStart call -- if this is true, the
   518  	// NodeSignalUpdated signal will be emitted and the Updating flag will be
   519  	// cleared, and DestroyDeleted called -- otherwise it is a no-op.
   520  	UpdateEnd(updt bool)
   521  
   522  	// UpdateEndNoSig is just like UpdateEnd except it does not emit a
   523  	// NodeSignalUpdated signal -- use this for situations where updating is
   524  	// already known to be in progress and the signal would be redundant.
   525  	UpdateEndNoSig(updt bool)
   526  
   527  	// UpdateSig just emits a NodeSignalUpdated if the Updating flag is not
   528  	// set -- use this to trigger an update of a given node when there aren't
   529  	// any structural changes and you don't need to prevent any lower-level
   530  	// updates -- much more efficient than a pair of UpdateStart /
   531  	// UpdateEnd's.  Returns true if an update signal was sent.
   532  	UpdateSig() bool
   533  
   534  	// Disconnect disconnects this node, by calling DisconnectAll() on
   535  	// any Signal fields.  Any Node that adds a Signal must define an
   536  	// updated version of this method that calls its embedded parent's
   537  	// version and then calls DisconnectAll() on its Signal fields.
   538  	Disconnect()
   539  
   540  	// DisconnectAll disconnects all the way from me down the tree.
   541  	DisconnectAll()
   542  
   543  	//////////////////////////////////////////////////////////////////////////
   544  	//  Field Value setting with notification
   545  
   546  	// SetField sets given field name to given value, using very robust
   547  	// conversion routines to e.g., convert from strings to numbers, and
   548  	// vice-versa, automatically.  Returns error if not successfully set.
   549  	// wrapped in UpdateStart / End and sets the ValUpdated flag.
   550  	SetField(field string, val any) error
   551  
   552  	//////////////////////////////////////////////////////////////////////////
   553  	//  Deep Copy of Trees
   554  
   555  	// CopyFrom another Ki node.  It is essential that source has Unique names!
   556  	// The Ki copy function recreates the entire tree in the copy, duplicating
   557  	// children etc, copying Props too.  It is very efficient by
   558  	// using the ConfigChildren method which attempts to preserve any existing
   559  	// nodes in the destination if they have the same name and type -- so a
   560  	// copy from a source to a target that only differ minimally will be
   561  	// minimally destructive.  Only copies to same types are supported.
   562  	// Signal connections are NOT copied.  No other Ki pointers are copied,
   563  	// and the field tag copy:"-" can be added for any other fields that
   564  	// should not be copied (unexported, lower-case fields are not copyable).
   565  	CopyFrom(frm Ki) error
   566  
   567  	// Clone creates and returns a deep copy of the tree from this node down.
   568  	// Any pointers within the cloned tree will correctly point within the new
   569  	// cloned tree (see Copy info).
   570  	Clone() Ki
   571  
   572  	// CopyFieldsFrom is the base-level copy method that any copy-intensive
   573  	// nodes should implement directly to explicitly copy relevant fields
   574  	// that should be copied, avoiding any internal pointers etc.
   575  	// This is the performance bottleneck in copying -- the Node version
   576  	// uses generic GenCopyFieldsFrom method using reflection etc
   577  	// which is very slow.  It can be ~10x faster overall to use custom
   578  	// method that explicitly copies each field.  When doing so, you
   579  	// must explicitly call the CopyFieldsFrom method on any embedded
   580  	// Ki types that you inherit from, and, critically, NONE of those
   581  	// can rely on the generic Node-level version.  Furthermore, if the
   582  	// actual end type itself does not define a custom version of this method
   583  	// then the generic one will be called for everything.
   584  	CopyFieldsFrom(frm any)
   585  
   586  	//////////////////////////////////////////////////////////////////////////
   587  	//  IO: for JSON and XML formats -- see also Slice
   588  	//  see https://github.com/goki/ki/wiki/Naming for IO naming conventions
   589  
   590  	// WriteJSON writes the tree to an io.Writer, using MarshalJSON -- also
   591  	// saves a critical starting record that allows file to be loaded de-novo
   592  	// and recreate the proper root type for the tree.
   593  	WriteJSON(writer io.Writer, indent bool) error
   594  
   595  	// SaveJSON saves the tree to a JSON-encoded file, using WriteJSON.
   596  	SaveJSON(filename string) error
   597  
   598  	// ReadJSON reads and unmarshals tree starting at this node, from a
   599  	// JSON-encoded byte stream via io.Reader.  First element in the stream
   600  	// must be of same type as this node -- see ReadNewJSON function to
   601  	// construct a new tree.  Uses ConfigureChildren to minimize changes from
   602  	// current tree relative to loading one -- wraps UnmarshalJSON and calls
   603  	// UnmarshalPost to recover pointers from paths.
   604  	ReadJSON(reader io.Reader) error
   605  
   606  	// OpenJSON opens file over this tree from a JSON-encoded file -- see
   607  	// ReadJSON for details, and OpenNewJSON for opening an entirely new tree.
   608  	OpenJSON(filename string) error
   609  
   610  	// WriteXML writes the tree to an XML-encoded byte string over io.Writer
   611  	// using MarshalXML.
   612  	WriteXML(writer io.Writer, indent bool) error
   613  
   614  	// ReadXML reads the tree from an XML-encoded byte string over io.Reader, calls
   615  	// UnmarshalPost to recover pointers from paths.
   616  	ReadXML(reader io.Reader) error
   617  
   618  	//////////////////////////////////////////////////////////////////////////
   619  	// Init events
   620  
   621  	// OnInit is called when the node is
   622  	// initialized (ie: through InitName).
   623  	// It is called before the node is added to the tree,
   624  	// so it will not have any parents or siblings.
   625  	// It will be called only once in the lifetime of the node.
   626  	// It does nothing by default, but it can be implemented
   627  	// by higher-level types that want to do something.
   628  	OnInit()
   629  
   630  	// OnAdd is called when the node is added to a parent.
   631  	// It will be called only once in the lifetime of the node,
   632  	// unless the node is moved. It will not be called on root
   633  	// nodes, as they are never added to a parent.
   634  	// It does nothing by default, but it can be implemented
   635  	// by higher-level types that want to do something.
   636  	OnAdd()
   637  
   638  	// OnChildAdded is called when a node is added to
   639  	// this node or any of its children. When a node is added to
   640  	// a tree, it calls [OnAdd] and then this function on each of its parents,
   641  	// going in order from the closest parent to the furthest parent.
   642  	// This function does nothing by default, but it can be
   643  	// implemented by higher-level types that want to do something.
   644  	OnChildAdded(child Ki)
   645  }
   646  
   647  // see node.go for struct implementing this interface
   648  
   649  // IMPORTANT: all types should initialize entry in package kit Types Registry
   650  
   651  // var KiT_TypeName = kit.Types.AddType(&TypeName{})
   652  
   653  // Func is a function to call on ki objects walking the tree -- return Break
   654  // = false means don't continue processing this branch of the tree, but other
   655  // branches can continue.  return Continue = true continues down the tree.
   656  type Func func(k Ki, level int, data any) bool
   657  
   658  // KiType is a Ki reflect.Type, suitable for checking for Type.Implements.
   659  var KiType = reflect.TypeOf((*Ki)(nil)).Elem()
   660  
   661  // IsKi returns true if the given type implements the Ki interface at any
   662  // level of embedded structure.
   663  func IsKi(typ reflect.Type) bool {
   664  	if typ == nil {
   665  		return false
   666  	}
   667  	return kit.EmbedImplements(typ, KiType)
   668  }
   669  
   670  // NewOfType makes a new Ki struct of given type -- must be a Ki type -- will
   671  // return nil if not.
   672  func NewOfType(typ reflect.Type) Ki {
   673  	nkid := reflect.New(typ).Interface()
   674  	kid, ok := nkid.(Ki)
   675  	if !ok {
   676  		log.Printf("ki.NewOfType: type %v cannot be converted into a Ki interface type\n", typ.String())
   677  		return nil
   678  	}
   679  	return kid
   680  }
   681  
   682  // Type returns the underlying struct type of given node
   683  func Type(k Ki) reflect.Type {
   684  	return reflect.TypeOf(k.This()).Elem()
   685  }
   686  
   687  // TypeEmbeds tests whether this node is of the given type, or it embeds
   688  // that type at any level of anonymous embedding -- use Embed to get the
   689  // embedded struct of that type from this node.
   690  func TypeEmbeds(k Ki, t reflect.Type) bool {
   691  	return kit.TypeEmbeds(Type(k), t)
   692  }