scrollbar.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package gui
  5. import (
  6. "github.com/g3n/engine/math32"
  7. "github.com/g3n/engine/window"
  8. )
  9. /***************************************
  10. ScrollBar Panel
  11. +--------------------------------+
  12. | scroll button |
  13. | +--------------+ |
  14. | | | |
  15. | | | |
  16. | +--------------+ |
  17. +--------------------------------+
  18. **/
  19. type ScrollBar struct {
  20. Panel // Embedded panel
  21. style *ScrollBarStyle // pointer to current style
  22. vertical bool // type of scrollbar
  23. button scrollBarButton // scrollbar button
  24. }
  25. type scrollBarButton struct {
  26. Panel // Embedded panel
  27. sb *ScrollBar // pointer to parent scroll bar
  28. pressed bool // mouse button pressed flag
  29. mouseX float32 // last mouse click x position
  30. mouseY float32 // last mouse click y position
  31. }
  32. type ScrollBarStyle struct {
  33. Paddings BorderSizes
  34. Borders BorderSizes
  35. BordersColor math32.Color4
  36. Color math32.Color
  37. Button ScrollBarButtonStyle
  38. }
  39. type ScrollBarButtonStyle struct {
  40. Borders BorderSizes
  41. BordersColor math32.Color4
  42. Color math32.Color
  43. Size float32
  44. }
  45. // NewVScrollBar creates and returns a pointer to a new vertical scroll bar
  46. // with the specified dimensions.
  47. func NewVScrollBar(width, height float32) *ScrollBar {
  48. return newScrollBar(width, height, true)
  49. }
  50. // NewHScrollBar creates and returns a pointer to a new horizontal scroll bar
  51. // with the specified dimensions.
  52. func NewHScrollBar(width, height float32) *ScrollBar {
  53. return newScrollBar(width, height, false)
  54. }
  55. // newScrollBar creates and returns a pointer to a new scroll bar panel
  56. // with the specified width, height, orientation and target.
  57. func newScrollBar(width, height float32, vertical bool) *ScrollBar {
  58. sb := new(ScrollBar)
  59. sb.initialize(width, height, vertical)
  60. return sb
  61. }
  62. // initialize initializes this scrollbar
  63. func (sb *ScrollBar) initialize(width, height float32, vertical bool) {
  64. sb.style = &StyleDefault.ScrollBar
  65. sb.vertical = vertical
  66. sb.Panel.Initialize(width, height)
  67. sb.Panel.Subscribe(OnMouseDown, sb.onMouse)
  68. // Initialize scrollbar button
  69. sb.button.Panel.Initialize(0, 0)
  70. sb.button.Panel.Subscribe(OnMouseDown, sb.button.onMouse)
  71. sb.button.Panel.Subscribe(OnMouseUp, sb.button.onMouse)
  72. sb.button.Panel.Subscribe(OnCursor, sb.button.onCursor)
  73. sb.button.SetMargins(1, 1, 1, 1)
  74. sb.button.sb = sb
  75. sb.Add(&sb.button)
  76. sb.update()
  77. sb.recalc()
  78. }
  79. // Value returns the current position of the button in the scrollbar
  80. // The returned value is between 0.0 and 1.0
  81. func (sb *ScrollBar) Value() float64 {
  82. if sb.vertical {
  83. return float64(sb.button.Position().Y) / (float64(sb.content.Height) - float64(sb.button.height))
  84. } else {
  85. return float64(sb.button.Position().X) / (float64(sb.content.Width) - float64(sb.button.width))
  86. }
  87. }
  88. // SetValue sets the position of the button of the scrollbar
  89. // from 0.0 (minimum) to 1.0 (maximum).
  90. func (sb *ScrollBar) SetValue(v float32) {
  91. v = math32.Clamp(v, 0.0, 1.0)
  92. if sb.vertical {
  93. pos := v * (float32(sb.content.Height) - float32(sb.button.height))
  94. sb.button.SetPositionY(pos)
  95. } else {
  96. pos := v * (float32(sb.content.Width) - float32(sb.button.width))
  97. sb.button.SetPositionX(pos)
  98. }
  99. }
  100. // onMouse receives subscribed mouse events over the scrollbar outer panel
  101. func (sb *ScrollBar) onMouse(evname string, ev interface{}) {
  102. e := ev.(*window.MouseEvent)
  103. if e.Button != window.MouseButtonLeft {
  104. return
  105. }
  106. if sb.vertical {
  107. posy := e.Ypos - sb.pospix.Y
  108. newY := math32.Clamp(posy-(sb.button.height/2), 0, sb.content.Height-sb.button.height)
  109. sb.button.SetPositionY(newY)
  110. } else {
  111. posx := e.Xpos - sb.pospix.X
  112. newX := math32.Clamp(posx-(sb.button.width/2), 0, sb.content.Width-sb.button.width)
  113. sb.button.SetPositionX(newX)
  114. }
  115. sb.root.StopPropagation(StopAll)
  116. sb.Dispatch(OnChange, nil)
  117. }
  118. // recalc recalculates sizes and positions
  119. func (sb *ScrollBar) recalc() {
  120. if sb.vertical {
  121. sb.button.SetSize(sb.content.Width, sb.style.Button.Size)
  122. } else {
  123. sb.button.SetSize(sb.style.Button.Size, sb.content.Height)
  124. }
  125. }
  126. // update updates border sizes and colors
  127. func (sb *ScrollBar) update() {
  128. sb.SetBordersFrom(&sb.style.Borders)
  129. sb.SetPaddingsFrom(&sb.style.Paddings)
  130. sb.SetBordersColor4(&sb.style.BordersColor)
  131. sb.SetColor(&sb.style.Color)
  132. sb.button.SetBordersFrom(&sb.style.Button.Borders)
  133. sb.button.SetBordersColor4(&sb.style.Button.BordersColor)
  134. sb.button.SetColor(&sb.style.Button.Color)
  135. }
  136. // onMouse receives subscribed mouse events for the scroll bar button
  137. func (button *scrollBarButton) onMouse(evname string, ev interface{}) {
  138. e := ev.(*window.MouseEvent)
  139. if e.Button != window.MouseButtonLeft {
  140. return
  141. }
  142. switch evname {
  143. case OnMouseDown:
  144. button.pressed = true
  145. button.mouseX = e.Xpos
  146. button.mouseY = e.Ypos
  147. button.sb.root.SetMouseFocus(button)
  148. case OnMouseUp:
  149. button.pressed = false
  150. button.sb.root.SetMouseFocus(nil)
  151. default:
  152. return
  153. }
  154. button.sb.root.StopPropagation(StopAll)
  155. }
  156. // onCursor receives subscribed cursor events for the scroll bar button
  157. func (button *scrollBarButton) onCursor(evname string, ev interface{}) {
  158. e := ev.(*window.CursorEvent)
  159. if !button.pressed {
  160. return
  161. }
  162. if button.sb.vertical {
  163. dy := button.mouseY - e.Ypos
  164. py := button.Position().Y
  165. button.SetPositionY(math32.Clamp(py-dy, 0, button.sb.content.Height-button.sb.style.Button.Size))
  166. } else {
  167. dx := button.mouseX - e.Xpos
  168. px := button.Position().X
  169. button.SetPositionX(math32.Clamp(px-dx, 0, button.sb.content.Width-button.sb.style.Button.Size))
  170. }
  171. button.mouseX = e.Xpos
  172. button.mouseY = e.Ypos
  173. button.sb.Dispatch(OnChange, nil)
  174. button.sb.root.StopPropagation(StopAll)
  175. }