panel.lua 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. return function(BOXUI)
  2. local utils = BOXUI.utils
  3. local includes = utils.includesPoint
  4. local intersects = utils.intersectsRect
  5. local newbox = utils.newbox
  6. local setbox = utils.setbox
  7. local M = utils.newclass("panel")
  8. M.init = function(self, x, y, width, height)
  9. x, y = (x or 0), (y or 0)
  10. width = width or love.graphics.getWidth()
  11. height = height or love.graphics.getHeight()
  12. self.theme = BOXUI.theme
  13. self.x, self.y = x, y
  14. self.width, self.height = width, height
  15. self.active = nil
  16. self.objects = {}
  17. self.mousepresses = {} -- track pressed buttons
  18. self.viewport = newbox("viewport", 0, 0, width, height)
  19. end
  20. M.find = function(self, object)
  21. local objects = self.objects
  22. for i, v in ipairs(objects) do
  23. if v == object then return i end
  24. end
  25. end
  26. M.remove = function(self, index)
  27. local object = self.objects[index]
  28. object.parent = nil
  29. if index == self.active then self.active = nil end
  30. table.remove(self.objects, index)
  31. if self.onRemove then self:onRemove(object) end
  32. end
  33. M.insert = function(self, object, index)
  34. local objects = self.objects
  35. object.parent = self
  36. if not index then return table.insert(objects, object) end
  37. print("inserting:", index)
  38. table.insert(objects, index, object)
  39. end
  40. M.maketop = function(self, index)
  41. local objects = self.objects
  42. if not index or index == #objects then return end
  43. table.insert(objects, objects[index])
  44. table.remove(objects, index)
  45. end
  46. M.wheelmoved = function(self, wx, wy)
  47. local active = self.active
  48. if active then return self.objects[active]:wheelmoved(wx, wy) end
  49. end
  50. M.mousemoved = function(self, x, y, dx, dy)
  51. local objects = self.objects
  52. local top = #objects
  53. if top == 0 then return end
  54. local relx, rely = x - self.x, y - self.y
  55. if objects[top].dragging then
  56. --self.dragging = true
  57. return objects[top]:mousemoved(relx, rely, dx, dy)
  58. end
  59. local prevactive, active = self.active, nil
  60. for i = top, 1, -1 do
  61. if includes(objects[i], relx, rely) then active = i; break end
  62. end
  63. self.active = active
  64. prevactive, active = objects[prevactive], objects[active]
  65. if prevactive ~= active then
  66. if prevactive and prevactive.unfocus then prevactive:unfocus() end
  67. if active and active.focus then active:focus() end
  68. end
  69. if active then
  70. return active:mousemoved(relx, rely, dx, dy)
  71. end
  72. objects[top]:mousemoved(relx, rely, dx, dy)
  73. end
  74. M.mousepressed = function(self, x, y, button)
  75. local objects = self.objects
  76. if #objects == 0 or not self.active then return end
  77. local active = objects[self.active]
  78. if active.movable and self.active ~= #objects then -- make active top object
  79. table.remove(objects, self.active)
  80. table.insert(objects, active)
  81. self.active = #objects
  82. end
  83. active:mousepressed(x - self.x, y - self.y, button)
  84. local waiters = self.mousepresses[button] or {}
  85. table.insert(waiters, active)
  86. self.mousepresses[button] = waiters
  87. end
  88. M.mousereleased = function(self, x, y, button)
  89. local waiters = self.mousepresses[button]
  90. if not waiters then return end -- prank call
  91. local objects = self.objects
  92. if #objects == 0 then return end
  93. local relx, rely = x - self.x, y - self.y
  94. for i, v in ipairs(waiters) do
  95. v:mousereleased(relx, rely, button)
  96. end
  97. self.mousepresses[button] = nil
  98. local dragged = objects[#objects].dragging
  99. if dragged then
  100. --self.dragging = false
  101. self:mousemoved(relx, rely, 0, 0)
  102. end
  103. end
  104. M.update = function(self, dt)
  105. local objects = self.objects
  106. if #objects == 0 or not self.active then return end
  107. objects[self.active]:update(dt)
  108. end
  109. M.draw = function(self, x, y)
  110. local vp = self.viewport
  111. x, y = self.x - vp.x + (x or 0), self.y - vp.y + (y or 0)
  112. local theme = self.theme
  113. local bt = theme.borderThickness
  114. local color = theme.borderFore
  115. love.graphics.setColor(theme.panelBack)
  116. --love.graphics.setLineWidth(2)
  117. love.graphics.rectangle("fill", x + bt, y + bt, self.width - 2 * bt , self.height - 2 * bt)
  118. local objects = self.objects
  119. for i, v in ipairs(objects) do
  120. if v.draw and intersects(v, 0, 0, self.width, self.height) then
  121. v:draw(x, y)
  122. end
  123. end
  124. end
  125. local dummyf = function() end
  126. --M.refresh = dummyf
  127. --M.expand = dummyf
  128. --M.redraw = dummyf
  129. --M.updateViewport = dummyf
  130. --M.focus = dummyf
  131. --M.unfocus = dummyf
  132. M.expand = function(self, width, height)
  133. self.width, self.height = width, height
  134. end
  135. M.updateViewport = function(self, vpx, vpy, vpw, vph)
  136. setbox(self.viewport, vpx, vpy, vpw, vph)
  137. end
  138. BOXUI.add(M)
  139. end