subwindow.nim 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. # author: Ethosa
  2. ## Extended version of SubWindow node.
  3. import ../thirdparty/sdl2 except Color
  4. import
  5. ../thirdparty/opengl,
  6. ../core/vector2,
  7. ../core/rect2,
  8. ../core/anchor,
  9. ../core/input,
  10. ../core/enums,
  11. ../core/color,
  12. ../core/image,
  13. ../core/font,
  14. ../core/themes,
  15. ../nodes/node,
  16. ../nodes/canvas,
  17. ../graphics/drawable,
  18. control,
  19. popup,
  20. label
  21. type
  22. SubWindowObj* = object of PopupObj
  23. left_taked*, right_taked*, top_taked*, bottom_taked*: bool
  24. title_taked*: bool
  25. icon*: GlTextureObj
  26. title_bar*: DrawableRef
  27. title_taked_pos*: Vector2Obj
  28. title*: LabelRef
  29. SubWindowRef* = ref SubWindowObj
  30. proc SubWindow*(name: string = "SubWindow"): SubWindowRef =
  31. ## Creates a new SubWindow.
  32. ##
  33. ## Arguments:
  34. ## - `name` is a node name.
  35. runnableExamples:
  36. var window = SubWindow("SubWindow")
  37. nodepattern(SubWindowRef)
  38. controlpattern()
  39. result.title_bar = Drawable()
  40. result.background.setColor(current_theme~background_deep)
  41. result.title_bar.setColor(current_theme~background)
  42. result.background.setBorderColor(current_theme~foreground)
  43. result.background.setBorderWidth(1)
  44. result.rect_size.x = 320
  45. result.rect_size.y = 220
  46. result.visibility = GONE
  47. result.title = Label("Title")
  48. result.title.text = stext"Title"
  49. result.title.text.rendered = false
  50. result.title.parent = result
  51. result.left_taked = false
  52. result.right_taked = false
  53. result.top_taked = false
  54. result.bottom_taked = false
  55. result.title_taked = false
  56. result.title_taked_pos = Vector2()
  57. result.icon = GlTextureObj(texture: 0)
  58. result.kind = SUB_WINDOW_NODE
  59. method bringToFront*(self: SubWindowRef) {.base.} =
  60. let par = self.parent
  61. self.parent.removeChild(self)
  62. par.addChild(self)
  63. method close*(self: SubWindowRef) {.base.} =
  64. ## Closes the window. alias of hide() method.
  65. self.hide()
  66. method draw*(self: SubWindowRef, w, h: GLfloat) =
  67. ## This uses in the `window.nim`.
  68. let
  69. x = -w/2 + self.global_position.x
  70. y = h/2 - self.global_position.y
  71. self.background.draw(x, y, self.rect_size.x, self.rect_size.y)
  72. for child in self.getChildIter():
  73. child.CanvasRef.calcGlobalPosition()
  74. if child.CanvasRef.global_position.x > self.global_position.x + self.rect_size.x:
  75. child.visibility = GONE
  76. elif child.CanvasRef.global_position.y > self.global_position.y + self.rect_size.y:
  77. child.visibility = GONE
  78. elif child.CanvasRef.global_position.x + child.CanvasRef.rect_size.x < self.global_position.x:
  79. child.visibility = GONE
  80. elif child.CanvasRef.global_position.y + child.CanvasRef.rect_size.y < self.global_position.y:
  81. child.visibility = GONE
  82. else:
  83. child.visibility = VISIBLE
  84. self.title_bar.draw(x, y, self.rect_size.x-1, 32)
  85. let size = self.title.text.getTextSize()
  86. self.title.position.x = self.rect_size.x / 2 - size.x / 2
  87. self.title.position.y = 1 + 15 - size.y / 2
  88. self.title.calcGlobalPosition()
  89. self.title.text.rendered = false
  90. self.title.draw(w, h)
  91. if self.icon.texture > 0'u32:
  92. glColor4f(1, 1, 1, 1)
  93. glEnable(GL_TEXTURE_2D)
  94. glBindTexture(GL_TEXTURE_2D, self.icon.texture)
  95. glBegin(GL_QUADS)
  96. glTexCoord2f(0, 0)
  97. glVertex2f(x+2, y-2)
  98. glTexCoord2f(0, 1)
  99. glVertex2f(x+2, y - 28)
  100. glTexCoord2f(1, 1)
  101. glVertex2f(x + 28, y - 28)
  102. glTexCoord2f(1, 0)
  103. glVertex2f(x + 28, y-2)
  104. glEnd()
  105. glDisable(GL_TEXTURE_2D)
  106. # Press
  107. if self.pressed:
  108. self.on_press(self, last_event.x, last_event.y)
  109. method duplicate*(self: SubWindowRef): SubWindowRef {.base.} =
  110. ## Duplicates SubWindow object and create a new SubWindow.
  111. self.deepCopy()
  112. method handle*(self: SubWindowRef, event: InputEvent, mouse_on: var NodeRef) =
  113. ## This uses in the `window.nim`.
  114. procCall self.ControlRef.handle(event, mouse_on)
  115. let
  116. left = event.x >= self.global_position.x-1 and event.x <= self.global_position.x+2
  117. right = event.x <= self.global_position.x+self.rect_size.x+1 and event.x >= self.global_position.x+self.rect_size.x-1
  118. top = event.y >= self.global_position.y-1 and event.y <= self.global_position.y+2
  119. bottom = event.y <= self.global_position.y+self.rect_size.y+1 and event.y >= self.global_position.y+self.rect_size.y-1
  120. title = Rect2(self.global_position+2, Vector2(self.rect_size.x-4, 32)).contains(event.x, event.y)
  121. when not defined(android) and not defined(ios):
  122. if left and top:
  123. setCursor(createSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE))
  124. elif left and bottom:
  125. setCursor(createSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW))
  126. elif right and bottom:
  127. setCursor(createSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE))
  128. elif right and top:
  129. setCursor(createSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW))
  130. elif left or right:
  131. setCursor(createSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE))
  132. elif bottom or top:
  133. setCursor(createSystemCursor(SDL_SYSTEM_CURSOR_SIZENS))
  134. else:
  135. setCursor(createSystemCursor(SDL_SYSTEM_CURSOR_ARROW))
  136. if event.kind == MOUSE and mouse_on == self:
  137. if event.pressed:
  138. self.bringToFront()
  139. if left and top:
  140. self.left_taked = true
  141. self.top_taked = true
  142. elif left and bottom:
  143. self.left_taked = true
  144. self.bottom_taked = true
  145. elif right and top:
  146. self.right_taked = true
  147. self.top_taked = true
  148. elif right and bottom:
  149. self.right_taked = true
  150. self.bottom_taked = true
  151. elif left:
  152. self.left_taked = true
  153. elif right:
  154. self.right_taked = true
  155. elif bottom:
  156. self.bottom_taked = true
  157. elif top:
  158. self.top_taked = true
  159. if title:
  160. self.title_taked = true
  161. self.title_taked_pos = Vector2(self.global_position.x - event.x, self.global_position.y - event.y)
  162. else:
  163. self.left_taked = false
  164. self.right_taked = false
  165. self.top_taked = false
  166. self.bottom_taked = false
  167. self.title_taked = false
  168. let
  169. left_p = self.global_position.x - event.x
  170. right_p = self.global_position.x + self.rect_size.x - event.x
  171. top_p = self.global_position.y - event.y
  172. bottom_p = self.global_position.y + self.rect_size.y - event.y
  173. if self.left_taked and self.rect_size.x + left_p > 128:
  174. self.position.x -= left_p
  175. self.rect_size.x += left_p
  176. if self.right_taked and self.rect_size.x - right_p > 128:
  177. self.rect_size.x -= right_p
  178. if self.top_taked and self.rect_size.y + top_p > 64:
  179. self.position.y -= top_p
  180. self.rect_size.y += top_p
  181. if self.bottom_taked and self.rect_size.y - bottom_p > 64:
  182. self.rect_size.y -= bottom_p
  183. if self.title_taked:
  184. self.position.x -= self.global_position.x - event.x
  185. self.position.y -= self.global_position.y - event.y
  186. self.position += self.title_taked_pos
  187. method open*(self: SubWindowRef) {.base.} =
  188. ## Opens the window. alias of show() method.
  189. self.show()
  190. method resize*(self: SubWindowRef, w, h: float) {.base.} =
  191. ## Resizes subwindow, if available.
  192. ##
  193. ## Arguments:
  194. ## - `w` is a new width.
  195. ## - `h` is a new height.
  196. if w > 128:
  197. self.rect_size.x = w
  198. if h > 64:
  199. self.rect_size.y = h
  200. method setBorderColor*(self: SubWindowRef, color: ColorRef) {.base.} =
  201. ## Changes border color.
  202. ##
  203. ## Arguments:
  204. ## - `color` is a new border color.
  205. self.background.setBorderColor(color)
  206. method setIcon*(self: SubWindowRef, gltexture: GlTextureObj) {.base.} =
  207. ## Changes icon.
  208. ##
  209. ## Arguments:
  210. ## - `gltexture` is a texture, loaded via load(file, mode=GL_RGB).
  211. self.icon = gltexture
  212. method setIcon*(self: SubWindowRef, file: string) {.base.} =
  213. ## Loads icon from file.
  214. ##
  215. ## Arguments:
  216. ## - `file` is an image file path.
  217. self.icon = load(file)
  218. method setTitleBarColor*(self: SubWindowRef, color: ColorRef) {.base.} =
  219. ## Changes title bar color.
  220. ##
  221. ## Arguments:
  222. ## - `color` is a new title bar color.
  223. self.title_bar.setColor(color)
  224. method setTitle*(self: SubWindowRef, title: string) {.base.} =
  225. ## Changes subwindow title.
  226. ##
  227. ## Arguments:
  228. ## - `title` is a new title.
  229. self.title.setText(title)