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.
 
 
 
 
 

98 lines
2.5 KiB

  1. package ui
  2. import (
  3. "git.kirsle.net/go/render"
  4. )
  5. // Place provides configuration fields for Frame.Place().
  6. type Place struct {
  7. // X and Y coordinates for explicit location of widget within its parent.
  8. // This placement option trumps all others.
  9. Point render.Point
  10. // Place relative to an edge of the window. The widget will stick to the
  11. // edge of the window even as it resizes. Options are ignored if Point
  12. // is set.
  13. Top int
  14. Left int
  15. Right int
  16. Bottom int
  17. Center bool
  18. Middle bool
  19. }
  20. // Strategy returns the placement strategy for a Place config struct.
  21. // Returns 'Point' if a render.Point is used (even if zero, zero)
  22. // Returns 'Side' if the side values are set.
  23. func (p Place) Strategy() string {
  24. if p.Top != 0 || p.Left != 0 || p.Right != 0 || p.Bottom != 0 || p.Center || p.Middle {
  25. return "Side"
  26. }
  27. return "Point"
  28. }
  29. // placedWidget holds the data for a widget placed in a frame.
  30. type placedWidget struct {
  31. widget Widget
  32. place Place
  33. }
  34. // Place a widget into the frame.
  35. func (w *Frame) Place(child Widget, config Place) {
  36. w.placed = append(w.placed, placedWidget{
  37. widget: child,
  38. place: config,
  39. })
  40. w.widgets = append(w.widgets, child)
  41. // Adopt the child widget so it can access the Frame.
  42. child.SetParent(w)
  43. }
  44. // computePlaced processes all the Place layout widgets in the Frame,
  45. // determining their X,Y location and whether they need to change.
  46. func (w *Frame) computePlaced(e render.Engine) {
  47. var (
  48. frameSize = w.BoxSize()
  49. )
  50. for _, row := range w.placed {
  51. // X,Y placement takes priority.
  52. switch row.place.Strategy() {
  53. case "Point":
  54. row.widget.MoveTo(row.place.Point)
  55. case "Side":
  56. var moveTo render.Point
  57. // Compute the initial X,Y based on Top, Left, Right, Bottom.
  58. if row.place.Left > 0 {
  59. moveTo.X = row.place.Left
  60. }
  61. if row.place.Top > 0 {
  62. moveTo.Y = row.place.Top
  63. }
  64. if row.place.Right > 0 {
  65. moveTo.X = frameSize.W - row.widget.Size().W - row.place.Right
  66. }
  67. if row.place.Bottom > 0 {
  68. moveTo.Y = frameSize.H - row.widget.Size().H - row.place.Bottom
  69. }
  70. // Center and Middle aligned values override Left/Right, Top/Bottom
  71. // settings respectively.
  72. if row.place.Center {
  73. moveTo.X = frameSize.W - (w.Size().W / 2) - (row.widget.Size().W / 2)
  74. }
  75. if row.place.Middle {
  76. moveTo.Y = frameSize.H - (w.Size().H / 2) - (row.widget.Size().H / 2)
  77. }
  78. row.widget.MoveTo(moveTo)
  79. }
  80. // If this widget itself has placed widgets, call its function too.
  81. if frame, ok := row.widget.(*Frame); ok {
  82. frame.computePlaced(e)
  83. }
  84. }
  85. }