scroll.nim 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. # author: Ethosa
  2. import
  3. ../thirdparty/opengl,
  4. ../core/vector2,
  5. ../core/rect2,
  6. ../core/anchor,
  7. ../core/input,
  8. ../core/enums,
  9. ../core/color,
  10. ../nodes/node,
  11. control
  12. type
  13. ScrollObj* = object of ControlObj
  14. thumb_y_has_mouse*, thumb_x_has_mouse*: bool
  15. thumb_width*, thumb_height*: float
  16. viewport_w*, viewport_h*: float
  17. viewport_x*, viewport_y*: float
  18. thumb_color*: ColorRef
  19. back_color*: ColorRef
  20. ScrollPtr* = ptr ScrollObj
  21. proc Scroll*(name: string, variable: var ScrollObj): ScrollPtr =
  22. ## Creates a new Scroll pointer.
  23. ##
  24. ## Arguments:
  25. ## - `name` is a node name.
  26. ## - `variable` is a ScrollObj variable.
  27. runnableExamples:
  28. var
  29. scobj: ScrollObj
  30. sc = Scroll("Scroll", scobj)
  31. nodepattern(ScrollObj)
  32. controlpattern()
  33. variable.rect_size.x = 256
  34. variable.rect_size.y = 256
  35. variable.viewport_h = 256
  36. variable.viewport_w = 256
  37. variable.viewport_x = 0
  38. variable.viewport_y = 0
  39. variable.thumb_width = 8
  40. variable.thumb_height = 8
  41. variable.back_color = Color(0, 0, 0, 128)
  42. variable.thumb_color = Color(0, 0, 0, 128)
  43. variable.thumb_y_has_mouse = false
  44. variable.thumb_x_has_mouse = false
  45. variable.mousemode = MOUSEMODE_IGNORE
  46. proc Scroll*(obj: var ScrollObj): ScrollPtr {.inline.} =
  47. ## Creates a new Scroll pointer with default name "Scroll".
  48. ##
  49. ## Arguments:
  50. ## - `variable` is a ScrollObj variable.
  51. runnableExamples:
  52. var
  53. scobj: ScrollObj
  54. sc = Scroll(scobj)
  55. Scroll("Scroll", obj)
  56. method addChild*(self: ScrollPtr, other: NodePtr) =
  57. ## Adds a new node in Scroll.
  58. ##
  59. ## Arguments:
  60. ## - `other` is other Node.
  61. if self.children.len() == 0:
  62. self.children.add(other)
  63. other.parent = self
  64. method duplicate*(self: ScrollPtr, obj: var ScrollObj): ScrollPtr {.base.} =
  65. ## Duplicates Scroll object and create a new Scroll pointer.
  66. obj = self[]
  67. obj.addr
  68. method resize*(canvas: ScrollPtr, w, h: GLfloat) =
  69. ## Resizes scroll.
  70. ##
  71. ## Arguments:
  72. ## - `w` is a new width.
  73. ## - `h` is a new height.
  74. canvas.rect_size.x = w
  75. canvas.rect_size.y = h
  76. method draw*(self: ScrollPtr, w, h: GLfloat) =
  77. ## This uses in the `window.nim`.
  78. self.calcGlobalPosition()
  79. let
  80. x = -w/2 + self.global_position.x
  81. y = h/2 - self.global_position.y
  82. glColor4f(self.background_color.r, self.background_color.g, self.background_color.b, self.background_color.a)
  83. glRectf(x, y, x+self.viewport_w, y-self.viewport_h)
  84. # Press
  85. if self.pressed:
  86. self.press(last_event.x, last_event.y)
  87. method draw2stage*(self: ScrollPtr, w, h: GLfloat) =
  88. ## This uses in the `window.nim`.
  89. let
  90. x = -w/2 + self.global_position.x
  91. y = h/2 - self.global_position.y
  92. if self.children.len() > 0:
  93. var child = self.children[0]
  94. self.resize(child.rect_size.x, child.rect_size.y)
  95. let
  96. thumb_h = self.viewport_h * (self.viewport_h / self.rect_size.y)
  97. thumb_w = self.viewport_w * (self.viewport_w / self.rect_size.x)
  98. thumb_x = self.viewport_w * (self.viewport_x / self.rect_size.x)
  99. thumb_y = self.viewport_h * (self.viewport_y / self.rect_size.y)
  100. child.position.x = -self.viewport_x
  101. child.position.y = -self.viewport_y
  102. # Vertical
  103. if self.viewport_h < self.rect_size.y:
  104. # Back:
  105. glColor4f(self.back_color.r, self.back_color.g, self.back_color.b, self.back_color.a)
  106. glRectf(x + self.viewport_w - self.thumb_width, y, x+self.viewport_w, y-self.viewport_h)
  107. # Thumb:
  108. glColor4f(self.thumb_color.r, self.thumb_color.g, self.thumb_color.b, self.thumb_color.a)
  109. glRectf(x + self.viewport_w - self.thumb_width, y - thumb_y, x+self.viewport_w, y - thumb_y - thumb_h)
  110. # Horizontal
  111. if self.viewport_w < self.rect_size.x:
  112. # Back:
  113. glColor4f(self.back_color.r, self.back_color.g, self.back_color.b, self.back_color.a)
  114. glRectf(x, y - self.viewport_h + self.thumb_height, x + self.viewport_w - self.thumb_width, y-self.viewport_h)
  115. # Thumb:
  116. glColor4f(self.thumb_color.r, self.thumb_color.g, self.thumb_color.b, self.thumb_color.a)
  117. glRectf(x + thumb_x, y - self.viewport_h + self.thumb_height, x + thumb_x + thumb_w, y-self.viewport_h)
  118. method scrollBy*(self: ScrollPtr, x, y: float) {.base.} =
  119. ## Scrolls by `x` and `y`, if available.
  120. if x + self.viewport_x + self.viewport_w < self.rect_size.x and x + self.viewport_x > 0:
  121. self.viewport_x += x
  122. elif x < 0:
  123. self.viewport_x = 0
  124. elif x > 0:
  125. self.viewport_x = self.rect_size.x - self.viewport_w
  126. if y + self.viewport_y + self.viewport_h < self.rect_size.y and y + self.viewport_y > 0:
  127. self.viewport_y += y
  128. elif y < 0:
  129. self.viewport_y = 0
  130. elif y > 0:
  131. self.viewport_y = self.rect_size.y - self.viewport_h
  132. method scrollTo*(self: ScrollPtr, x, y: float) {.base.} =
  133. ## Scrolls to `x` and `y` position.
  134. if x + self.viewport_w < self.rect_size.x and x > 0:
  135. self.viewport_x = x
  136. elif x < 0:
  137. self.viewport_x = 0
  138. elif x > 0:
  139. self.viewport_x = self.rect_size.x - self.viewport_w
  140. if y + self.viewport_h < self.rect_size.y and y > 0:
  141. self.viewport_y = y
  142. elif y < 0:
  143. self.viewport_y = 0
  144. elif y > 0:
  145. self.viewport_y = self.rect_size.y - self.viewport_h
  146. method handle*(self: ScrollPtr, event: InputEvent, mouse_on: var NodePtr) =
  147. ## handles user input. This uses in the `window.nim`.
  148. procCall self.ControlPtr.handle(event, mouse_on)
  149. let
  150. mouse_in = Rect2(self.global_position, Vector2(self.viewport_w, self.viewport_h)).hasPoint(event.x, event.y)
  151. thumb_h = self.viewport_h * (self.viewport_h / self.rect_size.y)
  152. thumb_w = self.viewport_w * (self.viewport_w / self.rect_size.x)
  153. thumb_x = self.viewport_w * (self.viewport_x / self.rect_size.x)
  154. thumb_y = self.viewport_h * (self.viewport_y / self.rect_size.y)
  155. mouse_in_y = Rect2(
  156. self.global_position.x + self.viewport_w - self.thumb_width,
  157. self.global_position.y + thumb_y,
  158. self.thumb_width,
  159. thumb_h
  160. ).hasPoint(event.x, event.y)
  161. mouse_in_x = Rect2(
  162. self.global_position.x + thumb_x,
  163. self.global_position.y + self.viewport_h - self.thumb_height,
  164. thumb_w,
  165. self.thumb_height
  166. ).hasPoint(event.x, event.y)
  167. if mouse_in: # Keyboard movement
  168. if event.kind == KEYBOARD:
  169. if event.key_cint in pressed_keys_cints: # Special chars
  170. if event.key_cint == K_UP:
  171. self.scrollBy(0, -40)
  172. elif event.key_cint == K_DOWN:
  173. self.scrollBy(0, 40)
  174. elif event.kind == WHEEL:
  175. self.scrollBy(0, -20 * event.yrel)
  176. # Mouse Y
  177. if (mouse_in_y and mouse_pressed and event.kind == MOUSE) or self.thumb_y_has_mouse:
  178. self.thumb_y_has_mouse = true
  179. self.scrollBy(0, -event.yrel)
  180. if not mouse_pressed and self.thumb_y_has_mouse:
  181. self.thumb_y_has_mouse = false
  182. # Mouse X
  183. if (mouse_in_x and mouse_pressed and event.kind == MOUSE) or self.thumb_x_has_mouse:
  184. self.thumb_x_has_mouse = true
  185. self.scrollBy(-event.xrel, 0)
  186. if not mouse_pressed and self.thumb_x_has_mouse:
  187. self.thumb_x_has_mouse = false