User interface toolkit for Go with support for SDL2 and HTML Canvas render targets.
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 

230 řádky
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. }