sprintf.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. package binding
  2. import (
  3. "fmt"
  4. "fyne.io/fyne/v2/storage"
  5. )
  6. type sprintfString struct {
  7. String
  8. format string
  9. source []DataItem
  10. err error
  11. }
  12. // NewSprintf returns a String binding that format its content using the
  13. // format string and the provide additional parameter that must be other
  14. // data bindings. This data binding use fmt.Sprintf and fmt.Scanf internally
  15. // and will have all the same limitation as those function.
  16. //
  17. // Since: 2.2
  18. func NewSprintf(format string, b ...DataItem) String {
  19. ret := &sprintfString{
  20. String: NewString(),
  21. format: format,
  22. source: append(make([]DataItem, 0, len(b)), b...),
  23. }
  24. for _, value := range b {
  25. value.AddListener(ret)
  26. }
  27. return ret
  28. }
  29. func (s *sprintfString) DataChanged() {
  30. data := make([]interface{}, 0, len(s.source))
  31. s.err = nil
  32. for _, value := range s.source {
  33. switch x := value.(type) {
  34. case Bool:
  35. b, err := x.Get()
  36. if err != nil {
  37. s.err = err
  38. return
  39. }
  40. data = append(data, b)
  41. case Bytes:
  42. b, err := x.Get()
  43. if err != nil {
  44. s.err = err
  45. return
  46. }
  47. data = append(data, b)
  48. case Float:
  49. f, err := x.Get()
  50. if err != nil {
  51. s.err = err
  52. return
  53. }
  54. data = append(data, f)
  55. case Int:
  56. i, err := x.Get()
  57. if err != nil {
  58. s.err = err
  59. return
  60. }
  61. data = append(data, i)
  62. case Rune:
  63. r, err := x.Get()
  64. if err != nil {
  65. s.err = err
  66. return
  67. }
  68. data = append(data, r)
  69. case String:
  70. str, err := x.Get()
  71. if err != nil {
  72. s.err = err
  73. // Set error?
  74. return
  75. }
  76. data = append(data, str)
  77. case URI:
  78. u, err := x.Get()
  79. if err != nil {
  80. s.err = err
  81. return
  82. }
  83. data = append(data, u)
  84. }
  85. }
  86. r := fmt.Sprintf(s.format, data...)
  87. s.String.Set(r)
  88. }
  89. func (s *sprintfString) Get() (string, error) {
  90. if s.err != nil {
  91. return "", s.err
  92. }
  93. return s.String.Get()
  94. }
  95. func (s *sprintfString) Set(str string) error {
  96. data := make([]interface{}, 0, len(s.source))
  97. s.err = nil
  98. for _, value := range s.source {
  99. switch value.(type) {
  100. case Bool:
  101. data = append(data, new(bool))
  102. case Bytes:
  103. return fmt.Errorf("impossible to convert '%s' to []bytes type", str)
  104. case Float:
  105. data = append(data, new(float64))
  106. case Int:
  107. data = append(data, new(int))
  108. case Rune:
  109. data = append(data, new(rune))
  110. case String:
  111. data = append(data, new(string))
  112. case URI:
  113. data = append(data, new(string))
  114. }
  115. }
  116. count, err := fmt.Sscanf(str, s.format, data...)
  117. if err != nil {
  118. return err
  119. }
  120. if count != len(data) {
  121. return fmt.Errorf("impossible to decode more than %v parameters in '%s' with format '%s'", count, str, s.format)
  122. }
  123. for i, value := range s.source {
  124. switch x := value.(type) {
  125. case Bool:
  126. v := data[i].(*bool)
  127. err := x.Set(*v)
  128. if err != nil {
  129. return err
  130. }
  131. case Bytes:
  132. return fmt.Errorf("impossible to convert '%s' to []bytes type", str)
  133. case Float:
  134. v := data[i].(*float64)
  135. err := x.Set(*v)
  136. if err != nil {
  137. return err
  138. }
  139. case Int:
  140. v := data[i].(*int)
  141. err := x.Set(*v)
  142. if err != nil {
  143. return err
  144. }
  145. case Rune:
  146. v := data[i].(*rune)
  147. err := x.Set(*v)
  148. if err != nil {
  149. return err
  150. }
  151. case String:
  152. v := data[i].(*string)
  153. err := x.Set(*v)
  154. if err != nil {
  155. return err
  156. }
  157. case URI:
  158. v := data[i].(*string)
  159. if v == nil {
  160. return fmt.Errorf("URI can not be nil in '%s'", str)
  161. }
  162. uri, err := storage.ParseURI(*v)
  163. if err != nil {
  164. return err
  165. }
  166. err = x.Set(uri)
  167. if err != nil {
  168. return err
  169. }
  170. }
  171. }
  172. return nil
  173. }
  174. // StringToStringWithFormat creates a binding that converts a string to another string using the specified format.
  175. // Changes to the returned String will be pushed to the passed in String and setting a new string value will parse and
  176. // set the underlying String if it matches the format and the parse was successful.
  177. //
  178. // Since: 2.2
  179. func StringToStringWithFormat(str String, format string) String {
  180. if format == "%s" { // Same as not using custom formatting.
  181. return str
  182. }
  183. return NewSprintf(format, str)
  184. }