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