10
|
1 /*******************************************************************************
|
|
2 * Copyright (c) 2000, 2007 IBM Corporation and others.
|
|
3 * All rights reserved. This program and the accompanying materials
|
|
4 * are made available under the terms of the Eclipse Public License v1.0
|
|
5 * which accompanies this distribution, and is available at
|
|
6 * http://www.eclipse.org/legal/epl-v10.html
|
|
7 *
|
|
8 * Contributors:
|
|
9 * IBM Corporation - initial API and implementation
|
|
10 * Port to the D programming language:
|
|
11 * Frank Benoit <benoit@tionex.de>
|
|
12 *******************************************************************************/
|
|
13 module dwtx.jface.viewers.CheckboxTreeViewer;
|
|
14
|
|
15 import dwtx.jface.viewers.TreeViewer;
|
|
16 import dwtx.jface.viewers.ICheckable;
|
|
17 import dwtx.jface.viewers.ICheckStateListener;
|
|
18 import dwtx.jface.viewers.CustomHashtable;
|
|
19 import dwtx.jface.viewers.CheckStateChangedEvent;
|
|
20
|
|
21 import tango.util.collection.ArraySeq;
|
|
22 import tango.util.collection.model.Seq;
|
|
23
|
|
24 import dwt.DWT;
|
|
25 import dwt.events.SelectionEvent;
|
|
26 import dwt.widgets.Composite;
|
|
27 import dwt.widgets.Control;
|
|
28 import dwt.widgets.Item;
|
|
29 import dwt.widgets.Tree;
|
|
30 import dwt.widgets.TreeItem;
|
|
31 import dwt.widgets.Widget;
|
|
32 import dwtx.core.runtime.Assert;
|
|
33 import dwtx.core.runtime.ListenerList;
|
|
34 import dwtx.jface.util.SafeRunnable;
|
|
35
|
|
36 import dwt.dwthelper.utils;
|
|
37 import dwt.dwthelper.Runnable;
|
|
38
|
|
39 /**
|
|
40 * A concrete tree-structured viewer based on an DWT <code>Tree</code>
|
|
41 * control with checkboxes on each node.
|
|
42 * <p>
|
|
43 * This class is not intended to be subclassed outside the viewer framework.
|
|
44 * It is designed to be instantiated with a pre-existing DWT tree control and configured
|
|
45 * with a domain-specific content provider, label provider, element filter (optional),
|
|
46 * and element sorter (optional).
|
|
47 * </p>
|
|
48 */
|
|
49 public class CheckboxTreeViewer : TreeViewer, ICheckable {
|
|
50
|
|
51 /**
|
|
52 * List of check state listeners (element type: <code>ICheckStateListener</code>).
|
|
53 */
|
|
54 private ListenerList checkStateListeners;
|
|
55
|
|
56 /**
|
|
57 * Last item clicked on, or <code>null</code> if none.
|
|
58 */
|
|
59 private TreeItem lastClickedItem = null;
|
|
60
|
|
61 /**
|
|
62 * Creates a tree viewer on a newly-created tree control under the given parent.
|
|
63 * The tree control is created using the DWT style bits: <code>CHECK</code> and <code>BORDER</code>.
|
|
64 * The viewer has no input, no content provider, a default label provider,
|
|
65 * no sorter, and no filters.
|
|
66 *
|
|
67 * @param parent the parent control
|
|
68 */
|
|
69 public this(Composite parent) {
|
|
70 this(parent, DWT.BORDER);
|
|
71 }
|
|
72
|
|
73 /**
|
|
74 * Creates a tree viewer on a newly-created tree control under the given parent.
|
|
75 * The tree control is created using the given DWT style bits, plus the <code>CHECK</code> style bit.
|
|
76 * The viewer has no input, no content provider, a default label provider,
|
|
77 * no sorter, and no filters.
|
|
78 *
|
|
79 * @param parent the parent control
|
|
80 * @param style the DWT style bits
|
|
81 */
|
|
82 public this(Composite parent, int style) {
|
|
83 this(new Tree(parent, DWT.CHECK | style));
|
|
84 }
|
|
85
|
|
86 /**
|
|
87 * Creates a tree viewer on the given tree control.
|
|
88 * The <code>DWT.CHECK</code> style bit must be set on the given tree control.
|
|
89 * The viewer has no input, no content provider, a default label provider,
|
|
90 * no sorter, and no filters.
|
|
91 *
|
|
92 * @param tree the tree control
|
|
93 */
|
|
94 public this(Tree tree) {
|
|
95 checkStateListeners = new ListenerList();
|
|
96 super(tree);
|
|
97 }
|
|
98
|
|
99 /* (non-Javadoc)
|
|
100 * Method declared on ICheckable.
|
|
101 */
|
|
102 public void addCheckStateListener(ICheckStateListener listener) {
|
|
103 checkStateListeners.add(cast(Object)listener);
|
|
104 }
|
|
105
|
|
106 /**
|
|
107 * Applies the checked and grayed states of the given widget and its
|
|
108 * descendents.
|
|
109 *
|
|
110 * @param checked a set of elements (element type: <code>Object</code>)
|
|
111 * @param grayed a set of elements (element type: <code>Object</code>)
|
|
112 * @param widget the widget
|
|
113 */
|
|
114 private void applyState(CustomHashtable checked, CustomHashtable grayed,
|
|
115 Widget widget) {
|
|
116 Item[] items = getChildren(widget);
|
|
117 for (int i = 0; i < items.length; i++) {
|
|
118 Item item = items[i];
|
|
119 if ( auto ti = cast(TreeItem) item ) {
|
|
120 Object data = item.getData();
|
|
121 if (data !is null) {
|
|
122 ti.setChecked(checked.containsKey(data));
|
|
123 ti.setGrayed(grayed.containsKey(data));
|
|
124 }
|
|
125 }
|
|
126 applyState(checked, grayed, item);
|
|
127 }
|
|
128 }
|
|
129
|
|
130 /**
|
|
131 * Notifies any check state listeners that the check state of an element has changed.
|
|
132 * Only listeners registered at the time this method is called are notified.
|
|
133 *
|
|
134 * @param event a check state changed event
|
|
135 *
|
|
136 * @see ICheckStateListener#checkStateChanged
|
|
137 */
|
|
138 protected void fireCheckStateChanged(CheckStateChangedEvent event) {
|
|
139 Object[] array = checkStateListeners.getListeners();
|
|
140 for (int i = 0; i < array.length; i++) {
|
39
|
141 SafeRunnable.run(new class(cast(ICheckStateListener) array[i]) SafeRunnable {
|
10
|
142 ICheckStateListener l;
|
39
|
143 this(ICheckStateListener a){
|
|
144 l = a;
|
10
|
145 }
|
|
146 public void run() {
|
|
147 l.checkStateChanged(event);
|
|
148 }
|
|
149 });
|
|
150 }
|
|
151
|
|
152 }
|
|
153
|
|
154 /**
|
|
155 * Gathers the checked and grayed states of the given widget and its
|
|
156 * descendents.
|
|
157 *
|
|
158 * @param checked a writable set of elements (element type: <code>Object</code>)
|
|
159 * @param grayed a writable set of elements (element type: <code>Object</code>)
|
|
160 * @param widget the widget
|
|
161 */
|
|
162 private void gatherState(CustomHashtable checked, CustomHashtable grayed,
|
|
163 Widget widget) {
|
|
164 Item[] items = getChildren(widget);
|
|
165 for (int i = 0; i < items.length; i++) {
|
|
166 Item item = items[i];
|
|
167 if ( auto ti = cast(TreeItem) item ) {
|
|
168 Object data = item.getData();
|
|
169 if (data !is null) {
|
|
170 if (ti.getChecked()) {
|
|
171 checked.put(data, data);
|
|
172 }
|
|
173 if (ti.getGrayed()) {
|
|
174 grayed.put(data, data);
|
|
175 }
|
|
176 }
|
|
177 }
|
|
178 gatherState(checked, grayed, item);
|
|
179 }
|
|
180 }
|
|
181
|
|
182 /* (non-Javadoc)
|
|
183 * Method declared on ICheckable.
|
|
184 */
|
|
185 public bool getChecked(Object element) {
|
|
186 Widget widget = findItem(element);
|
|
187 if ( auto ti = cast(TreeItem) widget ) {
|
|
188 return ti.getChecked();
|
|
189 }
|
|
190 return false;
|
|
191 }
|
|
192
|
|
193 /**
|
|
194 * Returns a list of checked elements in this viewer's tree,
|
|
195 * including currently hidden ones that are marked as
|
|
196 * checked but are under a collapsed ancestor.
|
|
197 * <p>
|
|
198 * This method is typically used when preserving the interesting
|
|
199 * state of a viewer; <code>setCheckedElements</code> is used during the restore.
|
|
200 * </p>
|
|
201 *
|
|
202 * @return the array of checked elements
|
|
203 *
|
|
204 * @see #setCheckedElements
|
|
205 */
|
|
206 public Object[] getCheckedElements() {
|
|
207 ArraySeq!(Object) v = new ArraySeq!(Object);
|
|
208 Control tree = getControl();
|
|
209 internalCollectChecked(v, tree);
|
|
210 return v.toArray();
|
|
211 }
|
|
212
|
|
213 /**
|
|
214 * Returns the grayed state of the given element.
|
|
215 *
|
|
216 * @param element the element
|
|
217 * @return <code>true</code> if the element is grayed,
|
|
218 * and <code>false</code> if not grayed
|
|
219 */
|
|
220 public bool getGrayed(Object element) {
|
|
221 Widget widget = findItem(element);
|
|
222 if ( auto ti = cast(TreeItem) widget ) {
|
|
223 return ti.getGrayed();
|
|
224 }
|
|
225 return false;
|
|
226 }
|
|
227
|
|
228 /**
|
|
229 * Returns a list of grayed elements in this viewer's tree,
|
|
230 * including currently hidden ones that are marked as
|
|
231 * grayed but are under a collapsed ancestor.
|
|
232 * <p>
|
|
233 * This method is typically used when preserving the interesting
|
|
234 * state of a viewer; <code>setGrayedElements</code> is used during the restore.
|
|
235 * </p>
|
|
236 *
|
|
237 * @return the array of grayed elements
|
|
238 *
|
|
239 * @see #setGrayedElements
|
|
240 */
|
|
241 public Object[] getGrayedElements() {
|
|
242 ArraySeq!(Object) result = new ArraySeq!(Object);
|
|
243 internalCollectGrayed(result, getControl());
|
|
244 return result.toArray();
|
|
245 }
|
|
246
|
|
247 /* (non-Javadoc)
|
|
248 * Method declared on StructuredViewer.
|
|
249 */
|
|
250 protected void handleDoubleSelect(SelectionEvent event) {
|
|
251
|
|
252 if (lastClickedItem !is null) {
|
|
253 TreeItem item = lastClickedItem;
|
|
254 Object data = item.getData();
|
|
255 if (data !is null) {
|
|
256 bool state = item.getChecked();
|
|
257 setChecked(data, !state);
|
|
258 fireCheckStateChanged(new CheckStateChangedEvent(this, data,
|
|
259 !state));
|
|
260 }
|
|
261 lastClickedItem = null;
|
|
262 } else {
|
|
263 super.handleDoubleSelect(event);
|
|
264 }
|
|
265 }
|
|
266
|
|
267 /* (non-Javadoc)
|
|
268 * Method declared on StructuredViewer.
|
|
269 */
|
|
270 protected void handleSelect(SelectionEvent event) {
|
|
271
|
|
272 lastClickedItem = null;
|
|
273 if (event.detail is DWT.CHECK) {
|
|
274 TreeItem item = cast(TreeItem) event.item;
|
|
275 lastClickedItem = item;
|
|
276 super.handleSelect(event);
|
|
277
|
|
278 Object data = item.getData();
|
|
279 if (data !is null) {
|
|
280 fireCheckStateChanged(new CheckStateChangedEvent(this, data,
|
|
281 item.getChecked()));
|
|
282 }
|
|
283 } else {
|
|
284 super.handleSelect(event);
|
|
285 }
|
|
286 }
|
|
287
|
|
288 /**
|
|
289 * Gathers the checked states of the given widget and its
|
|
290 * descendents, following a pre-order traversal of the tree.
|
|
291 *
|
|
292 * @param result a writable list of elements (element type: <code>Object</code>)
|
|
293 * @param widget the widget
|
|
294 */
|
|
295 private void internalCollectChecked(Seq!(Object) result, Widget widget) {
|
|
296 Item[] items = getChildren(widget);
|
|
297 for (int i = 0; i < items.length; i++) {
|
|
298 Item item = items[i];
|
|
299 if ( null !is cast(TreeItem)item && (cast(TreeItem) item).getChecked()) {
|
|
300 Object data = item.getData();
|
|
301 if (data !is null) {
|
|
302 result.append(data);
|
|
303 }
|
|
304 }
|
|
305 internalCollectChecked(result, item);
|
|
306 }
|
|
307 }
|
|
308
|
|
309 /**
|
|
310 * Gathers the grayed states of the given widget and its
|
|
311 * descendents, following a pre-order traversal of the tree.
|
|
312 *
|
|
313 * @param result a writable list of elements (element type: <code>Object</code>)
|
|
314 * @param widget the widget
|
|
315 */
|
|
316 private void internalCollectGrayed(Seq!(Object) result, Widget widget) {
|
|
317 Item[] items = getChildren(widget);
|
|
318 for (int i = 0; i < items.length; i++) {
|
|
319 Item item = items[i];
|
|
320 if (null !is cast(TreeItem)item && (cast(TreeItem) item).getGrayed()) {
|
|
321 Object data = item.getData();
|
|
322 if (data !is null) {
|
|
323 result.append(data);
|
|
324 }
|
|
325 }
|
|
326 internalCollectGrayed(result, item);
|
|
327 }
|
|
328 }
|
|
329
|
|
330 /**
|
|
331 * Sets the checked state of all items to correspond to the given set of checked elements.
|
|
332 *
|
|
333 * @param checkedElements the set (element type: <code>Object</code>) of elements which are checked
|
|
334 * @param widget the widget
|
|
335 */
|
|
336 private void internalSetChecked(CustomHashtable checkedElements,
|
|
337 Widget widget) {
|
|
338 Item[] items = getChildren(widget);
|
|
339 for (int i = 0; i < items.length; i++) {
|
|
340 TreeItem item = cast(TreeItem) items[i];
|
|
341 Object data = item.getData();
|
|
342 if (data !is null) {
|
|
343 bool checked = checkedElements.containsKey(data);
|
|
344 if (checked !is item.getChecked()) {
|
|
345 item.setChecked(checked);
|
|
346 }
|
|
347 }
|
|
348 internalSetChecked(checkedElements, item);
|
|
349 }
|
|
350 }
|
|
351
|
|
352 /**
|
|
353 * Sets the grayed state of all items to correspond to the given set of grayed elements.
|
|
354 *
|
|
355 * @param grayedElements the set (element type: <code>Object</code>) of elements which are grayed
|
|
356 * @param widget the widget
|
|
357 */
|
|
358 private void internalSetGrayed(CustomHashtable grayedElements, Widget widget) {
|
|
359 Item[] items = getChildren(widget);
|
|
360 for (int i = 0; i < items.length; i++) {
|
|
361 TreeItem item = cast(TreeItem) items[i];
|
|
362 Object data = item.getData();
|
|
363 if (data !is null) {
|
|
364 bool grayed = grayedElements.containsKey(data);
|
|
365 if (grayed !is item.getGrayed()) {
|
|
366 item.setGrayed(grayed);
|
|
367 }
|
|
368 }
|
|
369 internalSetGrayed(grayedElements, item);
|
|
370 }
|
|
371 }
|
|
372
|
|
373 /* (non-Javadoc)
|
|
374 * Method declared on Viewer.
|
|
375 */
|
|
376 protected void preservingSelection(Runnable updateCode) {
|
|
377
|
|
378 int n = getItemCount(getControl());
|
|
379 CustomHashtable checkedNodes = newHashtable(n * 2 + 1);
|
|
380 CustomHashtable grayedNodes = newHashtable(n * 2 + 1);
|
|
381
|
|
382 gatherState(checkedNodes, grayedNodes, getControl());
|
|
383
|
|
384 super.preservingSelection(updateCode);
|
|
385
|
|
386 applyState(checkedNodes, grayedNodes, getControl());
|
|
387 }
|
|
388
|
|
389 /* (non-Javadoc)
|
|
390 * Method declared on ICheckable.
|
|
391 */
|
|
392 public void removeCheckStateListener(ICheckStateListener listener) {
|
|
393 checkStateListeners.remove(cast(Object)listener);
|
|
394 }
|
|
395
|
|
396 /* (non-Javadoc)
|
|
397 * Method declared on ICheckable.
|
|
398 */
|
|
399 public bool setChecked(Object element, bool state) {
|
|
400 Assert.isNotNull(element);
|
|
401 Widget widget = internalExpand(element, false);
|
|
402 if ( auto ti = cast(TreeItem) widget ) {
|
|
403 ti.setChecked(state);
|
|
404 return true;
|
|
405 }
|
|
406 return false;
|
|
407 }
|
|
408
|
|
409 /**
|
|
410 * Sets the checked state for the children of the given item.
|
|
411 *
|
|
412 * @param item the item
|
|
413 * @param state <code>true</code> if the item should be checked,
|
|
414 * and <code>false</code> if it should be unchecked
|
|
415 */
|
|
416 private void setCheckedChildren(Item item, bool state) {
|
|
417 createChildren(item);
|
|
418 Item[] items = getChildren(item);
|
|
419 if (items !is null) {
|
|
420 for (int i = 0; i < items.length; i++) {
|
|
421 Item it = items[i];
|
|
422 if (it.getData() !is null && (null !is cast(TreeItem)it )) {
|
|
423 TreeItem treeItem = cast(TreeItem) it;
|
|
424 treeItem.setChecked(state);
|
|
425 setCheckedChildren(treeItem, state);
|
|
426 }
|
|
427 }
|
|
428 }
|
|
429 }
|
|
430
|
|
431 /**
|
|
432 * Sets which elements are checked in this viewer's tree.
|
|
433 * The given list contains the elements that are to be checked;
|
|
434 * all other elements are to be unchecked.
|
|
435 * Does not fire events to check state listeners.
|
|
436 * <p>
|
|
437 * This method is typically used when restoring the interesting
|
|
438 * state of a viewer captured by an earlier call to <code>getCheckedElements</code>.
|
|
439 * </p>
|
|
440 *
|
|
441 * @param elements the array of checked elements
|
|
442 * @see #getCheckedElements
|
|
443 */
|
|
444 public void setCheckedElements(Object[] elements) {
|
|
445 assertElementsNotNull(elements);
|
|
446 CustomHashtable checkedElements = newHashtable(elements.length * 2 + 1);
|
|
447 for (int i = 0; i < elements.length; ++i) {
|
|
448 Object element = elements[i];
|
|
449 // Ensure item exists for element
|
|
450 internalExpand(element, false);
|
|
451 checkedElements.put(element, element);
|
|
452 }
|
|
453 Control tree = getControl();
|
|
454 tree.setRedraw(false);
|
|
455 internalSetChecked(checkedElements, tree);
|
|
456 tree.setRedraw(true);
|
|
457 }
|
|
458
|
|
459 /**
|
|
460 * Sets the grayed state for the given element in this viewer.
|
|
461 *
|
|
462 * @param element the element
|
|
463 * @param state <code>true</code> if the item should be grayed,
|
|
464 * and <code>false</code> if it should be ungrayed
|
|
465 * @return <code>true</code> if the gray state could be set,
|
|
466 * and <code>false</code> otherwise
|
|
467 */
|
|
468 public bool setGrayed(Object element, bool state) {
|
|
469 Assert.isNotNull(element);
|
|
470 Widget widget = internalExpand(element, false);
|
|
471 if ( auto ti = cast(TreeItem) widget ) {
|
|
472 ti.setGrayed(state);
|
|
473 return true;
|
|
474 }
|
|
475 return false;
|
|
476 }
|
|
477
|
|
478 /**
|
|
479 * Check and gray the selection rather than calling both
|
|
480 * setGrayed and setChecked as an optimization.
|
|
481 * Does not fire events to check state listeners.
|
|
482 * @param element the item being checked
|
|
483 * @param state a bool indicating selection or deselection
|
|
484 * @return bool indicating success or failure.
|
|
485 */
|
|
486 public bool setGrayChecked(Object element, bool state) {
|
|
487 Assert.isNotNull(element);
|
|
488 Widget widget = internalExpand(element, false);
|
|
489 if (auto item = cast(TreeItem)widget ) {
|
|
490 item.setChecked(state);
|
|
491 item.setGrayed(state);
|
|
492 return true;
|
|
493 }
|
|
494 return false;
|
|
495 }
|
|
496
|
|
497 /**
|
|
498 * Sets which elements are grayed in this viewer's tree.
|
|
499 * The given list contains the elements that are to be grayed;
|
|
500 * all other elements are to be ungrayed.
|
|
501 * <p>
|
|
502 * This method is typically used when restoring the interesting
|
|
503 * state of a viewer captured by an earlier call to <code>getGrayedElements</code>.
|
|
504 * </p>
|
|
505 *
|
|
506 * @param elements the array of grayed elements
|
|
507 *
|
|
508 * @see #getGrayedElements
|
|
509 */
|
|
510 public void setGrayedElements(Object[] elements) {
|
|
511 assertElementsNotNull(elements);
|
|
512 CustomHashtable grayedElements = newHashtable(elements.length * 2 + 1);
|
|
513 for (int i = 0; i < elements.length; ++i) {
|
|
514 Object element = elements[i];
|
|
515 // Ensure item exists for element
|
|
516 internalExpand(element, false);
|
|
517 grayedElements.put(element, element);
|
|
518 }
|
|
519 Control tree = getControl();
|
|
520 tree.setRedraw(false);
|
|
521 internalSetGrayed(grayedElements, tree);
|
|
522 tree.setRedraw(true);
|
|
523 }
|
|
524
|
|
525 /**
|
|
526 * Sets the grayed state for the given element and its parents
|
|
527 * in this viewer.
|
|
528 *
|
|
529 * @param element the element
|
|
530 * @param state <code>true</code> if the item should be grayed,
|
|
531 * and <code>false</code> if it should be ungrayed
|
|
532 * @return <code>true</code> if the element is visible and the gray
|
|
533 * state could be set, and <code>false</code> otherwise
|
|
534 * @see #setGrayed
|
|
535 */
|
|
536 public bool setParentsGrayed(Object element, bool state) {
|
|
537 Assert.isNotNull(element);
|
|
538 Widget widget = internalExpand(element, false);
|
|
539 if (auto item = cast(TreeItem) widget ) {
|
|
540 item.setGrayed(state);
|
|
541 item = item.getParentItem();
|
|
542 while (item !is null) {
|
|
543 item.setGrayed(state);
|
|
544 item = item.getParentItem();
|
|
545 }
|
|
546 return true;
|
|
547 }
|
|
548 return false;
|
|
549 }
|
|
550
|
|
551 /**
|
|
552 * Sets the checked state for the given element and its visible
|
|
553 * children in this viewer.
|
|
554 * Assumes that the element has been expanded before. To enforce
|
|
555 * that the item is expanded, call <code>expandToLevel</code>
|
|
556 * for the element.
|
|
557 * Does not fire events to check state listeners.
|
|
558 *
|
|
559 * @param element the element
|
|
560 * @param state <code>true</code> if the item should be checked,
|
|
561 * and <code>false</code> if it should be unchecked
|
|
562 * @return <code>true</code> if the checked state could be set,
|
|
563 * and <code>false</code> otherwise
|
|
564 */
|
|
565 public bool setSubtreeChecked(Object element, bool state) {
|
|
566 Widget widget = internalExpand(element, false);
|
|
567 if (auto item = cast(TreeItem) widget ) {
|
|
568 item.setChecked(state);
|
|
569 setCheckedChildren(item, state);
|
|
570 return true;
|
|
571 }
|
|
572 return false;
|
|
573 }
|
|
574
|
|
575 /**
|
|
576 * Sets to the given value the checked state for all elements in this viewer.
|
|
577 * Does not fire events to check state listeners.
|
|
578 *
|
|
579 * @param state <code>true</code> if the element should be checked,
|
|
580 * and <code>false</code> if it should be unchecked
|
|
581 *
|
|
582 * @since 3.2
|
|
583 */
|
|
584 public void setAllChecked(bool state) {
|
|
585 setAllChecked(state, getTree().getItems());
|
|
586
|
|
587 }
|
|
588
|
|
589 /**
|
|
590 * Set the checked state of items and their children to state.
|
|
591 * @param state
|
|
592 * @param items
|
|
593 */
|
|
594 private void setAllChecked(bool state, TreeItem[] items) {
|
|
595 for (int i = 0; i < items.length; i++) {
|
|
596 items[i].setChecked(state);
|
|
597 TreeItem[] children = items[i].getItems();
|
|
598 setAllChecked(state, children);
|
|
599 }
|
|
600 }
|
|
601 }
|