diff -r 14dc2103a631 -r ed1c9f64298a trace/tracebuilder/com.nokia.tracebuilder.view/src/com/nokia/tracebuilder/view/CheckListCheckStateListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trace/tracebuilder/com.nokia.tracebuilder.view/src/com/nokia/tracebuilder/view/CheckListCheckStateListener.java Wed Jun 23 14:35:40 2010 +0300 @@ -0,0 +1,194 @@ +/* +* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +* State listener for tree viewer check boxes +* +*/ +package com.nokia.tracebuilder.view; + +import java.util.Iterator; + +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTreeViewer; +import org.eclipse.jface.viewers.ICheckStateListener; + +import com.nokia.tracebuilder.engine.CheckListDialogEntry; + +/** + * State listener for tree viewer check boxes + * + */ +final class CheckListCheckStateListener implements ICheckStateListener { + + /** + * Content provider + */ + private final CheckboxTreeViewer viewer; + + /** + * Constructor + * + * @param viewer + * the viewer + */ + CheckListCheckStateListener(CheckboxTreeViewer viewer) { + this.viewer = viewer; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.ICheckStateListener# + * checkStateChanged(org.eclipse.jface.viewers.CheckStateChangedEvent) + */ + public void checkStateChanged(CheckStateChangedEvent event) { + CheckListDialogEntry entry = (CheckListDialogEntry) event.getElement(); + boolean newState = event.getChecked(); + // View update is not needed with the entry that was clicked by user + checkEntryAndRelatives(entry, newState, false); + } + + /** + * Changes the state of an entry, its parent and children + * + * @param entry + * the entry + * @param newState + * the new entry state + * @param updateView + * true if view needs to be updated + * @return true if entries were changed + */ + private boolean checkEntryAndRelatives(CheckListDialogEntry entry, + boolean newState, boolean updateView) { + boolean changed = checkEntry(entry, newState, updateView); + if (changed) { + viewer.setSubtreeChecked(entry, newState); + checkChildren(entry, newState); + checkParent(entry); + } + return changed; + } + + /** + * Checks the children of given entry + * + * @param entry + * the entry + * @param newState + * the new state + */ + private void checkChildren(CheckListDialogEntry entry, boolean newState) { + for (CheckListDialogEntry child : entry) { + child.setChecked(newState); + checkChildren(child, newState); + } + } + + /** + * Checks an entry and unchecks the partially checked flag if it exists + * + * @param entry + * the entry + * @param newState + * the new entry state + * @param updateView + * true if view needs to be updated + * @return true if entry was changed + */ + private boolean checkEntry(CheckListDialogEntry entry, boolean newState, + boolean updateView) { + boolean retval; + if (entry.isChecked() != newState) { + entry.setChecked(newState); + if (entry.isPartiallyChecked()) { + entry.setPartiallyChecked(false); + viewer.setGrayChecked(entry, false); + } + if (updateView) { + viewer.setChecked(entry, newState); + } + retval = true; + } else { + retval = false; + } + return retval; + } + + /** + * Recursively checks the parent of the checked element. If all children are + * checked, the parent is checked. If all children are unchecked, the parent + * is unchecked. If children are partially checked, the parent is grayed. + * + * @param entry + * the entry whose parent needs to be checked + */ + private void checkParent(CheckListDialogEntry entry) { + CheckListDialogEntry parent = entry.getParent(); + if (parent != null && parent.hasChildren()) { + boolean checked = false; + boolean unchecked = false; + boolean partiallyChecked = false; + Iterator children = parent.getChildren(); + while (children.hasNext() && !partiallyChecked) { + CheckListDialogEntry child = children.next(); + boolean childChecked = child.isChecked(); + boolean childPartial = child.isPartiallyChecked(); + if (childPartial) { + partiallyChecked = true; + } else if (childChecked) { + checked = true; + if (unchecked) { + partiallyChecked = true; + } + } else { + unchecked = true; + if (checked) { + partiallyChecked = true; + } + } + } + if (partiallyChecked) { + if (!parent.isPartiallyChecked()) { + viewer.setGrayChecked(parent, true); + parent.setPartiallyChecked(true); + } else if (!parent.isChecked()) { + viewer.setChecked(parent, true); + } + // Checked flag needs to be set in both cases + parent.setChecked(true); + } else if (checked) { + if (parent.isPartiallyChecked()) { + viewer.setGrayed(parent, false); + parent.setPartiallyChecked(false); + } + if (!parent.isChecked()) { + viewer.setChecked(parent, true); + parent.setChecked(true); + } + } else { + if (parent.isPartiallyChecked()) { + viewer.setGrayChecked(parent, false); + parent.setPartiallyChecked(false); + } else if (parent.isChecked()) { + viewer.setChecked(parent, false); + } + // Checked flag needs to be set in both cases + parent.setChecked(false); + } + checkParent(parent); + } + } +}