select_entry.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package widget
  2. import (
  3. "fyne.io/fyne/v2"
  4. "fyne.io/fyne/v2/theme"
  5. )
  6. // SelectEntry is an input field which supports selecting from a fixed set of options.
  7. type SelectEntry struct {
  8. Entry
  9. dropDown *fyne.Menu
  10. popUp *PopUpMenu
  11. options []string
  12. }
  13. // NewSelectEntry creates a SelectEntry.
  14. func NewSelectEntry(options []string) *SelectEntry {
  15. e := &SelectEntry{options: options}
  16. e.ExtendBaseWidget(e)
  17. e.Wrapping = fyne.TextTruncate
  18. return e
  19. }
  20. // CreateRenderer returns a new renderer for this select entry.
  21. //
  22. // Implements: fyne.Widget
  23. func (e *SelectEntry) CreateRenderer() fyne.WidgetRenderer {
  24. e.ExtendBaseWidget(e)
  25. e.SetOptions(e.options)
  26. return e.Entry.CreateRenderer()
  27. }
  28. // Enable this widget, updating any style or features appropriately.
  29. //
  30. // Implements: fyne.DisableableWidget
  31. func (e *SelectEntry) Enable() {
  32. if e.ActionItem != nil {
  33. e.ActionItem.(fyne.Disableable).Enable()
  34. }
  35. e.Entry.Enable()
  36. }
  37. // Disable this widget so that it cannot be interacted with, updating any style appropriately.
  38. //
  39. // Implements: fyne.DisableableWidget
  40. func (e *SelectEntry) Disable() {
  41. if e.ActionItem != nil {
  42. e.ActionItem.(fyne.Disableable).Disable()
  43. }
  44. e.Entry.Disable()
  45. }
  46. // MinSize returns the minimal size of the select entry.
  47. //
  48. // Implements: fyne.Widget
  49. func (e *SelectEntry) MinSize() fyne.Size {
  50. e.ExtendBaseWidget(e)
  51. return e.Entry.MinSize()
  52. }
  53. // Move changes the relative position of the select entry.
  54. //
  55. // Implements: fyne.Widget
  56. func (e *SelectEntry) Move(pos fyne.Position) {
  57. e.Entry.Move(pos)
  58. if e.popUp != nil {
  59. e.popUp.Move(e.popUpPos())
  60. }
  61. }
  62. // Resize changes the size of the select entry.
  63. //
  64. // Implements: fyne.Widget
  65. func (e *SelectEntry) Resize(size fyne.Size) {
  66. e.Entry.Resize(size)
  67. if e.popUp != nil {
  68. e.popUp.Resize(fyne.NewSize(size.Width, e.popUp.Size().Height))
  69. }
  70. }
  71. // SetOptions sets the options the user might select from.
  72. func (e *SelectEntry) SetOptions(options []string) {
  73. e.options = options
  74. items := make([]*fyne.MenuItem, len(options))
  75. for i, option := range options {
  76. option := option // capture
  77. items[i] = fyne.NewMenuItem(option, func() { e.SetText(option) })
  78. }
  79. e.dropDown = fyne.NewMenu("", items...)
  80. if e.ActionItem == nil {
  81. e.ActionItem = e.setupDropDown()
  82. if e.Disabled() {
  83. e.ActionItem.(fyne.Disableable).Disable()
  84. }
  85. }
  86. }
  87. func (e *SelectEntry) popUpPos() fyne.Position {
  88. entryPos := fyne.CurrentApp().Driver().AbsolutePositionForObject(e.super())
  89. return entryPos.Add(fyne.NewPos(0, e.Size().Height-theme.InputBorderSize()))
  90. }
  91. func (e *SelectEntry) setupDropDown() *Button {
  92. dropDownButton := NewButton("", func() {
  93. c := fyne.CurrentApp().Driver().CanvasForObject(e.super())
  94. e.popUp = NewPopUpMenu(e.dropDown, c)
  95. e.popUp.ShowAtPosition(e.popUpPos())
  96. e.popUp.Resize(fyne.NewSize(e.Size().Width, e.popUp.MinSize().Height))
  97. })
  98. dropDownButton.Importance = LowImportance
  99. dropDownButton.SetIcon(theme.MenuDropDownIcon())
  100. return dropDownButton
  101. }