/*
* Copyright (c) 2008 Stiftung Deutsches Elektronen-Synchrotron,
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
*
* THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
* WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
* IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
* CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
* NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
* DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
* THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
* USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
* PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
* AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
*/
package org.csstudio.sds.ui.internal.preferences;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.TreeItem;
/**
* tree.addSelectionListener(new TreeCheckSelectionListener());.
* @author Toasta
*/
public class TreeCheckSelectionListener extends SelectionAdapter {
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
@Override
public void widgetSelected(SelectionEvent event) {
if (event.detail == SWT.CHECK) {
this.handleCheckedItem((TreeItem) event.item);
}
}
/**
* Updates the check-status of every affected <code>TreeItem</code> if the given item has been checked or unchecked.
* @param item the <code>TreeItem</code>
*/
private void handleCheckedItem(TreeItem item) {
//somebody selected the item, so it can't be grayed
item.setGrayed(false);
//check all children of the selected item
this.checkAllChildren(item);
//check all parents of the selected item
this.checkAllParents(item);
}
/**
* Checks all children of the given <code>TreeItem</code> like that item (checked or unchecked).
* <code>Grayed</code> is set to <code>false</code> at all children in any case, because every child
* just can be checked or unchecked.
* @param parent the <code>TreeItem</code>
*/
private void checkAllChildren(TreeItem parent) {
for (TreeItem child : parent.getItems()) {
child.setChecked(parent.getChecked());
child.setGrayed(false);
this.checkAllChildren(child);
}
}
/**
* Checks all parents of the given <code>TreeItem</code> depend on the check-status of their cildren.
* @param item the <code>TreeItem</code>
*/
private void checkAllParents(TreeItem item) {
TreeItem parent = item.getParentItem();
if (parent!=null) {
if (allDirectChildrenChecked(parent)) {
parent.setGrayed(false);
parent.setChecked(true);
} else {
if (allDirectChildrenUnchecked(parent)) {
parent.setGrayed(false);
parent.setChecked(false);
} else {
parent.setGrayed(true);
parent.setChecked(true);
}
}
this.checkAllParents(parent);
}
}
/**
* Returns whether all direct children of the given parent are really checked or not.
* Really checked means, that all children are checked without being grayed.
* @param parent the <code>TreeItem</code>
* @return <code>true</code>, if all direct children of the given parent are really checked, <code>false</code> otherwise
*/
private boolean allDirectChildrenChecked(TreeItem parent) {
TreeItem[] children = parent.getItems();
for (TreeItem child : children) {
if (!child.getChecked() || (child.getChecked() && child.getGrayed())) {
return false;
}
}
return true;
}
/**
* Returns whether all direct children of the given parent are really unchecked or not.
* Really unchecked means, that all children are unchecked never mind being grayed or not.
* @param parent the <code>TreeItem</code>
* @return <code>true</code>, if all direct children of the given parent are unchecked, <code>false</code> otherwise
*/
private boolean allDirectChildrenUnchecked(TreeItem parent) {
TreeItem[] children = parent.getItems();
for (TreeItem child : children) {
if (child.getChecked()) {
return false;
}
}
return true;
}
}