/******************************************************************************* * Copyright (c) 2007, 2012 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.browsing.ui.swt; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import org.simantics.browsing.ui.BuiltinKeys; import org.simantics.browsing.ui.NodeContext; import org.simantics.browsing.ui.NodeContext.PrimitiveQueryKey; import org.simantics.browsing.ui.PrimitiveQueryUpdater; import org.simantics.browsing.ui.common.property.IProperty; import org.simantics.browsing.ui.common.property.PropertyComparable; import org.simantics.browsing.ui.common.property.PropertyComparator; import org.simantics.utils.strings.EString; import org.simantics.utils.ui.AdaptionUtils; /** * A custom processor implementation for the {@link BuiltinKeys#IS_EXPANDED} * primitive query that specially handles all {@link NodeContext}s that contain * {@link PropertyComparable} inputs. * *

* This class is needed because default values for properties are generally * asserted and adding instance properties for subjects with default values * causes the data contained by IProperty instances to change. For this reason * {@link PropertyComparable} contains two methods: * {@link IProperty#propertyHashCode()} and * {@link PropertyComparable#propertyEquals(Object)} for comparing whether * two {@link PropertyComparable} instances represent the same property of the * same subject, regardless of the property value. This allows the UI to * correctly expand tree nodes for record-type and array-valued properties when * the value changes from asserted to direct or vice versa. * * @author Tuukka Lehtonen * * @see BuiltinKeys#IS_EXPANDED * @see IProperty * @see PropertyComparator */ public class PropertyIsExpandedProcessor extends DefaultIsExpandedProcessor { private static final boolean DEBUG = false; private final Set expandedProperties = new TreeSet(PropertyComparator.INSTANCE); private final Map expandedPropertyQueries = new TreeMap(PropertyComparator.INSTANCE); @Override public String toString() { return "PropertyIsExpandedProcessor"; } private PropertyComparable getProperty(NodeContext context) { return AdaptionUtils.adaptToSingle(context, PropertyComparable.class); } @Override public boolean setExpanded(NodeContext context, boolean expanded) { PropertyComparable prop = getProperty(context); if (prop != null) return _setExpanded(prop, expanded); return super.setExpanded(context, expanded); } private boolean _setExpanded(PropertyComparable prop, boolean expanded) { if (expanded) { return expandedProperties.add(prop); } else { return expandedProperties.remove(prop); } } @Override public Boolean query(PrimitiveQueryUpdater updater, NodeContext context, PrimitiveQueryKey key) { if (DEBUG) System.out.println("QUERY(" + context + ")"); PropertyComparable prop = getProperty(context); if (prop != null) { if (DEBUG) System.out.println("expanded properties:\n" + EString.implode(expandedProperties, "\n\t")); boolean isExpanded = expandedProperties.contains(prop); if (DEBUG) System.out.println("property.isExpanded(" + updater + ", " + prop + "): " + isExpanded); expandedPropertyQueries.put(prop, updater); return Boolean.valueOf(isExpanded); } return super.query(updater, context, key); } @Override protected boolean nodeStatusChanged(NodeContext context, boolean expanded) { boolean result = false; PropertyComparable prop = getProperty(context); if (prop != null) { if (DEBUG) System.out.println("nodeStatusChanged(" + prop + ", " + expanded + ")"); result = _setExpanded(prop, expanded); PrimitiveQueryUpdater updater = expandedPropertyQueries.get(prop); if (updater != null) updater.scheduleReplace(context, BuiltinKeys.IS_EXPANDED, expanded); } else { result = super.nodeStatusChanged(context, expanded); } return result; } @Override public void clear() { expandedProperties.clear(); expandedPropertyQueries.clear(); super.clear(); } }