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