3 class CheckListBoxButton : Button
5 isCheckbox = true, inactive = true, size = { 12, 12 };
7 bool CheckListBox::NotifyPushed(Button button, int x, int y, Modifiers mods)
9 currentRow = (DataRow)button.id;
10 ToggleCheck(currentRow);
14 bool CheckListBox::NotifyReleased(Button button, int x, int y, Modifiers mods)
19 bool OnMouseOver(int x, int y, Modifiers mods)
25 bool OnMouseLeave(Modifiers mods)
32 class CheckListBox : ListBox
34 Map<int, CheckListBoxButton> buttonMaps { };
35 AVLTree<DataRow> rowChecks { };
40 fullRowSelect = false, collapseControl = true, treeBranches = true, rootCollapseButton = true,
46 buttonMaps.RemoveAll();
49 bool NotifyCollapse(CheckListBox listBox, DataRow row, bool collapsed)
52 for(r = row.firstRow; r && r != row; )
56 MapIterator<int, Button> it { map = listBox.buttonMaps };
57 if(it.Index((int)r, false))
59 Button checkBox = it.data;
69 listBox.SetupButtons(r, false);
71 if(r.firstRow && !r.collapsed)
74 for(; r != row; r = r.parent)
75 if(r.next) { r = r.next; break; }
77 for(r = row.GetNextRow(); r; r = r.GetNextRow())
79 Button checkBox = listBox.buttonMaps[(int)r];
81 checkBox.position.y = 1 + (r.index + listBox.hasHeader) * listBox.rowHeight;
86 bool CheckPartialChecks(DataRow row)
89 for(r = row.firstRow; r; r = r.next)
91 if(rowChecks.Find(r) || CheckPartialChecks(r))
97 void SetupButtons(DataRow row, bool recurse)
100 CheckListBoxButton button;
101 int indent = checkIndent;
103 for(parent = row.parent; parent; parent = parent.parent) indent += 20;
104 button = buttonMaps[(int)row];
105 if(!button) button = CheckListBoxButton { this };
106 button.position = { 2 + indent, 1+(row.index + hasHeader) * rowHeight };
107 button.id = (int)row;
109 for(parent = row; parent; parent = parent.parent) if(rowChecks.Find(parent)) break;
112 button.checked = true;
113 button.buttonState = up;
117 button.checked = CheckPartialChecks(row);
118 button.buttonState = button.checked ? down : up;
121 buttonMaps[(int)row] = button;
122 if(recurse && !row.collapsed)
125 for(r = row.firstRow; r; r = r.next)
126 SetupButtons(r, recurse);
133 for(row = firstRow; row; row = row.next)
134 SetupButtons(row, true);
139 if(ListBox::OnCreate())
143 buttonMaps.RemoveAll();
145 for(row = firstRow; row; row = row.next)
146 SetupButtons(row, true);
152 void ToggleCheck(DataRow row)
154 CheckListBoxButton checkBox = buttonMaps[(int)row];
157 bool checked = false;
159 for(r = row; r; r = r.parent)
160 if(rowChecks.Find(r))
165 SetCheck(row, !checked);
169 void UncheckBoxes(DataRow row)
171 if(!row.parent || !row.parent.collapsed)
173 CheckListBoxButton button = buttonMaps[(int)row];
176 bool wasChecked = button.checked;
177 button.checked = false;
178 button.buttonState = up;
181 // if(!row.collapsed)
184 for(r = row.firstRow; r; r = r.next)
187 NotifyChanged(master, this, row);
190 void UnsetChildren(DataRow row)
193 CheckListBoxButton button = buttonMaps[(int)row];
196 bool wasChecked = button.checked;
197 button.checked = true;
198 button.buttonState = up;
201 for(r = row.firstRow; r; r = r.next)
203 Iterator<DataRow> it { rowChecks };
208 NotifyChanged(master, this, r);
212 void SetCheck(DataRow row, bool checked)
215 bool wasChecked = false;
217 for(parent = row; parent; parent = parent.parent)
219 if(rowChecks.Find(parent)) { wasChecked = true; break; }
221 if(checked != wasChecked)
223 modifiedDocument = true;
224 // NotifyChanged(master, this, row);
228 // Check if all siblings are checked, if so go up until we reach a row not fully checked
232 for(r = rr.parent.firstRow; r; r = r.next)
234 if(r != rr && !rowChecks.Find(r))
237 if(r || !row.parent) break;
243 // Take out all children from rowChecks, checking them all
246 for(parent = row.parent; parent; parent = parent.parent)
248 CheckListBoxButton button = buttonMaps[(int)parent];
252 button.checked = true;
253 button.buttonState = down;
255 NotifyChanged(master, this, parent);
265 Iterator<DataRow> it { rowChecks };
274 for(r = row.parent.firstRow; r; r = r.next)
284 for(parent = row.parent; parent; parent = parent.parent)
286 CheckListBoxButton button = buttonMaps[(int)parent];
289 if(CheckPartialChecks(parent))
291 button.checked = true;
292 button.buttonState = down;
296 button.checked = false;
297 button.buttonState = up;
300 NotifyChanged(master, this, parent);
305 NotifyChanged(master, this, row);
309 bool NotifyKeyDown(CheckListBox listBox, DataRow row, Key key, unichar ch)
313 listBox.ToggleCheck(row);
319 bool OnKeyHit(Key key, unichar ch)
323 return ListBox::OnKeyHit(key, ch);
326 bool NotifyDoubleClick(CheckListBox listBox, int x, int y, Modifiers mods)
328 listBox.OnLeftButtonDown(x, y, mods);
332 bool NotifyReclick(CheckListBox listBox, DataRow row, Modifiers mods)
334 if(row == listBox.currentRow)
335 listBox.ToggleCheck(row);
340 bool IsChecked(DataRow row)
342 CheckListBoxButton button = buttonMaps[(int)row];
344 for(parent = row; parent; parent = parent.parent) if(rowChecks.Find(parent)) return true;
345 // For partially checked because of children:
346 if(button && button.checked)
351 // virtual void Window::NotifyChecked(CheckListBox listBox, DataRow row);