1 |
176 |
Thurallor-7095 |
TableControl = class(Turbine.UI.Control); |
2 |
|
Thurallor-7095 |
|
3 |
|
Thurallor-7095 |
-- Add SetRowVisible(). |
4 |
|
Thurallor-7095 |
-- SetColumnVisible(), add right-click menu to select columns |
5 |
|
Thurallor-7095 |
-- Add horizontal / vertical orientation? |
6 |
|
Thurallor-7095 |
-- MinimumSize (horizontal) style |
7 |
|
Thurallor-7095 |
|
8 |
177 |
Thurallor-7095 |
function TableControl:Constructor(style, options) |
9 |
176 |
Thurallor-7095 |
Turbine.UI.Control.Constructor(self); |
10 |
|
Thurallor-7095 |
self:SetMouseVisible(false); |
11 |
177 |
Thurallor-7095 |
|
12 |
|
Thurallor-7095 |
if (not options) then |
13 |
|
Thurallor-7095 |
options = {}; |
14 |
|
Thurallor-7095 |
options.columnLockingEnabled = true; |
15 |
|
Thurallor-7095 |
end |
16 |
176 |
Thurallor-7095 |
|
17 |
|
Thurallor-7095 |
if (not style) then |
18 |
|
Thurallor-7095 |
style = {} |
19 |
|
Thurallor-7095 |
style.horizontalCellSpacing = -1; |
20 |
|
Thurallor-7095 |
style.verticalCellSpacing = -1; |
21 |
|
Thurallor-7095 |
style.minimumColumnWidth = 10; |
22 |
|
Thurallor-7095 |
style.heading = { |
23 |
|
Thurallor-7095 |
|
24 |
|
Thurallor-7095 |
-- Built-in styles (Turbine.UI.Control) |
25 |
|
Thurallor-7095 |
BackColor = Turbine.UI.Color(1, 0, 0.38, .67); |
26 |
|
Thurallor-7095 |
Enabled = true; |
27 |
|
Thurallor-7095 |
Font = Turbine.UI.Lotro.Font.Verdana14; |
28 |
177 |
Thurallor-7095 |
ForeColor = Turbine.UI.Color.White; |
29 |
176 |
Thurallor-7095 |
Height = 24; |
30 |
|
Thurallor-7095 |
Multiline = false; |
31 |
|
Thurallor-7095 |
TextAlignment = Turbine.UI.ContentAlignment.MiddleCenter; |
32 |
|
Thurallor-7095 |
ReadOnly = true; |
33 |
|
Thurallor-7095 |
Selectable = false; |
34 |
|
Thurallor-7095 |
MarkupEnabled = true; -- so we can underline the text when sorting |
35 |
|
Thurallor-7095 |
|
36 |
|
Thurallor-7095 |
-- Special styles (TableControl) |
37 |
|
Thurallor-7095 |
Object = Turbine.UI.Lotro.TextBox; -- what kind of object to create for each heading |
38 |
|
Thurallor-7095 |
HighlightColor = Turbine.UI.Color(1, 0, 0.57, 1); |
39 |
|
Thurallor-7095 |
}; |
40 |
|
Thurallor-7095 |
style.column = { |
41 |
|
Thurallor-7095 |
SortMethod = function(a, b) |
42 |
|
Thurallor-7095 |
-- Takes two cells as arguments, returns -1, 0, or 1 |
43 |
|
Thurallor-7095 |
local aText, bText = a:GetText(), b:GetText(); |
44 |
|
Thurallor-7095 |
if (aText < bText) then |
45 |
|
Thurallor-7095 |
return -1; |
46 |
|
Thurallor-7095 |
elseif (aText > bText) then |
47 |
|
Thurallor-7095 |
return 1; |
48 |
|
Thurallor-7095 |
else |
49 |
|
Thurallor-7095 |
return 0; |
50 |
|
Thurallor-7095 |
end |
51 |
|
Thurallor-7095 |
end |
52 |
|
Thurallor-7095 |
}; |
53 |
|
Thurallor-7095 |
style.cell = { |
54 |
|
Thurallor-7095 |
|
55 |
|
Thurallor-7095 |
-- Built-in styles (Turbine.UI.Control) |
56 |
|
Thurallor-7095 |
BackColor = Turbine.UI.Color(1, 0, 0.19, 0.33); |
57 |
|
Thurallor-7095 |
Enabled = true; |
58 |
|
Thurallor-7095 |
Font = Turbine.UI.Lotro.Font.Verdana14; |
59 |
177 |
Thurallor-7095 |
ForeColor = Turbine.UI.Color.Silver; |
60 |
176 |
Thurallor-7095 |
Height = 24; |
61 |
|
Thurallor-7095 |
Multiline = false; |
62 |
|
Thurallor-7095 |
TextAlignment = Turbine.UI.ContentAlignment.MiddleCenter; |
63 |
|
Thurallor-7095 |
ReadOnly = true; |
64 |
|
Thurallor-7095 |
|
65 |
|
Thurallor-7095 |
-- Special styles (TableControl) |
66 |
|
Thurallor-7095 |
Object = Turbine.UI.Lotro.TextBox; -- what kind of object to create for each cell |
67 |
|
Thurallor-7095 |
HighlightColor = Turbine.UI.Color(1, 0, 0.57, 1); |
68 |
|
Thurallor-7095 |
}; |
69 |
|
Thurallor-7095 |
style.toolTip = { |
70 |
|
Thurallor-7095 |
|
71 |
|
Thurallor-7095 |
-- Built-in styles (Turbine.UI.Label) |
72 |
|
Thurallor-7095 |
BackColor = Turbine.UI.Color(0.9, 0, 0, 0); |
73 |
|
Thurallor-7095 |
ForeColor = Turbine.UI.Color.White; |
74 |
|
Thurallor-7095 |
Font = Turbine.UI.Lotro.Font.Verdana14; |
75 |
|
Thurallor-7095 |
FontStyle = Turbine.UI.FontStyle.Outline; |
76 |
|
Thurallor-7095 |
OutlineColor = Turbine.UI.Color(0.5, 0, 0, 0); |
77 |
|
Thurallor-7095 |
Height = 14; |
78 |
|
Thurallor-7095 |
}; |
79 |
|
Thurallor-7095 |
style.edgeMover = { |
80 |
|
Thurallor-7095 |
|
81 |
|
Thurallor-7095 |
-- Built-in styles (Turbine.UI.Control) |
82 |
|
Thurallor-7095 |
Width = 5; |
83 |
|
Thurallor-7095 |
BackColor = Turbine.UI.Color(0.75, 0, .19, .33); |
84 |
|
Thurallor-7095 |
BackColorBlendMode = Turbine.UI.BlendMode.Overlay; |
85 |
|
Thurallor-7095 |
}; |
86 |
|
Thurallor-7095 |
style.marquee = { |
87 |
|
Thurallor-7095 |
Color = Turbine.UI.Color(1, 0, 0.57, 1); |
88 |
|
Thurallor-7095 |
AntsEnabled = true; |
89 |
|
Thurallor-7095 |
Speed = 20; -- updates per second |
90 |
|
Thurallor-7095 |
}; |
91 |
|
Thurallor-7095 |
end |
92 |
|
Thurallor-7095 |
|
93 |
|
Thurallor-7095 |
self.rows = Turbine.UI.ListBox(); |
94 |
|
Thurallor-7095 |
self.rowsByName = {}; |
95 |
|
Thurallor-7095 |
self.rows:SetParent(self); |
96 |
|
Thurallor-7095 |
-- The cell container must be in front of the headings, in case they overlap |
97 |
|
Thurallor-7095 |
-- due to verticalCellSpacing < 0. |
98 |
|
Thurallor-7095 |
self.rows:SetZOrder(1); |
99 |
|
Thurallor-7095 |
self.rows.MouseClick = function() |
100 |
|
Thurallor-7095 |
self:Deselect(); |
101 |
|
Thurallor-7095 |
end |
102 |
|
Thurallor-7095 |
self.rows.SelectedIndexChanged = function() |
103 |
|
Thurallor-7095 |
self:_SelectRow(self.rows:GetSelectedItem()); |
104 |
|
Thurallor-7095 |
end |
105 |
|
Thurallor-7095 |
self.rowWidth = 0; |
106 |
|
Thurallor-7095 |
|
107 |
|
Thurallor-7095 |
self.vScrollBar = Turbine.UI.Lotro.ScrollBar(); |
108 |
|
Thurallor-7095 |
self.vScrollBar:SetOrientation(Turbine.UI.Orientation.Vertical); |
109 |
|
Thurallor-7095 |
self.vScrollBar:SetParent(self); |
110 |
|
Thurallor-7095 |
self.vScrollBar:SetWidth(10); |
111 |
|
Thurallor-7095 |
self.rows:SetVerticalScrollBar(self.vScrollBar); |
112 |
|
Thurallor-7095 |
self.vScrollBar.VisibleChanged = function() |
113 |
|
Thurallor-7095 |
self:SetWidth(self:GetWidth()); |
114 |
|
Thurallor-7095 |
end |
115 |
|
Thurallor-7095 |
|
116 |
|
Thurallor-7095 |
self.columns = {}; |
117 |
|
Thurallor-7095 |
self.columnsByName = {}; |
118 |
|
Thurallor-7095 |
self.totalWeight = 0; |
119 |
|
Thurallor-7095 |
self.edgeMovers = {}; |
120 |
|
Thurallor-7095 |
|
121 |
|
Thurallor-7095 |
self:SetStyle(style); |
122 |
177 |
Thurallor-7095 |
self:SetOptions(options); |
123 |
176 |
Thurallor-7095 |
end |
124 |
|
Thurallor-7095 |
|
125 |
|
Thurallor-7095 |
function TableControl:SetStyle(style) |
126 |
|
Thurallor-7095 |
self.style = style; |
127 |
|
Thurallor-7095 |
self.rows:SetTop(self.style.heading.Height + self.style.verticalCellSpacing); |
128 |
|
Thurallor-7095 |
if (self.marquee) then |
129 |
|
Thurallor-7095 |
self:_ApplyStyles(self.marquee, style.marquee); |
130 |
|
Thurallor-7095 |
end |
131 |
|
Thurallor-7095 |
-- to do: update other styles |
132 |
|
Thurallor-7095 |
end |
133 |
|
Thurallor-7095 |
|
134 |
|
Thurallor-7095 |
function TableControl:GetStyle() |
135 |
|
Thurallor-7095 |
return self.style; |
136 |
|
Thurallor-7095 |
end |
137 |
|
Thurallor-7095 |
|
138 |
177 |
Thurallor-7095 |
function TableControl:SetOptions(options) |
139 |
|
Thurallor-7095 |
self.options = options; |
140 |
|
Thurallor-7095 |
-- to do: apply updated options |
141 |
|
Thurallor-7095 |
end |
142 |
|
Thurallor-7095 |
|
143 |
|
Thurallor-7095 |
function TableControl:GetOptions() |
144 |
|
Thurallor-7095 |
return self.options; |
145 |
|
Thurallor-7095 |
end |
146 |
|
Thurallor-7095 |
|
147 |
176 |
Thurallor-7095 |
function TableControl:GetDimensions() |
148 |
|
Thurallor-7095 |
return #self.rows:GetItemCount(), #self.columns; |
149 |
|
Thurallor-7095 |
end |
150 |
|
Thurallor-7095 |
|
151 |
|
Thurallor-7095 |
function TableControl:AddColumn(name, text, weight, sortMethod, locked) |
152 |
|
Thurallor-7095 |
if (weight == nil) then |
153 |
|
Thurallor-7095 |
weight = 1.0; |
154 |
|
Thurallor-7095 |
end |
155 |
|
Thurallor-7095 |
if (sortMethod == nil) then |
156 |
|
Thurallor-7095 |
sortMethod = self.style.column.SortMethod; |
157 |
|
Thurallor-7095 |
end |
158 |
|
Thurallor-7095 |
if (locked == nil) then |
159 |
|
Thurallor-7095 |
locked = false; |
160 |
|
Thurallor-7095 |
end |
161 |
|
Thurallor-7095 |
|
162 |
|
Thurallor-7095 |
-- Create and initialize new column object |
163 |
|
Thurallor-7095 |
local column = { |
164 |
|
Thurallor-7095 |
name = name; |
165 |
|
Thurallor-7095 |
heading = nil; |
166 |
|
Thurallor-7095 |
weight = 0; -- this gets set below |
167 |
|
Thurallor-7095 |
locked = false; -- this gets set below |
168 |
|
Thurallor-7095 |
sortMethod = sortMethod; |
169 |
|
Thurallor-7095 |
}; |
170 |
|
Thurallor-7095 |
table.insert(self.columns, column); |
171 |
|
Thurallor-7095 |
local col = #self.columns; |
172 |
|
Thurallor-7095 |
self.columnsByName[name] = col; |
173 |
|
Thurallor-7095 |
|
174 |
|
Thurallor-7095 |
-- Add a cell to each row and a heading |
175 |
|
Thurallor-7095 |
column.heading = self:_CreateHeading(col, text); |
176 |
|
Thurallor-7095 |
for row = 1, self.rows:GetItemCount() do |
177 |
|
Thurallor-7095 |
self:SetCell(row, col); |
178 |
|
Thurallor-7095 |
end |
179 |
|
Thurallor-7095 |
|
180 |
|
Thurallor-7095 |
-- Add lock icon |
181 |
|
Thurallor-7095 |
column.lockIcon = Turbine.UI.Control(); |
182 |
|
Thurallor-7095 |
column.lockIcon:SetParent(column.heading); |
183 |
|
Thurallor-7095 |
column.lockIcon:SetVisible(false); |
184 |
|
Thurallor-7095 |
column.lockIcon:SetBackground(0x41007E30); |
185 |
|
Thurallor-7095 |
column.lockIcon:SetBlendMode(Turbine.UI.BlendMode.AlphaBlend); |
186 |
|
Thurallor-7095 |
column.lockIcon:SetZOrder(1); |
187 |
|
Thurallor-7095 |
Thurallor.UI.Tooltip(L:GetText("/TableControl/HeadingMenu/UnlockColumn")):Attach(column.lockIcon); |
188 |
|
Thurallor-7095 |
column.lockIcon.MouseClick = function(_, args) |
189 |
|
Thurallor-7095 |
if (args.Button == Turbine.UI.MouseButton.Left) then |
190 |
|
Thurallor-7095 |
self:SetColumnLocked(name, false); |
191 |
|
Thurallor-7095 |
end |
192 |
|
Thurallor-7095 |
end |
193 |
|
Thurallor-7095 |
--column.lockIcon:SetBackColor(Turbine.UI.Color(0.5, 1, 0, 0)); |
194 |
|
Thurallor-7095 |
|
195 |
|
Thurallor-7095 |
-- Add lock mask control |
196 |
|
Thurallor-7095 |
column.lockMask = Turbine.UI.Control(); |
197 |
|
Thurallor-7095 |
column.lockMask:SetZOrder(3); -- in front of cells |
198 |
|
Thurallor-7095 |
--column.lockMask:SetBackColor(Turbine.UI.Color(0.5, 1, 0, 0)); |
199 |
|
Thurallor-7095 |
|
200 |
|
Thurallor-7095 |
self:SetColumnWeight(col, weight); -- also calls _UpdateColumnWidths() |
201 |
|
Thurallor-7095 |
self:SetColumnLocked(name, locked); |
202 |
|
Thurallor-7095 |
|
203 |
|
Thurallor-7095 |
return column; |
204 |
|
Thurallor-7095 |
end |
205 |
|
Thurallor-7095 |
|
206 |
|
Thurallor-7095 |
function TableControl:_CreateHeading(col, text) |
207 |
|
Thurallor-7095 |
local heading = self.style.heading.Object(); |
208 |
|
Thurallor-7095 |
self:_ApplyStyles(heading, self.style.heading); |
209 |
|
Thurallor-7095 |
heading:SetParent(self); |
210 |
|
Thurallor-7095 |
heading:SetText(text); |
211 |
|
Thurallor-7095 |
heading.col = col; |
212 |
|
Thurallor-7095 |
|
213 |
|
Thurallor-7095 |
AddCallback(heading, "MouseEnter", function() |
214 |
|
Thurallor-7095 |
heading.mouseInside = true; |
215 |
|
Thurallor-7095 |
heading:SetBackColor(self.style.heading.HighlightColor); |
216 |
|
Thurallor-7095 |
end); |
217 |
|
Thurallor-7095 |
AddCallback(heading, "MouseLeave", function() |
218 |
|
Thurallor-7095 |
heading.mouseInside = false; |
219 |
|
Thurallor-7095 |
if (not heading.mouseDown) then |
220 |
|
Thurallor-7095 |
heading:SetBackColor(self.style.heading.BackColor); |
221 |
|
Thurallor-7095 |
end |
222 |
|
Thurallor-7095 |
end); |
223 |
|
Thurallor-7095 |
AddCallback(heading, "MouseDown", function(_, args) |
224 |
|
Thurallor-7095 |
if (args.Button == Turbine.UI.MouseButton.Left) then |
225 |
|
Thurallor-7095 |
heading.mouseDown = true; |
226 |
|
Thurallor-7095 |
heading.mouseStartX = Turbine.UI.Display.GetMouseX(); |
227 |
|
Thurallor-7095 |
heading.startLeft = heading:GetLeft(); |
228 |
|
Thurallor-7095 |
end |
229 |
|
Thurallor-7095 |
end); |
230 |
|
Thurallor-7095 |
AddCallback(heading, "MouseClick", function(_, args) |
231 |
|
Thurallor-7095 |
if (args.Button == Turbine.UI.MouseButton.Left) then |
232 |
|
Thurallor-7095 |
if (heading.mouseMoved) then |
233 |
|
Thurallor-7095 |
heading.mouseMoved = false; |
234 |
|
Thurallor-7095 |
else |
235 |
|
Thurallor-7095 |
self:_SortColumn(heading.col); |
236 |
|
Thurallor-7095 |
end |
237 |
|
Thurallor-7095 |
elseif (args.Button == Turbine.UI.MouseButton.Right) then |
238 |
|
Thurallor-7095 |
self:_ShowHeadingMenu(heading.col); |
239 |
|
Thurallor-7095 |
end |
240 |
|
Thurallor-7095 |
end); |
241 |
|
Thurallor-7095 |
AddCallback(heading, "MouseMove", function(_, args) |
242 |
|
Thurallor-7095 |
if (heading.mouseDown) then |
243 |
|
Thurallor-7095 |
heading.mouseMoved = true; |
244 |
|
Thurallor-7095 |
heading:SetZOrder(1); |
245 |
|
Thurallor-7095 |
local deltaX = Turbine.UI.Display.GetMouseX() - heading.mouseStartX; |
246 |
|
Thurallor-7095 |
local left = math.min(math.max(0, heading.startLeft + deltaX), self.rowWidth - heading:GetWidth()); |
247 |
|
Thurallor-7095 |
heading:SetLeft(left); |
248 |
|
Thurallor-7095 |
deltaX = left - heading.startLeft; |
249 |
|
Thurallor-7095 |
self:_ColumnDragged(heading.col, deltaX); |
250 |
|
Thurallor-7095 |
end |
251 |
|
Thurallor-7095 |
end); |
252 |
|
Thurallor-7095 |
AddCallback(heading, "MouseUp", function(_, args) |
253 |
|
Thurallor-7095 |
if (args.Button == Turbine.UI.MouseButton.Left) then |
254 |
|
Thurallor-7095 |
heading.mouseDown = false; |
255 |
|
Thurallor-7095 |
if (heading.mouseMoved) then |
256 |
|
Thurallor-7095 |
heading:SetZOrder(0); |
257 |
|
Thurallor-7095 |
self:_UpdateColumnWidths(); |
258 |
|
Thurallor-7095 |
end |
259 |
|
Thurallor-7095 |
if (not heading.mouseInside) then |
260 |
|
Thurallor-7095 |
heading:SetBackColor(self.style.heading.BackColor); |
261 |
|
Thurallor-7095 |
end |
262 |
|
Thurallor-7095 |
end |
263 |
|
Thurallor-7095 |
end); |
264 |
177 |
Thurallor-7095 |
if (self.columns[col].sortMethod) then |
265 |
|
Thurallor-7095 |
Thurallor.UI.Tooltip(function() return L:GetText("/TableControl/HeadingMenu/SortColumn") end):Attach(heading); |
266 |
|
Thurallor-7095 |
end |
267 |
176 |
Thurallor-7095 |
|
268 |
|
Thurallor-7095 |
return heading; |
269 |
|
Thurallor-7095 |
end |
270 |
|
Thurallor-7095 |
|
271 |
|
Thurallor-7095 |
function TableControl:_ColumnDragged(col, deltaX) |
272 |
|
Thurallor-7095 |
local heading = self.columns[col].heading; |
273 |
|
Thurallor-7095 |
local leftEdge = heading:GetLeft(); |
274 |
|
Thurallor-7095 |
local rightEdge = leftEdge + heading:GetWidth(); |
275 |
|
Thurallor-7095 |
|
276 |
|
Thurallor-7095 |
local swapped = false; |
277 |
|
Thurallor-7095 |
if (deltaX < 0) then |
278 |
|
Thurallor-7095 |
-- Find visible column to the left, if any |
279 |
|
Thurallor-7095 |
for c = col - 1, 1, -1 do |
280 |
|
Thurallor-7095 |
local other = self.columns[c]; |
281 |
|
Thurallor-7095 |
if (other.weight > 0) then |
282 |
|
Thurallor-7095 |
local center = other.heading:GetLeft() + math.floor(0.5 + (other.heading:GetWidth() / 2)); |
283 |
|
Thurallor-7095 |
if (leftEdge < center) then |
284 |
|
Thurallor-7095 |
--Puts("deltaX = " .. deltaX .. "; halfWidth = " .. halfWidth .. "; hw = " .. hw); |
285 |
|
Thurallor-7095 |
--Puts("swapping left: " .. col .. ", " .. c); |
286 |
|
Thurallor-7095 |
self:_SwapColumns(col, c); |
287 |
|
Thurallor-7095 |
swapped = true; |
288 |
|
Thurallor-7095 |
break; |
289 |
|
Thurallor-7095 |
end |
290 |
|
Thurallor-7095 |
end |
291 |
|
Thurallor-7095 |
end |
292 |
|
Thurallor-7095 |
else |
293 |
|
Thurallor-7095 |
-- Find visible column to the right, if any |
294 |
|
Thurallor-7095 |
for c = col + 1, #self.columns do |
295 |
|
Thurallor-7095 |
local other = self.columns[c]; |
296 |
|
Thurallor-7095 |
if (other.weight > 0) then |
297 |
|
Thurallor-7095 |
local center = other.heading:GetLeft() + math.floor(0.5 + (other.heading:GetWidth() / 2)); |
298 |
|
Thurallor-7095 |
if (rightEdge > center) then |
299 |
|
Thurallor-7095 |
--Puts("deltaX = " .. deltaX .. "; halfWidth = " .. halfWidth .. "; hw = " .. hw); |
300 |
|
Thurallor-7095 |
--Puts("swapping right: " .. col .. ", " .. c); |
301 |
|
Thurallor-7095 |
self:_SwapColumns(col, c); |
302 |
|
Thurallor-7095 |
swapped = true; |
303 |
|
Thurallor-7095 |
break; |
304 |
|
Thurallor-7095 |
end |
305 |
|
Thurallor-7095 |
end |
306 |
|
Thurallor-7095 |
end |
307 |
|
Thurallor-7095 |
end |
308 |
|
Thurallor-7095 |
|
309 |
|
Thurallor-7095 |
--Puts("before: " .. heading:GetLeft()); |
310 |
|
Thurallor-7095 |
heading.startLeft = heading:GetLeft(); |
311 |
|
Thurallor-7095 |
heading:SetLeft(leftEdge); |
312 |
|
Thurallor-7095 |
deltaX = leftEdge - heading.startLeft; |
313 |
|
Thurallor-7095 |
heading.mouseStartX = Turbine.UI.Display:GetMouseX() - deltaX; |
314 |
|
Thurallor-7095 |
--Puts("after: " .. heading:GetLeft()); |
315 |
|
Thurallor-7095 |
end |
316 |
|
Thurallor-7095 |
|
317 |
|
Thurallor-7095 |
function TableControl:_SwapColumns(a, b) |
318 |
|
Thurallor-7095 |
local temp = self.columns[a]; |
319 |
|
Thurallor-7095 |
self.columns[a] = self.columns[b]; |
320 |
|
Thurallor-7095 |
self.columns[b] = temp; |
321 |
|
Thurallor-7095 |
|
322 |
|
Thurallor-7095 |
self.columns[a].heading.col = a; |
323 |
|
Thurallor-7095 |
self.columns[b].heading.col = b; |
324 |
|
Thurallor-7095 |
self.columnsByName[self.columns[a].name] = a; |
325 |
|
Thurallor-7095 |
self.columnsByName[self.columns[b].name] = b; |
326 |
|
Thurallor-7095 |
|
327 |
|
Thurallor-7095 |
for row = 1, self.rows:GetItemCount() do |
328 |
|
Thurallor-7095 |
local cells = self.rows:GetItem(row).cells; |
329 |
|
Thurallor-7095 |
temp = cells[a]; |
330 |
|
Thurallor-7095 |
cells[a] = cells[b]; |
331 |
|
Thurallor-7095 |
cells[b] = temp; |
332 |
|
Thurallor-7095 |
end |
333 |
|
Thurallor-7095 |
|
334 |
|
Thurallor-7095 |
-- If one of the swapped columns is sorted, update the lastSort data structure |
335 |
|
Thurallor-7095 |
if (self.lastSort) then |
336 |
|
Thurallor-7095 |
if (self.lastSort.col == a) then |
337 |
|
Thurallor-7095 |
self.lastSort.col = b; |
338 |
|
Thurallor-7095 |
self.lastSort.compare = self:_GetCompareFunction(b); |
339 |
|
Thurallor-7095 |
elseif (self.lastSort.col == b) then |
340 |
|
Thurallor-7095 |
self.lastSort.col = a; |
341 |
|
Thurallor-7095 |
self.lastSort.compare = self:_GetCompareFunction(a); |
342 |
|
Thurallor-7095 |
end |
343 |
|
Thurallor-7095 |
end |
344 |
|
Thurallor-7095 |
|
345 |
|
Thurallor-7095 |
self:_UpdateColumnWidths(); |
346 |
|
Thurallor-7095 |
self:_DoCallbacks("PresentationChanged", { Desc = "Columns swapped positions" }); |
347 |
|
Thurallor-7095 |
end |
348 |
|
Thurallor-7095 |
|
349 |
|
Thurallor-7095 |
function TableControl:_ShowHeadingMenu(col) |
350 |
|
Thurallor-7095 |
local column = self.columns[col]; |
351 |
|
Thurallor-7095 |
local contextMenu = Turbine.UI.ContextMenu(); |
352 |
|
Thurallor-7095 |
local menuItems = contextMenu:GetItems(); |
353 |
|
Thurallor-7095 |
local prevContext = L:SetContext("/TableControl/HeadingMenu"); |
354 |
|
Thurallor-7095 |
|
355 |
|
Thurallor-7095 |
if (self.totalWeight > column.weight) then |
356 |
|
Thurallor-7095 |
local hideItem = Turbine.UI.MenuItem(L:GetText("HideColumn")); |
357 |
|
Thurallor-7095 |
hideItem.Click = function() |
358 |
|
Thurallor-7095 |
self:SetColumnWeight(col, 0); |
359 |
|
Thurallor-7095 |
end |
360 |
|
Thurallor-7095 |
menuItems:Add(hideItem); |
361 |
|
Thurallor-7095 |
end |
362 |
|
Thurallor-7095 |
|
363 |
|
Thurallor-7095 |
if (#self.columns > 1) then |
364 |
|
Thurallor-7095 |
local showItem = Turbine.UI.MenuItem(L:GetText("ShowColumns")); |
365 |
|
Thurallor-7095 |
local colItems = showItem:GetItems(); |
366 |
|
Thurallor-7095 |
for c = 1, #self.columns do |
367 |
|
Thurallor-7095 |
local other = self.columns[c]; |
368 |
|
Thurallor-7095 |
local name = other.heading:GetText(); |
369 |
|
Thurallor-7095 |
local item = Turbine.UI.MenuItem(name, true, true); |
370 |
|
Thurallor-7095 |
if (other.weight > 0) then |
371 |
|
Thurallor-7095 |
item.Click = function() |
372 |
|
Thurallor-7095 |
self:SetColumnWeight(c, 0); |
373 |
|
Thurallor-7095 |
end |
374 |
|
Thurallor-7095 |
else |
375 |
|
Thurallor-7095 |
item:SetChecked(false); |
376 |
|
Thurallor-7095 |
item.Click = function() |
377 |
|
Thurallor-7095 |
self:SetColumnWeight(c, 1); |
378 |
|
Thurallor-7095 |
end |
379 |
|
Thurallor-7095 |
end |
380 |
|
Thurallor-7095 |
colItems:Add(item); |
381 |
|
Thurallor-7095 |
end |
382 |
|
Thurallor-7095 |
menuItems:Add(showItem); |
383 |
|
Thurallor-7095 |
end |
384 |
|
Thurallor-7095 |
|
385 |
|
Thurallor-7095 |
if (column.sortMethod) then |
386 |
|
Thurallor-7095 |
local sortItem = Turbine.UI.MenuItem(L:GetText("SortColumn")); |
387 |
|
Thurallor-7095 |
sortItem.Click = function() |
388 |
|
Thurallor-7095 |
self:_SortColumn(col); |
389 |
|
Thurallor-7095 |
end |
390 |
|
Thurallor-7095 |
menuItems:Add(sortItem); |
391 |
|
Thurallor-7095 |
end |
392 |
|
Thurallor-7095 |
|
393 |
177 |
Thurallor-7095 |
if (self.options.columnLockingEnabled) then |
394 |
|
Thurallor-7095 |
local lockItem = Turbine.UI.MenuItem(L:GetText("LockColumn"), true, column.locked); |
395 |
|
Thurallor-7095 |
lockItem.Click = function() |
396 |
|
Thurallor-7095 |
self:SetColumnLocked(column.name, not column.locked); |
397 |
|
Thurallor-7095 |
end |
398 |
|
Thurallor-7095 |
menuItems:Add(lockItem); |
399 |
176 |
Thurallor-7095 |
end |
400 |
|
Thurallor-7095 |
|
401 |
|
Thurallor-7095 |
contextMenu:ShowMenu(); |
402 |
|
Thurallor-7095 |
L:SetContext(prevContext); |
403 |
|
Thurallor-7095 |
end |
404 |
|
Thurallor-7095 |
|
405 |
|
Thurallor-7095 |
function TableControl:SortColumn(name, dir) |
406 |
|
Thurallor-7095 |
local col = self.columnsByName[name]; |
407 |
|
Thurallor-7095 |
local column = self.columns[col]; |
408 |
|
Thurallor-7095 |
column.sortDirection = not dir; |
409 |
|
Thurallor-7095 |
self:_SortColumn(col); |
410 |
|
Thurallor-7095 |
end |
411 |
|
Thurallor-7095 |
|
412 |
|
Thurallor-7095 |
function TableControl:_SortColumn(col) |
413 |
|
Thurallor-7095 |
local column = self.columns[col]; |
414 |
|
Thurallor-7095 |
if (not column.sortMethod) then |
415 |
|
Thurallor-7095 |
return; |
416 |
|
Thurallor-7095 |
end |
417 |
|
Thurallor-7095 |
|
418 |
|
Thurallor-7095 |
-- Show sort indication icon |
419 |
|
Thurallor-7095 |
if (not self.sortIcon) then |
420 |
|
Thurallor-7095 |
self.sortIcon = Turbine.UI.Control(); |
421 |
|
Thurallor-7095 |
self.sortIcon:SetMouseVisible(false); |
422 |
|
Thurallor-7095 |
self.sortIcon:SetSize(10, 10); |
423 |
|
Thurallor-7095 |
self.sortIcon:SetBlendMode(Turbine.UI.BlendMode.Overlay); |
424 |
|
Thurallor-7095 |
end; |
425 |
|
Thurallor-7095 |
self.sortIcon:SetParent(column.heading); |
426 |
|
Thurallor-7095 |
self.sortIcon:SetZOrder(1); |
427 |
|
Thurallor-7095 |
local inset = math.floor(0.5 + (column.heading:GetHeight() - 10) / 2); |
428 |
|
Thurallor-7095 |
self.sortIcon:SetPosition(inset, inset); |
429 |
|
Thurallor-7095 |
if (column.sortDirection) then |
430 |
|
Thurallor-7095 |
self.sortIcon:SetBackground(0x4100028E); -- â–¼ |
431 |
|
Thurallor-7095 |
else |
432 |
|
Thurallor-7095 |
self.sortIcon:SetBackground(0x4100028C); -- â–² |
433 |
|
Thurallor-7095 |
end |
434 |
|
Thurallor-7095 |
|
435 |
|
Thurallor-7095 |
-- Toggle between ascending/descending when creating the sort function |
436 |
|
Thurallor-7095 |
column.sortDirection = not column.sortDirection; |
437 |
|
Thurallor-7095 |
local compare = self:_GetCompareFunction(col); |
438 |
|
Thurallor-7095 |
self.lastSort = { col = col; compare = compare }; |
439 |
|
Thurallor-7095 |
self:_ReSort(); |
440 |
|
Thurallor-7095 |
|
441 |
|
Thurallor-7095 |
self:_DoCallbacks("PresentationChanged", { Desc = "Column sort changed" }); |
442 |
|
Thurallor-7095 |
end |
443 |
|
Thurallor-7095 |
|
444 |
|
Thurallor-7095 |
function TableControl:_GetCompareFunction(col) |
445 |
|
Thurallor-7095 |
local column = self.columns[col]; |
446 |
|
Thurallor-7095 |
if (column.sortDirection) then |
447 |
|
Thurallor-7095 |
return function(a, b) |
448 |
|
Thurallor-7095 |
-- Takes rowContainers as args, returns true or false |
449 |
|
Thurallor-7095 |
local sortResult = column.sortMethod(a.cells[col], b.cells[col]); |
450 |
|
Thurallor-7095 |
if (sortResult == 0) then |
451 |
|
Thurallor-7095 |
-- Make the sorting "stable" to allow sorting by multiple columns in sequence |
452 |
|
Thurallor-7095 |
return a.idx > b.idx; |
453 |
|
Thurallor-7095 |
else |
454 |
|
Thurallor-7095 |
return (sortResult > 0); |
455 |
|
Thurallor-7095 |
end |
456 |
|
Thurallor-7095 |
end |
457 |
|
Thurallor-7095 |
else |
458 |
|
Thurallor-7095 |
return function(a, b) |
459 |
|
Thurallor-7095 |
-- Takes rowContainers as args, returns true or false |
460 |
|
Thurallor-7095 |
local sortResult = column.sortMethod(b.cells[col], a.cells[col]); |
461 |
|
Thurallor-7095 |
if (sortResult == 0) then |
462 |
|
Thurallor-7095 |
-- Make the sorting "stable" to allow sorting by multiple columns in sequence |
463 |
|
Thurallor-7095 |
return a.idx > b.idx; |
464 |
|
Thurallor-7095 |
else |
465 |
|
Thurallor-7095 |
return (sortResult > 0); |
466 |
|
Thurallor-7095 |
end |
467 |
|
Thurallor-7095 |
end |
468 |
|
Thurallor-7095 |
end |
469 |
|
Thurallor-7095 |
end |
470 |
|
Thurallor-7095 |
|
471 |
|
Thurallor-7095 |
function TableControl:_CreateCell(row, col) |
472 |
|
Thurallor-7095 |
local rowContainer = self.rows:GetItem(row); |
473 |
|
Thurallor-7095 |
local cell = self.style.cell.Object(); |
474 |
|
Thurallor-7095 |
self:_ApplyStyles(cell, self.style.cell); |
475 |
|
Thurallor-7095 |
return cell; |
476 |
|
Thurallor-7095 |
end |
477 |
|
Thurallor-7095 |
|
478 |
|
Thurallor-7095 |
function TableControl:_CreateEdgeMovers() |
479 |
|
Thurallor-7095 |
-- Destroy previous objects |
480 |
|
Thurallor-7095 |
for edge = 1, #self.edgeMovers do |
481 |
|
Thurallor-7095 |
self.edgeMovers[edge]:SetParent(nil); |
482 |
|
Thurallor-7095 |
end |
483 |
|
Thurallor-7095 |
self.edgeMovers = {}; |
484 |
|
Thurallor-7095 |
|
485 |
|
Thurallor-7095 |
-- Only show an EdgeMover between two visible (weight > 0) columns. |
486 |
|
Thurallor-7095 |
local prev = nil; |
487 |
|
Thurallor-7095 |
for col = 1, #self.columns do |
488 |
|
Thurallor-7095 |
if (self.columns[col].weight > 0) then |
489 |
|
Thurallor-7095 |
if (prev) then |
490 |
|
Thurallor-7095 |
-- Found a pair of visible columns. |
491 |
|
Thurallor-7095 |
local edgeMover = Thurallor.UI.EdgeMover(Turbine.UI.Orientation.Vertical); |
492 |
|
Thurallor-7095 |
edgeMover.leftColumn = prev; |
493 |
|
Thurallor-7095 |
edgeMover.rightColumn = col; |
494 |
|
Thurallor-7095 |
edgeMover:SetParent(self); |
495 |
|
Thurallor-7095 |
edgeMover:SetZOrder(1); -- in front of rows |
496 |
|
Thurallor-7095 |
self:_ApplyStyles(edgeMover, self.style.edgeMover); |
497 |
|
Thurallor-7095 |
AddCallback(edgeMover, "EdgeMoved", function() |
498 |
|
Thurallor-7095 |
self:_EdgeMoved(edgeMover); |
499 |
|
Thurallor-7095 |
end); |
500 |
|
Thurallor-7095 |
AddCallback(edgeMover, "MouseUp", function() |
501 |
|
Thurallor-7095 |
-- EdgeMover may set a column weight to zero; if so, disable the column's EdgeMover. |
502 |
|
Thurallor-7095 |
self:_CreateEdgeMovers(); |
503 |
|
Thurallor-7095 |
end); |
504 |
|
Thurallor-7095 |
table.insert(self.edgeMovers, edgeMover); |
505 |
|
Thurallor-7095 |
end |
506 |
|
Thurallor-7095 |
prev = col; |
507 |
|
Thurallor-7095 |
end |
508 |
|
Thurallor-7095 |
end |
509 |
|
Thurallor-7095 |
self:_PlaceEdgeMovers(); |
510 |
|
Thurallor-7095 |
self:_DoCallbacks("PresentationChanged", { Desc = "Column weight(s) changed" }); |
511 |
|
Thurallor-7095 |
end |
512 |
|
Thurallor-7095 |
|
513 |
|
Thurallor-7095 |
function TableControl:_EdgeMoved(edgeMover) |
514 |
|
Thurallor-7095 |
local x, y = self:GetMousePosition(); |
515 |
|
Thurallor-7095 |
local minWidth = self.style.minimumColumnWidth; |
516 |
|
Thurallor-7095 |
|
517 |
|
Thurallor-7095 |
local leftCol = self.columns[edgeMover.leftColumn]; |
518 |
|
Thurallor-7095 |
local leftHeading = leftCol.heading; |
519 |
|
Thurallor-7095 |
x = math.max(x, leftHeading:GetLeft() + minWidth); |
520 |
|
Thurallor-7095 |
|
521 |
|
Thurallor-7095 |
local rightCol = self.columns[edgeMover.rightColumn]; |
522 |
|
Thurallor-7095 |
local rightHeading = rightCol.heading; |
523 |
|
Thurallor-7095 |
x = math.min(x, rightHeading:GetLeft() + rightHeading:GetWidth() - minWidth); |
524 |
|
Thurallor-7095 |
|
525 |
|
Thurallor-7095 |
local leftWidth = x - leftHeading:GetLeft(); |
526 |
|
Thurallor-7095 |
local rightWidth = rightHeading:GetLeft() + rightHeading:GetWidth() - x; |
527 |
|
Thurallor-7095 |
local bothWidth = leftWidth + rightWidth; |
528 |
|
Thurallor-7095 |
local bothWeight = leftCol.weight + rightCol.weight; |
529 |
|
Thurallor-7095 |
|
530 |
|
Thurallor-7095 |
leftCol.weight = bothWeight * (leftWidth / bothWidth); |
531 |
|
Thurallor-7095 |
rightCol.weight = bothWeight * (rightWidth / bothWidth); |
532 |
|
Thurallor-7095 |
|
533 |
|
Thurallor-7095 |
self:_UpdateColumnWidths(); |
534 |
|
Thurallor-7095 |
end |
535 |
|
Thurallor-7095 |
|
536 |
|
Thurallor-7095 |
function TableControl:_DoCallbacks(event, args) |
537 |
|
Thurallor-7095 |
if (not self.callbacksDisabled) then |
538 |
|
Thurallor-7095 |
DoCallbacks(self, event, args); |
539 |
|
Thurallor-7095 |
end |
540 |
|
Thurallor-7095 |
end |
541 |
|
Thurallor-7095 |
|
542 |
|
Thurallor-7095 |
function TableControl:GetColumnWeight(colName) |
543 |
|
Thurallor-7095 |
local col = self.columnsByName[colName]; |
544 |
|
Thurallor-7095 |
if (not col) then |
545 |
|
Thurallor-7095 |
error("no such column: " .. colName, 2); |
546 |
|
Thurallor-7095 |
end |
547 |
|
Thurallor-7095 |
local column = self.columns[col]; |
548 |
|
Thurallor-7095 |
return column.weight; |
549 |
|
Thurallor-7095 |
end |
550 |
|
Thurallor-7095 |
|
551 |
|
Thurallor-7095 |
function TableControl:SetColumnWeight(col, weight) |
552 |
|
Thurallor-7095 |
local column = self.columns[col]; |
553 |
|
Thurallor-7095 |
local prevWeight = column.weight; |
554 |
|
Thurallor-7095 |
self.totalWeight = self.totalWeight - prevWeight + weight; |
555 |
|
Thurallor-7095 |
column.weight = weight; |
556 |
|
Thurallor-7095 |
if ((weight == 0) and (prevWeight > 0)) then |
557 |
|
Thurallor-7095 |
column.heading:SetParent(nil); |
558 |
|
Thurallor-7095 |
for row = 1, self.rows:GetItemCount() do |
559 |
|
Thurallor-7095 |
local rowContainer = self.rows:GetItem(row); |
560 |
|
Thurallor-7095 |
rowContainer.cells[col]:SetParent(nil); |
561 |
|
Thurallor-7095 |
end |
562 |
|
Thurallor-7095 |
self:_CreateEdgeMovers(); |
563 |
|
Thurallor-7095 |
elseif ((weight > 0) and (prevWeight == 0)) then |
564 |
|
Thurallor-7095 |
column.heading:SetParent(self); |
565 |
|
Thurallor-7095 |
for row = 1, self.rows:GetItemCount() do |
566 |
|
Thurallor-7095 |
local rowContainer = self.rows:GetItem(row); |
567 |
|
Thurallor-7095 |
rowContainer.cells[col]:SetParent(rowContainer); |
568 |
|
Thurallor-7095 |
end |
569 |
|
Thurallor-7095 |
self:_CreateEdgeMovers(); |
570 |
|
Thurallor-7095 |
end |
571 |
|
Thurallor-7095 |
self:_UpdateColumnWidths(); |
572 |
|
Thurallor-7095 |
column.prevWeight = prevWeight; |
573 |
|
Thurallor-7095 |
end |
574 |
|
Thurallor-7095 |
|
575 |
|
Thurallor-7095 |
-- "Presentation" includes (so far) |
576 |
|
Thurallor-7095 |
-- - the user's choices of column weights, visibility and ordering |
577 |
|
Thurallor-7095 |
-- - the sorted column and direction |
578 |
|
Thurallor-7095 |
function TableControl:GetPresentation() |
579 |
|
Thurallor-7095 |
local columns = {}; |
580 |
|
Thurallor-7095 |
for col = 1, #self.columns do |
581 |
|
Thurallor-7095 |
local column = self.columns[col]; |
582 |
|
Thurallor-7095 |
table.insert(columns, { column.name, column.weight, column.locked }); |
583 |
|
Thurallor-7095 |
end |
584 |
|
Thurallor-7095 |
|
585 |
|
Thurallor-7095 |
local presentation = {}; |
586 |
|
Thurallor-7095 |
presentation.columns = columns; |
587 |
|
Thurallor-7095 |
if (self.lastSort) then |
588 |
|
Thurallor-7095 |
local column = self.columns[self.lastSort.col]; |
589 |
|
Thurallor-7095 |
presentation.sort = { column = column.name; dir = column.sortDirection }; |
590 |
|
Thurallor-7095 |
end |
591 |
|
Thurallor-7095 |
|
592 |
|
Thurallor-7095 |
return presentation; |
593 |
|
Thurallor-7095 |
end |
594 |
|
Thurallor-7095 |
|
595 |
|
Thurallor-7095 |
function TableControl:SetPresentation(presentation) |
596 |
|
Thurallor-7095 |
|
597 |
|
Thurallor-7095 |
-- Make a local copy of presentation, so we can modify it. Remove any columns |
598 |
|
Thurallor-7095 |
-- from it that don't exist in the table. |
599 |
|
Thurallor-7095 |
local temp = {}; |
600 |
|
Thurallor-7095 |
for n, colInfo in ipairs(presentation.columns) do |
601 |
|
Thurallor-7095 |
local name, weight, locked = unpack(colInfo); |
602 |
|
Thurallor-7095 |
if (self.columnsByName[name]) then |
603 |
|
Thurallor-7095 |
table.insert(temp, { name, weight, locked }); |
604 |
|
Thurallor-7095 |
end |
605 |
|
Thurallor-7095 |
end |
606 |
|
Thurallor-7095 |
presentation.columns = temp; |
607 |
|
Thurallor-7095 |
|
608 |
|
Thurallor-7095 |
-- Get column weights from presentation |
609 |
|
Thurallor-7095 |
local foundColumns = {}; |
610 |
|
Thurallor-7095 |
for col = 1, #presentation.columns do |
611 |
|
Thurallor-7095 |
local name, weight = unpack(presentation.columns[col]); |
612 |
|
Thurallor-7095 |
foundColumns[name] = weight; |
613 |
|
Thurallor-7095 |
end |
614 |
|
Thurallor-7095 |
|
615 |
|
Thurallor-7095 |
-- Handle columns that aren't specified in the presentation |
616 |
|
Thurallor-7095 |
-- Set their weight to 0. |
617 |
|
Thurallor-7095 |
for name, col in pairs(self.columnsByName) do |
618 |
|
Thurallor-7095 |
if (foundColumns[name] == nil) then |
619 |
|
Thurallor-7095 |
foundColumns[name] = true; |
620 |
|
Thurallor-7095 |
table.insert(presentation.columns, { name, 0 }); |
621 |
|
Thurallor-7095 |
end |
622 |
|
Thurallor-7095 |
end |
623 |
|
Thurallor-7095 |
|
624 |
|
Thurallor-7095 |
-- Create a new cell list in each rowContainer |
625 |
|
Thurallor-7095 |
for row = 1, self.rows:GetItemCount() do |
626 |
|
Thurallor-7095 |
self.rows:GetItem(row).newCells = {}; |
627 |
|
Thurallor-7095 |
end |
628 |
|
Thurallor-7095 |
|
629 |
|
Thurallor-7095 |
-- Apply the new ordering and weights (and locks) to the columns |
630 |
|
Thurallor-7095 |
local oldColumns = self.columns; |
631 |
|
Thurallor-7095 |
self.columns = {}; |
632 |
|
Thurallor-7095 |
self.totalWeight = 0; |
633 |
|
Thurallor-7095 |
for col = 1, #presentation.columns do |
634 |
|
Thurallor-7095 |
local name, weight, locked = unpack(presentation.columns[col]); |
635 |
|
Thurallor-7095 |
local oldCol = self.columnsByName[name]; |
636 |
|
Thurallor-7095 |
local column = oldColumns[oldCol]; |
637 |
|
Thurallor-7095 |
self.totalWeight = self.totalWeight + weight; |
638 |
|
Thurallor-7095 |
column.weight = weight; |
639 |
|
Thurallor-7095 |
if (locked ~= nil) then |
640 |
|
Thurallor-7095 |
column.locked = locked; |
641 |
|
Thurallor-7095 |
end |
642 |
|
Thurallor-7095 |
column.heading.col = col; |
643 |
|
Thurallor-7095 |
column.heading:SetParent((weight > 0) and self or nil); |
644 |
|
Thurallor-7095 |
self.columnsByName[name] = col; |
645 |
|
Thurallor-7095 |
table.insert(self.columns, column); |
646 |
|
Thurallor-7095 |
for row = 1, self.rows:GetItemCount() do |
647 |
|
Thurallor-7095 |
local rowContainer = self.rows:GetItem(row); |
648 |
|
Thurallor-7095 |
local cell = rowContainer.cells[oldCol]; |
649 |
|
Thurallor-7095 |
rowContainer.newCells[col] = cell; |
650 |
|
Thurallor-7095 |
cell:SetParent((weight > 0) and rowContainer or nil); |
651 |
|
Thurallor-7095 |
end |
652 |
|
Thurallor-7095 |
end |
653 |
|
Thurallor-7095 |
|
654 |
|
Thurallor-7095 |
-- Start using the new cell list in each rowContainer |
655 |
|
Thurallor-7095 |
for row = 1, self.rows:GetItemCount() do |
656 |
|
Thurallor-7095 |
local rowContainer = self.rows:GetItem(row); |
657 |
|
Thurallor-7095 |
rowContainer.cells = rowContainer.newCells; |
658 |
|
Thurallor-7095 |
rowContainer.newCells = {}; |
659 |
|
Thurallor-7095 |
end |
660 |
|
Thurallor-7095 |
|
661 |
|
Thurallor-7095 |
-- Move the cells into their new positions |
662 |
|
Thurallor-7095 |
self:_CreateEdgeMovers(); |
663 |
|
Thurallor-7095 |
self:_UpdateColumnWidths(); |
664 |
|
Thurallor-7095 |
|
665 |
|
Thurallor-7095 |
-- Apply the sort (if any) |
666 |
|
Thurallor-7095 |
if (presentation.sort) then |
667 |
|
Thurallor-7095 |
local col = self.columnsByName[presentation.sort.column]; |
668 |
|
Thurallor-7095 |
local column = self.columns[col]; |
669 |
|
Thurallor-7095 |
if (column) then |
670 |
|
Thurallor-7095 |
column.sortDirection = not presentation.sort.dir; |
671 |
|
Thurallor-7095 |
self:_SortColumn(col); |
672 |
|
Thurallor-7095 |
end |
673 |
|
Thurallor-7095 |
end |
674 |
|
Thurallor-7095 |
|
675 |
|
Thurallor-7095 |
-- Apply the locks |
676 |
|
Thurallor-7095 |
for col = 1, #self.columns do |
677 |
|
Thurallor-7095 |
local column = self.columns[col]; |
678 |
|
Thurallor-7095 |
self:SetColumnLocked(column.name, column.locked); |
679 |
|
Thurallor-7095 |
end |
680 |
|
Thurallor-7095 |
end |
681 |
|
Thurallor-7095 |
|
682 |
|
Thurallor-7095 |
function TableControl:GetRow(name) |
683 |
|
Thurallor-7095 |
return self.rowsByName[name]; |
684 |
|
Thurallor-7095 |
end |
685 |
|
Thurallor-7095 |
|
686 |
|
Thurallor-7095 |
function TableControl:_GetToolTip(rowContainer) |
687 |
|
Thurallor-7095 |
local function AddLabel(parent, top, prevMaxWidth, text, align) |
688 |
|
Thurallor-7095 |
local label = Turbine.UI.Label(); |
689 |
|
Thurallor-7095 |
label:SetTextAlignment(align); |
690 |
|
Thurallor-7095 |
self:_ApplyStyles(label, self.style.toolTip); |
691 |
|
Thurallor-7095 |
label:SetBackColor(nil); |
692 |
|
Thurallor-7095 |
label:SetText(text); |
693 |
|
Thurallor-7095 |
label:AutoSize(); |
694 |
|
Thurallor-7095 |
label:SetParent(parent); |
695 |
|
Thurallor-7095 |
label:SetTop(top); |
696 |
|
Thurallor-7095 |
AddCallback(parent, "SizeChanged", function() label:SetWidth(parent:GetWidth()) end); |
697 |
|
Thurallor-7095 |
return top + label:GetHeight(), math.max(prevMaxWidth, label:GetWidth()); |
698 |
|
Thurallor-7095 |
end |
699 |
|
Thurallor-7095 |
|
700 |
|
Thurallor-7095 |
local toolTip = Turbine.UI.Control(); |
701 |
|
Thurallor-7095 |
local colNames = Turbine.UI.Control(); |
702 |
|
Thurallor-7095 |
local cellValues = Turbine.UI.Control(); |
703 |
|
Thurallor-7095 |
colNames:SetParent(toolTip); |
704 |
|
Thurallor-7095 |
cellValues:SetParent(toolTip); |
705 |
|
Thurallor-7095 |
|
706 |
|
Thurallor-7095 |
local colNamesWidth = 0; |
707 |
|
Thurallor-7095 |
local cellValuesWidth = 0; |
708 |
|
Thurallor-7095 |
local top = 0; |
709 |
|
Thurallor-7095 |
for c = 1, #self.columns do |
710 |
|
Thurallor-7095 |
local column = self.columns[c]; |
711 |
|
Thurallor-7095 |
local colName = column.heading:GetText() .. ": "; |
712 |
|
Thurallor-7095 |
local cell = rowContainer.cells[c]; |
713 |
|
Thurallor-7095 |
local cellValue = (cell.GetText and cell:GetText() and (cell:GetText() ~= "") and tostring(cell:GetText())); |
714 |
|
Thurallor-7095 |
if (cellValue) then |
715 |
|
Thurallor-7095 |
_, colNamesWidth = AddLabel(colNames, top, colNamesWidth, colName, Turbine.UI.ContentAlignment.MiddleRight); |
716 |
|
Thurallor-7095 |
top, cellValuesWidth = AddLabel(cellValues, top, cellValuesWidth, cellValue, Turbine.UI.ContentAlignment.MiddleLeft); |
717 |
|
Thurallor-7095 |
end |
718 |
|
Thurallor-7095 |
end |
719 |
|
Thurallor-7095 |
|
720 |
|
Thurallor-7095 |
colNames:SetSize(colNamesWidth, top); |
721 |
|
Thurallor-7095 |
colNames:SetPosition(0, 3); |
722 |
|
Thurallor-7095 |
cellValues:SetSize(cellValuesWidth, top); |
723 |
|
Thurallor-7095 |
cellValues:SetPosition(colNamesWidth, 3); |
724 |
|
Thurallor-7095 |
self:_ApplyStyles(toolTip, self.style.toolTip); |
725 |
|
Thurallor-7095 |
toolTip:SetSize(colNamesWidth + cellValuesWidth, top + 6); |
726 |
|
Thurallor-7095 |
|
727 |
|
Thurallor-7095 |
return toolTip; |
728 |
|
Thurallor-7095 |
end |
729 |
|
Thurallor-7095 |
|
730 |
|
Thurallor-7095 |
function TableControl:AddRow(name, moreRows) |
731 |
|
Thurallor-7095 |
local rowContainer = Turbine.UI.Control(); |
732 |
|
Thurallor-7095 |
rowContainer.idx = math.huge; |
733 |
|
Thurallor-7095 |
rowContainer:SetWidth(self.rowWidth); |
734 |
|
Thurallor-7095 |
rowContainer.name = name; |
735 |
|
Thurallor-7095 |
rowContainer.cells = {}; |
736 |
|
Thurallor-7095 |
self.rows:AddItem(rowContainer); |
737 |
|
Thurallor-7095 |
self.rowsByName[name] = rowContainer; |
738 |
|
Thurallor-7095 |
local row = self.rows:GetItemCount(); |
739 |
|
Thurallor-7095 |
|
740 |
|
Thurallor-7095 |
-- Add new cells |
741 |
|
Thurallor-7095 |
self:SetRowVisible(row, false); |
742 |
|
Thurallor-7095 |
for col = 1, #self.columns do |
743 |
|
Thurallor-7095 |
self:SetCell(row, col); |
744 |
|
Thurallor-7095 |
end |
745 |
177 |
Thurallor-7095 |
|
746 |
176 |
Thurallor-7095 |
-- Add mask overlay. We want the user to have to select the row before clicking again |
747 |
|
Thurallor-7095 |
-- on a particular cell to edit it. |
748 |
|
Thurallor-7095 |
local mask = Turbine.UI.Control(); |
749 |
|
Thurallor-7095 |
mask:SetParent(rowContainer); |
750 |
|
Thurallor-7095 |
mask:SetSize(rowContainer:GetSize()); |
751 |
|
Thurallor-7095 |
--mask:SetBackColor(Turbine.UI.Color(0.25, 1, 0, 0)); |
752 |
|
Thurallor-7095 |
--mask:SetBackColorBlendMode(Turbine.UI.BlendMode.Overlay); |
753 |
|
Thurallor-7095 |
mask:SetZOrder(3); -- in front of cells |
754 |
|
Thurallor-7095 |
rowContainer.mask = mask; |
755 |
|
Thurallor-7095 |
|
756 |
|
Thurallor-7095 |
-- Add event behaviors |
757 |
|
Thurallor-7095 |
rowContainer.PositionChanged = function(ctl) |
758 |
|
Thurallor-7095 |
if ((self.selectedRow == ctl) and self.marquee) then |
759 |
|
Thurallor-7095 |
self.marquee:SetPosition(ctl:GetPosition()); |
760 |
|
Thurallor-7095 |
end |
761 |
|
Thurallor-7095 |
end |
762 |
|
Thurallor-7095 |
rowContainer.SizeChanged = function(ctl) |
763 |
|
Thurallor-7095 |
ctl.mask:SetSize(ctl:GetSize()); |
764 |
|
Thurallor-7095 |
if ((self.selectedRow == ctl) and self.marquee) then |
765 |
|
Thurallor-7095 |
self.marquee:SetSize(ctl:GetSize()); |
766 |
|
Thurallor-7095 |
end |
767 |
|
Thurallor-7095 |
end |
768 |
|
Thurallor-7095 |
mask.MouseEnter = function() |
769 |
|
Thurallor-7095 |
for c = 1, #self.columns do |
770 |
|
Thurallor-7095 |
rowContainer.cells[c]:SetBackColor(self.style.cell.HighlightColor); |
771 |
|
Thurallor-7095 |
end |
772 |
|
Thurallor-7095 |
end |
773 |
|
Thurallor-7095 |
mask.MouseLeave = function() |
774 |
|
Thurallor-7095 |
for c = 1, #self.columns do |
775 |
|
Thurallor-7095 |
rowContainer.cells[c]:SetBackColor(self.style.cell.BackColor); |
776 |
|
Thurallor-7095 |
end |
777 |
|
Thurallor-7095 |
end |
778 |
|
Thurallor-7095 |
mask.MouseClick = function(_, args) |
779 |
|
Thurallor-7095 |
if (args.Button == Turbine.UI.MouseButton.Right) then |
780 |
|
Thurallor-7095 |
DoCallbacks(rowContainer, "ContextMenu"); |
781 |
|
Thurallor-7095 |
elseif (args.Button == Turbine.UI.MouseButton.Left) then |
782 |
|
Thurallor-7095 |
-- The ListBox control didn't steal the left-mouse click, because the |
783 |
|
Thurallor-7095 |
-- user clicked the already-selected item. *facepalm* |
784 |
|
Thurallor-7095 |
DoCallbacks(self.rows, "SelectedIndexChanged"); |
785 |
|
Thurallor-7095 |
end |
786 |
|
Thurallor-7095 |
end |
787 |
|
Thurallor-7095 |
Thurallor.UI.Tooltip(function() return self:_GetToolTip(rowContainer) end):Attach(mask); |
788 |
|
Thurallor-7095 |
|
789 |
|
Thurallor-7095 |
self:_UpdateLastRow(); -- also calls SetRowVisible(row, true) |
790 |
|
Thurallor-7095 |
|
791 |
|
Thurallor-7095 |
-- Table needs to be resorted, if enabled |
792 |
|
Thurallor-7095 |
if ((not moreRows) and self.lastSort) then |
793 |
|
Thurallor-7095 |
self:ReSort(); |
794 |
|
Thurallor-7095 |
-- if not auto-sorting, then hide the sort icon |
795 |
|
Thurallor-7095 |
end |
796 |
|
Thurallor-7095 |
|
797 |
|
Thurallor-7095 |
-- Return a table of cells indexed by column name |
798 |
|
Thurallor-7095 |
local cells = {}; |
799 |
|
Thurallor-7095 |
for c = 1, #self.columns do |
800 |
|
Thurallor-7095 |
local colName = self.columns[c].name; |
801 |
|
Thurallor-7095 |
cells[colName] = rowContainer.cells[c]; |
802 |
|
Thurallor-7095 |
end |
803 |
177 |
Thurallor-7095 |
|
804 |
|
Thurallor-7095 |
return rowContainer, cells, row; |
805 |
176 |
Thurallor-7095 |
end |
806 |
|
Thurallor-7095 |
|
807 |
|
Thurallor-7095 |
function TableControl:ReSort(now) |
808 |
|
Thurallor-7095 |
if (self.lastSort) then |
809 |
|
Thurallor-7095 |
self.lastSort.sorted = false; |
810 |
|
Thurallor-7095 |
if (now) then |
811 |
|
Thurallor-7095 |
self:_ReSort(); |
812 |
|
Thurallor-7095 |
else |
813 |
|
Thurallor-7095 |
self:SetWantsUpdates(true); |
814 |
|
Thurallor-7095 |
end |
815 |
|
Thurallor-7095 |
end |
816 |
|
Thurallor-7095 |
end |
817 |
|
Thurallor-7095 |
|
818 |
|
Thurallor-7095 |
function TableControl:Update() |
819 |
|
Thurallor-7095 |
self:_ReSort(); |
820 |
|
Thurallor-7095 |
self:SetWantsUpdates(false); |
821 |
|
Thurallor-7095 |
end |
822 |
|
Thurallor-7095 |
|
823 |
|
Thurallor-7095 |
-- Reapply the most recent sort |
824 |
|
Thurallor-7095 |
function TableControl:_ReSort() |
825 |
|
Thurallor-7095 |
if (self.lastSort) then |
826 |
|
Thurallor-7095 |
local rows = self.rows; |
827 |
|
Thurallor-7095 |
rows:Sort(self.lastSort.compare); |
828 |
|
Thurallor-7095 |
for idx = 1, rows:GetItemCount() do |
829 |
|
Thurallor-7095 |
local row = rows:GetItem(idx); |
830 |
|
Thurallor-7095 |
row.idx = idx; |
831 |
|
Thurallor-7095 |
end |
832 |
|
Thurallor-7095 |
self.lastSort.sorted = true; |
833 |
|
Thurallor-7095 |
self:_UpdateLastRow(); |
834 |
|
Thurallor-7095 |
end |
835 |
|
Thurallor-7095 |
end |
836 |
|
Thurallor-7095 |
|
837 |
|
Thurallor-7095 |
-- Can specify colName or nil; returns column name of sorted column or nil |
838 |
|
Thurallor-7095 |
function TableControl:IsSorted(colName) |
839 |
|
Thurallor-7095 |
if ((self.lastSort) and (self.lastSort.sorted)) then |
840 |
|
Thurallor-7095 |
local sortedCol = self.columns[self.lastSort.col]; |
841 |
|
Thurallor-7095 |
if (not colName) then |
842 |
|
Thurallor-7095 |
return sortedCol.name; |
843 |
|
Thurallor-7095 |
else |
844 |
|
Thurallor-7095 |
if (self.lastSort.col == self.columnsByName[colName]) then |
845 |
|
Thurallor-7095 |
return colName; |
846 |
|
Thurallor-7095 |
end |
847 |
|
Thurallor-7095 |
end |
848 |
|
Thurallor-7095 |
end |
849 |
|
Thurallor-7095 |
end |
850 |
|
Thurallor-7095 |
|
851 |
|
Thurallor-7095 |
function TableControl:IsColumnLocked(colName) |
852 |
|
Thurallor-7095 |
if (colName) then |
853 |
|
Thurallor-7095 |
local col = self.columnsByName[colName]; |
854 |
|
Thurallor-7095 |
if (col) then |
855 |
|
Thurallor-7095 |
return self.columns[col].locked; |
856 |
|
Thurallor-7095 |
end |
857 |
|
Thurallor-7095 |
end |
858 |
|
Thurallor-7095 |
end |
859 |
|
Thurallor-7095 |
|
860 |
|
Thurallor-7095 |
function TableControl:SetColumnLocked(colName, locked) |
861 |
177 |
Thurallor-7095 |
if (colName and self.options.columnLockingEnabled) then |
862 |
176 |
Thurallor-7095 |
local col = self.columnsByName[colName]; |
863 |
|
Thurallor-7095 |
if (col) then |
864 |
|
Thurallor-7095 |
local column = self.columns[col]; |
865 |
|
Thurallor-7095 |
local changed = (column.locked ~= locked); |
866 |
|
Thurallor-7095 |
column.locked = locked; |
867 |
|
Thurallor-7095 |
column.lockIcon:SetVisible(locked); |
868 |
|
Thurallor-7095 |
self:_PlaceColumnLockMasks(); |
869 |
|
Thurallor-7095 |
if (changed) then |
870 |
|
Thurallor-7095 |
DoCallbacks(self, "PresentationChanged", { Desc = "Column " .. (locked and "locked" or "unlocked") }); |
871 |
|
Thurallor-7095 |
end |
872 |
|
Thurallor-7095 |
end |
873 |
|
Thurallor-7095 |
end |
874 |
|
Thurallor-7095 |
end |
875 |
|
Thurallor-7095 |
|
876 |
|
Thurallor-7095 |
function TableControl:SelectRow(rowName) |
877 |
|
Thurallor-7095 |
if (rowName) then |
878 |
|
Thurallor-7095 |
self:_SelectRow(self.rowsByName[rowName]); |
879 |
|
Thurallor-7095 |
else |
880 |
|
Thurallor-7095 |
self:_SelectRow(nil); |
881 |
|
Thurallor-7095 |
end |
882 |
|
Thurallor-7095 |
end |
883 |
|
Thurallor-7095 |
|
884 |
|
Thurallor-7095 |
function TableControl:_SelectRow(rowContainer) |
885 |
|
Thurallor-7095 |
local oldSelectedRow = self.selectedRow; |
886 |
|
Thurallor-7095 |
self.selectedRow = rowContainer; |
887 |
|
Thurallor-7095 |
|
888 |
|
Thurallor-7095 |
-- Re-enable mask on previous row |
889 |
|
Thurallor-7095 |
if (oldSelectedRow) then |
890 |
|
Thurallor-7095 |
oldSelectedRow.mask:SetMouseVisible(true); |
891 |
|
Thurallor-7095 |
end |
892 |
|
Thurallor-7095 |
|
893 |
|
Thurallor-7095 |
-- Remove old marquee, if any |
894 |
|
Thurallor-7095 |
if (self.marquee) then |
895 |
|
Thurallor-7095 |
self.marquee:SetParent(nil); |
896 |
|
Thurallor-7095 |
self.marquee = nil; |
897 |
|
Thurallor-7095 |
end |
898 |
|
Thurallor-7095 |
|
899 |
|
Thurallor-7095 |
if (rowContainer) then |
900 |
|
Thurallor-7095 |
rowContainer:Focus(); |
901 |
|
Thurallor-7095 |
|
902 |
|
Thurallor-7095 |
-- Create new marquee and attach it |
903 |
|
Thurallor-7095 |
self.marquee = Thurallor.UI.Marquee(); |
904 |
|
Thurallor-7095 |
self:_ApplyStyles(self.marquee, self.style.marquee); |
905 |
|
Thurallor-7095 |
local height = 0; |
906 |
|
Thurallor-7095 |
for _, cell in pairs(rowContainer.cells) do |
907 |
|
Thurallor-7095 |
height = math.max(height, cell:GetHeight()); |
908 |
|
Thurallor-7095 |
end |
909 |
|
Thurallor-7095 |
self.marquee:SetPosition(rowContainer:GetPosition()); |
910 |
|
Thurallor-7095 |
self.marquee:SetSize(rowContainer:GetWidth(), height); |
911 |
|
Thurallor-7095 |
self.marquee:SetParent(self.rows); |
912 |
|
Thurallor-7095 |
|
913 |
|
Thurallor-7095 |
-- Disable mask to allow mouse clicks to reach the cells |
914 |
|
Thurallor-7095 |
rowContainer.mask:SetMouseVisible(false); |
915 |
|
Thurallor-7095 |
|
916 |
|
Thurallor-7095 |
-- Unless they're locked; then we still need to intercept mouse clicks |
917 |
|
Thurallor-7095 |
self:_PlaceColumnLockMasks(); |
918 |
|
Thurallor-7095 |
else |
919 |
|
Thurallor-7095 |
self.rows:Focus(); |
920 |
|
Thurallor-7095 |
end |
921 |
|
Thurallor-7095 |
|
922 |
|
Thurallor-7095 |
local oldName = (oldSelectedRow and oldSelectedRow.name) or nil; |
923 |
|
Thurallor-7095 |
local newName = (rowContainer and rowContainer.name) or nil; |
924 |
|
Thurallor-7095 |
self:_DoCallbacks("SelectionChanged", { New = newName; Old = oldName }); |
925 |
|
Thurallor-7095 |
end |
926 |
|
Thurallor-7095 |
|
927 |
|
Thurallor-7095 |
function TableControl:Deselect() |
928 |
|
Thurallor-7095 |
self:_SelectRow(nil); |
929 |
|
Thurallor-7095 |
end |
930 |
|
Thurallor-7095 |
|
931 |
|
Thurallor-7095 |
function TableControl:InsertRows(beforeRow, numNewRows) |
932 |
|
Thurallor-7095 |
end |
933 |
|
Thurallor-7095 |
|
934 |
|
Thurallor-7095 |
function TableControl:RowIsVisible(row) |
935 |
|
Thurallor-7095 |
return (self.rows:GetItem(row):GetHeight() > 0); |
936 |
|
Thurallor-7095 |
end |
937 |
|
Thurallor-7095 |
|
938 |
|
Thurallor-7095 |
function TableControl:EnsureVisible(rowName) |
939 |
|
Thurallor-7095 |
if (rowName) then |
940 |
|
Thurallor-7095 |
-- local left, top = self.rows:PointToScreen(0, 0); |
941 |
|
Thurallor-7095 |
local rowContainer = self.rowsByName[rowName]; |
942 |
|
Thurallor-7095 |
if (rowContainer) then |
943 |
|
Thurallor-7095 |
-- local x, y = rowContainer:PointToScreen(0, 0); |
944 |
|
Thurallor-7095 |
self.rows:EnsureVisible(self.rows:IndexOfItem(rowContainer)); |
945 |
|
Thurallor-7095 |
end |
946 |
|
Thurallor-7095 |
end |
947 |
|
Thurallor-7095 |
end |
948 |
|
Thurallor-7095 |
|
949 |
|
Thurallor-7095 |
function TableControl:SetRowVisible(row, visible) |
950 |
|
Thurallor-7095 |
local rowContainer = self.rows:GetItem(row); |
951 |
|
Thurallor-7095 |
if (visible) then |
952 |
|
Thurallor-7095 |
-- Set container height to maximum of cell heights |
953 |
|
Thurallor-7095 |
local maxHeight = 0; |
954 |
|
Thurallor-7095 |
for _, cell in pairs(rowContainer.cells) do |
955 |
|
Thurallor-7095 |
maxHeight = math.max(maxHeight, cell:GetHeight()); |
956 |
|
Thurallor-7095 |
end |
957 |
|
Thurallor-7095 |
if (rowContainer ~= self.lastRow) then |
958 |
|
Thurallor-7095 |
maxHeight = maxHeight + self.style.verticalCellSpacing; |
959 |
|
Thurallor-7095 |
end |
960 |
|
Thurallor-7095 |
rowContainer:SetHeight(maxHeight); |
961 |
|
Thurallor-7095 |
else |
962 |
|
Thurallor-7095 |
rowContainer:SetHeight(0); |
963 |
|
Thurallor-7095 |
end |
964 |
|
Thurallor-7095 |
end |
965 |
|
Thurallor-7095 |
|
966 |
|
Thurallor-7095 |
-- Last row needs to be slightly different cosmetically |
967 |
|
Thurallor-7095 |
function TableControl:_UpdateLastRow() |
968 |
|
Thurallor-7095 |
local prev = self.lastRow; |
969 |
|
Thurallor-7095 |
local row = self.rows:GetItemCount(); |
970 |
|
Thurallor-7095 |
if (row > 0) then |
971 |
|
Thurallor-7095 |
self.lastRow = self.rows:GetItem(row); |
972 |
|
Thurallor-7095 |
self:SetRowVisible(row, true); |
973 |
|
Thurallor-7095 |
else |
974 |
|
Thurallor-7095 |
self.lastRow = nil; |
975 |
|
Thurallor-7095 |
end |
976 |
|
Thurallor-7095 |
if (prev) then |
977 |
|
Thurallor-7095 |
self:SetRowVisible(self.rows:IndexOfItem(prev), true); |
978 |
|
Thurallor-7095 |
end |
979 |
|
Thurallor-7095 |
end |
980 |
|
Thurallor-7095 |
|
981 |
|
Thurallor-7095 |
function TableControl:DeleteRow(rowName) |
982 |
|
Thurallor-7095 |
local rowContainer = self.rowsByName[rowName]; |
983 |
|
Thurallor-7095 |
if (self.selectedRow == rowContainer) then |
984 |
|
Thurallor-7095 |
self:Deselect(); |
985 |
|
Thurallor-7095 |
end |
986 |
|
Thurallor-7095 |
self.rows:RemoveItem(rowContainer); |
987 |
|
Thurallor-7095 |
self.rowsByName[rowName] = nil; |
988 |
|
Thurallor-7095 |
if (self.lastRow == rowContainer) then |
989 |
|
Thurallor-7095 |
self.lastRow = nil; |
990 |
|
Thurallor-7095 |
self:_UpdateLastRow(); |
991 |
|
Thurallor-7095 |
end |
992 |
|
Thurallor-7095 |
end |
993 |
|
Thurallor-7095 |
|
994 |
|
Thurallor-7095 |
function TableControl:GetRowCells(row) |
995 |
|
Thurallor-7095 |
return unpack(self.rows:GetItem(row).cells); |
996 |
|
Thurallor-7095 |
end |
997 |
|
Thurallor-7095 |
|
998 |
|
Thurallor-7095 |
function TableControl:GetCell(row, col) |
999 |
|
Thurallor-7095 |
return self.rows:GetItem(row).cells[col]; |
1000 |
|
Thurallor-7095 |
end |
1001 |
|
Thurallor-7095 |
|
1002 |
|
Thurallor-7095 |
function TableControl:GetHeading(colName) |
1003 |
|
Thurallor-7095 |
local col = self.columnsByName[colName]; |
1004 |
|
Thurallor-7095 |
if (col) then |
1005 |
|
Thurallor-7095 |
local column = self.columns[col]; |
1006 |
|
Thurallor-7095 |
return column.heading; |
1007 |
|
Thurallor-7095 |
end |
1008 |
|
Thurallor-7095 |
end |
1009 |
|
Thurallor-7095 |
|
1010 |
|
Thurallor-7095 |
function TableControl:SetCell(row, col, object) |
1011 |
|
Thurallor-7095 |
local column = self.columns[col]; |
1012 |
|
Thurallor-7095 |
local heading = column.heading; |
1013 |
|
Thurallor-7095 |
local rowContainer = self.rows:GetItem(row); |
1014 |
|
Thurallor-7095 |
|
1015 |
|
Thurallor-7095 |
-- Delete old cell (if any) |
1016 |
|
Thurallor-7095 |
local oldCell = rowContainer.cells[col]; |
1017 |
|
Thurallor-7095 |
if (oldCell) then |
1018 |
|
Thurallor-7095 |
oldCell:SetParent(nil); |
1019 |
|
Thurallor-7095 |
if (oldCell.Close) then |
1020 |
|
Thurallor-7095 |
oldCell:Close(); |
1021 |
|
Thurallor-7095 |
end |
1022 |
|
Thurallor-7095 |
end |
1023 |
|
Thurallor-7095 |
|
1024 |
|
Thurallor-7095 |
-- Create new cell, or use the supplied object |
1025 |
|
Thurallor-7095 |
local newCell = object; |
1026 |
|
Thurallor-7095 |
if (object == nil) then |
1027 |
|
Thurallor-7095 |
newCell = self:_CreateCell(row, col); |
1028 |
|
Thurallor-7095 |
end |
1029 |
|
Thurallor-7095 |
|
1030 |
|
Thurallor-7095 |
-- Place the cell within in the row container |
1031 |
|
Thurallor-7095 |
local left = heading:GetLeft(); |
1032 |
|
Thurallor-7095 |
local width = heading:GetWidth(); |
1033 |
|
Thurallor-7095 |
newCell:SetParent(rowContainer); |
1034 |
|
Thurallor-7095 |
if (column.weight == 0) then |
1035 |
|
Thurallor-7095 |
newCell:SetParent(nil); |
1036 |
|
Thurallor-7095 |
end |
1037 |
|
Thurallor-7095 |
rowContainer.cells[col] = newCell; |
1038 |
|
Thurallor-7095 |
newCell:SetWidth(width); |
1039 |
|
Thurallor-7095 |
newCell:SetPosition(left, top); |
1040 |
|
Thurallor-7095 |
|
1041 |
|
Thurallor-7095 |
-- Update the row container height, if necessary |
1042 |
|
Thurallor-7095 |
if (rowContainer:GetHeight() > 0) then |
1043 |
|
Thurallor-7095 |
self:SetRowVisible(true); |
1044 |
|
Thurallor-7095 |
end |
1045 |
|
Thurallor-7095 |
|
1046 |
|
Thurallor-7095 |
return newCell; |
1047 |
|
Thurallor-7095 |
end |
1048 |
|
Thurallor-7095 |
|
1049 |
|
Thurallor-7095 |
function TableControl:_ApplyStyles(object, styles) |
1050 |
|
Thurallor-7095 |
for s in keys(styles) do |
1051 |
|
Thurallor-7095 |
local SetFunction = object["Set" .. s]; |
1052 |
|
Thurallor-7095 |
if (SetFunction) then |
1053 |
|
Thurallor-7095 |
SetFunction(object, styles[s]); |
1054 |
|
Thurallor-7095 |
end |
1055 |
|
Thurallor-7095 |
end |
1056 |
|
Thurallor-7095 |
end |
1057 |
|
Thurallor-7095 |
|
1058 |
|
Thurallor-7095 |
function TableControl:_UpdateColumnWidths() |
1059 |
|
Thurallor-7095 |
-- Find last visible column |
1060 |
|
Thurallor-7095 |
local rightCol; |
1061 |
|
Thurallor-7095 |
for col = 1, #self.columns do |
1062 |
|
Thurallor-7095 |
local column = self.columns[col]; |
1063 |
|
Thurallor-7095 |
if (column.weight > 0) then |
1064 |
|
Thurallor-7095 |
rightCol = col; |
1065 |
|
Thurallor-7095 |
end |
1066 |
|
Thurallor-7095 |
end |
1067 |
|
Thurallor-7095 |
|
1068 |
|
Thurallor-7095 |
local totalWidth = self.rowWidth - ((#self.columns - 1) * self.style.horizontalCellSpacing); |
1069 |
|
Thurallor-7095 |
local totalWeight = self.totalWeight; |
1070 |
|
Thurallor-7095 |
local left = 0; |
1071 |
|
Thurallor-7095 |
local weightExpended = 0; |
1072 |
|
Thurallor-7095 |
for col = 1, #self.columns do |
1073 |
|
Thurallor-7095 |
local column = self.columns[col]; |
1074 |
|
Thurallor-7095 |
local weight = column.weight; |
1075 |
|
Thurallor-7095 |
if (weight > 0) then |
1076 |
|
Thurallor-7095 |
local heading = column.heading; |
1077 |
|
Thurallor-7095 |
local width = math.floor(0.5 + totalWidth * (weight / totalWeight)); |
1078 |
|
Thurallor-7095 |
width = math.min(width, self.rowWidth - left) |
1079 |
|
Thurallor-7095 |
if (col == rightCol) then |
1080 |
|
Thurallor-7095 |
width = self.rowWidth - left; |
1081 |
|
Thurallor-7095 |
end |
1082 |
|
Thurallor-7095 |
heading:SetLeft(left); |
1083 |
|
Thurallor-7095 |
heading:SetWidth(width); |
1084 |
|
Thurallor-7095 |
column.lockIcon:SetPosition(width - 19, -11); |
1085 |
|
Thurallor-7095 |
-- optimization to do: only need to do the following loop if heading left/width changed |
1086 |
|
Thurallor-7095 |
for row = 1, self.rows:GetItemCount() do |
1087 |
|
Thurallor-7095 |
local cell = self.rows:GetItem(row).cells[col]; |
1088 |
|
Thurallor-7095 |
cell:SetLeft(left); |
1089 |
|
Thurallor-7095 |
cell:SetWidth(width); |
1090 |
|
Thurallor-7095 |
end |
1091 |
|
Thurallor-7095 |
weightExpended = weightExpended + weight; |
1092 |
|
Thurallor-7095 |
left = left + width + self.style.horizontalCellSpacing; |
1093 |
|
Thurallor-7095 |
end |
1094 |
|
Thurallor-7095 |
end |
1095 |
|
Thurallor-7095 |
self:_PlaceEdgeMovers(); |
1096 |
|
Thurallor-7095 |
self:_PlaceColumnLockMasks(); |
1097 |
|
Thurallor-7095 |
end |
1098 |
|
Thurallor-7095 |
|
1099 |
|
Thurallor-7095 |
function TableControl:SetSize(width, height) |
1100 |
|
Thurallor-7095 |
self:SetWidth(width); |
1101 |
|
Thurallor-7095 |
self:SetHeight(height); |
1102 |
|
Thurallor-7095 |
end |
1103 |
|
Thurallor-7095 |
|
1104 |
|
Thurallor-7095 |
function TableControl:SetWidth(width) |
1105 |
|
Thurallor-7095 |
Turbine.UI.Control.SetWidth(self, width); |
1106 |
|
Thurallor-7095 |
self.rowWidth = width; |
1107 |
|
Thurallor-7095 |
if (self.vScrollBar:IsVisible()) then |
1108 |
|
Thurallor-7095 |
self.rowWidth = width - 10; |
1109 |
|
Thurallor-7095 |
self.vScrollBar:SetLeft(self.rowWidth); |
1110 |
|
Thurallor-7095 |
end |
1111 |
|
Thurallor-7095 |
self.rows:SetWidth(self.rowWidth); |
1112 |
|
Thurallor-7095 |
for row = 1, self.rows:GetItemCount() do |
1113 |
|
Thurallor-7095 |
self.rows:GetItem(row):SetWidth(self.rowWidth); |
1114 |
|
Thurallor-7095 |
end |
1115 |
|
Thurallor-7095 |
self:_UpdateColumnWidths(); |
1116 |
|
Thurallor-7095 |
end |
1117 |
|
Thurallor-7095 |
|
1118 |
|
Thurallor-7095 |
function TableControl:SetHeight(height) |
1119 |
|
Thurallor-7095 |
Turbine.UI.Control.SetHeight(self, height); |
1120 |
|
Thurallor-7095 |
self.rows:SetHeight(height - self.rows:GetTop()); |
1121 |
|
Thurallor-7095 |
self.vScrollBar:SetHeight(height); |
1122 |
|
Thurallor-7095 |
self:_PlaceEdgeMovers(); -- update EdgeMover heights |
1123 |
|
Thurallor-7095 |
end |
1124 |
|
Thurallor-7095 |
|
1125 |
|
Thurallor-7095 |
function TableControl:_PlaceEdgeMovers() |
1126 |
|
Thurallor-7095 |
height = self:GetHeight(); |
1127 |
|
Thurallor-7095 |
for e = 1, #self.edgeMovers do |
1128 |
|
Thurallor-7095 |
local edgeMover = self.edgeMovers[e]; |
1129 |
|
Thurallor-7095 |
local headingToLeft = self.columns[edgeMover.leftColumn].heading; |
1130 |
|
Thurallor-7095 |
local headingToRight = self.columns[edgeMover.rightColumn].heading; |
1131 |
|
Thurallor-7095 |
|
1132 |
|
Thurallor-7095 |
local left = headingToLeft:GetLeft() + headingToLeft:GetWidth(); |
1133 |
|
Thurallor-7095 |
local right = headingToRight:GetLeft(); |
1134 |
|
Thurallor-7095 |
if (left > right) then -- columns overlap? |
1135 |
|
Thurallor-7095 |
left = right; |
1136 |
|
Thurallor-7095 |
end |
1137 |
|
Thurallor-7095 |
local center = (left + right) / 2; |
1138 |
|
Thurallor-7095 |
local width = edgeMover:GetWidth(); |
1139 |
|
Thurallor-7095 |
left = math.floor(0.5 + center - (width / 2)); |
1140 |
|
Thurallor-7095 |
|
1141 |
|
Thurallor-7095 |
edgeMover:SetLeft(left); |
1142 |
|
Thurallor-7095 |
edgeMover:SetHeight(height); |
1143 |
|
Thurallor-7095 |
end |
1144 |
|
Thurallor-7095 |
end |
1145 |
|
Thurallor-7095 |
|
1146 |
|
Thurallor-7095 |
function TableControl:_PlaceColumnLockMasks() |
1147 |
|
Thurallor-7095 |
if (self.selectedRow) then |
1148 |
|
Thurallor-7095 |
for col = 1, #self.columns do |
1149 |
|
Thurallor-7095 |
local column = self.columns[col]; |
1150 |
|
Thurallor-7095 |
if (column.locked and (column.weight > 0)) then |
1151 |
|
Thurallor-7095 |
column.lockMask:SetParent(self.selectedRow); |
1152 |
|
Thurallor-7095 |
column.lockMask:SetPosition(column.heading:GetLeft(), 0); |
1153 |
|
Thurallor-7095 |
column.lockMask:SetSize(column.heading:GetWidth(), self.selectedRow:GetHeight()); |
1154 |
|
Thurallor-7095 |
column.lockMask:SetMouseVisible(true); |
1155 |
|
Thurallor-7095 |
else |
1156 |
|
Thurallor-7095 |
column.lockMask:SetMouseVisible(false); |
1157 |
|
Thurallor-7095 |
end |
1158 |
|
Thurallor-7095 |
end |
1159 |
|
Thurallor-7095 |
end |
1160 |
|
Thurallor-7095 |
end |
1161 |
|
Thurallor-7095 |
|
1162 |
|
Thurallor-7095 |
-- For iterating over an array of cells in a for loop. Example: |
1163 |
|
Thurallor-7095 |
-- To change the color of every cell in the first two columns: |
1164 |
|
Thurallor-7095 |
-- for cell in tblCtl:CellIterator(1, 1, nil, 2) do |
1165 |
|
Thurallor-7095 |
-- cell:SetBackColor(Turbine.UI.Color.White); |
1166 |
|
Thurallor-7095 |
-- end |
1167 |
|
Thurallor-7095 |
function TableControl:CellIterator(firstRow, firstCol, lastRow, lastCol) |
1168 |
|
Thurallor-7095 |
if (firstRow == nil) then |
1169 |
|
Thurallor-7095 |
firstRow = 1; |
1170 |
|
Thurallor-7095 |
end |
1171 |
|
Thurallor-7095 |
if (lastRow == nil) then |
1172 |
|
Thurallor-7095 |
lastRow = self.rows:GetItemCount(); |
1173 |
|
Thurallor-7095 |
end |
1174 |
|
Thurallor-7095 |
if (firstCol == nil) then |
1175 |
|
Thurallor-7095 |
firstCol = 1; |
1176 |
|
Thurallor-7095 |
end |
1177 |
|
Thurallor-7095 |
if (lastCol == nil) then |
1178 |
|
Thurallor-7095 |
lastCol = #self.columns; |
1179 |
|
Thurallor-7095 |
end |
1180 |
|
Thurallor-7095 |
|
1181 |
|
Thurallor-7095 |
local state = { |
1182 |
|
Thurallor-7095 |
["self"] = self; |
1183 |
|
Thurallor-7095 |
["firstRow"] = firstRow; |
1184 |
|
Thurallor-7095 |
["firstCol"] = firstCol; |
1185 |
|
Thurallor-7095 |
["lastRow"] = lastRow; |
1186 |
|
Thurallor-7095 |
["lastCol"] = lastCol; |
1187 |
|
Thurallor-7095 |
["row"] = firstRow; |
1188 |
|
Thurallor-7095 |
["column"] = firstCol |
1189 |
|
Thurallor-7095 |
}; |
1190 |
|
Thurallor-7095 |
local function iterator(state) |
1191 |
|
Thurallor-7095 |
if (state.row > state.lastRow) then |
1192 |
|
Thurallor-7095 |
return nil; |
1193 |
|
Thurallor-7095 |
end |
1194 |
|
Thurallor-7095 |
local cell = TableControl.GetCell(state.self, state.row, state.column); |
1195 |
|
Thurallor-7095 |
state.column = state.column + 1; |
1196 |
|
Thurallor-7095 |
if (state.column > state.lastCol) then |
1197 |
|
Thurallor-7095 |
state.column = state.firstCol; |
1198 |
|
Thurallor-7095 |
state.row = state.row + 1; |
1199 |
|
Thurallor-7095 |
end |
1200 |
|
Thurallor-7095 |
return cell; |
1201 |
|
Thurallor-7095 |
end |
1202 |
|
Thurallor-7095 |
return iterator, state, nil; |
1203 |
|
Thurallor-7095 |
end |
1204 |
|
Thurallor-7095 |
|
1205 |
|
Thurallor-7095 |
-- For calling member functions of many cells at once. Examples: |
1206 |
|
Thurallor-7095 |
-- minCellHeight = math.min(t:CellAggregator(1, 1, 1, 3):GetHeight()); |
1207 |
|
Thurallor-7095 |
-- t:CellAggregator():SetBackColor(Turbine.UI.Color(1, 1, 1, 1)); |
1208 |
|
Thurallor-7095 |
function TableControl:CellAggregator(firstRow, firstCol, lastRow, lastCol) |
1209 |
|
Thurallor-7095 |
local temp = {}; |
1210 |
|
Thurallor-7095 |
temp.iterator = {self:CellIterator(firstRow, firstCol, lastRow, lastCol)}; |
1211 |
|
Thurallor-7095 |
local temp_metatable = {}; |
1212 |
|
Thurallor-7095 |
temp_metatable.__index = function(tab, key) |
1213 |
|
Thurallor-7095 |
rawset(tab, "funcName", key); |
1214 |
|
Thurallor-7095 |
return tab; |
1215 |
|
Thurallor-7095 |
end; |
1216 |
|
Thurallor-7095 |
temp_metatable.__call = function(tab, _, ...) |
1217 |
|
Thurallor-7095 |
local funcName = rawget(tab, "funcName"); |
1218 |
|
Thurallor-7095 |
local results = {}; |
1219 |
|
Thurallor-7095 |
for cell in unpack(rawget(tab, "iterator")) do |
1220 |
|
Thurallor-7095 |
local r = {cell[funcName](cell, ...)}; |
1221 |
|
Thurallor-7095 |
for v in values(r) do |
1222 |
|
Thurallor-7095 |
table.insert(results, v); |
1223 |
|
Thurallor-7095 |
end |
1224 |
|
Thurallor-7095 |
end |
1225 |
|
Thurallor-7095 |
return unpack(results); |
1226 |
|
Thurallor-7095 |
end; |
1227 |
|
Thurallor-7095 |
setmetatable(temp, temp_metatable); |
1228 |
|
Thurallor-7095 |
return temp; |
1229 |
|
Thurallor-7095 |
end |
1230 |
|
Thurallor-7095 |
|
1231 |
|
Thurallor-7095 |
Thurallor = Thurallor or {}; |
1232 |
|
Thurallor-7095 |
Thurallor.UI = Thurallor.UI or {}; |
1233 |
|
Thurallor-7095 |
Thurallor.UI.TableControl = TableControl; |