93 lines
1.6 KiB
Go
93 lines
1.6 KiB
Go
|
package binding
|
||
|
|
||
|
// DataTreeRootID const is the value used as ID for the root of any tree binding.
|
||
|
const DataTreeRootID = ""
|
||
|
|
||
|
// DataTree is the base interface for all bindable data trees.
|
||
|
//
|
||
|
// Since: 2.4
|
||
|
type DataTree interface {
|
||
|
DataItem
|
||
|
GetItem(id string) (DataItem, error)
|
||
|
ChildIDs(string) []string
|
||
|
}
|
||
|
|
||
|
type treeBase struct {
|
||
|
base
|
||
|
|
||
|
ids map[string][]string
|
||
|
items map[string]DataItem
|
||
|
}
|
||
|
|
||
|
// GetItem returns the DataItem at the specified id.
|
||
|
func (t *treeBase) GetItem(id string) (DataItem, error) {
|
||
|
t.lock.RLock()
|
||
|
defer t.lock.RUnlock()
|
||
|
|
||
|
if item, ok := t.items[id]; ok {
|
||
|
return item, nil
|
||
|
}
|
||
|
|
||
|
return nil, errOutOfBounds
|
||
|
}
|
||
|
|
||
|
// ChildIDs returns the ordered IDs of items in this data tree that are children of the specified ID.
|
||
|
func (t *treeBase) ChildIDs(id string) []string {
|
||
|
t.lock.RLock()
|
||
|
defer t.lock.RUnlock()
|
||
|
|
||
|
if ids, ok := t.ids[id]; ok {
|
||
|
return ids
|
||
|
}
|
||
|
|
||
|
return []string{}
|
||
|
}
|
||
|
|
||
|
func (t *treeBase) appendItem(i DataItem, id, parent string) {
|
||
|
t.items[id] = i
|
||
|
ids, ok := t.ids[parent]
|
||
|
if !ok {
|
||
|
ids = make([]string, 0)
|
||
|
}
|
||
|
|
||
|
for _, in := range ids {
|
||
|
if in == id {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
t.ids[parent] = append(ids, id)
|
||
|
}
|
||
|
|
||
|
func (t *treeBase) deleteItem(id, parent string) {
|
||
|
delete(t.items, id)
|
||
|
|
||
|
ids, ok := t.ids[parent]
|
||
|
if !ok {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
off := -1
|
||
|
for i, id2 := range ids {
|
||
|
if id2 == id {
|
||
|
off = i
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
if off == -1 {
|
||
|
return
|
||
|
}
|
||
|
t.ids[parent] = append(ids[:off], ids[off+1:]...)
|
||
|
}
|
||
|
|
||
|
func parentIDFor(id string, ids map[string][]string) string {
|
||
|
for parent, list := range ids {
|
||
|
for _, child := range list {
|
||
|
if child == id {
|
||
|
return parent
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ""
|
||
|
}
|