mapbinding.go 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. package binding
  2. import (
  3. "errors"
  4. "reflect"
  5. "fyne.io/fyne/v2"
  6. )
  7. // DataMap is the base interface for all bindable data maps.
  8. //
  9. // Since: 2.0
  10. type DataMap interface {
  11. DataItem
  12. GetItem(string) (DataItem, error)
  13. Keys() []string
  14. }
  15. // ExternalUntypedMap is a map data binding with all values untyped (interface{}), connected to an external data source.
  16. //
  17. // Since: 2.0
  18. type ExternalUntypedMap interface {
  19. UntypedMap
  20. Reload() error
  21. }
  22. // UntypedMap is a map data binding with all values Untyped (interface{}).
  23. //
  24. // Since: 2.0
  25. type UntypedMap interface {
  26. DataMap
  27. Delete(string)
  28. Get() (map[string]interface{}, error)
  29. GetValue(string) (interface{}, error)
  30. Set(map[string]interface{}) error
  31. SetValue(string, interface{}) error
  32. }
  33. // NewUntypedMap creates a new, empty map binding of string to interface{}.
  34. //
  35. // Since: 2.0
  36. func NewUntypedMap() UntypedMap {
  37. return &mapBase{items: make(map[string]reflectUntyped), val: &map[string]interface{}{}}
  38. }
  39. // BindUntypedMap creates a new map binding of string to interface{} based on the data passed.
  40. // If your code changes the content of the map this refers to you should call Reload() to inform the bindings.
  41. //
  42. // Since: 2.0
  43. func BindUntypedMap(d *map[string]interface{}) ExternalUntypedMap {
  44. if d == nil {
  45. return NewUntypedMap().(ExternalUntypedMap)
  46. }
  47. m := &mapBase{items: make(map[string]reflectUntyped), val: d, updateExternal: true}
  48. for k := range *d {
  49. m.setItem(k, bindUntypedMapValue(d, k, m.updateExternal))
  50. }
  51. return m
  52. }
  53. // Struct is the base interface for a bound struct type.
  54. //
  55. // Since: 2.0
  56. type Struct interface {
  57. DataMap
  58. GetValue(string) (interface{}, error)
  59. SetValue(string, interface{}) error
  60. Reload() error
  61. }
  62. // BindStruct creates a new map binding of string to interface{} using the struct passed as data.
  63. // The key for each item is a string representation of each exported field with the value set as an interface{}.
  64. // Only exported fields are included.
  65. //
  66. // Since: 2.0
  67. func BindStruct(i interface{}) Struct {
  68. if i == nil {
  69. return NewUntypedMap().(Struct)
  70. }
  71. t := reflect.TypeOf(i)
  72. if t.Kind() != reflect.Ptr ||
  73. (reflect.TypeOf(reflect.ValueOf(i).Elem()).Kind() != reflect.Struct) {
  74. fyne.LogError("Invalid type passed to BindStruct, must be pointer to struct", nil)
  75. return NewUntypedMap().(Struct)
  76. }
  77. s := &boundStruct{orig: i}
  78. s.items = make(map[string]reflectUntyped)
  79. s.val = &map[string]interface{}{}
  80. s.updateExternal = true
  81. v := reflect.ValueOf(i).Elem()
  82. t = v.Type()
  83. for j := 0; j < v.NumField(); j++ {
  84. f := v.Field(j)
  85. if !f.CanSet() {
  86. continue
  87. }
  88. key := t.Field(j).Name
  89. s.items[key] = bindReflect(f)
  90. (*s.val)[key] = f.Interface()
  91. }
  92. return s
  93. }
  94. type reflectUntyped interface {
  95. DataItem
  96. get() (interface{}, error)
  97. set(interface{}) error
  98. }
  99. type mapBase struct {
  100. base
  101. updateExternal bool
  102. items map[string]reflectUntyped
  103. val *map[string]interface{}
  104. }
  105. func (b *mapBase) GetItem(key string) (DataItem, error) {
  106. b.lock.RLock()
  107. defer b.lock.RUnlock()
  108. if v, ok := b.items[key]; ok {
  109. return v, nil
  110. }
  111. return nil, errKeyNotFound
  112. }
  113. func (b *mapBase) Keys() []string {
  114. b.lock.Lock()
  115. defer b.lock.Unlock()
  116. ret := make([]string, len(b.items))
  117. i := 0
  118. for k := range b.items {
  119. ret[i] = k
  120. i++
  121. }
  122. return ret
  123. }
  124. func (b *mapBase) Delete(key string) {
  125. b.lock.Lock()
  126. defer b.lock.Unlock()
  127. delete(b.items, key)
  128. b.trigger()
  129. }
  130. func (b *mapBase) Get() (map[string]interface{}, error) {
  131. b.lock.RLock()
  132. defer b.lock.RUnlock()
  133. if b.val == nil {
  134. return map[string]interface{}{}, nil
  135. }
  136. return *b.val, nil
  137. }
  138. func (b *mapBase) GetValue(key string) (interface{}, error) {
  139. b.lock.RLock()
  140. defer b.lock.RUnlock()
  141. if i, ok := b.items[key]; ok {
  142. return i.get()
  143. }
  144. return nil, errKeyNotFound
  145. }
  146. func (b *mapBase) Reload() error {
  147. b.lock.Lock()
  148. defer b.lock.Unlock()
  149. return b.doReload()
  150. }
  151. func (b *mapBase) Set(v map[string]interface{}) error {
  152. b.lock.Lock()
  153. defer b.lock.Unlock()
  154. if b.val == nil { // was not initialized with a blank value, recover
  155. b.val = &v
  156. b.trigger()
  157. return nil
  158. }
  159. *b.val = v
  160. return b.doReload()
  161. }
  162. func (b *mapBase) SetValue(key string, d interface{}) error {
  163. b.lock.Lock()
  164. defer b.lock.Unlock()
  165. if i, ok := b.items[key]; ok {
  166. return i.set(d)
  167. }
  168. (*b.val)[key] = d
  169. item := bindUntypedMapValue(b.val, key, b.updateExternal)
  170. b.setItem(key, item)
  171. return nil
  172. }
  173. func (b *mapBase) doReload() (retErr error) {
  174. changed := false
  175. // add new
  176. for key := range *b.val {
  177. _, found := b.items[key]
  178. if !found {
  179. b.setItem(key, bindUntypedMapValue(b.val, key, b.updateExternal))
  180. changed = true
  181. }
  182. }
  183. // remove old
  184. for key := range b.items {
  185. _, found := (*b.val)[key]
  186. if !found {
  187. delete(b.items, key)
  188. changed = true
  189. }
  190. }
  191. if changed {
  192. b.trigger()
  193. }
  194. for k, item := range b.items {
  195. var err error
  196. if b.updateExternal {
  197. err = item.(*boundExternalMapValue).setIfChanged((*b.val)[k])
  198. } else {
  199. err = item.(*boundMapValue).set((*b.val)[k])
  200. }
  201. if err != nil {
  202. retErr = err
  203. }
  204. }
  205. return
  206. }
  207. func (b *mapBase) setItem(key string, d reflectUntyped) {
  208. b.items[key] = d
  209. b.trigger()
  210. }
  211. type boundStruct struct {
  212. mapBase
  213. orig interface{}
  214. }
  215. func (b *boundStruct) Reload() (retErr error) {
  216. b.lock.Lock()
  217. defer b.lock.Unlock()
  218. v := reflect.ValueOf(b.orig).Elem()
  219. t := v.Type()
  220. for j := 0; j < v.NumField(); j++ {
  221. f := v.Field(j)
  222. if !f.CanSet() {
  223. continue
  224. }
  225. kind := f.Kind()
  226. if kind == reflect.Slice || kind == reflect.Struct {
  227. fyne.LogError("Data binding does not yet support slice or struct elements in a struct", nil)
  228. continue
  229. }
  230. key := t.Field(j).Name
  231. old := (*b.val)[key]
  232. if f.Interface() == old {
  233. continue
  234. }
  235. var err error
  236. switch kind {
  237. case reflect.Bool:
  238. err = b.items[key].(*reflectBool).Set(f.Bool())
  239. case reflect.Float32, reflect.Float64:
  240. err = b.items[key].(*reflectFloat).Set(f.Float())
  241. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  242. err = b.items[key].(*reflectInt).Set(int(f.Int()))
  243. case reflect.String:
  244. err = b.items[key].(*reflectString).Set(f.String())
  245. }
  246. if err != nil {
  247. retErr = err
  248. }
  249. (*b.val)[key] = f.Interface()
  250. }
  251. return
  252. }
  253. func bindUntypedMapValue(m *map[string]interface{}, k string, external bool) reflectUntyped {
  254. if external {
  255. ret := &boundExternalMapValue{old: (*m)[k]}
  256. ret.val = m
  257. ret.key = k
  258. return ret
  259. }
  260. return &boundMapValue{val: m, key: k}
  261. }
  262. type boundMapValue struct {
  263. base
  264. val *map[string]interface{}
  265. key string
  266. }
  267. func (b *boundMapValue) get() (interface{}, error) {
  268. if v, ok := (*b.val)[b.key]; ok {
  269. return v, nil
  270. }
  271. return nil, errKeyNotFound
  272. }
  273. func (b *boundMapValue) set(val interface{}) error {
  274. (*b.val)[b.key] = val
  275. b.trigger()
  276. return nil
  277. }
  278. type boundExternalMapValue struct {
  279. boundMapValue
  280. old interface{}
  281. }
  282. func (b *boundExternalMapValue) setIfChanged(val interface{}) error {
  283. if val == b.old {
  284. return nil
  285. }
  286. b.old = val
  287. return b.set(val)
  288. }
  289. type boundReflect struct {
  290. base
  291. val reflect.Value
  292. }
  293. func (b *boundReflect) get() (interface{}, error) {
  294. return b.val.Interface(), nil
  295. }
  296. func (b *boundReflect) set(val interface{}) (err error) {
  297. defer func() {
  298. if r := recover(); r != nil {
  299. err = errors.New("unable to set bool in data binding")
  300. }
  301. }()
  302. b.val.Set(reflect.ValueOf(val))
  303. b.trigger()
  304. return nil
  305. }
  306. type reflectBool struct {
  307. boundReflect
  308. }
  309. func (r *reflectBool) Get() (val bool, err error) {
  310. defer func() {
  311. if r := recover(); r != nil {
  312. err = errors.New("invalid bool value in data binding")
  313. }
  314. }()
  315. val = r.val.Bool()
  316. return
  317. }
  318. func (r *reflectBool) Set(b bool) (err error) {
  319. defer func() {
  320. if r := recover(); r != nil {
  321. err = errors.New("unable to set bool in data binding")
  322. }
  323. }()
  324. r.val.SetBool(b)
  325. r.trigger()
  326. return
  327. }
  328. func bindReflectBool(f reflect.Value) reflectUntyped {
  329. r := &reflectBool{}
  330. r.val = f
  331. return r
  332. }
  333. type reflectFloat struct {
  334. boundReflect
  335. }
  336. func (r *reflectFloat) Get() (val float64, err error) {
  337. defer func() {
  338. if r := recover(); r != nil {
  339. err = errors.New("invalid float64 value in data binding")
  340. }
  341. }()
  342. val = r.val.Float()
  343. return
  344. }
  345. func (r *reflectFloat) Set(f float64) (err error) {
  346. defer func() {
  347. if r := recover(); r != nil {
  348. err = errors.New("unable to set float64 in data binding")
  349. }
  350. }()
  351. r.val.SetFloat(f)
  352. r.trigger()
  353. return
  354. }
  355. func bindReflectFloat(f reflect.Value) reflectUntyped {
  356. r := &reflectFloat{}
  357. r.val = f
  358. return r
  359. }
  360. type reflectInt struct {
  361. boundReflect
  362. }
  363. func (r *reflectInt) Get() (val int, err error) {
  364. defer func() {
  365. if r := recover(); r != nil {
  366. err = errors.New("invalid int value in data binding")
  367. }
  368. }()
  369. val = int(r.val.Int())
  370. return
  371. }
  372. func (r *reflectInt) Set(i int) (err error) {
  373. defer func() {
  374. if r := recover(); r != nil {
  375. err = errors.New("unable to set int in data binding")
  376. }
  377. }()
  378. r.val.SetInt(int64(i))
  379. r.trigger()
  380. return
  381. }
  382. func bindReflectInt(f reflect.Value) reflectUntyped {
  383. r := &reflectInt{}
  384. r.val = f
  385. return r
  386. }
  387. type reflectString struct {
  388. boundReflect
  389. }
  390. func (r *reflectString) Get() (val string, err error) {
  391. defer func() {
  392. if r := recover(); r != nil {
  393. err = errors.New("invalid string value in data binding")
  394. }
  395. }()
  396. val = r.val.String()
  397. return
  398. }
  399. func (r *reflectString) Set(s string) (err error) {
  400. defer func() {
  401. if r := recover(); r != nil {
  402. err = errors.New("unable to set string in data binding")
  403. }
  404. }()
  405. r.val.SetString(s)
  406. r.trigger()
  407. return
  408. }
  409. func bindReflectString(f reflect.Value) reflectUntyped {
  410. r := &reflectString{}
  411. r.val = f
  412. return r
  413. }
  414. func bindReflect(field reflect.Value) reflectUntyped {
  415. switch field.Kind() {
  416. case reflect.Bool:
  417. return bindReflectBool(field)
  418. case reflect.Float32, reflect.Float64:
  419. return bindReflectFloat(field)
  420. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  421. return bindReflectInt(field)
  422. case reflect.String:
  423. return bindReflectString(field)
  424. }
  425. return &boundReflect{val: field}
  426. }