github.com/goki/ki@v1.1.17/ki/node.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 "bytes" 9 "encoding/gob" 10 "errors" 11 "fmt" 12 "strconv" 13 "sync/atomic" 14 "unsafe" 15 16 "log" 17 "reflect" 18 "strings" 19 20 "github.com/goki/ki/bitflag" 21 "github.com/goki/ki/kit" 22 "github.com/jinzhu/copier" 23 ) 24 25 // The Node implements the Ki interface and provides the core functionality 26 // for the GoKi tree -- use the Node as an embedded struct or as a struct 27 // field -- the embedded version supports full JSON save / load. 28 // 29 // The desc: key for fields is used by the GoGi GUI viewer for help / tooltip 30 // info -- add these to all your derived struct's fields. See relevant docs 31 // for other such tags controlling a wide range of GUI and other functionality 32 // -- Ki makes extensive use of such tags. 33 type Node struct { 34 35 // Ki.Name() user-supplied name of this node -- can be empty or non-unique 36 Nm string `copy:"-" label:"Name" desc:"Ki.Name() user-supplied name of this node -- can be empty or non-unique"` 37 38 // [tableview: -] bit flags for internal node state 39 Flag int64 `tableview:"-" copy:"-" json:"-" xml:"-" max-width:"80" height:"3" desc:"bit flags for internal node state"` 40 41 // [tableview: -] Ki.Properties() property map for arbitrary extensible properties, including style properties 42 Props Props `tableview:"-" xml:"-" copy:"-" label:"Properties" desc:"Ki.Properties() property map for arbitrary extensible properties, including style properties"` 43 44 // [view: -] [tableview: -] Ki.Parent() parent of this node -- set automatically when this node is added as a child of parent 45 Par Ki `tableview:"-" copy:"-" json:"-" xml:"-" label:"Parent" view:"-" desc:"Ki.Parent() parent of this node -- set automatically when this node is added as a child of parent"` 46 47 // [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 48 Kids Slice `tableview:"-" copy:"-" label:"Children" desc:"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"` 49 50 // [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 51 NodeSig Signal `copy:"-" json:"-" xml:"-" view:"-" desc:"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"` 52 53 // [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. 54 Ths Ki `copy:"-" json:"-" xml:"-" view:"-" desc:"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."` 55 56 // [view: -] last value of our index -- used as a starting point for finding us in our parent next time -- is not guaranteed to be accurate! use IndexInParent() method 57 index int `copy:"-" json:"-" xml:"-" view:"-" desc:"last value of our index -- used as a starting point for finding us in our parent next time -- is not guaranteed to be accurate! use IndexInParent() method"` 58 59 // [view: -] optional depth parameter of this node -- only valid during specific contexts, not generally -- e.g., used in FuncDownBreadthFirst function 60 depth int `copy:"-" json:"-" xml:"-" view:"-" desc:"optional depth parameter of this node -- only valid during specific contexts, not generally -- e.g., used in FuncDownBreadthFirst function"` 61 62 // [view: -] cached version of the field offsets relative to base Node address -- used in generic field access. 63 fieldOffs []uintptr `copy:"-" json:"-" xml:"-" view:"-" desc:"cached version of the field offsets relative to base Node address -- used in generic field access."` 64 } 65 66 // must register all new types so type names can be looked up by name -- also props 67 // EnumType:Flags registers KiT_Flags as type for Flags field for GUI views 68 // Nodes can also use type properties e.g., StructViewFields key with props 69 // inside that to set view properties for types, e.g., to hide or show 70 // some of these base Node flags. 71 var KiT_Node = kit.Types.AddType(&Node{}, Props{EnumTypeFlag: KiT_Flags}) 72 73 // check implementation of [Ki] interface 74 var _ = Ki(&Node{}) 75 76 // EnumTypeFlag is a [Props] property name that 77 // indicates what enum type to use as the type for 78 // the flags field in GUI views. Its value should be 79 // of the type [reflect.Type] 80 const EnumTypeFlag string = "EnumType:Flag" 81 82 ////////////////////////////////////////////////////////////////////////// 83 // fmt.Stringer 84 85 // String implements the fmt.stringer interface -- returns the Path of the node 86 func (n *Node) String() string { 87 return n.This().Path() 88 } 89 90 ////////////////////////////////////////////////////////////////////////// 91 // Basic Ki fields 92 93 // This returns the Ki interface that guarantees access to the Ki 94 // interface in a way that always reveals the underlying type 95 // (e.g., in reflect calls). Returns nil if node is nil, 96 // has been destroyed, or is improperly constructed. 97 func (n *Node) This() Ki { 98 if n == nil || n.IsDestroyed() { 99 return nil 100 } 101 return n.Ths 102 } 103 104 // AsNode returns the *ki.Node base type for this node. 105 func (n *Node) AsNode() *Node { 106 return n 107 } 108 109 // InitName initializes this node to given actual object as a Ki interface 110 // and sets its name. The names should be unique among children of a node. 111 // This is needed for root nodes -- automatically done for other nodes 112 // when they are added to the Ki tree. 113 // Even though this is a method and gets the method receiver, it needs 114 // an "external" version of itself passed as the first arg, from which 115 // the proper Ki interface pointer will be obtained. This is the only 116 // way to get virtual functional calling to work within the Go framework. 117 func (n *Node) InitName(k Ki, name string) { 118 InitNode(k) 119 n.SetName(name) 120 } 121 122 // Embed returns the embedded struct of given type from this node (or nil 123 // if it does not embed that type, or the type is not a Ki type -- see 124 // kit.Embed for a generic interface{} version. 125 func (n *Node) Embed(t reflect.Type) Ki { 126 if n == nil { 127 return nil 128 } 129 es := kit.Embed(n.This(), t) 130 if es != nil { 131 k, ok := es.(Ki) 132 if ok { 133 return k 134 } 135 log.Printf("ki.Embed on: %v embedded struct is not a Ki type -- use kit.Embed for a more general version\n", n.Path()) 136 return nil 137 } 138 return nil 139 } 140 141 // BaseIface returns the base interface type for all elements 142 // within this tree. Use reflect.TypeOf((*<interface_type>)(nil)).Elem(). 143 // Used e.g., for determining what types of children 144 // can be created (see kit.EmbedImplements for test method) 145 func (n *Node) BaseIface() reflect.Type { 146 return KiType 147 } 148 149 // Name returns the user-defined name of the object (Node.Nm), 150 // for finding elements, generating paths, IO, etc. 151 func (n *Node) Name() string { 152 return n.Nm 153 } 154 155 // SetName sets the name of this node. 156 // Names should generally be unique across children of each node. 157 // See Unique* functions to check / fix. 158 // If node requires non-unique names, add a separate Label field. 159 // Does NOT wrap in UpdateStart / End. 160 func (n *Node) SetName(name string) { 161 n.Nm = name 162 } 163 164 ////////////////////////////////////////////////////////////////////////// 165 // Parents 166 167 // Parent returns the parent of this Ki (Node.Par) -- Ki has strict 168 // one-parent, no-cycles structure -- see SetParent. 169 func (n *Node) Parent() Ki { 170 return n.Par 171 } 172 173 // IndexInParent returns our index within our parent object -- caches the 174 // last value and uses that for an optimized search so subsequent calls 175 // are typically quite fast. Returns false if we don't have a parent. 176 func (n *Node) IndexInParent() (int, bool) { 177 if n.Par == nil { 178 return -1, false 179 } 180 idx, ok := n.Par.Children().IndexOf(n.This(), n.index) // very fast if index is close.. 181 if ok { 182 n.index = idx 183 } 184 return idx, ok 185 } 186 187 // ParentLevel finds a given potential parent node recursively up the 188 // hierarchy, returning level above current node that the parent was 189 // found, and -1 if not found. 190 func (n *Node) ParentLevel(par Ki) int { 191 parLev := -1 192 n.FuncUpParent(0, n, func(k Ki, level int, d any) bool { 193 if k == par { 194 parLev = level 195 return Break 196 } 197 return Continue 198 }) 199 return parLev 200 } 201 202 // ParentByName finds first parent recursively up hierarchy that matches 203 // given name -- returns nil if not found. 204 func (n *Node) ParentByName(name string) Ki { 205 if IsRoot(n) { 206 return nil 207 } 208 if n.Par.Name() == name { 209 return n.Par 210 } 211 return n.Par.ParentByName(name) 212 } 213 214 // ParentByNameTry finds first parent recursively up hierarchy that matches 215 // given name -- returns error if not found. 216 func (n *Node) ParentByNameTry(name string) (Ki, error) { 217 par := n.ParentByName(name) 218 if par != nil { 219 return par, nil 220 } 221 return nil, fmt.Errorf("ki %v: Parent name: %v not found", n.Nm, name) 222 } 223 224 // ParentByType finds parent recursively up hierarchy, by type, and 225 // returns nil if not found. If embeds is true, then it looks for any 226 // type that embeds the given type at any level of anonymous embedding. 227 func (n *Node) ParentByType(t reflect.Type, embeds bool) Ki { 228 if IsRoot(n) { 229 return nil 230 } 231 if embeds { 232 if TypeEmbeds(n.Par, t) { 233 return n.Par 234 } 235 } else { 236 if Type(n.Par) == t { 237 return n.Par 238 } 239 } 240 return n.Par.ParentByType(t, embeds) 241 } 242 243 // ParentByTypeTry finds parent recursively up hierarchy, by type, and 244 // returns error if not found. If embeds is true, then it looks for any 245 // type that embeds the given type at any level of anonymous embedding. 246 func (n *Node) ParentByTypeTry(t reflect.Type, embeds bool) (Ki, error) { 247 par := n.ParentByType(t, embeds) 248 if par != nil { 249 return par, nil 250 } 251 return nil, fmt.Errorf("ki %v: Parent of type: %v not found", n.Nm, t) 252 } 253 254 ////////////////////////////////////////////////////////////////////////// 255 // Children 256 257 // HasChildren tests whether this node has children (i.e., non-terminal). 258 func (n *Node) HasChildren() bool { 259 return len(n.Kids) > 0 260 } 261 262 // NumChildren returns the number of children of this node. 263 func (n *Node) NumChildren() int { 264 return len(n.Kids) 265 } 266 267 // Children returns a pointer to the slice of children (Node.Kids) -- use 268 // methods on ki.Slice for further ways to access (ByName, ByType, etc). 269 // Slice can be modified directly (e.g., sort, reorder) but Add* / Delete* 270 // methods on parent node should be used to ensure proper tracking. 271 func (n *Node) Children() *Slice { 272 return &n.Kids 273 } 274 275 // IsValidIndex returns error if given index is not valid for accessing children 276 // nil otherwise. 277 func (n *Node) IsValidIndex(idx int) error { 278 sz := len(n.Kids) 279 if idx >= 0 && idx < sz { 280 return nil 281 } 282 return fmt.Errorf("ki %v: invalid index: %v -- len = %v", n.Nm, idx, sz) 283 } 284 285 // Child returns the child at given index -- will panic if index is invalid. 286 // See methods on ki.Slice for more ways to access. 287 func (n *Node) Child(idx int) Ki { 288 return n.Kids[idx] 289 } 290 291 // ChildTry returns the child at given index. Try version returns error if index is invalid. 292 // See methods on ki.Slice for more ways to acces. 293 func (n *Node) ChildTry(idx int) (Ki, error) { 294 if err := n.IsValidIndex(idx); err != nil { 295 return nil, err 296 } 297 return n.Kids[idx], nil 298 } 299 300 // ChildByName returns first element that has given name, nil if not found. 301 // startIdx arg allows for optimized bidirectional find if you have 302 // an idea where it might be -- can be key speedup for large lists -- pass 303 // [ki.StartMiddle] to start in the middle (good default). 304 func (n *Node) ChildByName(name string, startIdx int) Ki { 305 return n.Kids.ElemByName(name, startIdx) 306 } 307 308 // ChildByNameTry returns first element that has given name, error if not found. 309 // startIdx arg allows for optimized bidirectional find if you have 310 // an idea where it might be -- can be key speedup for large lists -- pass 311 // [ki.StartMiddle] to start in the middle (good default). 312 func (n *Node) ChildByNameTry(name string, startIdx int) (Ki, error) { 313 idx, ok := n.Kids.IndexByName(name, startIdx) 314 if !ok { 315 return nil, fmt.Errorf("ki %v: child named: %v not found", n.Nm, name) 316 } 317 return n.Kids[idx], nil 318 } 319 320 // ChildByType returns first element that has given type, nil if not found. 321 // If embeds is true, then it looks for any type that embeds the given type 322 // at any level of anonymous embedding. 323 // startIdx arg allows for optimized bidirectional find if you have 324 // an idea where it might be -- can be key speedup for large lists -- pass 325 // [ki.StartMiddle] to start in the middle (good default). 326 func (n *Node) ChildByType(t reflect.Type, embeds bool, startIdx int) Ki { 327 return n.Kids.ElemByType(t, embeds, startIdx) 328 } 329 330 // ChildByTypeTry returns first element that has given name -- Try version 331 // returns error message if not found. 332 // If embeds is true, then it looks for any type that embeds the given type 333 // at any level of anonymous embedding. 334 // startIdx arg allows for optimized bidirectional find if you have 335 // an idea where it might be -- can be key speedup for large lists -- pass 336 // [ki.StartMiddle] to start in the middle (good default). 337 func (n *Node) ChildByTypeTry(t reflect.Type, embeds bool, startIdx int) (Ki, error) { 338 idx, ok := n.Kids.IndexByType(t, embeds, startIdx) 339 if !ok { 340 return nil, fmt.Errorf("ki %v: child of type: %t not found", n.Nm, t) 341 } 342 return n.Kids[idx], nil 343 } 344 345 ////////////////////////////////////////////////////////////////////////// 346 // Paths 347 348 // EscapePathName returns a name that replaces any path delimiter symbols 349 // . or / with \, and \\ escaped versions. 350 func EscapePathName(name string) string { 351 return strings.Replace(strings.Replace(name, ".", `\,`, -1), "/", `\\`, -1) 352 } 353 354 // UnescapePathName returns a name that replaces any escaped path delimiter symbols 355 // \, or \\ with . and / unescaped versions. 356 func UnescapePathName(name string) string { 357 return strings.Replace(strings.Replace(name, `\,`, ".", -1), `\\`, "/", -1) 358 } 359 360 // Path returns path to this node from the tree root, using node Names 361 // separated by / and fields by . 362 // Node names escape any existing / and . characters to \\ and \, 363 // Path is only valid when child names are unique (see Unique* functions) 364 func (n *Node) Path() string { 365 if n.Par != nil { 366 if n.IsField() { 367 return n.Par.Path() + "." + EscapePathName(n.Nm) 368 } 369 return n.Par.Path() + "/" + EscapePathName(n.Nm) 370 } 371 return "/" + EscapePathName(n.Nm) 372 } 373 374 // PathFrom returns path to this node from given parent node, using 375 // node Names separated by / and fields by . 376 // Node names escape any existing / and . characters to \\ and \, 377 // Path is only valid for finding items when child names are unique 378 // (see Unique* functions) 379 func (n *Node) PathFrom(par Ki) string { 380 if n.Par != nil { 381 ppath := "" 382 if n.Par == par { 383 ppath = "/" + EscapePathName(par.Name()) 384 } else { 385 ppath = n.Par.PathFrom(par) 386 } 387 if n.IsField() { 388 return ppath + "." + EscapePathName(n.Nm) 389 } 390 return ppath + "/" + EscapePathName(n.Nm) 391 } 392 return "/" + n.Nm 393 } 394 395 // find the child on the path 396 func findPathChild(k Ki, child string) (int, bool) { 397 if child[0] == '[' && child[len(child)-1] == ']' { 398 idx, err := strconv.Atoi(child[1 : len(child)-1]) 399 if err != nil { 400 return idx, false 401 } 402 if idx < 0 { // from end 403 idx = len(*k.Children()) + idx 404 } 405 if k.Children().IsValidIndex(idx) != nil { 406 return idx, false 407 } 408 return idx, true 409 } 410 return k.Children().IndexByName(child, 0) 411 } 412 413 // FindPath returns Ki object at given path, starting from this node 414 // (e.g., the root). If this node is not the root, then the path 415 // to this node is subtracted from the start of the path if present there. 416 // FindPath only works correctly when names are unique. 417 // Path has node Names separated by / and fields by . 418 // Node names escape any existing / and . characters to \\ and \, 419 // There is also support for [idx] index-based access for any given path 420 // element, for cases when indexes are more useful than names. 421 // Returns nil if not found. 422 func (n *Node) FindPath(path string) Ki { 423 if n.Par != nil { // we are not root.. 424 myp := n.Path() 425 path = strings.TrimPrefix(path, myp) 426 } 427 curn := Ki(n) 428 pels := strings.Split(strings.Trim(strings.TrimSpace(path), "\""), "/") 429 for i, pe := range pels { 430 if len(pe) == 0 { 431 continue 432 } 433 if i <= 1 && curn.Name() == UnescapePathName(pe) { 434 continue 435 } 436 if strings.Contains(pe, ".") { // has fields 437 fels := strings.Split(pe, ".") 438 // find the child first, then the fields 439 idx, ok := findPathChild(curn, UnescapePathName(fels[0])) 440 if !ok { 441 return nil 442 } 443 curn = (*(curn.Children()))[idx] 444 for i := 1; i < len(fels); i++ { 445 fe := UnescapePathName(fels[i]) 446 fk := KiFieldByName(curn.AsNode(), fe) 447 if fk == nil { 448 return nil 449 } 450 curn = fk 451 } 452 } else { 453 idx, ok := findPathChild(curn, UnescapePathName(pe)) 454 if !ok { 455 return nil 456 } 457 curn = (*(curn.Children()))[idx] 458 } 459 } 460 return curn 461 } 462 463 // FindPathTry returns Ki object at given path, starting from this node 464 // (e.g., the root). If this node is not the root, then the path 465 // to this node is subtracted from the start of the path if present there. 466 // FindPath only works correctly when names are unique. 467 // Path has node Names separated by / and fields by . 468 // Node names escape any existing / and . characters to \\ and \, 469 // There is also support for [idx] index-based access for any given path 470 // element, for cases when indexes are more useful than names. 471 // Returns error if not found. 472 func (n *Node) FindPathTry(path string) (Ki, error) { 473 fk := n.This().FindPath(path) 474 if fk != nil { 475 return fk, nil 476 } 477 return nil, fmt.Errorf("ki %v: element at path: %v not found", n.Nm, path) 478 } 479 480 ////////////////////////////////////////////////////////////////////////// 481 // Adding, Inserting Children 482 483 // AddChild adds given child at end of children list. 484 // The kid node is assumed to not be on another tree (see MoveToParent) 485 // and the existing name should be unique among children. 486 // No UpdateStart / End wrapping is done: do that externally as needed. 487 // Can also call SetFlag(ki.ChildAdded) if notification is needed. 488 func (n *Node) AddChild(kid Ki) error { 489 if err := ThisCheck(n); err != nil { 490 return err 491 } 492 InitNode(kid) 493 n.Kids = append(n.Kids, kid) 494 SetParent(kid, n.This()) // key to set new parent before deleting: indicates move instead of delete 495 return nil 496 } 497 498 // AddNewChild creates a new child of given type and 499 // add at end of children list. 500 // The name should be unique among children. 501 // No UpdateStart / End wrapping is done: do that externally as needed. 502 // Can also call SetChildAdded() if notification is needed. 503 func (n *Node) AddNewChild(typ reflect.Type, name string) Ki { 504 if err := ThisCheck(n); err != nil { 505 return nil 506 } 507 kid := NewOfType(typ) 508 InitNode(kid) 509 n.Kids = append(n.Kids, kid) 510 kid.SetName(name) 511 SetParent(kid, n.This()) 512 return kid 513 } 514 515 // SetChild sets child at given index to be the given item -- if name is 516 // non-empty then it sets the name of the child as well -- just calls Init 517 // (or InitName) on the child, and SetParent. 518 // Names should be unique among children. 519 // No UpdateStart / End wrapping is done: do that externally as needed. 520 // Can also call SetChildAdded() if notification is needed. 521 func (n *Node) SetChild(kid Ki, idx int, name string) error { 522 if err := n.Kids.IsValidIndex(idx); err != nil { 523 return err 524 } 525 if name != "" { 526 kid.InitName(kid, name) 527 } else { 528 InitNode(kid) 529 } 530 n.Kids[idx] = kid 531 SetParent(kid, n.This()) 532 return nil 533 } 534 535 // InsertChild adds given child at position in children list. 536 // The kid node is assumed to not be on another tree (see MoveToParent) 537 // and the existing name should be unique among children. 538 // No UpdateStart / End wrapping is done: do that externally as needed. 539 // Can also call SetChildAdded() if notification is needed. 540 func (n *Node) InsertChild(kid Ki, at int) error { 541 if err := ThisCheck(n); err != nil { 542 return err 543 } 544 InitNode(kid) 545 n.Kids.Insert(kid, at) 546 SetParent(kid, n.This()) 547 return nil 548 } 549 550 // InsertNewChild creates a new child of given type and 551 // add at position in children list. 552 // The name should be unique among children. 553 // No UpdateStart / End wrapping is done: do that externally as needed. 554 // Can also call SetChildAdded() if notification is needed. 555 func (n *Node) InsertNewChild(typ reflect.Type, at int, name string) Ki { 556 if err := ThisCheck(n); err != nil { 557 return nil 558 } 559 kid := NewOfType(typ) 560 InitNode(kid) 561 n.Kids.Insert(kid, at) 562 kid.SetName(name) 563 SetParent(kid, n.This()) 564 return kid 565 } 566 567 // SetNChildren ensures that there are exactly n children, deleting any 568 // extra, and creating any new ones, using AddNewChild with given type and 569 // naming according to nameStubX where X is the index of the child. 570 // 571 // IMPORTANT: returns whether any modifications were made (mods) AND if 572 // that is true, the result from the corresponding UpdateStart call -- 573 // UpdateEnd is NOT called, allowing for further subsequent updates before 574 // you call UpdateEnd(updt) 575 // 576 // Note that this does not ensure existing children are of given type, or 577 // change their names -- use ConfigChildren for those cases. 578 // This function is for simpler cases where a parent uses this function 579 // consistently to manage children all of the same type. 580 func (n *Node) SetNChildren(trgn int, typ reflect.Type, nameStub string) (mods, updt bool) { 581 mods, updt = false, false 582 sz := len(n.Kids) 583 if trgn == sz { 584 return 585 } 586 for sz > trgn { 587 if !mods { 588 mods = true 589 updt = n.UpdateStart() 590 } 591 sz-- 592 n.DeleteChildAtIndex(sz, true) 593 } 594 for sz < trgn { 595 if !mods { 596 mods = true 597 updt = n.UpdateStart() 598 } 599 nm := fmt.Sprintf("%s%d", nameStub, sz) 600 n.InsertNewChild(typ, sz, nm) 601 sz++ 602 } 603 return 604 } 605 606 // ConfigChildren configures children according to given list of 607 // type-and-name's -- attempts to have minimal impact relative to existing 608 // items that fit the type and name constraints (they are moved into the 609 // corresponding positions), and any extra children are removed, and new 610 // ones added, to match the specified config. If uniqNm, then names 611 // represent UniqueNames (this results in Name == UniqueName for created 612 // children). 613 // 614 // IMPORTANT: returns whether any modifications were made (mods) AND if 615 // that is true, the result from the corresponding UpdateStart call -- 616 // UpdateEnd is NOT called, allowing for further subsequent updates before 617 // you call UpdateEnd(updt). 618 func (n *Node) ConfigChildren(config kit.TypeAndNameList) (mods, updt bool) { 619 return n.Kids.Config(n.This(), config) 620 } 621 622 ////////////////////////////////////////////////////////////////////////// 623 // Deleting Children 624 625 // DeleteChildAtIndex deletes child at given index (returns error for 626 // invalid index). 627 // Wraps delete in UpdateStart / End and sets ChildDeleted flag. 628 func (n *Node) DeleteChildAtIndex(idx int, destroy bool) error { 629 child, err := n.ChildTry(idx) 630 if err != nil { 631 return err 632 } 633 updt := n.UpdateStart() 634 n.SetFlag(int(ChildDeleted)) 635 if child.Parent() == n.This() { 636 // only deleting if we are still parent -- change parent first to 637 // signal move delete is always sent live to affected node without 638 // update blocking note: children of child etc will not send a signal 639 // at this point -- only later at destroy -- up to this parent to 640 // manage all that 641 child.SetFlag(int(NodeDeleted)) 642 child.NodeSignal().Emit(child, int64(NodeSignalDeleting), nil) 643 SetParent(child, nil) 644 } 645 n.Kids.DeleteAtIndex(idx) 646 if destroy { 647 DelMgr.Add(child) 648 } 649 UpdateReset(child) // it won't get the UpdateEnd from us anymore -- init fresh in any case 650 n.UpdateEnd(updt) 651 return nil 652 } 653 654 // DeleteChild deletes child node, returning error if not found in 655 // Children. 656 // Wraps delete in UpdateStart / End and sets ChildDeleted flag. 657 func (n *Node) DeleteChild(child Ki, destroy bool) error { 658 if child == nil { 659 return errors.New("ki DeleteChild: child is nil") 660 } 661 idx, ok := n.Kids.IndexOf(child, 0) 662 if !ok { 663 return fmt.Errorf("ki %v: child: %v not found", n.Nm, child.Path()) 664 } 665 return n.DeleteChildAtIndex(idx, destroy) 666 } 667 668 // DeleteChildByName deletes child node by name -- returns child, error 669 // if not found. 670 // Wraps delete in UpdateStart / End and sets ChildDeleted flag. 671 func (n *Node) DeleteChildByName(name string, destroy bool) (Ki, error) { 672 idx, ok := n.Kids.IndexByName(name, 0) 673 if !ok { 674 return nil, fmt.Errorf("ki %v: child named: %v not found", n.Nm, name) 675 } 676 child := n.Kids[idx] 677 return child, n.DeleteChildAtIndex(idx, destroy) 678 } 679 680 // DeleteChildren deletes all children nodes -- destroy will add removed 681 // children to deleted list, to be destroyed later -- otherwise children 682 // remain intact but parent is nil -- could be inserted elsewhere, but you 683 // better have kept a slice of them before calling this. 684 func (n *Node) DeleteChildren(destroy bool) { 685 updt := n.UpdateStart() 686 n.SetFlag(int(ChildrenDeleted)) 687 kids := n.Kids 688 n.Kids = n.Kids[:0] // preserves capacity of list 689 for _, child := range kids { 690 if child == nil { 691 continue 692 } 693 child.SetFlag(int(NodeDeleted)) 694 child.NodeSignal().Emit(child, int64(NodeSignalDeleting), nil) 695 SetParent(child, nil) 696 UpdateReset(child) 697 } 698 if destroy { 699 DelMgr.Add(kids...) 700 } 701 n.UpdateEnd(updt) 702 } 703 704 // Delete deletes this node from its parent children list -- destroy will 705 // add removed child to deleted list, to be destroyed later -- otherwise 706 // child remains intact but parent is nil -- could be inserted elsewhere. 707 func (n *Node) Delete(destroy bool) { 708 if n.Par == nil { 709 if destroy { 710 n.This().Destroy() 711 } 712 } else { 713 n.Par.DeleteChild(n.This(), destroy) 714 } 715 } 716 717 // Destroy calls DisconnectAll to cut all pointers and signal connections, 718 // and remove all children and their childrens-children, etc. 719 func (n *Node) Destroy() { 720 // fmt.Printf("Destroying: %v %T %p Kids: %v\n", n.Nm, n.This(), n.This(), len(n.Kids)) 721 if n.This() == nil { // already dead! 722 return 723 } 724 n.DisconnectAll() 725 n.DeleteChildren(true) // first delete all my children 726 // and destroy all my fields 727 n.FuncFields(0, nil, func(k Ki, level int, d any) bool { 728 k.Destroy() 729 return true 730 }) 731 DelMgr.DestroyDeleted() // then destroy all those kids 732 n.SetFlag(int(NodeDestroyed)) 733 n.Ths = nil // last gasp: lose our own sense of self.. 734 // note: above is thread-safe because This() accessor checks Destroyed 735 } 736 737 ////////////////////////////////////////////////////////////////////////// 738 // Flags 739 740 // Flags returns an atomically safe copy of the bit flags for this node -- 741 // can use bitflag package to check lags. 742 // See Flags type for standard values used in Ki Node -- 743 // can be extended from FlagsN up to 64 bit capacity. 744 // Note that we must always use atomic access as *some* things need to be atomic, 745 // and with bits, that means that *all* access needs to be atomic, 746 // as you cannot atomically update just a single bit. 747 func (n *Node) Flags() int64 { 748 return atomic.LoadInt64(&n.Flag) 749 } 750 751 // HasFlag checks if flag is set 752 // using atomic, safe for concurrent access 753 func (n *Node) HasFlag(flag int) bool { 754 return bitflag.HasAtomic(&n.Flag, flag) 755 } 756 757 // SetFlag sets the given flag(s) 758 // using atomic, safe for concurrent access 759 func (n *Node) SetFlag(flag ...int) { 760 bitflag.SetAtomic(&n.Flag, flag...) 761 } 762 763 // SetFlagState sets the given flag(s) to given state 764 // using atomic, safe for concurrent access 765 func (n *Node) SetFlagState(on bool, flag ...int) { 766 bitflag.SetStateAtomic(&n.Flag, on, flag...) 767 } 768 769 // SetFlagMask sets the given flags as a mask 770 // using atomic, safe for concurrent access 771 func (n *Node) SetFlagMask(mask int64) { 772 bitflag.SetMaskAtomic(&n.Flag, mask) 773 } 774 775 // ClearFlag clears the given flag(s) 776 // using atomic, safe for concurrent access 777 func (n *Node) ClearFlag(flag ...int) { 778 bitflag.ClearAtomic(&n.Flag, flag...) 779 } 780 781 // ClearFlagMask clears the given flags as a bitmask 782 // using atomic, safe for concurrent access 783 func (n *Node) ClearFlagMask(mask int64) { 784 bitflag.ClearMaskAtomic(&n.Flag, mask) 785 } 786 787 // IsField checks if this is a field on a parent struct (via IsField 788 // Flag), as opposed to a child in Children -- Ki nodes can be added as 789 // fields to structs and they are automatically parented and named with 790 // field name during Init function -- essentially they function as fixed 791 // children of the parent struct, and are automatically included in 792 // FuncDown* traversals, etc -- see also FunFields. 793 func (n *Node) IsField() bool { 794 return bitflag.HasAtomic(&n.Flag, int(IsField)) 795 } 796 797 // IsUpdating checks if node is currently updating. 798 func (n *Node) IsUpdating() bool { 799 return bitflag.HasAtomic(&n.Flag, int(Updating)) 800 } 801 802 // OnlySelfUpdate checks if this node only applies UpdateStart / End logic 803 // to itself, not its children (which is the default) (via Flag of same 804 // name) -- useful for a parent node that has a different function than 805 // its children. 806 func (n *Node) OnlySelfUpdate() bool { 807 return bitflag.HasAtomic(&n.Flag, int(OnlySelfUpdate)) 808 } 809 810 // SetOnlySelfUpdate sets the OnlySelfUpdate flag -- see OnlySelfUpdate 811 // method and flag. 812 func (n *Node) SetOnlySelfUpdate() { 813 n.SetFlag(int(OnlySelfUpdate)) 814 } 815 816 // SetChildAdded sets the ChildAdded flag -- set when notification is needed 817 // for Add, Insert methods 818 func (n *Node) SetChildAdded() { 819 n.SetFlag(int(ChildAdded)) 820 } 821 822 // SetValUpdated sets the ValUpdated flag -- set when notification is needed 823 // for modifying a value (field, prop, etc) 824 func (n *Node) SetValUpdated() { 825 n.SetFlag(int(ValUpdated)) 826 } 827 828 // IsDeleted checks if this node has just been deleted (within last update 829 // cycle), indicated by the NodeDeleted flag which is set when the node is 830 // deleted, and is cleared at next UpdateStart call. 831 func (n *Node) IsDeleted() bool { 832 return bitflag.HasAtomic(&n.Flag, int(NodeDeleted)) 833 } 834 835 // IsDestroyed checks if this node has been destroyed -- the NodeDestroyed 836 // flag is set at start of Destroy function -- the Signal Emit process 837 // checks for destroyed receiver nodes and removes connections to them 838 // automatically -- other places where pointers to potentially destroyed 839 // nodes may linger should also check this flag and reset those pointers. 840 func (n *Node) IsDestroyed() bool { 841 return bitflag.HasAtomic(&n.Flag, int(NodeDestroyed)) 842 } 843 844 ////////////////////////////////////////////////////////////////////////// 845 // Property interface with inheritance -- nodes can inherit props from parents 846 847 // Properties (Node.Props) tell the GoGi GUI or other frameworks operating 848 // on Trees about special features of each node -- functions below support 849 // inheritance up Tree -- see kit convert.go for robust convenience 850 // methods for converting interface{} values to standard types. 851 func (n *Node) Properties() *Props { 852 return &n.Props 853 } 854 855 // SetProp sets given property key to value val. 856 // initializes property map if nil. 857 func (n *Node) SetProp(key string, val any) { 858 if n.Props == nil { 859 n.Props = make(Props) 860 } 861 n.Props[key] = val 862 } 863 864 // SetPropStr sets given property key to value val as a string (e.g., for python wrapper) 865 // Initializes property map if nil. 866 func (n *Node) SetPropStr(key string, val string) { 867 n.SetProp(key, val) 868 } 869 870 // SetPropInt sets given property key to value val as an int (e.g., for python wrapper) 871 // Initializes property map if nil. 872 func (n *Node) SetPropInt(key string, val int) { 873 n.SetProp(key, val) 874 } 875 876 // SetPropFloat64 sets given property key to value val as a float64 (e.g., for python wrapper) 877 // Initializes property map if nil. 878 func (n *Node) SetPropFloat64(key string, val float64) { 879 n.SetProp(key, val) 880 } 881 882 // SetSubProps sets given property key to sub-Props value (e.g., for python wrapper) 883 // Initializes property map if nil. 884 func (n *Node) SetSubProps(key string, val Props) { 885 n.SetProp(key, val) 886 } 887 888 // SetProps sets a whole set of properties 889 func (n *Node) SetProps(props Props) { 890 if n.Props == nil { 891 n.Props = make(Props, len(props)) 892 } 893 for key, val := range props { 894 n.Props[key] = val 895 } 896 } 897 898 // Prop returns property value for key that is known to exist. 899 // Returns nil if it actually doesn't -- this version allows 900 // direct conversion of return. See PropTry for version with 901 // error message if uncertain if property exists. 902 func (n *Node) Prop(key string) any { 903 return n.Props[key] 904 } 905 906 // PropTry returns property value for key. Returns error message 907 // if property with that key does not exist. 908 func (n *Node) PropTry(key string) (any, error) { 909 v, ok := n.Props[key] 910 if !ok { 911 return v, fmt.Errorf("ki.PropTry, could not find property with key %v on node %v", key, n.Nm) 912 } 913 return v, nil 914 } 915 916 // PropInherit gets property value from key with options for inheriting 917 // property from parents and / or type-level properties. If inherit, then 918 // checks all parents. If typ then checks property on type as well 919 // (registered via KiT type registry). Returns false if not set anywhere. 920 func (n *Node) PropInherit(key string, inherit, typ bool) (any, bool) { 921 // pr := prof.Start("PropInherit") 922 // defer pr.End() 923 v, ok := n.Props[key] 924 if ok { 925 return v, ok 926 } 927 if inherit && n.Par != nil { 928 v, ok = n.Par.PropInherit(key, inherit, typ) 929 if ok { 930 return v, ok 931 } 932 } 933 if typ { 934 return kit.Types.Prop(Type(n.This()), key) 935 } 936 return nil, false 937 } 938 939 // DeleteProp deletes property key on this node. 940 func (n *Node) DeleteProp(key string) { 941 if n.Props == nil { 942 return 943 } 944 delete(n.Props, key) 945 } 946 947 func init() { 948 gob.Register(Props{}) 949 } 950 951 // CopyPropsFrom copies our properties from another node -- if deep then 952 // does a deep copy -- otherwise copied map just points to same values in 953 // the original map (and we don't reset our map first -- call 954 // DeleteAllProps to do that -- deep copy uses gob encode / decode -- 955 // usually not needed). 956 func (n *Node) CopyPropsFrom(frm Ki, deep bool) error { 957 if *(frm.Properties()) == nil { 958 return nil 959 } 960 // pr := prof.Start("CopyPropsFrom") 961 // defer pr.End() 962 if n.Props == nil { 963 n.Props = make(Props) 964 } 965 fmP := *(frm.Properties()) 966 if deep { 967 // code from https://gist.github.com/soroushjp/0ec92102641ddfc3ad5515ca76405f4d 968 var buf bytes.Buffer 969 enc := gob.NewEncoder(&buf) 970 dec := gob.NewDecoder(&buf) 971 err := enc.Encode(fmP) 972 if err != nil { 973 return err 974 } 975 err = dec.Decode(&n.Props) 976 if err != nil { 977 return err 978 } 979 return nil 980 } 981 for k, v := range fmP { 982 n.Props[k] = v 983 } 984 return nil 985 } 986 987 // PropTag returns the name to look for in type properties, for types 988 // that are valid options for values that can be set in Props. For example 989 // in GoGi, it is "style-props" which is then set for all types that can 990 // be used in a style (colors, enum options, etc) 991 func (n *Node) PropTag() string { 992 return "" 993 } 994 995 ////////////////////////////////////////////////////////////////////////// 996 // Tree walking and state updating 997 998 // FlatFieldsValueFunc is the Node version of this function from kit/embeds.go 999 // it is very slow and should be avoided at all costs! 1000 func FlatFieldsValueFunc(stru any, fun func(stru any, typ reflect.Type, field reflect.StructField, fieldVal reflect.Value) bool) bool { 1001 v := kit.NonPtrValue(reflect.ValueOf(stru)) 1002 typ := v.Type() 1003 if typ == nil || typ == KiT_Node { // this is only diff from embeds.go version -- prevent processing of any Node fields 1004 return true 1005 } 1006 rval := true 1007 for i := 0; i < typ.NumField(); i++ { 1008 f := typ.Field(i) 1009 vf := v.Field(i) 1010 if !vf.CanInterface() { 1011 continue 1012 } 1013 vfi := vf.Interface() // todo: check for interfaceablity etc 1014 if vfi == nil || vfi == stru { 1015 continue 1016 } 1017 if f.Type.Kind() == reflect.Struct && f.Anonymous && kit.PtrType(f.Type) != KiT_Node { 1018 rval = FlatFieldsValueFunc(kit.PtrValue(vf).Interface(), fun) 1019 if !rval { 1020 break 1021 } 1022 } else { 1023 rval = fun(vfi, typ, f, vf) 1024 if !rval { 1025 break 1026 } 1027 } 1028 } 1029 return rval 1030 } 1031 1032 // FuncFields calls function on all Ki fields within this node. 1033 func (n *Node) FuncFields(level int, data any, fun Func) { 1034 if n.This() == nil { 1035 return 1036 } 1037 op := uintptr(unsafe.Pointer(n)) 1038 foffs := KiFieldOffs(n) 1039 for _, fo := range foffs { 1040 fn := (*Node)(unsafe.Pointer(op + fo)) 1041 fun(fn.This(), level, data) 1042 } 1043 } 1044 1045 // FuncUp calls function on given node and all the way up to its parents, 1046 // and so on -- sequentially all in current go routine (generally 1047 // necessary for going up, which is typically quite fast anyway) -- level 1048 // is incremented after each step (starts at 0, goes up), and passed to 1049 // function -- returns false if fun aborts with false, else true. 1050 func (n *Node) FuncUp(level int, data any, fun Func) bool { 1051 cur := n.This() 1052 for { 1053 if !fun(cur, level, data) { // false return means stop 1054 return false 1055 } 1056 level++ 1057 par := cur.Parent() 1058 if par == nil || par == cur { // prevent loops 1059 return true 1060 } 1061 cur = par 1062 } 1063 return true 1064 } 1065 1066 // FuncUpParent calls function on parent of node and all the way up to its 1067 // parents, and so on -- sequentially all in current go routine (generally 1068 // necessary for going up, which is typically quite fast anyway) -- level 1069 // is incremented after each step (starts at 0, goes up), and passed to 1070 // function -- returns false if fun aborts with false, else true. 1071 func (n *Node) FuncUpParent(level int, data any, fun Func) bool { 1072 if IsRoot(n) { 1073 return true 1074 } 1075 cur := n.Parent() 1076 for { 1077 if !fun(cur, level, data) { // false return means stop 1078 return false 1079 } 1080 level++ 1081 par := cur.Parent() 1082 if par == nil || par == cur { // prevent loops 1083 return true 1084 } 1085 cur = par 1086 } 1087 } 1088 1089 //////////////////////////////////////////////////////////////////////// 1090 // FuncDown -- Traversal records 1091 1092 // TravIdxs are tree traversal indexes 1093 type TravIdxs struct { 1094 1095 // current index of field: -1 for start 1096 Field int `desc:"current index of field: -1 for start"` 1097 1098 // current index of children: -1 for start 1099 Child int `desc:"current index of children: -1 for start"` 1100 } 1101 1102 // TravMap is a map for recording the traversal of nodes 1103 type TravMap map[Ki]TravIdxs 1104 1105 // Start is called at start of traversal 1106 func (tm TravMap) Start(k Ki) { 1107 tm[k] = TravIdxs{-1, -1} 1108 } 1109 1110 // End deletes node once done at end of traversal 1111 func (tm TravMap) End(k Ki) { 1112 delete(tm, k) 1113 } 1114 1115 // Set updates traversal state 1116 func (tm TravMap) Set(k Ki, curField, curChild int) { 1117 tm[k] = TravIdxs{curField, curChild} 1118 } 1119 1120 // Get retrieves current traversal state 1121 func (tm TravMap) Get(k Ki) (curField, curChild int) { 1122 tr := tm[k] 1123 return tr.Field, tr.Child 1124 } 1125 1126 // strategy -- same as used in TreeView: 1127 // https://stackoverflow.com/questions/5278580/non-recursive-depth-first-search-algorithm 1128 1129 // FuncDownMeFirst calls function on this node (MeFirst) and then iterates 1130 // in a depth-first manner over all the children, including Ki Node fields, 1131 // which are processed first before children. 1132 // The node traversal is non-recursive and uses locally-allocated state -- safe 1133 // for concurrent calling (modulo conflict management in function call itself). 1134 // Function calls are sequential all in current go routine. 1135 // The level var tracks overall depth in the tree. 1136 // If fun returns false then any further traversal of that branch of the tree is 1137 // aborted, but other branches continue -- i.e., if fun on current node 1138 // returns false, children are not processed further. 1139 func (n *Node) FuncDownMeFirst(level int, data any, fun Func) { 1140 if n.This() == nil || n.IsDeleted() { 1141 return 1142 } 1143 tm := TravMap{} // not significantly faster to pre-allocate larger size 1144 start := n.This() 1145 cur := start 1146 tm.Start(cur) 1147 outer: 1148 for { 1149 if cur.This() != nil && !cur.IsDeleted() && fun(cur, level, data) { // false return means stop 1150 level++ // this is the descent branch 1151 if KiHasKiFields(cur.AsNode()) { 1152 tm.Set(cur, 0, -1) 1153 nxt := KiField(cur.AsNode(), 0).This() 1154 if nxt != nil { 1155 cur = nxt 1156 tm.Start(cur) 1157 continue 1158 } 1159 } 1160 if cur.HasChildren() { 1161 tm.Set(cur, 0, 0) // 0 for no fields 1162 nxt := cur.Child(0) 1163 if nxt != nil && nxt.This() != nil && !nxt.IsDeleted() { 1164 cur = nxt.This() 1165 tm.Start(cur) 1166 continue 1167 } 1168 } 1169 } else { 1170 tm.Set(cur, NumKiFields(cur.AsNode()), cur.NumChildren()) 1171 level++ // we will pop back up out of this next 1172 } 1173 // if we get here, we're in the ascent branch -- move to the right and then up 1174 for { 1175 curField, curChild := tm.Get(cur) 1176 if KiHasKiFields(cur.AsNode()) { 1177 if (curField + 1) < NumKiFields(cur.AsNode()) { 1178 curField++ 1179 tm.Set(cur, curField, curChild) 1180 nxt := KiField(cur.AsNode(), curField).This() 1181 if nxt != nil { 1182 cur = nxt 1183 tm.Start(cur) 1184 continue outer 1185 } 1186 continue 1187 } 1188 } 1189 if (curChild + 1) < cur.NumChildren() { 1190 curChild++ 1191 tm.Set(cur, curField, curChild) 1192 nxt := cur.Child(curChild) 1193 if nxt != nil && nxt.This() != nil && !nxt.IsDeleted() { 1194 cur = nxt.This() 1195 tm.Start(cur) 1196 continue outer 1197 } 1198 continue 1199 } 1200 tm.End(cur) 1201 // couldn't go right, move up.. 1202 if cur == start { 1203 break outer // done! 1204 } 1205 level-- 1206 par := cur.Parent() 1207 if par == nil || par == cur { // shouldn't happen, but does.. 1208 // fmt.Printf("nil / cur parent %v\n", par) 1209 break outer 1210 } 1211 cur = par 1212 } 1213 } 1214 } 1215 1216 // FuncDownMeLast iterates in a depth-first manner over the children, calling 1217 // doChildTestFunc on each node to test if processing should proceed (if it returns 1218 // false then that branch of the tree is not further processed), and then 1219 // calls given fun function after all of a node's children (including fields) 1220 // have been iterated over ("Me Last"). 1221 // The node traversal is non-recursive and uses locally-allocated state -- safe 1222 // for concurrent calling (modulo conflict management in function call itself). 1223 // Function calls are sequential all in current go routine. 1224 // The level var tracks overall depth in the tree. 1225 func (n *Node) FuncDownMeLast(level int, data any, doChildTestFunc Func, fun Func) { 1226 if n.This() == nil || n.IsDeleted() { 1227 return 1228 } 1229 tm := TravMap{} // not significantly faster to pre-allocate larger size 1230 start := n.This() 1231 cur := start 1232 tm.Start(cur) 1233 outer: 1234 for { 1235 if cur.This() != nil && !cur.IsDeleted() && doChildTestFunc(cur, level, data) { // false return means stop 1236 level++ // this is the descent branch 1237 if KiHasKiFields(cur.AsNode()) { 1238 tm.Set(cur, 0, -1) 1239 nxt := KiField(cur.AsNode(), 0).This() 1240 if nxt != nil { 1241 cur = nxt 1242 tm.Set(cur, -1, -1) 1243 continue 1244 } 1245 } 1246 if cur.HasChildren() { 1247 tm.Set(cur, 0, 0) // 0 for no fields 1248 nxt := cur.Child(0) 1249 if nxt != nil && nxt.This() != nil && !nxt.IsDeleted() { 1250 cur = nxt.This() 1251 tm.Set(cur, -1, -1) 1252 continue 1253 } 1254 } 1255 } else { 1256 tm.Set(cur, NumKiFields(cur.AsNode()), cur.NumChildren()) 1257 level++ // we will pop back up out of this next 1258 } 1259 // if we get here, we're in the ascent branch -- move to the right and then up 1260 for { 1261 curField, curChild := tm.Get(cur) 1262 if KiHasKiFields(cur.AsNode()) { 1263 if (curField + 1) < NumKiFields(cur.AsNode()) { 1264 curField++ 1265 tm.Set(cur, curField, curChild) 1266 nxt := KiField(cur.AsNode(), curField).This() 1267 if nxt != nil { 1268 cur = nxt 1269 tm.Set(cur, -1, -1) 1270 continue outer 1271 } 1272 continue 1273 } 1274 } 1275 if (curChild + 1) < cur.NumChildren() { 1276 curChild++ 1277 tm.Set(cur, curField, curChild) 1278 nxt := cur.Child(curChild) 1279 if nxt != nil && nxt.This() != nil && !nxt.IsDeleted() { 1280 cur = nxt.This() 1281 tm.Start(cur) 1282 continue outer 1283 } 1284 continue 1285 } 1286 level-- 1287 fun(cur, level, data) // now we call the function, last.. 1288 // couldn't go right, move up.. 1289 tm.End(cur) 1290 if cur == start { 1291 break outer // done! 1292 } 1293 par := cur.Parent() 1294 if par == nil || par == cur { // shouldn't happen 1295 break outer 1296 } 1297 cur = par 1298 } 1299 } 1300 } 1301 1302 // Note: it does not appear that there is a good recursive BFS search strategy 1303 // https://herringtondarkholme.github.io/2014/02/17/generator/ 1304 // https://stackoverflow.com/questions/2549541/performing-breadth-first-search-recursively/2549825#2549825 1305 1306 // FuncDownBreadthFirst calls function on all children in breadth-first order 1307 // using the standard queue strategy. This depends on and updates the 1308 // Depth parameter of the node. If fun returns false then any further 1309 // traversal of that branch of the tree is aborted, but other branches continue. 1310 func (n *Node) FuncDownBreadthFirst(level int, data any, fun Func) { 1311 start := n.This() 1312 1313 SetDepth(start, level) 1314 queue := make([]Ki, 1) 1315 queue[0] = start 1316 1317 for { 1318 if len(queue) == 0 { 1319 break 1320 } 1321 cur := queue[0] 1322 depth := Depth(cur) 1323 queue = queue[1:] 1324 1325 if cur.This() != nil && !cur.IsDeleted() && fun(cur, depth, data) { // false return means don't proceed 1326 if KiHasKiFields(cur.AsNode()) { 1327 cur.FuncFields(depth+1, data, func(k Ki, level int, d any) bool { 1328 SetDepth(k, level) 1329 queue = append(queue, k) 1330 return true 1331 }) 1332 } 1333 for _, k := range *cur.Children() { 1334 if k != nil && k.This() != nil && !k.IsDeleted() { 1335 SetDepth(k, depth+1) 1336 queue = append(queue, k) 1337 } 1338 } 1339 } 1340 } 1341 } 1342 1343 ////////////////////////////////////////////////////////////////////////// 1344 // State update signaling -- automatically consolidates all changes across 1345 // levels so there is only one update at highest level of modification 1346 // All modification starts with UpdateStart() and ends with UpdateEnd() 1347 1348 // after an UpdateEnd, DestroyDeleted is called 1349 1350 // NodeSignal returns the main signal for this node that is used for 1351 // update, child signals. 1352 func (n *Node) NodeSignal() *Signal { 1353 return &n.NodeSig 1354 } 1355 1356 // UpdateStart should be called when starting to modify the tree (state or 1357 // structure) -- returns whether this node was first to set the Updating 1358 // flag (if so, all children have their Updating flag set -- pass the 1359 // result to UpdateEnd -- automatically determines the highest level 1360 // updated, within the normal top-down updating sequence -- can be called 1361 // multiple times at multiple levels -- it is essential to ensure that all 1362 // such Start's have an End! Usage: 1363 // 1364 // updt := n.UpdateStart() 1365 // ... code 1366 // n.UpdateEnd(updt) 1367 // 1368 // or 1369 // 1370 // updt := n.UpdateStart() 1371 // defer n.UpdateEnd(updt) 1372 // ... code 1373 func (n *Node) UpdateStart() bool { 1374 if n.IsUpdating() || n.IsDestroyed() { 1375 return false 1376 } 1377 if n.OnlySelfUpdate() { 1378 n.SetFlag(int(Updating)) 1379 } else { 1380 // pr := prof.Start("ki.Node.UpdateStart") 1381 n.FuncDownMeFirst(0, nil, func(k Ki, level int, d any) bool { 1382 if !k.IsUpdating() { 1383 k.ClearFlagMask(int64(UpdateFlagsMask)) 1384 k.SetFlag(int(Updating)) 1385 return Continue 1386 } 1387 return Break // bail -- already updating 1388 }) 1389 // pr.End() 1390 } 1391 return true 1392 } 1393 1394 // UpdateEnd should be called when done updating after an UpdateStart, and 1395 // passed the result of the UpdateStart call -- if this is true, the 1396 // NodeSignalUpdated signal will be emitted and the Updating flag will be 1397 // cleared, and DestroyDeleted called -- otherwise it is a no-op. 1398 func (n *Node) UpdateEnd(updt bool) { 1399 if !updt { 1400 return 1401 } 1402 if n.IsDestroyed() || n.IsDeleted() { 1403 return 1404 } 1405 if bitflag.HasAnyAtomic(&n.Flag, int(ChildDeleted), int(ChildrenDeleted)) { 1406 DelMgr.DestroyDeleted() 1407 } 1408 if n.OnlySelfUpdate() { 1409 n.ClearFlag(int(Updating)) 1410 n.NodeSignal().Emit(n.This(), int64(NodeSignalUpdated), n.Flags()) 1411 } else { 1412 // pr := prof.Start("ki.Node.UpdateEnd") 1413 n.FuncDownMeFirst(0, nil, func(k Ki, level int, d any) bool { 1414 k.ClearFlag(int(Updating)) // note: could check first and break here but good to ensure all clear 1415 return true 1416 }) 1417 // pr.End() 1418 n.NodeSignal().Emit(n.This(), int64(NodeSignalUpdated), n.Flags()) 1419 } 1420 } 1421 1422 // UpdateEndNoSig is just like UpdateEnd except it does not emit a 1423 // NodeSignalUpdated signal -- use this for situations where updating is 1424 // already known to be in progress and the signal would be redundant. 1425 func (n *Node) UpdateEndNoSig(updt bool) { 1426 if !updt { 1427 return 1428 } 1429 if n.IsDestroyed() || n.IsDeleted() { 1430 return 1431 } 1432 if bitflag.HasAnyAtomic(&n.Flag, int(ChildDeleted), int(ChildrenDeleted)) { 1433 DelMgr.DestroyDeleted() 1434 } 1435 if n.OnlySelfUpdate() { 1436 n.ClearFlag(int(Updating)) 1437 // n.NodeSignal().Emit(n.This(), int64(NodeSignalUpdated), n.Flags()) 1438 } else { 1439 n.FuncDownMeFirst(0, nil, func(k Ki, level int, d any) bool { 1440 k.ClearFlag(int(Updating)) // note: could check first and break here but good to ensure all clear 1441 return true 1442 }) 1443 // n.NodeSignal().Emit(n.This(), int64(NodeSignalUpdated), n.Flags()) 1444 } 1445 } 1446 1447 // UpdateSig just emits a NodeSignalUpdated if the Updating flag is not 1448 // set -- use this to trigger an update of a given node when there aren't 1449 // any structural changes and you don't need to prevent any lower-level 1450 // updates -- much more efficient than a pair of UpdateStart / 1451 // UpdateEnd's. Returns true if an update signal was sent. 1452 func (n *Node) UpdateSig() bool { 1453 if n.IsUpdating() || n.IsDestroyed() { 1454 return false 1455 } 1456 n.NodeSignal().Emit(n.This(), int64(NodeSignalUpdated), n.Flags()) 1457 return true 1458 } 1459 1460 // Disconnect disconnects this node, by calling DisconnectAll() on 1461 // any Signal fields. Any Node that adds a Signal must define an 1462 // updated version of this method that calls its embedded parent's 1463 // version and then calls DisconnectAll() on its Signal fields. 1464 func (n *Node) Disconnect() { 1465 n.NodeSig.DisconnectAll() 1466 } 1467 1468 // DisconnectAll disconnects all the way from me down the tree. 1469 func (n *Node) DisconnectAll() { 1470 n.FuncDownMeFirst(0, nil, func(k Ki, level int, d any) bool { 1471 k.Disconnect() 1472 return true 1473 }) 1474 } 1475 1476 ////////////////////////////////////////////////////////////////////////// 1477 // Field Value setting with notification 1478 1479 // SetField sets given field name to given value, using very robust 1480 // conversion routines to e.g., convert from strings to numbers, and 1481 // vice-versa, automatically. Returns error if not successfully set. 1482 // wrapped in UpdateStart / End and sets the ValUpdated flag. 1483 func (n *Node) SetField(field string, val any) error { 1484 fv := kit.FlatFieldValueByName(n.This(), field) 1485 if !fv.IsValid() { 1486 return fmt.Errorf("ki.SetField, could not find field %v on node %v", field, n.Nm) 1487 } 1488 updt := n.UpdateStart() 1489 var err error 1490 if field == "Nm" { 1491 n.SetName(kit.ToString(val)) 1492 n.SetValUpdated() 1493 } else { 1494 if kit.SetRobust(kit.PtrValue(fv).Interface(), val) { 1495 n.SetValUpdated() 1496 } else { 1497 err = fmt.Errorf("ki.SetField, SetRobust failed to set field %v on node %v to value: %v", field, n.Nm, val) 1498 } 1499 } 1500 n.UpdateEnd(updt) 1501 return err 1502 } 1503 1504 ////////////////////////////////////////////////////////////////////////// 1505 // Deep Copy / Clone 1506 1507 // note: we use the copy from direction as the receiver is modified whereas the 1508 // from is not and assignment is typically in same direction 1509 1510 // CopyFrom another Ki node. It is essential that source has Unique names! 1511 // The Ki copy function recreates the entire tree in the copy, duplicating 1512 // children etc, copying Props too. It is very efficient by 1513 // using the ConfigChildren method which attempts to preserve any existing 1514 // nodes in the destination if they have the same name and type -- so a 1515 // copy from a source to a target that only differ minimally will be 1516 // minimally destructive. Only copies to same types are supported. 1517 // Signal connections are NOT copied. No other Ki pointers are copied, 1518 // and the field tag copy:"-" can be added for any other fields that 1519 // should not be copied (unexported, lower-case fields are not copyable). 1520 func (n *Node) CopyFrom(frm Ki) error { 1521 if frm == nil { 1522 err := fmt.Errorf("ki.Node CopyFrom into %v -- null 'from' source", n.Path()) 1523 log.Println(err) 1524 return err 1525 } 1526 if Type(n.This()) != Type(frm.This()) { 1527 err := fmt.Errorf("ki.Node Copy to %v from %v -- must have same types, but %v != %v", n.Path(), frm.Path(), Type(n.This()).Name(), Type(frm.This()).Name()) 1528 log.Println(err) 1529 return err 1530 } 1531 updt := n.UpdateStart() 1532 defer n.UpdateEnd(updt) 1533 err := CopyFromRaw(n.This(), frm) 1534 return err 1535 } 1536 1537 // Clone creates and returns a deep copy of the tree from this node down. 1538 // Any pointers within the cloned tree will correctly point within the new 1539 // cloned tree (see Copy info). 1540 func (n *Node) Clone() Ki { 1541 nki := NewOfType(Type(n.This())) 1542 nki.InitName(nki, n.Nm) 1543 nki.CopyFrom(n.This()) 1544 return nki 1545 } 1546 1547 // CopyFromRaw performs a raw copy that just does the deep copy of the 1548 // bits and doesn't do anything with pointers. 1549 func CopyFromRaw(kn, frm Ki) error { 1550 kn.Children().ConfigCopy(kn.This(), *frm.Children()) 1551 n := kn.AsNode() 1552 fmp := *frm.Properties() 1553 n.Props = make(Props, len(fmp)) 1554 n.Props.CopyFrom(fmp, DeepCopy) 1555 1556 kn.This().CopyFieldsFrom(frm) 1557 for i, kid := range *kn.Children() { 1558 fmk := frm.Child(i) 1559 CopyFromRaw(kid, fmk) 1560 } 1561 return nil 1562 } 1563 1564 // CopyFieldsFrom copies from primary fields of source object, 1565 // recursively following anonymous embedded structs 1566 func (n *Node) CopyFieldsFrom(frm any) { 1567 GenCopyFieldsFrom(n.This(), frm) 1568 } 1569 1570 // GenCopyFieldsFrom is a general-purpose copy of primary fields 1571 // of source object, recursively following anonymous embedded structs 1572 func GenCopyFieldsFrom(to any, frm any) { 1573 // pr := prof.Start("GenCopyFieldsFrom") 1574 // defer pr.End() 1575 kitype := KiType 1576 tv := kit.NonPtrValue(reflect.ValueOf(to)) 1577 sv := kit.NonPtrValue(reflect.ValueOf(frm)) 1578 typ := tv.Type() 1579 if kit.ShortTypeName(typ) == "ki.Node" { 1580 return // nothing to copy for base node! 1581 } 1582 for i := 0; i < typ.NumField(); i++ { 1583 f := typ.Field(i) 1584 tf := tv.Field(i) 1585 if !tf.CanInterface() { 1586 continue 1587 } 1588 ctag := f.Tag.Get("copy") 1589 if ctag == "-" { 1590 continue 1591 } 1592 sf := sv.Field(i) 1593 tfpi := kit.PtrValue(tf).Interface() 1594 sfpi := kit.PtrValue(sf).Interface() 1595 if f.Type.Kind() == reflect.Struct && f.Anonymous { 1596 // the generic version cannot ever go back to the node-specific 1597 // because the n.This() is ALWAYS the final type, not the intermediate 1598 // embedded ones 1599 GenCopyFieldsFrom(tfpi, sfpi) 1600 } else { 1601 switch { 1602 case sf.Kind() == reflect.Struct && kit.EmbedImplements(sf.Type(), kitype): 1603 sfk := sfpi.(Ki) 1604 tfk := tfpi.(Ki) 1605 if tfk != nil && sfk != nil { 1606 tfk.CopyFrom(sfk) 1607 } 1608 case f.Type == KiT_Signal: // note: don't copy signals by default 1609 case sf.Type().AssignableTo(tf.Type()): 1610 tf.Set(sf) 1611 // kit.PtrValue(tf).Set(sf) 1612 default: 1613 // use copier https://github.com/jinzhu/copier which handles as much as possible.. 1614 // pr := prof.Start("Copier") 1615 copier.Copy(tfpi, sfpi) 1616 // pr.End() 1617 } 1618 } 1619 1620 } 1621 } 1622 1623 // OnInit is a placeholder implementation of 1624 // [Ki.OnInit] that does nothing. 1625 func (n *Node) OnInit() {} 1626 1627 // OnAdd is a placeholder implementation of 1628 // [Ki.OnAdd] that does nothing. 1629 func (n *Node) OnAdd() {} 1630 1631 // OnChildAdded is a placeholder implementation of 1632 // [Ki.OnChildAdded] that does nothing. 1633 func (n *Node) OnChildAdded(child Ki) {}