Window.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. package giu
  2. import (
  3. "fmt"
  4. "github.com/AllenDang/imgui-go"
  5. )
  6. // SingleWindow creates one window filling all available space
  7. // in MasterWindow. If SingleWindow is set up, no other windows can't be
  8. // definied.
  9. func SingleWindow() *WindowWidget {
  10. size := Context.platform.DisplaySize()
  11. title := fmt.Sprintf("SingleWindow_%d", Context.GetWidgetIndex())
  12. return Window(title).
  13. Flags(
  14. imgui.WindowFlagsNoTitleBar|
  15. imgui.WindowFlagsNoCollapse|
  16. imgui.WindowFlagsNoScrollbar|
  17. imgui.WindowFlagsNoMove|
  18. imgui.WindowFlagsNoResize).
  19. Size(size[0], size[1])
  20. }
  21. // SingleWindowWithMenuBar creates a SingleWindow and allows to add menubar on its top.
  22. func SingleWindowWithMenuBar() *WindowWidget {
  23. size := Context.platform.DisplaySize()
  24. title := fmt.Sprintf("SingleWindow_%d", Context.GetWidgetIndex())
  25. return Window(title).
  26. Flags(
  27. imgui.WindowFlagsNoTitleBar|
  28. imgui.WindowFlagsNoCollapse|
  29. imgui.WindowFlagsNoScrollbar|
  30. imgui.WindowFlagsNoMove|
  31. imgui.WindowFlagsMenuBar|
  32. imgui.WindowFlagsNoResize).Size(size[0], size[1])
  33. }
  34. var _ Disposable = &windowState{}
  35. type windowState struct {
  36. hasFocus bool
  37. currentPosition,
  38. currentSize imgui.Vec2
  39. }
  40. // Dispose implements Disposable interface.
  41. func (s *windowState) Dispose() {
  42. // noop
  43. }
  44. // WindowWidget represents imgui.Window
  45. // Windows are used to display ui widgets.
  46. // They are in second place in the giu hierarchy (after the MasterWindow)
  47. // NOTE: to disable multiple window, use SingleWindow.
  48. type WindowWidget struct {
  49. title string
  50. open *bool
  51. flags WindowFlags
  52. x, y float32
  53. width, height float32
  54. bringToFront bool
  55. }
  56. // Window creates a WindowWidget.
  57. func Window(title string) *WindowWidget {
  58. return &WindowWidget{
  59. title: title,
  60. }
  61. }
  62. // IsOpen sets if window widget is `opened` (minimalized).
  63. func (w *WindowWidget) IsOpen(open *bool) *WindowWidget {
  64. w.open = open
  65. return w
  66. }
  67. // Flags sets window flags.
  68. func (w *WindowWidget) Flags(flags WindowFlags) *WindowWidget {
  69. w.flags = flags
  70. return w
  71. }
  72. // Size sets window size
  73. // NOTE: size can be changed by user, if you want to prevent
  74. // user from changing window size, use NoResize flag.
  75. func (w *WindowWidget) Size(width, height float32) *WindowWidget {
  76. w.width, w.height = width, height
  77. return w
  78. }
  79. // Pos sets the window start position
  80. // NOTE: The position could be changed by user later.
  81. // To prevent user from changin window position use
  82. // WIndowFlagsNoMove.
  83. func (w *WindowWidget) Pos(x, y float32) *WindowWidget {
  84. w.x, w.y = x, y
  85. return w
  86. }
  87. // Layout is a final step of the window setup.
  88. // it should be called to add a layout to the window and build it.
  89. func (w *WindowWidget) Layout(widgets ...Widget) {
  90. if widgets == nil {
  91. return
  92. }
  93. ws := w.getState()
  94. if w.flags&imgui.WindowFlagsNoMove != 0 && w.flags&imgui.WindowFlagsNoResize != 0 {
  95. imgui.SetNextWindowPos(imgui.Vec2{X: w.x, Y: w.y})
  96. imgui.SetNextWindowSize(imgui.Vec2{X: w.width, Y: w.height})
  97. } else {
  98. imgui.SetNextWindowPosV(imgui.Vec2{X: w.x, Y: w.y}, imgui.ConditionFirstUseEver, imgui.Vec2{X: 0, Y: 0})
  99. imgui.SetNextWindowSizeV(imgui.Vec2{X: w.width, Y: w.height}, imgui.ConditionFirstUseEver)
  100. }
  101. if w.bringToFront {
  102. imgui.SetNextWindowFocus()
  103. w.bringToFront = false
  104. }
  105. widgets = append(widgets,
  106. Custom(func() {
  107. hasFocus := IsWindowFocused(0)
  108. if !hasFocus && ws.hasFocus {
  109. Context.InputHandler.UnregisterWindowShortcuts()
  110. }
  111. ws.hasFocus = hasFocus
  112. ws.currentPosition = imgui.WindowPos()
  113. ws.currentSize = imgui.WindowSize()
  114. }),
  115. )
  116. showed := imgui.BeginV(tStr(w.title), w.open, int(w.flags))
  117. if showed {
  118. Layout(widgets).Build()
  119. }
  120. imgui.End()
  121. }
  122. // CurrentPosition returns a current position of the window.
  123. func (w *WindowWidget) CurrentPosition() (x, y float32) {
  124. pos := w.getState().currentPosition
  125. return pos.X, pos.Y
  126. }
  127. // CurrentSize returns current size of the window.
  128. func (w *WindowWidget) CurrentSize() (width, height float32) {
  129. size := w.getState().currentSize
  130. return size.X, size.Y
  131. }
  132. // BringToFront sets window focused.
  133. func (w *WindowWidget) BringToFront() {
  134. w.bringToFront = true
  135. }
  136. // HasFocus returns true if window is focused.
  137. func (w *WindowWidget) HasFocus() bool {
  138. return w.getState().hasFocus
  139. }
  140. // RegisterKeyboardShortcuts adds local (window-level) keyboard shortcuts
  141. // see InputHandler.go.
  142. func (w *WindowWidget) RegisterKeyboardShortcuts(s ...WindowShortcut) *WindowWidget {
  143. if w.HasFocus() {
  144. for _, shortcut := range s {
  145. Context.InputHandler.RegisterKeyboardShortcuts(Shortcut{
  146. Key: shortcut.Key,
  147. Modifier: shortcut.Modifier,
  148. Callback: shortcut.Callback,
  149. IsGlobal: LocalShortcut,
  150. })
  151. }
  152. }
  153. return w
  154. }
  155. func (w *WindowWidget) getStateID() string {
  156. return fmt.Sprintf("%s_windowState", w.title)
  157. }
  158. // returns window state.
  159. func (w *WindowWidget) getState() (state *windowState) {
  160. if s := Context.GetState(w.getStateID()); s != nil {
  161. var isOk bool
  162. state, isOk = s.(*windowState)
  163. Assert(isOk, "WindowWidget", "getState", "unexpected state recovered.")
  164. } else {
  165. state = &windowState{}
  166. Context.SetState(w.getStateID(), state)
  167. }
  168. return state
  169. }