1817 lines
36 KiB
Go
1817 lines
36 KiB
Go
// auto-generated
|
|
// **** THIS FILE IS AUTO-GENERATED, PLEASE DO NOT EDIT IT **** //
|
|
|
|
package binding
|
|
|
|
import (
|
|
"bytes"
|
|
|
|
"fyne.io/fyne/v2"
|
|
)
|
|
|
|
// BoolTree supports binding a tree of bool values.
|
|
//
|
|
// Since: 2.4
|
|
type BoolTree interface {
|
|
DataTree
|
|
|
|
Append(parent, id string, value bool) error
|
|
Get() (map[string][]string, map[string]bool, error)
|
|
GetValue(id string) (bool, error)
|
|
Prepend(parent, id string, value bool) error
|
|
Set(ids map[string][]string, values map[string]bool) error
|
|
SetValue(id string, value bool) error
|
|
}
|
|
|
|
// ExternalBoolTree supports binding a tree of bool values from an external variable.
|
|
//
|
|
// Since: 2.4
|
|
type ExternalBoolTree interface {
|
|
BoolTree
|
|
|
|
Reload() error
|
|
}
|
|
|
|
// NewBoolTree returns a bindable tree of bool values.
|
|
//
|
|
// Since: 2.4
|
|
func NewBoolTree() BoolTree {
|
|
t := &boundBoolTree{val: &map[string]bool{}}
|
|
t.ids = make(map[string][]string)
|
|
t.items = make(map[string]DataItem)
|
|
return t
|
|
}
|
|
|
|
// BindBoolTree returns a bound tree of bool values, based on the contents of the passed values.
|
|
// The ids map specifies how each item relates to its parent (with id ""), with the values being in the v map.
|
|
// If your code changes the content of the maps this refers to you should call Reload() to inform the bindings.
|
|
//
|
|
// Since: 2.4
|
|
func BindBoolTree(ids *map[string][]string, v *map[string]bool) ExternalBoolTree {
|
|
if v == nil {
|
|
return NewBoolTree().(ExternalBoolTree)
|
|
}
|
|
|
|
t := &boundBoolTree{val: v, updateExternal: true}
|
|
t.ids = make(map[string][]string)
|
|
t.items = make(map[string]DataItem)
|
|
|
|
for parent, children := range *ids {
|
|
for _, leaf := range children {
|
|
t.appendItem(bindBoolTreeItem(v, leaf, t.updateExternal), leaf, parent)
|
|
}
|
|
}
|
|
|
|
return t
|
|
}
|
|
|
|
type boundBoolTree struct {
|
|
treeBase
|
|
|
|
updateExternal bool
|
|
val *map[string]bool
|
|
}
|
|
|
|
func (t *boundBoolTree) Append(parent, id string, val bool) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
ids, ok := t.ids[parent]
|
|
if !ok {
|
|
ids = make([]string, 0)
|
|
}
|
|
|
|
t.ids[parent] = append(ids, id)
|
|
v := *t.val
|
|
v[id] = val
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundBoolTree) Get() (map[string][]string, map[string]bool, error) {
|
|
t.lock.RLock()
|
|
defer t.lock.RUnlock()
|
|
|
|
return t.ids, *t.val, nil
|
|
}
|
|
|
|
func (t *boundBoolTree) GetValue(id string) (bool, error) {
|
|
t.lock.RLock()
|
|
defer t.lock.RUnlock()
|
|
|
|
if item, ok := (*t.val)[id]; ok {
|
|
return item, nil
|
|
}
|
|
|
|
return false, errOutOfBounds
|
|
}
|
|
|
|
func (t *boundBoolTree) Prepend(parent, id string, val bool) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
ids, ok := t.ids[parent]
|
|
if !ok {
|
|
ids = make([]string, 0)
|
|
}
|
|
|
|
t.ids[parent] = append([]string{id}, ids...)
|
|
v := *t.val
|
|
v[id] = val
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundBoolTree) Reload() error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundBoolTree) Set(ids map[string][]string, v map[string]bool) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
t.ids = ids
|
|
*t.val = v
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundBoolTree) doReload() (retErr error) {
|
|
updated := []string{}
|
|
fire := false
|
|
for id := range *t.val {
|
|
found := false
|
|
for child := range t.items {
|
|
if child == id { // update existing
|
|
updated = append(updated, id)
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if found {
|
|
continue
|
|
}
|
|
|
|
// append new
|
|
t.appendItem(bindBoolTreeItem(t.val, id, t.updateExternal), id, parentIDFor(id, t.ids))
|
|
updated = append(updated, id)
|
|
fire = true
|
|
}
|
|
|
|
for id := range t.items {
|
|
remove := true
|
|
for _, done := range updated {
|
|
if done == id {
|
|
remove = false
|
|
break
|
|
}
|
|
}
|
|
|
|
if remove { // remove item no longer present
|
|
fire = true
|
|
t.deleteItem(id, parentIDFor(id, t.ids))
|
|
}
|
|
}
|
|
if fire {
|
|
t.trigger()
|
|
}
|
|
|
|
for id, item := range t.items {
|
|
var err error
|
|
if t.updateExternal {
|
|
item.(*boundExternalBoolTreeItem).lock.Lock()
|
|
err = item.(*boundExternalBoolTreeItem).setIfChanged((*t.val)[id])
|
|
item.(*boundExternalBoolTreeItem).lock.Unlock()
|
|
} else {
|
|
item.(*boundBoolTreeItem).lock.Lock()
|
|
err = item.(*boundBoolTreeItem).doSet((*t.val)[id])
|
|
item.(*boundBoolTreeItem).lock.Unlock()
|
|
}
|
|
if err != nil {
|
|
retErr = err
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (t *boundBoolTree) SetValue(id string, v bool) error {
|
|
t.lock.Lock()
|
|
(*t.val)[id] = v
|
|
t.lock.Unlock()
|
|
|
|
item, err := t.GetItem(id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return item.(Bool).Set(v)
|
|
}
|
|
|
|
func bindBoolTreeItem(v *map[string]bool, id string, external bool) Bool {
|
|
if external {
|
|
ret := &boundExternalBoolTreeItem{old: (*v)[id]}
|
|
ret.val = v
|
|
ret.id = id
|
|
return ret
|
|
}
|
|
|
|
return &boundBoolTreeItem{id: id, val: v}
|
|
}
|
|
|
|
type boundBoolTreeItem struct {
|
|
base
|
|
|
|
val *map[string]bool
|
|
id string
|
|
}
|
|
|
|
func (t *boundBoolTreeItem) Get() (bool, error) {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
v := *t.val
|
|
if item, ok := v[t.id]; ok {
|
|
return item, nil
|
|
}
|
|
|
|
return false, errOutOfBounds
|
|
}
|
|
|
|
func (t *boundBoolTreeItem) Set(val bool) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
return t.doSet(val)
|
|
}
|
|
|
|
func (t *boundBoolTreeItem) doSet(val bool) error {
|
|
(*t.val)[t.id] = val
|
|
|
|
t.trigger()
|
|
return nil
|
|
}
|
|
|
|
type boundExternalBoolTreeItem struct {
|
|
boundBoolTreeItem
|
|
|
|
old bool
|
|
}
|
|
|
|
func (t *boundExternalBoolTreeItem) setIfChanged(val bool) error {
|
|
if val == t.old {
|
|
return nil
|
|
}
|
|
(*t.val)[t.id] = val
|
|
t.old = val
|
|
|
|
t.trigger()
|
|
return nil
|
|
}
|
|
|
|
// BytesTree supports binding a tree of []byte values.
|
|
//
|
|
// Since: 2.4
|
|
type BytesTree interface {
|
|
DataTree
|
|
|
|
Append(parent, id string, value []byte) error
|
|
Get() (map[string][]string, map[string][]byte, error)
|
|
GetValue(id string) ([]byte, error)
|
|
Prepend(parent, id string, value []byte) error
|
|
Set(ids map[string][]string, values map[string][]byte) error
|
|
SetValue(id string, value []byte) error
|
|
}
|
|
|
|
// ExternalBytesTree supports binding a tree of []byte values from an external variable.
|
|
//
|
|
// Since: 2.4
|
|
type ExternalBytesTree interface {
|
|
BytesTree
|
|
|
|
Reload() error
|
|
}
|
|
|
|
// NewBytesTree returns a bindable tree of []byte values.
|
|
//
|
|
// Since: 2.4
|
|
func NewBytesTree() BytesTree {
|
|
t := &boundBytesTree{val: &map[string][]byte{}}
|
|
t.ids = make(map[string][]string)
|
|
t.items = make(map[string]DataItem)
|
|
return t
|
|
}
|
|
|
|
// BindBytesTree returns a bound tree of []byte values, based on the contents of the passed values.
|
|
// The ids map specifies how each item relates to its parent (with id ""), with the values being in the v map.
|
|
// If your code changes the content of the maps this refers to you should call Reload() to inform the bindings.
|
|
//
|
|
// Since: 2.4
|
|
func BindBytesTree(ids *map[string][]string, v *map[string][]byte) ExternalBytesTree {
|
|
if v == nil {
|
|
return NewBytesTree().(ExternalBytesTree)
|
|
}
|
|
|
|
t := &boundBytesTree{val: v, updateExternal: true}
|
|
t.ids = make(map[string][]string)
|
|
t.items = make(map[string]DataItem)
|
|
|
|
for parent, children := range *ids {
|
|
for _, leaf := range children {
|
|
t.appendItem(bindBytesTreeItem(v, leaf, t.updateExternal), leaf, parent)
|
|
}
|
|
}
|
|
|
|
return t
|
|
}
|
|
|
|
type boundBytesTree struct {
|
|
treeBase
|
|
|
|
updateExternal bool
|
|
val *map[string][]byte
|
|
}
|
|
|
|
func (t *boundBytesTree) Append(parent, id string, val []byte) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
ids, ok := t.ids[parent]
|
|
if !ok {
|
|
ids = make([]string, 0)
|
|
}
|
|
|
|
t.ids[parent] = append(ids, id)
|
|
v := *t.val
|
|
v[id] = val
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundBytesTree) Get() (map[string][]string, map[string][]byte, error) {
|
|
t.lock.RLock()
|
|
defer t.lock.RUnlock()
|
|
|
|
return t.ids, *t.val, nil
|
|
}
|
|
|
|
func (t *boundBytesTree) GetValue(id string) ([]byte, error) {
|
|
t.lock.RLock()
|
|
defer t.lock.RUnlock()
|
|
|
|
if item, ok := (*t.val)[id]; ok {
|
|
return item, nil
|
|
}
|
|
|
|
return nil, errOutOfBounds
|
|
}
|
|
|
|
func (t *boundBytesTree) Prepend(parent, id string, val []byte) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
ids, ok := t.ids[parent]
|
|
if !ok {
|
|
ids = make([]string, 0)
|
|
}
|
|
|
|
t.ids[parent] = append([]string{id}, ids...)
|
|
v := *t.val
|
|
v[id] = val
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundBytesTree) Reload() error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundBytesTree) Set(ids map[string][]string, v map[string][]byte) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
t.ids = ids
|
|
*t.val = v
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundBytesTree) doReload() (retErr error) {
|
|
updated := []string{}
|
|
fire := false
|
|
for id := range *t.val {
|
|
found := false
|
|
for child := range t.items {
|
|
if child == id { // update existing
|
|
updated = append(updated, id)
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if found {
|
|
continue
|
|
}
|
|
|
|
// append new
|
|
t.appendItem(bindBytesTreeItem(t.val, id, t.updateExternal), id, parentIDFor(id, t.ids))
|
|
updated = append(updated, id)
|
|
fire = true
|
|
}
|
|
|
|
for id := range t.items {
|
|
remove := true
|
|
for _, done := range updated {
|
|
if done == id {
|
|
remove = false
|
|
break
|
|
}
|
|
}
|
|
|
|
if remove { // remove item no longer present
|
|
fire = true
|
|
t.deleteItem(id, parentIDFor(id, t.ids))
|
|
}
|
|
}
|
|
if fire {
|
|
t.trigger()
|
|
}
|
|
|
|
for id, item := range t.items {
|
|
var err error
|
|
if t.updateExternal {
|
|
item.(*boundExternalBytesTreeItem).lock.Lock()
|
|
err = item.(*boundExternalBytesTreeItem).setIfChanged((*t.val)[id])
|
|
item.(*boundExternalBytesTreeItem).lock.Unlock()
|
|
} else {
|
|
item.(*boundBytesTreeItem).lock.Lock()
|
|
err = item.(*boundBytesTreeItem).doSet((*t.val)[id])
|
|
item.(*boundBytesTreeItem).lock.Unlock()
|
|
}
|
|
if err != nil {
|
|
retErr = err
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (t *boundBytesTree) SetValue(id string, v []byte) error {
|
|
t.lock.Lock()
|
|
(*t.val)[id] = v
|
|
t.lock.Unlock()
|
|
|
|
item, err := t.GetItem(id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return item.(Bytes).Set(v)
|
|
}
|
|
|
|
func bindBytesTreeItem(v *map[string][]byte, id string, external bool) Bytes {
|
|
if external {
|
|
ret := &boundExternalBytesTreeItem{old: (*v)[id]}
|
|
ret.val = v
|
|
ret.id = id
|
|
return ret
|
|
}
|
|
|
|
return &boundBytesTreeItem{id: id, val: v}
|
|
}
|
|
|
|
type boundBytesTreeItem struct {
|
|
base
|
|
|
|
val *map[string][]byte
|
|
id string
|
|
}
|
|
|
|
func (t *boundBytesTreeItem) Get() ([]byte, error) {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
v := *t.val
|
|
if item, ok := v[t.id]; ok {
|
|
return item, nil
|
|
}
|
|
|
|
return nil, errOutOfBounds
|
|
}
|
|
|
|
func (t *boundBytesTreeItem) Set(val []byte) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
return t.doSet(val)
|
|
}
|
|
|
|
func (t *boundBytesTreeItem) doSet(val []byte) error {
|
|
(*t.val)[t.id] = val
|
|
|
|
t.trigger()
|
|
return nil
|
|
}
|
|
|
|
type boundExternalBytesTreeItem struct {
|
|
boundBytesTreeItem
|
|
|
|
old []byte
|
|
}
|
|
|
|
func (t *boundExternalBytesTreeItem) setIfChanged(val []byte) error {
|
|
if bytes.Equal(val, t.old) {
|
|
return nil
|
|
}
|
|
(*t.val)[t.id] = val
|
|
t.old = val
|
|
|
|
t.trigger()
|
|
return nil
|
|
}
|
|
|
|
// FloatTree supports binding a tree of float64 values.
|
|
//
|
|
// Since: 2.4
|
|
type FloatTree interface {
|
|
DataTree
|
|
|
|
Append(parent, id string, value float64) error
|
|
Get() (map[string][]string, map[string]float64, error)
|
|
GetValue(id string) (float64, error)
|
|
Prepend(parent, id string, value float64) error
|
|
Set(ids map[string][]string, values map[string]float64) error
|
|
SetValue(id string, value float64) error
|
|
}
|
|
|
|
// ExternalFloatTree supports binding a tree of float64 values from an external variable.
|
|
//
|
|
// Since: 2.4
|
|
type ExternalFloatTree interface {
|
|
FloatTree
|
|
|
|
Reload() error
|
|
}
|
|
|
|
// NewFloatTree returns a bindable tree of float64 values.
|
|
//
|
|
// Since: 2.4
|
|
func NewFloatTree() FloatTree {
|
|
t := &boundFloatTree{val: &map[string]float64{}}
|
|
t.ids = make(map[string][]string)
|
|
t.items = make(map[string]DataItem)
|
|
return t
|
|
}
|
|
|
|
// BindFloatTree returns a bound tree of float64 values, based on the contents of the passed values.
|
|
// The ids map specifies how each item relates to its parent (with id ""), with the values being in the v map.
|
|
// If your code changes the content of the maps this refers to you should call Reload() to inform the bindings.
|
|
//
|
|
// Since: 2.4
|
|
func BindFloatTree(ids *map[string][]string, v *map[string]float64) ExternalFloatTree {
|
|
if v == nil {
|
|
return NewFloatTree().(ExternalFloatTree)
|
|
}
|
|
|
|
t := &boundFloatTree{val: v, updateExternal: true}
|
|
t.ids = make(map[string][]string)
|
|
t.items = make(map[string]DataItem)
|
|
|
|
for parent, children := range *ids {
|
|
for _, leaf := range children {
|
|
t.appendItem(bindFloatTreeItem(v, leaf, t.updateExternal), leaf, parent)
|
|
}
|
|
}
|
|
|
|
return t
|
|
}
|
|
|
|
type boundFloatTree struct {
|
|
treeBase
|
|
|
|
updateExternal bool
|
|
val *map[string]float64
|
|
}
|
|
|
|
func (t *boundFloatTree) Append(parent, id string, val float64) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
ids, ok := t.ids[parent]
|
|
if !ok {
|
|
ids = make([]string, 0)
|
|
}
|
|
|
|
t.ids[parent] = append(ids, id)
|
|
v := *t.val
|
|
v[id] = val
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundFloatTree) Get() (map[string][]string, map[string]float64, error) {
|
|
t.lock.RLock()
|
|
defer t.lock.RUnlock()
|
|
|
|
return t.ids, *t.val, nil
|
|
}
|
|
|
|
func (t *boundFloatTree) GetValue(id string) (float64, error) {
|
|
t.lock.RLock()
|
|
defer t.lock.RUnlock()
|
|
|
|
if item, ok := (*t.val)[id]; ok {
|
|
return item, nil
|
|
}
|
|
|
|
return 0.0, errOutOfBounds
|
|
}
|
|
|
|
func (t *boundFloatTree) Prepend(parent, id string, val float64) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
ids, ok := t.ids[parent]
|
|
if !ok {
|
|
ids = make([]string, 0)
|
|
}
|
|
|
|
t.ids[parent] = append([]string{id}, ids...)
|
|
v := *t.val
|
|
v[id] = val
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundFloatTree) Reload() error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundFloatTree) Set(ids map[string][]string, v map[string]float64) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
t.ids = ids
|
|
*t.val = v
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundFloatTree) doReload() (retErr error) {
|
|
updated := []string{}
|
|
fire := false
|
|
for id := range *t.val {
|
|
found := false
|
|
for child := range t.items {
|
|
if child == id { // update existing
|
|
updated = append(updated, id)
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if found {
|
|
continue
|
|
}
|
|
|
|
// append new
|
|
t.appendItem(bindFloatTreeItem(t.val, id, t.updateExternal), id, parentIDFor(id, t.ids))
|
|
updated = append(updated, id)
|
|
fire = true
|
|
}
|
|
|
|
for id := range t.items {
|
|
remove := true
|
|
for _, done := range updated {
|
|
if done == id {
|
|
remove = false
|
|
break
|
|
}
|
|
}
|
|
|
|
if remove { // remove item no longer present
|
|
fire = true
|
|
t.deleteItem(id, parentIDFor(id, t.ids))
|
|
}
|
|
}
|
|
if fire {
|
|
t.trigger()
|
|
}
|
|
|
|
for id, item := range t.items {
|
|
var err error
|
|
if t.updateExternal {
|
|
item.(*boundExternalFloatTreeItem).lock.Lock()
|
|
err = item.(*boundExternalFloatTreeItem).setIfChanged((*t.val)[id])
|
|
item.(*boundExternalFloatTreeItem).lock.Unlock()
|
|
} else {
|
|
item.(*boundFloatTreeItem).lock.Lock()
|
|
err = item.(*boundFloatTreeItem).doSet((*t.val)[id])
|
|
item.(*boundFloatTreeItem).lock.Unlock()
|
|
}
|
|
if err != nil {
|
|
retErr = err
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (t *boundFloatTree) SetValue(id string, v float64) error {
|
|
t.lock.Lock()
|
|
(*t.val)[id] = v
|
|
t.lock.Unlock()
|
|
|
|
item, err := t.GetItem(id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return item.(Float).Set(v)
|
|
}
|
|
|
|
func bindFloatTreeItem(v *map[string]float64, id string, external bool) Float {
|
|
if external {
|
|
ret := &boundExternalFloatTreeItem{old: (*v)[id]}
|
|
ret.val = v
|
|
ret.id = id
|
|
return ret
|
|
}
|
|
|
|
return &boundFloatTreeItem{id: id, val: v}
|
|
}
|
|
|
|
type boundFloatTreeItem struct {
|
|
base
|
|
|
|
val *map[string]float64
|
|
id string
|
|
}
|
|
|
|
func (t *boundFloatTreeItem) Get() (float64, error) {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
v := *t.val
|
|
if item, ok := v[t.id]; ok {
|
|
return item, nil
|
|
}
|
|
|
|
return 0.0, errOutOfBounds
|
|
}
|
|
|
|
func (t *boundFloatTreeItem) Set(val float64) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
return t.doSet(val)
|
|
}
|
|
|
|
func (t *boundFloatTreeItem) doSet(val float64) error {
|
|
(*t.val)[t.id] = val
|
|
|
|
t.trigger()
|
|
return nil
|
|
}
|
|
|
|
type boundExternalFloatTreeItem struct {
|
|
boundFloatTreeItem
|
|
|
|
old float64
|
|
}
|
|
|
|
func (t *boundExternalFloatTreeItem) setIfChanged(val float64) error {
|
|
if val == t.old {
|
|
return nil
|
|
}
|
|
(*t.val)[t.id] = val
|
|
t.old = val
|
|
|
|
t.trigger()
|
|
return nil
|
|
}
|
|
|
|
// IntTree supports binding a tree of int values.
|
|
//
|
|
// Since: 2.4
|
|
type IntTree interface {
|
|
DataTree
|
|
|
|
Append(parent, id string, value int) error
|
|
Get() (map[string][]string, map[string]int, error)
|
|
GetValue(id string) (int, error)
|
|
Prepend(parent, id string, value int) error
|
|
Set(ids map[string][]string, values map[string]int) error
|
|
SetValue(id string, value int) error
|
|
}
|
|
|
|
// ExternalIntTree supports binding a tree of int values from an external variable.
|
|
//
|
|
// Since: 2.4
|
|
type ExternalIntTree interface {
|
|
IntTree
|
|
|
|
Reload() error
|
|
}
|
|
|
|
// NewIntTree returns a bindable tree of int values.
|
|
//
|
|
// Since: 2.4
|
|
func NewIntTree() IntTree {
|
|
t := &boundIntTree{val: &map[string]int{}}
|
|
t.ids = make(map[string][]string)
|
|
t.items = make(map[string]DataItem)
|
|
return t
|
|
}
|
|
|
|
// BindIntTree returns a bound tree of int values, based on the contents of the passed values.
|
|
// The ids map specifies how each item relates to its parent (with id ""), with the values being in the v map.
|
|
// If your code changes the content of the maps this refers to you should call Reload() to inform the bindings.
|
|
//
|
|
// Since: 2.4
|
|
func BindIntTree(ids *map[string][]string, v *map[string]int) ExternalIntTree {
|
|
if v == nil {
|
|
return NewIntTree().(ExternalIntTree)
|
|
}
|
|
|
|
t := &boundIntTree{val: v, updateExternal: true}
|
|
t.ids = make(map[string][]string)
|
|
t.items = make(map[string]DataItem)
|
|
|
|
for parent, children := range *ids {
|
|
for _, leaf := range children {
|
|
t.appendItem(bindIntTreeItem(v, leaf, t.updateExternal), leaf, parent)
|
|
}
|
|
}
|
|
|
|
return t
|
|
}
|
|
|
|
type boundIntTree struct {
|
|
treeBase
|
|
|
|
updateExternal bool
|
|
val *map[string]int
|
|
}
|
|
|
|
func (t *boundIntTree) Append(parent, id string, val int) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
ids, ok := t.ids[parent]
|
|
if !ok {
|
|
ids = make([]string, 0)
|
|
}
|
|
|
|
t.ids[parent] = append(ids, id)
|
|
v := *t.val
|
|
v[id] = val
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundIntTree) Get() (map[string][]string, map[string]int, error) {
|
|
t.lock.RLock()
|
|
defer t.lock.RUnlock()
|
|
|
|
return t.ids, *t.val, nil
|
|
}
|
|
|
|
func (t *boundIntTree) GetValue(id string) (int, error) {
|
|
t.lock.RLock()
|
|
defer t.lock.RUnlock()
|
|
|
|
if item, ok := (*t.val)[id]; ok {
|
|
return item, nil
|
|
}
|
|
|
|
return 0, errOutOfBounds
|
|
}
|
|
|
|
func (t *boundIntTree) Prepend(parent, id string, val int) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
ids, ok := t.ids[parent]
|
|
if !ok {
|
|
ids = make([]string, 0)
|
|
}
|
|
|
|
t.ids[parent] = append([]string{id}, ids...)
|
|
v := *t.val
|
|
v[id] = val
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundIntTree) Reload() error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundIntTree) Set(ids map[string][]string, v map[string]int) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
t.ids = ids
|
|
*t.val = v
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundIntTree) doReload() (retErr error) {
|
|
updated := []string{}
|
|
fire := false
|
|
for id := range *t.val {
|
|
found := false
|
|
for child := range t.items {
|
|
if child == id { // update existing
|
|
updated = append(updated, id)
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if found {
|
|
continue
|
|
}
|
|
|
|
// append new
|
|
t.appendItem(bindIntTreeItem(t.val, id, t.updateExternal), id, parentIDFor(id, t.ids))
|
|
updated = append(updated, id)
|
|
fire = true
|
|
}
|
|
|
|
for id := range t.items {
|
|
remove := true
|
|
for _, done := range updated {
|
|
if done == id {
|
|
remove = false
|
|
break
|
|
}
|
|
}
|
|
|
|
if remove { // remove item no longer present
|
|
fire = true
|
|
t.deleteItem(id, parentIDFor(id, t.ids))
|
|
}
|
|
}
|
|
if fire {
|
|
t.trigger()
|
|
}
|
|
|
|
for id, item := range t.items {
|
|
var err error
|
|
if t.updateExternal {
|
|
item.(*boundExternalIntTreeItem).lock.Lock()
|
|
err = item.(*boundExternalIntTreeItem).setIfChanged((*t.val)[id])
|
|
item.(*boundExternalIntTreeItem).lock.Unlock()
|
|
} else {
|
|
item.(*boundIntTreeItem).lock.Lock()
|
|
err = item.(*boundIntTreeItem).doSet((*t.val)[id])
|
|
item.(*boundIntTreeItem).lock.Unlock()
|
|
}
|
|
if err != nil {
|
|
retErr = err
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (t *boundIntTree) SetValue(id string, v int) error {
|
|
t.lock.Lock()
|
|
(*t.val)[id] = v
|
|
t.lock.Unlock()
|
|
|
|
item, err := t.GetItem(id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return item.(Int).Set(v)
|
|
}
|
|
|
|
func bindIntTreeItem(v *map[string]int, id string, external bool) Int {
|
|
if external {
|
|
ret := &boundExternalIntTreeItem{old: (*v)[id]}
|
|
ret.val = v
|
|
ret.id = id
|
|
return ret
|
|
}
|
|
|
|
return &boundIntTreeItem{id: id, val: v}
|
|
}
|
|
|
|
type boundIntTreeItem struct {
|
|
base
|
|
|
|
val *map[string]int
|
|
id string
|
|
}
|
|
|
|
func (t *boundIntTreeItem) Get() (int, error) {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
v := *t.val
|
|
if item, ok := v[t.id]; ok {
|
|
return item, nil
|
|
}
|
|
|
|
return 0, errOutOfBounds
|
|
}
|
|
|
|
func (t *boundIntTreeItem) Set(val int) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
return t.doSet(val)
|
|
}
|
|
|
|
func (t *boundIntTreeItem) doSet(val int) error {
|
|
(*t.val)[t.id] = val
|
|
|
|
t.trigger()
|
|
return nil
|
|
}
|
|
|
|
type boundExternalIntTreeItem struct {
|
|
boundIntTreeItem
|
|
|
|
old int
|
|
}
|
|
|
|
func (t *boundExternalIntTreeItem) setIfChanged(val int) error {
|
|
if val == t.old {
|
|
return nil
|
|
}
|
|
(*t.val)[t.id] = val
|
|
t.old = val
|
|
|
|
t.trigger()
|
|
return nil
|
|
}
|
|
|
|
// RuneTree supports binding a tree of rune values.
|
|
//
|
|
// Since: 2.4
|
|
type RuneTree interface {
|
|
DataTree
|
|
|
|
Append(parent, id string, value rune) error
|
|
Get() (map[string][]string, map[string]rune, error)
|
|
GetValue(id string) (rune, error)
|
|
Prepend(parent, id string, value rune) error
|
|
Set(ids map[string][]string, values map[string]rune) error
|
|
SetValue(id string, value rune) error
|
|
}
|
|
|
|
// ExternalRuneTree supports binding a tree of rune values from an external variable.
|
|
//
|
|
// Since: 2.4
|
|
type ExternalRuneTree interface {
|
|
RuneTree
|
|
|
|
Reload() error
|
|
}
|
|
|
|
// NewRuneTree returns a bindable tree of rune values.
|
|
//
|
|
// Since: 2.4
|
|
func NewRuneTree() RuneTree {
|
|
t := &boundRuneTree{val: &map[string]rune{}}
|
|
t.ids = make(map[string][]string)
|
|
t.items = make(map[string]DataItem)
|
|
return t
|
|
}
|
|
|
|
// BindRuneTree returns a bound tree of rune values, based on the contents of the passed values.
|
|
// The ids map specifies how each item relates to its parent (with id ""), with the values being in the v map.
|
|
// If your code changes the content of the maps this refers to you should call Reload() to inform the bindings.
|
|
//
|
|
// Since: 2.4
|
|
func BindRuneTree(ids *map[string][]string, v *map[string]rune) ExternalRuneTree {
|
|
if v == nil {
|
|
return NewRuneTree().(ExternalRuneTree)
|
|
}
|
|
|
|
t := &boundRuneTree{val: v, updateExternal: true}
|
|
t.ids = make(map[string][]string)
|
|
t.items = make(map[string]DataItem)
|
|
|
|
for parent, children := range *ids {
|
|
for _, leaf := range children {
|
|
t.appendItem(bindRuneTreeItem(v, leaf, t.updateExternal), leaf, parent)
|
|
}
|
|
}
|
|
|
|
return t
|
|
}
|
|
|
|
type boundRuneTree struct {
|
|
treeBase
|
|
|
|
updateExternal bool
|
|
val *map[string]rune
|
|
}
|
|
|
|
func (t *boundRuneTree) Append(parent, id string, val rune) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
ids, ok := t.ids[parent]
|
|
if !ok {
|
|
ids = make([]string, 0)
|
|
}
|
|
|
|
t.ids[parent] = append(ids, id)
|
|
v := *t.val
|
|
v[id] = val
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundRuneTree) Get() (map[string][]string, map[string]rune, error) {
|
|
t.lock.RLock()
|
|
defer t.lock.RUnlock()
|
|
|
|
return t.ids, *t.val, nil
|
|
}
|
|
|
|
func (t *boundRuneTree) GetValue(id string) (rune, error) {
|
|
t.lock.RLock()
|
|
defer t.lock.RUnlock()
|
|
|
|
if item, ok := (*t.val)[id]; ok {
|
|
return item, nil
|
|
}
|
|
|
|
return rune(0), errOutOfBounds
|
|
}
|
|
|
|
func (t *boundRuneTree) Prepend(parent, id string, val rune) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
ids, ok := t.ids[parent]
|
|
if !ok {
|
|
ids = make([]string, 0)
|
|
}
|
|
|
|
t.ids[parent] = append([]string{id}, ids...)
|
|
v := *t.val
|
|
v[id] = val
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundRuneTree) Reload() error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundRuneTree) Set(ids map[string][]string, v map[string]rune) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
t.ids = ids
|
|
*t.val = v
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundRuneTree) doReload() (retErr error) {
|
|
updated := []string{}
|
|
fire := false
|
|
for id := range *t.val {
|
|
found := false
|
|
for child := range t.items {
|
|
if child == id { // update existing
|
|
updated = append(updated, id)
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if found {
|
|
continue
|
|
}
|
|
|
|
// append new
|
|
t.appendItem(bindRuneTreeItem(t.val, id, t.updateExternal), id, parentIDFor(id, t.ids))
|
|
updated = append(updated, id)
|
|
fire = true
|
|
}
|
|
|
|
for id := range t.items {
|
|
remove := true
|
|
for _, done := range updated {
|
|
if done == id {
|
|
remove = false
|
|
break
|
|
}
|
|
}
|
|
|
|
if remove { // remove item no longer present
|
|
fire = true
|
|
t.deleteItem(id, parentIDFor(id, t.ids))
|
|
}
|
|
}
|
|
if fire {
|
|
t.trigger()
|
|
}
|
|
|
|
for id, item := range t.items {
|
|
var err error
|
|
if t.updateExternal {
|
|
item.(*boundExternalRuneTreeItem).lock.Lock()
|
|
err = item.(*boundExternalRuneTreeItem).setIfChanged((*t.val)[id])
|
|
item.(*boundExternalRuneTreeItem).lock.Unlock()
|
|
} else {
|
|
item.(*boundRuneTreeItem).lock.Lock()
|
|
err = item.(*boundRuneTreeItem).doSet((*t.val)[id])
|
|
item.(*boundRuneTreeItem).lock.Unlock()
|
|
}
|
|
if err != nil {
|
|
retErr = err
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (t *boundRuneTree) SetValue(id string, v rune) error {
|
|
t.lock.Lock()
|
|
(*t.val)[id] = v
|
|
t.lock.Unlock()
|
|
|
|
item, err := t.GetItem(id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return item.(Rune).Set(v)
|
|
}
|
|
|
|
func bindRuneTreeItem(v *map[string]rune, id string, external bool) Rune {
|
|
if external {
|
|
ret := &boundExternalRuneTreeItem{old: (*v)[id]}
|
|
ret.val = v
|
|
ret.id = id
|
|
return ret
|
|
}
|
|
|
|
return &boundRuneTreeItem{id: id, val: v}
|
|
}
|
|
|
|
type boundRuneTreeItem struct {
|
|
base
|
|
|
|
val *map[string]rune
|
|
id string
|
|
}
|
|
|
|
func (t *boundRuneTreeItem) Get() (rune, error) {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
v := *t.val
|
|
if item, ok := v[t.id]; ok {
|
|
return item, nil
|
|
}
|
|
|
|
return rune(0), errOutOfBounds
|
|
}
|
|
|
|
func (t *boundRuneTreeItem) Set(val rune) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
return t.doSet(val)
|
|
}
|
|
|
|
func (t *boundRuneTreeItem) doSet(val rune) error {
|
|
(*t.val)[t.id] = val
|
|
|
|
t.trigger()
|
|
return nil
|
|
}
|
|
|
|
type boundExternalRuneTreeItem struct {
|
|
boundRuneTreeItem
|
|
|
|
old rune
|
|
}
|
|
|
|
func (t *boundExternalRuneTreeItem) setIfChanged(val rune) error {
|
|
if val == t.old {
|
|
return nil
|
|
}
|
|
(*t.val)[t.id] = val
|
|
t.old = val
|
|
|
|
t.trigger()
|
|
return nil
|
|
}
|
|
|
|
// StringTree supports binding a tree of string values.
|
|
//
|
|
// Since: 2.4
|
|
type StringTree interface {
|
|
DataTree
|
|
|
|
Append(parent, id string, value string) error
|
|
Get() (map[string][]string, map[string]string, error)
|
|
GetValue(id string) (string, error)
|
|
Prepend(parent, id string, value string) error
|
|
Set(ids map[string][]string, values map[string]string) error
|
|
SetValue(id string, value string) error
|
|
}
|
|
|
|
// ExternalStringTree supports binding a tree of string values from an external variable.
|
|
//
|
|
// Since: 2.4
|
|
type ExternalStringTree interface {
|
|
StringTree
|
|
|
|
Reload() error
|
|
}
|
|
|
|
// NewStringTree returns a bindable tree of string values.
|
|
//
|
|
// Since: 2.4
|
|
func NewStringTree() StringTree {
|
|
t := &boundStringTree{val: &map[string]string{}}
|
|
t.ids = make(map[string][]string)
|
|
t.items = make(map[string]DataItem)
|
|
return t
|
|
}
|
|
|
|
// BindStringTree returns a bound tree of string values, based on the contents of the passed values.
|
|
// The ids map specifies how each item relates to its parent (with id ""), with the values being in the v map.
|
|
// If your code changes the content of the maps this refers to you should call Reload() to inform the bindings.
|
|
//
|
|
// Since: 2.4
|
|
func BindStringTree(ids *map[string][]string, v *map[string]string) ExternalStringTree {
|
|
if v == nil {
|
|
return NewStringTree().(ExternalStringTree)
|
|
}
|
|
|
|
t := &boundStringTree{val: v, updateExternal: true}
|
|
t.ids = make(map[string][]string)
|
|
t.items = make(map[string]DataItem)
|
|
|
|
for parent, children := range *ids {
|
|
for _, leaf := range children {
|
|
t.appendItem(bindStringTreeItem(v, leaf, t.updateExternal), leaf, parent)
|
|
}
|
|
}
|
|
|
|
return t
|
|
}
|
|
|
|
type boundStringTree struct {
|
|
treeBase
|
|
|
|
updateExternal bool
|
|
val *map[string]string
|
|
}
|
|
|
|
func (t *boundStringTree) Append(parent, id string, val string) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
ids, ok := t.ids[parent]
|
|
if !ok {
|
|
ids = make([]string, 0)
|
|
}
|
|
|
|
t.ids[parent] = append(ids, id)
|
|
v := *t.val
|
|
v[id] = val
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundStringTree) Get() (map[string][]string, map[string]string, error) {
|
|
t.lock.RLock()
|
|
defer t.lock.RUnlock()
|
|
|
|
return t.ids, *t.val, nil
|
|
}
|
|
|
|
func (t *boundStringTree) GetValue(id string) (string, error) {
|
|
t.lock.RLock()
|
|
defer t.lock.RUnlock()
|
|
|
|
if item, ok := (*t.val)[id]; ok {
|
|
return item, nil
|
|
}
|
|
|
|
return "", errOutOfBounds
|
|
}
|
|
|
|
func (t *boundStringTree) Prepend(parent, id string, val string) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
ids, ok := t.ids[parent]
|
|
if !ok {
|
|
ids = make([]string, 0)
|
|
}
|
|
|
|
t.ids[parent] = append([]string{id}, ids...)
|
|
v := *t.val
|
|
v[id] = val
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundStringTree) Reload() error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundStringTree) Set(ids map[string][]string, v map[string]string) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
t.ids = ids
|
|
*t.val = v
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundStringTree) doReload() (retErr error) {
|
|
updated := []string{}
|
|
fire := false
|
|
for id := range *t.val {
|
|
found := false
|
|
for child := range t.items {
|
|
if child == id { // update existing
|
|
updated = append(updated, id)
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if found {
|
|
continue
|
|
}
|
|
|
|
// append new
|
|
t.appendItem(bindStringTreeItem(t.val, id, t.updateExternal), id, parentIDFor(id, t.ids))
|
|
updated = append(updated, id)
|
|
fire = true
|
|
}
|
|
|
|
for id := range t.items {
|
|
remove := true
|
|
for _, done := range updated {
|
|
if done == id {
|
|
remove = false
|
|
break
|
|
}
|
|
}
|
|
|
|
if remove { // remove item no longer present
|
|
fire = true
|
|
t.deleteItem(id, parentIDFor(id, t.ids))
|
|
}
|
|
}
|
|
if fire {
|
|
t.trigger()
|
|
}
|
|
|
|
for id, item := range t.items {
|
|
var err error
|
|
if t.updateExternal {
|
|
item.(*boundExternalStringTreeItem).lock.Lock()
|
|
err = item.(*boundExternalStringTreeItem).setIfChanged((*t.val)[id])
|
|
item.(*boundExternalStringTreeItem).lock.Unlock()
|
|
} else {
|
|
item.(*boundStringTreeItem).lock.Lock()
|
|
err = item.(*boundStringTreeItem).doSet((*t.val)[id])
|
|
item.(*boundStringTreeItem).lock.Unlock()
|
|
}
|
|
if err != nil {
|
|
retErr = err
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (t *boundStringTree) SetValue(id string, v string) error {
|
|
t.lock.Lock()
|
|
(*t.val)[id] = v
|
|
t.lock.Unlock()
|
|
|
|
item, err := t.GetItem(id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return item.(String).Set(v)
|
|
}
|
|
|
|
func bindStringTreeItem(v *map[string]string, id string, external bool) String {
|
|
if external {
|
|
ret := &boundExternalStringTreeItem{old: (*v)[id]}
|
|
ret.val = v
|
|
ret.id = id
|
|
return ret
|
|
}
|
|
|
|
return &boundStringTreeItem{id: id, val: v}
|
|
}
|
|
|
|
type boundStringTreeItem struct {
|
|
base
|
|
|
|
val *map[string]string
|
|
id string
|
|
}
|
|
|
|
func (t *boundStringTreeItem) Get() (string, error) {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
v := *t.val
|
|
if item, ok := v[t.id]; ok {
|
|
return item, nil
|
|
}
|
|
|
|
return "", errOutOfBounds
|
|
}
|
|
|
|
func (t *boundStringTreeItem) Set(val string) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
return t.doSet(val)
|
|
}
|
|
|
|
func (t *boundStringTreeItem) doSet(val string) error {
|
|
(*t.val)[t.id] = val
|
|
|
|
t.trigger()
|
|
return nil
|
|
}
|
|
|
|
type boundExternalStringTreeItem struct {
|
|
boundStringTreeItem
|
|
|
|
old string
|
|
}
|
|
|
|
func (t *boundExternalStringTreeItem) setIfChanged(val string) error {
|
|
if val == t.old {
|
|
return nil
|
|
}
|
|
(*t.val)[t.id] = val
|
|
t.old = val
|
|
|
|
t.trigger()
|
|
return nil
|
|
}
|
|
|
|
// URITree supports binding a tree of fyne.URI values.
|
|
//
|
|
// Since: 2.4
|
|
type URITree interface {
|
|
DataTree
|
|
|
|
Append(parent, id string, value fyne.URI) error
|
|
Get() (map[string][]string, map[string]fyne.URI, error)
|
|
GetValue(id string) (fyne.URI, error)
|
|
Prepend(parent, id string, value fyne.URI) error
|
|
Set(ids map[string][]string, values map[string]fyne.URI) error
|
|
SetValue(id string, value fyne.URI) error
|
|
}
|
|
|
|
// ExternalURITree supports binding a tree of fyne.URI values from an external variable.
|
|
//
|
|
// Since: 2.4
|
|
type ExternalURITree interface {
|
|
URITree
|
|
|
|
Reload() error
|
|
}
|
|
|
|
// NewURITree returns a bindable tree of fyne.URI values.
|
|
//
|
|
// Since: 2.4
|
|
func NewURITree() URITree {
|
|
t := &boundURITree{val: &map[string]fyne.URI{}}
|
|
t.ids = make(map[string][]string)
|
|
t.items = make(map[string]DataItem)
|
|
return t
|
|
}
|
|
|
|
// BindURITree returns a bound tree of fyne.URI values, based on the contents of the passed values.
|
|
// The ids map specifies how each item relates to its parent (with id ""), with the values being in the v map.
|
|
// If your code changes the content of the maps this refers to you should call Reload() to inform the bindings.
|
|
//
|
|
// Since: 2.4
|
|
func BindURITree(ids *map[string][]string, v *map[string]fyne.URI) ExternalURITree {
|
|
if v == nil {
|
|
return NewURITree().(ExternalURITree)
|
|
}
|
|
|
|
t := &boundURITree{val: v, updateExternal: true}
|
|
t.ids = make(map[string][]string)
|
|
t.items = make(map[string]DataItem)
|
|
|
|
for parent, children := range *ids {
|
|
for _, leaf := range children {
|
|
t.appendItem(bindURITreeItem(v, leaf, t.updateExternal), leaf, parent)
|
|
}
|
|
}
|
|
|
|
return t
|
|
}
|
|
|
|
type boundURITree struct {
|
|
treeBase
|
|
|
|
updateExternal bool
|
|
val *map[string]fyne.URI
|
|
}
|
|
|
|
func (t *boundURITree) Append(parent, id string, val fyne.URI) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
ids, ok := t.ids[parent]
|
|
if !ok {
|
|
ids = make([]string, 0)
|
|
}
|
|
|
|
t.ids[parent] = append(ids, id)
|
|
v := *t.val
|
|
v[id] = val
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundURITree) Get() (map[string][]string, map[string]fyne.URI, error) {
|
|
t.lock.RLock()
|
|
defer t.lock.RUnlock()
|
|
|
|
return t.ids, *t.val, nil
|
|
}
|
|
|
|
func (t *boundURITree) GetValue(id string) (fyne.URI, error) {
|
|
t.lock.RLock()
|
|
defer t.lock.RUnlock()
|
|
|
|
if item, ok := (*t.val)[id]; ok {
|
|
return item, nil
|
|
}
|
|
|
|
return fyne.URI(nil), errOutOfBounds
|
|
}
|
|
|
|
func (t *boundURITree) Prepend(parent, id string, val fyne.URI) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
ids, ok := t.ids[parent]
|
|
if !ok {
|
|
ids = make([]string, 0)
|
|
}
|
|
|
|
t.ids[parent] = append([]string{id}, ids...)
|
|
v := *t.val
|
|
v[id] = val
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundURITree) Reload() error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundURITree) Set(ids map[string][]string, v map[string]fyne.URI) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
t.ids = ids
|
|
*t.val = v
|
|
|
|
return t.doReload()
|
|
}
|
|
|
|
func (t *boundURITree) doReload() (retErr error) {
|
|
updated := []string{}
|
|
fire := false
|
|
for id := range *t.val {
|
|
found := false
|
|
for child := range t.items {
|
|
if child == id { // update existing
|
|
updated = append(updated, id)
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if found {
|
|
continue
|
|
}
|
|
|
|
// append new
|
|
t.appendItem(bindURITreeItem(t.val, id, t.updateExternal), id, parentIDFor(id, t.ids))
|
|
updated = append(updated, id)
|
|
fire = true
|
|
}
|
|
|
|
for id := range t.items {
|
|
remove := true
|
|
for _, done := range updated {
|
|
if done == id {
|
|
remove = false
|
|
break
|
|
}
|
|
}
|
|
|
|
if remove { // remove item no longer present
|
|
fire = true
|
|
t.deleteItem(id, parentIDFor(id, t.ids))
|
|
}
|
|
}
|
|
if fire {
|
|
t.trigger()
|
|
}
|
|
|
|
for id, item := range t.items {
|
|
var err error
|
|
if t.updateExternal {
|
|
item.(*boundExternalURITreeItem).lock.Lock()
|
|
err = item.(*boundExternalURITreeItem).setIfChanged((*t.val)[id])
|
|
item.(*boundExternalURITreeItem).lock.Unlock()
|
|
} else {
|
|
item.(*boundURITreeItem).lock.Lock()
|
|
err = item.(*boundURITreeItem).doSet((*t.val)[id])
|
|
item.(*boundURITreeItem).lock.Unlock()
|
|
}
|
|
if err != nil {
|
|
retErr = err
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (t *boundURITree) SetValue(id string, v fyne.URI) error {
|
|
t.lock.Lock()
|
|
(*t.val)[id] = v
|
|
t.lock.Unlock()
|
|
|
|
item, err := t.GetItem(id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return item.(URI).Set(v)
|
|
}
|
|
|
|
func bindURITreeItem(v *map[string]fyne.URI, id string, external bool) URI {
|
|
if external {
|
|
ret := &boundExternalURITreeItem{old: (*v)[id]}
|
|
ret.val = v
|
|
ret.id = id
|
|
return ret
|
|
}
|
|
|
|
return &boundURITreeItem{id: id, val: v}
|
|
}
|
|
|
|
type boundURITreeItem struct {
|
|
base
|
|
|
|
val *map[string]fyne.URI
|
|
id string
|
|
}
|
|
|
|
func (t *boundURITreeItem) Get() (fyne.URI, error) {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
v := *t.val
|
|
if item, ok := v[t.id]; ok {
|
|
return item, nil
|
|
}
|
|
|
|
return fyne.URI(nil), errOutOfBounds
|
|
}
|
|
|
|
func (t *boundURITreeItem) Set(val fyne.URI) error {
|
|
t.lock.Lock()
|
|
defer t.lock.Unlock()
|
|
|
|
return t.doSet(val)
|
|
}
|
|
|
|
func (t *boundURITreeItem) doSet(val fyne.URI) error {
|
|
(*t.val)[t.id] = val
|
|
|
|
t.trigger()
|
|
return nil
|
|
}
|
|
|
|
type boundExternalURITreeItem struct {
|
|
boundURITreeItem
|
|
|
|
old fyne.URI
|
|
}
|
|
|
|
func (t *boundExternalURITreeItem) setIfChanged(val fyne.URI) error {
|
|
if compareURI(val, t.old) {
|
|
return nil
|
|
}
|
|
(*t.val)[t.id] = val
|
|
t.old = val
|
|
|
|
t.trigger()
|
|
return nil
|
|
}
|