X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.modeling.ui%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Fui%2Factions%2FConfigureConnectionTypes.java;fp=bundles%2Forg.simantics.modeling.ui%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Fui%2Factions%2FConfigureConnectionTypes.java;h=20bb053db057817ae9f901f72e6817b1e62333ff;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/actions/ConfigureConnectionTypes.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/actions/ConfigureConnectionTypes.java new file mode 100644 index 000000000..20bb053db --- /dev/null +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/actions/ConfigureConnectionTypes.java @@ -0,0 +1,307 @@ +/******************************************************************************* + * Copyright (c) 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.modeling.ui.actions; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.viewers.ICheckStateProvider; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.ui.PlatformUI; +import org.simantics.Simantics; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.PossibleIndexRoot; +import org.simantics.db.common.request.UniqueRead; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.adapter.ActionFactory; +import org.simantics.db.layer0.adapter.ActionFactory2; +import org.simantics.db.request.Read; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.modeling.AssignConnectionTypesRequest; +import org.simantics.modeling.GetConnectionTypes; +import org.simantics.structural2.modelingRules.AllowedConnectionTypes; +import org.simantics.utils.strings.AlphanumComparator; +import org.simantics.utils.ui.ErrorLogger; +import org.simantics.utils.ui.dialogs.ShowMessage; + +/** + * @author Antti Villberg + */ +public class ConfigureConnectionTypes implements ActionFactory, ActionFactory2 { + + @Override + public Runnable create(Collection targets) { + final ArrayList resources = new ArrayList(); + for (Object target : targets) { + if (!(target instanceof Resource)) + return null; + resources.add((Resource) target); + } + return new Runnable() { + @Override + public void run() { + assignTypes(resources); + } + }; + } + + @Override + public Runnable create(Object target) { + if(!(target instanceof Resource)) + return null; + final Resource connectionPoint = (Resource)target; + return new Runnable() { + @Override + public void run() { + assignTypes(Collections.singletonList(connectionPoint)); + } + }; + } + + private static final ConnectionType[] NO_CONNECTION_TYPES = new ConnectionType[0]; + + static enum Tristate { + NONE, SOME, ALL; + + public static Tristate add(Tristate current, boolean next) { + if (current == null) + return next ? ALL : NONE; + switch (current) { + case ALL: return next ? ALL : SOME; + case SOME: return next ? SOME : SOME; + case NONE: return next ? SOME : NONE; + default: return NONE; + } + } + } + + private static class ConnectionType implements Comparable { + Resource resource; + String name; + Tristate originallySelected; + Tristate selected; + + public ConnectionType(Resource resource, String name, Tristate originallySelected, Tristate selected) { + super(); + this.resource = resource; + this.name = name; + this.originallySelected = originallySelected; + this.selected = selected; + } + + @Override + public int compareTo(ConnectionType o) { + return AlphanumComparator.CASE_INSENSITIVE_COMPARATOR.compare(name, o.name); + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[name=" + name + + ", originally selected=" + originallySelected + + ", selected=" + selected + "]"; + } + } + + private static class ContentProviderImpl implements IStructuredContentProvider { + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + @Override + public void dispose() { + } + + @Override + public Object[] getElements(Object inputElement) { + return (Object[])inputElement; + } + }; + + private static class LabelProviderImpl extends LabelProvider { + @Override + public String getText(Object element) { + return ((ConnectionType)element).name; + } + } + + private static class CheckStateProviderImpl implements ICheckStateProvider { + @Override + public boolean isChecked(Object element) { + return ((ConnectionType) element).selected != Tristate.NONE; + } + @Override + public boolean isGrayed(Object element) { + return ((ConnectionType) element).selected == Tristate.SOME; + } + } + + private static Resource getCommonModel(final Collection connectionPoints) { + try { + return Simantics.sync(new UniqueRead() { + @Override + public Resource perform(ReadGraph graph) throws DatabaseException { + return getPossibleIndexRoot(graph, connectionPoints); + } + }); + } catch (DatabaseException e) { + ErrorLogger.defaultLogError(e); + return null; + } + } + + private static Resource getPossibleIndexRoot(ReadGraph g, Collection connectionPoints) throws DatabaseException { + Resource model = null; + for (Resource connectionPoint : connectionPoints) { + Resource m = getIndexRootOf(g, connectionPoint); + if (m == null) + return null; + if (model == null) + model = m; + else if (!model.equals(m)) + return null; + } + return model; + } + + private static Resource getIndexRootOf(ReadGraph g, Resource connectionPoint) throws DatabaseException { + return g.syncRequest(new PossibleIndexRoot(connectionPoint)); + } + + private static ConnectionType[] getConnectionTypes(final Collection connectionPoints) { + try { + return Simantics.getSession().syncRequest(new Read() { + @Override + public ConnectionType[] perform(ReadGraph g) throws DatabaseException { + return getConnectionTypes(g, connectionPoints); + } + }); + } catch(DatabaseException e) { + e.printStackTrace(); + return NO_CONNECTION_TYPES; + } + } + + private static ConnectionType[] getConnectionTypes(ReadGraph g, Collection connectionPoints) throws DatabaseException { + Resource root = getPossibleIndexRoot(g, connectionPoints); + if (root == null) + return NO_CONNECTION_TYPES; + // All connection points have same index root. + // Resolve the connection type selection states now. + ArrayList result = new ArrayList(); + DiagramResource DIA = DiagramResource.getInstance(g); + for (Resource type : GetConnectionTypes.getConnectionTypes(g, root)) { + Tristate selected = getConnectionTypeSelectionState(g, type, connectionPoints, DIA); + selected = selected != null ? selected : Tristate.NONE; + result.add( new ConnectionType( + type, + NameUtils.getSafeLabel(g, type), + selected, + selected) ); + } + //System.out.println("result: " + EString.implode(result)); + Collections.sort(result); + //System.out.println("sorted result: " + EString.implode(result)); + return result.toArray(new ConnectionType[result.size()]); + } + + protected static Tristate getConnectionTypeSelectionState(ReadGraph graph, Resource connectionType, + Collection connectionPoints, DiagramResource DIA) throws DatabaseException { + Tristate selected = null; + for (Resource connectionPoint : connectionPoints) { + Collection allowed = graph.syncRequest(new AllowedConnectionTypes(connectionPoint)); + selected = Tristate.add(selected, allowed.contains(connectionType)); + } + return selected != null ? selected : Tristate.NONE; + } + + private static ConnectionType[] selectedElements(ConnectionType[] connectionTypes) { + int count = 0; + for(ConnectionType connectionType : connectionTypes) + if(connectionType.selected != Tristate.NONE) + ++count; + ConnectionType[] result = new ConnectionType[count]; + count = 0; + for(ConnectionType connectionType : connectionTypes) + if(connectionType.selected != Tristate.NONE) + result[count++] = connectionType; + return result; + } + + public void assignTypes(final Collection connectionPoints) { + if (connectionPoints.isEmpty()) + return; + + final Resource indexRoot = getCommonModel(connectionPoints); + if (indexRoot == null) { + ShowMessage.showInformation("Same Model Required", "All the selected connection points must be from within the same index root."); + return; + } + + final AtomicReference types = + new AtomicReference( getConnectionTypes(connectionPoints) ); + + StringBuilder message = new StringBuilder(); + if (connectionPoints.size() > 1) + message.append("Select connection types for the selected connection points"); + else + message.append("Select connection types for the selected connection point"); + + ConfigureConnectionTypesDialog dialog = new ConfigureConnectionTypesDialog( + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), + types.get(), + new ContentProviderImpl(), + new LabelProviderImpl(), + new CheckStateProviderImpl(), + message.toString()) { + + @Override + protected void checkStateChanged(Object[] elements, boolean checked) { + for (Object _g : elements) { + ConnectionType g = (ConnectionType) _g; + g.selected = checked ? Tristate.ALL : Tristate.NONE; + // Refresh checked states through provider. + listViewer.refresh(); + } + } + + }; + dialog.setTitle("Connection Type Assignments"); + dialog.setInitialSelections(selectedElements(types.get())); + if (dialog.open() == Dialog.OK) { + final ArrayList added = new ArrayList(); + final ArrayList removed = new ArrayList(); + for (ConnectionType g : types.get()) { + if (g.selected != g.originallySelected && g.selected == Tristate.ALL) + added.add(g); + if (g.selected != g.originallySelected && g.selected == Tristate.NONE) + removed.add(g); + } + if (!added.isEmpty() || !removed.isEmpty()) { + ArrayList addedConnectionTypes = new ArrayList(); + ArrayList removedConnectionTypes = new ArrayList(); + for (ConnectionType type : added) + addedConnectionTypes.add(type.resource); + for (ConnectionType type : removed) + removedConnectionTypes.add(type.resource); + Simantics.getSession().asyncRequest(new AssignConnectionTypesRequest(addedConnectionTypes, removedConnectionTypes, connectionPoints)); + } + } + } + +}