progress_bar.nim 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. # author: Ethosa
  2. ## It provides primitive display progress.
  3. import
  4. ../thirdparty/opengl,
  5. ../core/vector2,
  6. ../core/rect2,
  7. ../core/anchor,
  8. ../core/input,
  9. ../core/color,
  10. ../core/enums,
  11. ../nodes/node,
  12. ../nodes/canvas,
  13. ../graphics/drawable,
  14. control,
  15. math
  16. const CIRCLE_STEP: float = TAU * 0.01
  17. type
  18. ProgressBarType* {.pure.} = enum
  19. PROGRESS_BAR_HORIZONTAL,
  20. PROGRESS_BAR_VERTICAL,
  21. PROGRESS_BAR_CIRCLE
  22. ProgressBarObj* = object of ControlRef
  23. max_value*, value*: float
  24. progress_color*: ColorRef
  25. indeterminate_val*: float
  26. indeterminate*: bool
  27. progress_type*: ProgressBarType
  28. ProgressBarRef* = ref ProgressBarObj
  29. proc ProgressBar*(name: string = "ProgressBar"): ProgressBarRef =
  30. ## Creates a new ProgressBar.
  31. ##
  32. ## Arguments:
  33. ## - `name` is a node name.
  34. runnableExamples:
  35. var p = ProgressBar("ProgressBar")
  36. nodepattern(ProgressBarRef)
  37. controlpattern()
  38. result.value = 0
  39. result.max_value = 100
  40. result.progress_color = Color(0.6, 0.6, 0.6)
  41. result.rect_size.x = 120
  42. result.rect_size.y = 20
  43. result.indeterminate = false
  44. result.indeterminate_val = 0
  45. result.progress_type = PROGRESS_BAR_HORIZONTAL
  46. result.kind = PROGRESS_BAR_NODE
  47. method draw*(self: ProgressBarRef, w, h: GLfloat) =
  48. ## It uses for redraw ProgressBar.
  49. let
  50. x = -w/2 + self.global_position.x
  51. y = h/2 - self.global_position.y
  52. # draw progress
  53. let progress_percent = self.value / self.max_value
  54. case self.progress_type
  55. of PROGRESS_BAR_HORIZONTAL:
  56. procCall self.ControlRef.draw(w, h)
  57. glColor4f(self.progress_color.r, self.progress_color.g, self.progress_color.b, self.progress_color.a)
  58. let progress_width = progress_percent * self.rect_size.x
  59. if self.indeterminate:
  60. if self.indeterminate_val - progress_width < self.rect_size.x:
  61. self.indeterminate_val += self.rect_size.x * 0.01
  62. else:
  63. self.indeterminate_val = -progress_width
  64. glRectf(
  65. normalize(x + self.indeterminate_val, x, x + self.rect_size.x), y,
  66. normalize(x + self.indeterminate_val + progress_width, x, x + self.rect_size.x), y - self.rect_size.y)
  67. else:
  68. glRectf(x, y, x + progress_width, y - self.rect_size.y)
  69. of PROGRESS_BAR_VERTICAL:
  70. procCall self.ControlRef.draw(w, h)
  71. glColor4f(self.progress_color.r, self.progress_color.g, self.progress_color.b, self.progress_color.a)
  72. let progress_width = progress_percent * self.rect_size.y
  73. if self.indeterminate:
  74. if self.indeterminate_val - progress_width < self.rect_size.y:
  75. self.indeterminate_val += self.rect_size.y * 0.01
  76. else:
  77. self.indeterminate_val = -progress_width
  78. glRectf(
  79. x, normalize(y - self.indeterminate_val, y - self.rect_size.y, y),
  80. x + self.rect_size.x, normalize(y - self.indeterminate_val - progress_width, y - self.rect_size.y, y))
  81. else:
  82. glRectf(x, y, x + self.rect_size.x, y - progress_width)
  83. of PROGRESS_BAR_CIRCLE:
  84. self.CanvasRef.calcGlobalPosition()
  85. let
  86. progress_width = progress_percent * TAU
  87. cx = x + (self.rect_size.x / 2)
  88. cy = y - (self.rect_size.y / 2)
  89. orad = min(self.rect_size.x, self.rect_size.y) / 2
  90. irad = (min(self.rect_size.x, self.rect_size.y) / 2) - 5f
  91. # background:
  92. glColor4f(self.background.getColor().r, self.background.getColor().g, self.background.getColor().b, self.background.getColor().a)
  93. glBegin(GL_TRIANGLE_STRIP)
  94. for i in 0..90:
  95. let angle = TAU * (i/90)
  96. glVertex2f(cx + orad*cos(angle), cy - orad*sin(angle))
  97. glVertex2f(cx + irad*cos(angle), cy - irad*sin(angle))
  98. glEnd()
  99. # progress:
  100. glColor4f(self.progress_color.r, self.progress_color.g, self.progress_color.b, self.progress_color.a)
  101. if self.indeterminate:
  102. if self.indeterminate_val - progress_width < TAU:
  103. self.indeterminate_val += CIRCLE_STEP
  104. else:
  105. self.indeterminate_val = -progress_width
  106. glBegin(GL_TRIANGLE_STRIP)
  107. for i in 0..90:
  108. let angle = TAU * (i/90)
  109. if angle > self.indeterminate_val and angle < progress_width + self.indeterminate_val:
  110. glVertex2f(cx + orad*cos(angle), cy - orad*sin(angle))
  111. glVertex2f(cx + irad*cos(angle), cy - irad*sin(angle))
  112. glEnd()
  113. else:
  114. glBegin(GL_TRIANGLE_STRIP)
  115. for i in 0..90:
  116. let angle = TAU * (i/90)
  117. if angle < progress_width:
  118. glVertex2f(cx + orad*cos(angle), cy - orad*sin(angle))
  119. glVertex2f(cx + irad*cos(angle), cy - irad*sin(angle))
  120. glEnd()
  121. method duplicate*(self: ProgressBarRef): ProgressBarRef {.base.} =
  122. ## Duplicates ProgressBar object and create a new ProgressBar.
  123. self.deepCopy()
  124. method setMaxValue*(self: ProgressBarRef, value: float) {.base.} =
  125. ## Changes max value.
  126. if value > self.value:
  127. self.max_value = value
  128. else:
  129. self.max_value = self.value
  130. method setProgress*(self: ProgressBarRef, value: float) {.base.} =
  131. ## Changes progress.
  132. if value > self.max_value:
  133. self.value = self.max_value
  134. else:
  135. self.value = value
  136. method setProgressColor*(self: ProgressBarRef, color: ColorRef) {.base.} =
  137. ## Changes progress color.
  138. ## For change background color use `setBackgroundColor` method.
  139. self.progress_color = color