2 public import static "ecere"
7 class CheckListBoxButton : Button
9 isCheckbox = true, inactive = true, size = { 12, 12 };
11 bool CheckListBox::NotifyPushed(Button button, int x, int y, Modifiers mods)
13 currentRow = (DataRow)(intptr)button.id;
14 ToggleCheck(currentRow);
18 bool CheckListBox::NotifyReleased(Button button, int x, int y, Modifiers mods)
23 bool OnMouseOver(int x, int y, Modifiers mods)
29 bool OnMouseLeave(Modifiers mods)
36 class CheckListBox : ListBox
38 Map<uintptr, CheckListBoxButton> buttonMaps { };
39 AVLTree<DataRow> rowChecks { };
40 AVLTree<DataRow> rowDisabled { };
45 fullRowSelect = false, collapseControl = true, treeBranches = true, rootCollapseButton = true,
51 buttonMaps.RemoveAll();
54 bool NotifyCollapse(CheckListBox listBox, DataRow row, bool collapsed)
57 for(r = row.firstRow; r && r != row; )
61 MapIterator<uintptr, Button> it { map = listBox.buttonMaps };
62 if(it.Index((uintptr)r, false))
64 Button checkBox = it.data;
74 listBox.SetupButtons(r, false);
76 if(r.firstRow && !r.collapsed)
79 for(; r != row; r = r.parent)
80 if(r.next) { r = r.next; break; }
82 for(r = row.GetNextRow(); r; r = r.GetNextRow())
84 Button checkBox = listBox.buttonMaps[(uintptr)r];
86 checkBox.position.y = 1 + (r.index + listBox.hasHeader) * listBox.rowHeight;
91 bool CheckPartialChecks(DataRow row)
94 for(r = row.firstRow; r; r = r.next)
96 if(rowChecks.Find(r) || CheckPartialChecks(r))
102 void SetupButtons(DataRow row, bool recurse)
105 CheckListBoxButton button;
106 int indent = checkIndent;
108 for(parent = row.parent; parent; parent = parent.parent) indent += 20;
109 button = buttonMaps[(uintptr)row];
110 if(!button) button = CheckListBoxButton { this };
111 button.position = { 2 + indent, 1+(row.index + hasHeader) * rowHeight };
112 button.id = (uintptr)row;
114 for(parent = row; parent; parent = parent.parent) if(rowChecks.Find(parent)) break;
117 button.checked = true;
118 button.buttonState = up;
122 button.checked = CheckPartialChecks(row);
123 button.buttonState = button.checked ? down : up;
125 if(rowDisabled.Find(row))
126 button.disabled = true;
128 buttonMaps[(uintptr)row] = button;
129 if(recurse && !row.collapsed)
132 for(r = row.firstRow; r; r = r.next)
133 SetupButtons(r, recurse);
140 for(row = firstRow; row; row = row.next)
141 SetupButtons(row, true);
146 if(ListBox::OnCreate())
150 buttonMaps.RemoveAll();
152 for(row = firstRow; row; row = row.next)
153 SetupButtons(row, true);
159 void ToggleCheck(DataRow row)
161 CheckListBoxButton checkBox = buttonMaps[(uintptr)row];
162 if(checkBox && !checkBox.disabled)
164 bool checked = false;
166 for(r = row; r; r = r.parent)
167 if(rowChecks.Find(r))
172 SetCheck(row, !checked);
176 void UncheckBoxes(DataRow row)
178 if(!row.parent || !row.parent.collapsed)
180 CheckListBoxButton button = buttonMaps[(uintptr)row];
183 button.checked = false;
184 button.buttonState = up;
187 // if(!row.collapsed)
190 for(r = row.firstRow; r; r = r.next)
193 NotifyChecked(master, this, row);
196 void UnsetChildren(DataRow row)
199 CheckListBoxButton button = buttonMaps[(uintptr)row];
202 button.checked = true;
203 button.buttonState = up;
206 for(r = row.firstRow; r; r = r.next)
208 Iterator<DataRow, DataRow> it { rowChecks };
213 NotifyChecked(master, this, r);
217 void SetCheck(DataRow row, bool checked)
220 bool wasChecked = false;
222 for(parent = row; parent; parent = parent.parent)
224 if(rowChecks.Find(parent)) { wasChecked = true; break; }
226 if(checked != wasChecked)
228 modifiedDocument = true;
229 // NotifyChecked(master, this, row);
233 // Check if all siblings are checked, if so go up until we reach a row not fully checked
237 for(r = rr.parent.firstRow; r; r = r.next)
239 if(r != rr && !rowChecks.Find(r))
242 if(r || !rr.parent) break;
248 // Take out all children from rowChecks, checking them all
251 NotifyChecked(master, this, rr);
253 for(parent = rr.parent; parent; parent = parent.parent)
255 CheckListBoxButton button = buttonMaps[(uintptr)parent];
258 button.checked = true;
259 button.buttonState = down;
261 NotifyChecked(master, this, parent);
272 Iterator<DataRow, DataRow> it { rowChecks };
281 for(r = rr.parent.firstRow; r; r = r.next)
292 for(; parent; parent = parent.parent)
294 CheckListBoxButton button = buttonMaps[(uintptr)parent];
297 if(CheckPartialChecks(parent))
299 button.checked = true;
300 button.buttonState = down;
304 button.checked = false;
305 button.buttonState = up;
308 NotifyChecked(master, this, parent);
315 bool NotifyKeyDown(CheckListBox listBox, DataRow row, Key key, unichar ch)
319 listBox.ToggleCheck(row);
325 bool OnKeyHit(Key key, unichar ch)
329 return ListBox::OnKeyHit(key, ch);
332 bool NotifyDoubleClick(CheckListBox listBox, int x, int y, Modifiers mods)
334 listBox.OnLeftButtonDown(x, y, mods);
338 bool NotifyReclick(CheckListBox listBox, DataRow row, Modifiers mods)
340 if(row == listBox.currentRow)
341 listBox.ToggleCheck(row);
346 bool IsChecked(DataRow row)
348 CheckListBoxButton button = buttonMaps[(uintptr)row];
350 for(parent = row; parent; parent = parent.parent) if(rowChecks.Find(parent)) return true;
351 // For partially checked because of children:
352 if(button && button.checked)
357 bool IsFullyChecked(DataRow row)
360 for(parent = row; parent; parent = parent.parent) if(rowChecks.Find(parent)) return true;
364 virtual void Window::NotifyChecked(CheckListBox listBox, DataRow row);
366 void SetDisabled(DataRow row, bool disabled)
368 CheckListBoxButton checkBox = buttonMaps[(uintptr)row];
370 checkBox.disabled = disabled;
372 if(rowDisabled.Find(row))
375 rowDisabled.TakeOut(row);
380 rowDisabled.Add(row);