grid.lua 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. -- @author cedlemo
  2. --
  3. --
  4. local base = require("wibox.layout.base")
  5. local widget_base = require("wibox.widget.base")
  6. local table = table
  7. local pairs = pairs
  8. local floor = math.floor
  9. local wibox = require('wibox')
  10. local helpers = require('blingbling.helpers')
  11. local grid = { mt = {} }
  12. local data = setmetatable({}, { __mode = "k" })
  13. local function round(x)
  14. return floor(x + 0.5)
  15. end
  16. function grid:draw(wibox, cr, width, height)
  17. local median_width = floor(width / data[self].num_columns)
  18. local median_height = floor(height / data[self].num_lines)
  19. local pos = 0
  20. for _, d in pairs(data[self].widgets) do
  21. local x, y, w, h
  22. x = round(median_width * (d.left - 1))
  23. y = round(median_height * (d.top - 1))
  24. w = floor(median_width * d.cols)
  25. h = floor(median_height * d.lines)
  26. -- Keep for widget debug
  27. -- str = "x " .. tostring(x) .. " y ".. tostring(y) .. " w " .. tostring(w) .. " h " .. tostring(h)
  28. -- print("width " .. tostring(width) .. "height " .. tostring(height))
  29. -- print("columns ".. tostring(data[self].num_columns) .. "median_width ".. tostring(median_width))
  30. -- print("lines ".. tostring(data[self].num_lines) .. "median_height ".. tostring(median_height))
  31. -- print(str)
  32. base.draw_widget(wibox, cr, d.widget, x, y, w, h)
  33. end
  34. end
  35. local function matrix_add(matrix, object, x, y, w, h)
  36. for i = 1, (y - 1) do
  37. if matrix[i] == nil then matrix[i] = {} end
  38. end
  39. for i=0, (h - 1) do
  40. if matrix[y + i] == nil then matrix[y + i] = {} end
  41. local line = matrix[y + i]
  42. if #line < x - 1 then
  43. for j = #line + 1, (x - 1) do
  44. table.insert(line, j, "-") -- TODO find another way to use sparse table [w1,nil,nil,w2]
  45. end
  46. end
  47. for j=0,(w -1) do
  48. table.insert(line, x + j, object)
  49. end
  50. end
  51. end
  52. function grid:add_child(child, left, top, n_cols, n_lines)
  53. widget_base.check_widget(child)
  54. matrix_add(data[self].matrix, child, left, top, n_cols, n_lines)
  55. local widget_data = {}
  56. widget_data.widget = child
  57. widget_data.left = left
  58. widget_data.top = top
  59. widget_data.cols = n_cols
  60. widget_data.lines = n_lines
  61. table.insert(data[self].widgets, widget_data)
  62. if data[self].num_lines < n_lines + (top - 1) then
  63. data[self].num_lines = n_lines + (top - 1)
  64. end
  65. if data[self].num_columns < n_cols + (left - 1) then
  66. data[self].num_columns = n_cols + (left - 1)
  67. end
  68. child:connect_signal("widget::updated", self._emit_updated)
  69. self._emit_updated()
  70. end
  71. function grid:get_child(left, top)
  72. return data[self].matrix[left][top]
  73. end
  74. function grid:set_padding(padding)
  75. end
  76. function grid:fit(width, height)
  77. local matrix = data[self].matrix
  78. local max_width = 0
  79. local cumul_height = 0
  80. for _,line in ipairs(matrix) do
  81. local prev_widget = nil
  82. local max_height = 0
  83. for i,w in ipairs(line) do
  84. local cumul_width = 0
  85. -- See TODO line 58
  86. if (prev_widget == nil or w ~= prev_widget) and w ~= "-" then
  87. local w,h = w:fit(width, height)
  88. cumul_width = cumul_width + w
  89. if max_height < h then max_height = h end
  90. prev_widget = w
  91. end
  92. if max_width < cumul_width then max_width = cumul_width end
  93. end
  94. cumul_height = max_height + cumul_height
  95. end
  96. return max_width, cumul_height
  97. end
  98. function grid.new()
  99. local _grid = widget_base.make_widget()
  100. data[_grid] = {}
  101. data[_grid].matrix = {} -- Used a map for access through get_child
  102. data[_grid].widgets = {}
  103. data[_grid].num_lines = 0
  104. data[_grid].num_columns = 0
  105. _grid._emit_updated = function()
  106. _grid:emit_signal("widget::updated")
  107. end
  108. _grid.add_child = grid.add_child
  109. _grid.get_child = grid.get_child
  110. _grid.set_padding = grid.set_padding
  111. _grid.draw = grid.draw
  112. _grid.fit = grid.fit
  113. return _grid
  114. end
  115. function grid.mt:__call(...)
  116. return grid.new(...)
  117. end
  118. return setmetatable(grid, grid.mt)