User interface toolkit for Go with support for SDL2 and HTML Canvas render targets.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

114 lines
2.4 KiB

  1. package ui
  2. import (
  3. "errors"
  4. "fmt"
  5. "git.kirsle.net/go/render"
  6. )
  7. // Frame is a widget that contains other widgets.
  8. type Frame struct {
  9. Name string
  10. BaseWidget
  11. // Widget placement settings.
  12. packs map[Side][]packedWidget // Packed widgets
  13. placed []placedWidget // Placed widgets
  14. widgets []Widget
  15. }
  16. // NewFrame creates a new Frame.
  17. func NewFrame(name string) *Frame {
  18. w := &Frame{
  19. Name: name,
  20. packs: map[Side][]packedWidget{},
  21. widgets: []Widget{},
  22. }
  23. w.SetBackground(render.RGBA(1, 0, 0, 0)) // invisible default BG
  24. w.IDFunc(func() string {
  25. return fmt.Sprintf("Frame<%s>",
  26. name,
  27. )
  28. })
  29. return w
  30. }
  31. // Setup ensures all the Frame's data is initialized and not null.
  32. func (w *Frame) Setup() {
  33. if w.packs == nil {
  34. w.packs = map[Side][]packedWidget{}
  35. }
  36. if w.widgets == nil {
  37. w.widgets = []Widget{}
  38. }
  39. }
  40. // Add a child widget to the frame. When the frame Presents itself, it also
  41. // presents child widgets. This method is safe to call multiple times: it ensures
  42. // the widget is not already a child of the Frame before adding it.
  43. func (w *Frame) Add(child Widget) error {
  44. if child == w {
  45. return errors.New("can't add self to frame")
  46. }
  47. // Ensure child is new to the frame.
  48. for _, widget := range w.widgets {
  49. if widget == child {
  50. return errors.New("widget already added to frame")
  51. }
  52. }
  53. w.widgets = append(w.widgets, child)
  54. return nil
  55. }
  56. // Children returns all of the child widgets.
  57. func (w *Frame) Children() []Widget {
  58. return w.widgets
  59. }
  60. // Compute the size of the Frame.
  61. func (w *Frame) Compute(e render.Engine) {
  62. w.computePacked(e)
  63. w.computePlaced(e)
  64. // Call the BaseWidget Compute in case we have subscribers.
  65. w.BaseWidget.Compute(e)
  66. }
  67. // Present the Frame.
  68. func (w *Frame) Present(e render.Engine, P render.Point) {
  69. if w.Hidden() {
  70. return
  71. }
  72. var (
  73. S = w.Size()
  74. )
  75. // Draw the widget's border and everything.
  76. w.DrawBox(e, P)
  77. // Draw the background color.
  78. e.DrawBox(w.Background(), render.Rect{
  79. X: P.X + w.BoxThickness(1),
  80. Y: P.Y + w.BoxThickness(1),
  81. W: S.W - w.BoxThickness(2),
  82. H: S.H - w.BoxThickness(2),
  83. })
  84. // Draw the widgets.
  85. for _, child := range w.widgets {
  86. // child.Compute(e)
  87. p := child.Point()
  88. moveTo := render.NewPoint(
  89. P.X+p.X+w.BoxThickness(1),
  90. P.Y+p.Y+w.BoxThickness(1),
  91. )
  92. child.Present(e, moveTo)
  93. }
  94. // Call the BaseWidget Present in case we have subscribers.
  95. w.BaseWidget.Present(e, P)
  96. }