User interface toolkit for Go with support for SDL2 and HTML Canvas render targets.
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 

230 wiersze
4.3 KiB

  1. package ui
  2. import (
  3. "fmt"
  4. "strconv"
  5. "git.kirsle.net/go/render"
  6. )
  7. // Pager is a frame with Pagers for paginated UI.
  8. type Pager struct {
  9. BaseWidget
  10. // Config settings. NOTE: these are copied in the constructor,
  11. // be sure to update it there too if you add a new option!
  12. Name string // totally optional name
  13. Page int // default 1
  14. Pages int
  15. PerPage int // default 20
  16. MaxPageButtons int // max no. of individual pages to show, 0 = no limit
  17. Font render.Text
  18. OnChange func(page, perPage int)
  19. supervisor *Supervisor
  20. child Widget
  21. buttons []Widget
  22. page string // radio button value of Page
  23. // Private options.
  24. hovering bool
  25. clicked bool
  26. }
  27. // NewPager creates a new Pager.
  28. func NewPager(config Pager) *Pager {
  29. w := &Pager{
  30. Page: config.Page,
  31. Pages: config.Pages,
  32. PerPage: config.PerPage,
  33. MaxPageButtons: config.MaxPageButtons,
  34. Font: config.Font,
  35. OnChange: config.OnChange,
  36. buttons: []Widget{},
  37. }
  38. // default settings
  39. if w.Page == 0 {
  40. w.Page = 1
  41. }
  42. if w.PerPage == 0 {
  43. w.PerPage = 20
  44. }
  45. w.IDFunc(func() string {
  46. return fmt.Sprintf("Pager<%d of %d>", w.Page, w.PerPage)
  47. })
  48. w.child = w.setup()
  49. return w
  50. }
  51. // Supervise the pager to make its buttons work.
  52. func (w *Pager) Supervise(s *Supervisor) {
  53. w.supervisor = s
  54. for _, btn := range w.buttons {
  55. w.supervisor.Add(btn)
  56. }
  57. }
  58. // setup the frame
  59. func (w *Pager) setup() *Frame {
  60. frame := NewFrame("Pager Frame")
  61. frame.SetParent(w)
  62. if w.Pages == 0 {
  63. return frame
  64. }
  65. w.buttons = []Widget{}
  66. w.page = fmt.Sprintf("%d", w.Page)
  67. // Previous Page Button
  68. prev := NewButton("Previous", NewLabel(Label{
  69. Text: "<",
  70. Font: w.Font,
  71. }))
  72. w.buttons = append(w.buttons, prev)
  73. prev.Handle(Click, func(ed EventData) error {
  74. return w.next(-1)
  75. })
  76. frame.Pack(prev, Pack{
  77. Side: W,
  78. })
  79. // Draw the numbered buttons.
  80. for i := 1; i <= w.Pages; i++ {
  81. page := fmt.Sprintf("%d", i)
  82. if w.MaxPageButtons > 0 {
  83. if i > w.MaxPageButtons {
  84. break
  85. }
  86. // The final button shown; make this one always reflect the
  87. // current page IF the current page is greater than this one.
  88. if w.Page >= i && w.Page != i {
  89. continue
  90. }
  91. }
  92. btn := NewRadioButton(
  93. "Page "+page,
  94. &w.page,
  95. page,
  96. NewLabel(Label{
  97. Text: page,
  98. Font: w.Font,
  99. }))
  100. w.buttons = append(w.buttons, btn)
  101. btn.Handle(Click, func(ed EventData) error {
  102. if w.OnChange != nil {
  103. page, _ := strconv.Atoi(w.page)
  104. w.OnChange(page, w.PerPage)
  105. }
  106. return nil
  107. })
  108. if w.supervisor != nil {
  109. w.supervisor.Add(btn)
  110. }
  111. frame.Pack(btn, Pack{
  112. Side: W,
  113. })
  114. }
  115. // Next Page Button
  116. next := NewButton("Next", NewLabel(Label{
  117. Text: ">",
  118. Font: w.Font,
  119. }))
  120. w.buttons = append(w.buttons, next)
  121. next.Handle(Click, func(ed EventData) error {
  122. return w.next(1)
  123. })
  124. frame.Pack(next, Pack{
  125. Side: W,
  126. })
  127. return frame
  128. }
  129. // next (1) or previous (-1) button
  130. func (w *Pager) next(value int) error {
  131. fmt.Printf("next(%d)\n", value)
  132. intvalue, _ := strconv.Atoi(w.page)
  133. intvalue += value
  134. if intvalue < 1 {
  135. intvalue = 1
  136. } else if intvalue > w.Pages {
  137. intvalue = w.Pages
  138. }
  139. w.page = fmt.Sprintf("%d", intvalue)
  140. if w.OnChange != nil {
  141. w.OnChange(intvalue, w.PerPage)
  142. }
  143. return nil
  144. }
  145. // Compute the size of the Pager.
  146. func (w *Pager) Compute(e render.Engine) {
  147. // Compute the size of the inner widget first.
  148. w.child.Compute(e)
  149. // Auto-resize only if we haven't been given a fixed size.
  150. if !w.FixedSize() {
  151. size := w.child.Size()
  152. w.Resize(render.Rect{
  153. W: size.W + w.BoxThickness(2),
  154. H: size.H + w.BoxThickness(2),
  155. })
  156. }
  157. w.BaseWidget.Compute(e)
  158. }
  159. // Present the Pager.
  160. func (w *Pager) Present(e render.Engine, P render.Point) {
  161. if w.Hidden() {
  162. return
  163. }
  164. w.Compute(e)
  165. var (
  166. S = w.Size()
  167. ChildSize = w.child.Size()
  168. )
  169. // Draw the widget's border and everything.
  170. w.DrawBox(e, P)
  171. // Offset further if we are currently sunken.
  172. var clickOffset int
  173. if w.clicked {
  174. clickOffset++
  175. }
  176. // Where to place the child widget.
  177. moveTo := render.Point{
  178. X: P.X + w.BoxThickness(1) + clickOffset,
  179. Y: P.Y + w.BoxThickness(1) + clickOffset,
  180. }
  181. // If we're bigger than we need to be, center the child widget.
  182. if S.Bigger(ChildSize) {
  183. moveTo.X = P.X + (S.W / 2) - (ChildSize.W / 2)
  184. }
  185. // Draw the text label inside.
  186. w.child.Present(e, moveTo)
  187. w.BaseWidget.Present(e, P)
  188. }