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.
 
 
 
 
 

170 lines
3.4 KiB

  1. // +build js,wasm
  2. // WebAssembly version of the window manager demo.
  3. // To build: make wasm
  4. // To test: make wasm-serve
  5. package main
  6. import (
  7. "fmt"
  8. "time"
  9. "git.kirsle.net/go/render"
  10. "git.kirsle.net/go/render/canvas"
  11. "git.kirsle.net/go/ui"
  12. )
  13. // Program globals.
  14. var (
  15. ThrottleFPS = 1000 / 60
  16. // Size of the MainWindow.
  17. Width = 1024
  18. Height = 768
  19. // Cascade offset for creating multiple windows.
  20. Cascade = render.NewPoint(10, 32)
  21. CascadeStep = render.NewPoint(24, 24)
  22. CascadeLoops = 1
  23. // Colors for each window created.
  24. WindowColors = []render.Color{
  25. render.Blue,
  26. render.Red,
  27. render.DarkYellow,
  28. render.DarkGreen,
  29. render.DarkCyan,
  30. render.DarkBlue,
  31. render.DarkRed,
  32. }
  33. WindowID int
  34. OpenWindows int
  35. )
  36. func main() {
  37. mw, err := canvas.New("canvas")
  38. if err != nil {
  39. panic(err)
  40. }
  41. // Bind DOM event handlers.
  42. mw.AddEventListeners()
  43. supervisor := ui.NewSupervisor()
  44. frame := ui.NewFrame("Main Frame")
  45. frame.Resize(render.NewRect(mw.WindowSize()))
  46. frame.Compute(mw)
  47. _, height := mw.WindowSize()
  48. lbl := ui.NewLabel(ui.Label{
  49. Text: "Window Manager Demo",
  50. Font: render.Text{
  51. FontFilename: "DejaVuSans.ttf",
  52. Size: 32,
  53. Color: render.SkyBlue,
  54. Shadow: render.SkyBlue.Darken(60),
  55. },
  56. })
  57. lbl.Compute(mw)
  58. lbl.MoveTo(render.NewPoint(
  59. 20,
  60. height-lbl.Size().H-20,
  61. ))
  62. // Menu bar.
  63. menu := ui.NewMenuBar("Main Menu")
  64. file := menu.AddMenu("Options")
  65. file.AddItem("New window", func() {
  66. addWindow(mw, frame, supervisor)
  67. })
  68. file.AddItem("Close all windows", func() {
  69. OpenWindows -= supervisor.CloseAllWindows()
  70. })
  71. menu.Supervise(supervisor)
  72. menu.Compute(mw)
  73. frame.Pack(menu, menu.PackTop())
  74. // Add some windows to play with.
  75. addWindow(mw, frame, supervisor)
  76. addWindow(mw, frame, supervisor)
  77. for {
  78. mw.Clear(render.RGBA(255, 255, 200, 255))
  79. start := time.Now()
  80. ev, err := mw.Poll()
  81. if err != nil {
  82. panic(err)
  83. }
  84. frame.Present(mw, frame.Point())
  85. lbl.Present(mw, lbl.Point())
  86. supervisor.Loop(ev)
  87. supervisor.Present(mw)
  88. var delay uint32
  89. elapsed := time.Now().Sub(start)
  90. tmp := elapsed / time.Millisecond
  91. if ThrottleFPS-int(tmp) > 0 {
  92. delay = uint32(ThrottleFPS - int(tmp))
  93. }
  94. mw.Delay(delay)
  95. }
  96. }
  97. // Add a new child window.
  98. func addWindow(engine render.Engine, parent *ui.Frame, sup *ui.Supervisor) {
  99. var (
  100. color = WindowColors[WindowID%len(WindowColors)]
  101. title = fmt.Sprintf("Window %d", WindowID+1)
  102. )
  103. WindowID++
  104. win1 := ui.NewWindow(title)
  105. win1.SetButtons(ui.CloseButton)
  106. win1.ActiveTitleBackground = color
  107. win1.InactiveTitleBackground = color.Darken(60)
  108. win1.InactiveTitleForeground = render.Grey
  109. win1.Configure(ui.Config{
  110. Width: 320,
  111. Height: 240,
  112. })
  113. win1.Compute(engine)
  114. win1.Supervise(sup)
  115. // Re-open a window when the last one is closed.
  116. OpenWindows++
  117. win1.Handle(ui.CloseWindow, func(ed ui.EventData) error {
  118. OpenWindows--
  119. if OpenWindows <= 0 {
  120. addWindow(engine, parent, sup)
  121. }
  122. return nil
  123. })
  124. // Default placement via cascade.
  125. win1.MoveTo(Cascade)
  126. Cascade.Add(CascadeStep)
  127. if Cascade.Y > Height-240-64 {
  128. CascadeLoops++
  129. Cascade.Y = 24
  130. Cascade.X = 24 * CascadeLoops
  131. }
  132. // Add a window duplicator button.
  133. btn2 := ui.NewButton(title+":Button2", ui.NewLabel(ui.Label{
  134. Text: "New Window",
  135. }))
  136. btn2.Handle(ui.Click, func(ed ui.EventData) error {
  137. addWindow(engine, parent, sup)
  138. return nil
  139. })
  140. sup.Add(btn2)
  141. win1.Place(btn2, ui.Place{
  142. Top: 10,
  143. Right: 10,
  144. })
  145. }