--- /dev/null
+package org.simantics.modeling.ui.actions;
+
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.UnaryRead;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.layer0.Layer0;
+import org.simantics.modeling.MigrateModel;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.structural.stubs.StructuralResource2;
+import org.simantics.ui.utils.ResourceAdaptionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SwitchComponentTypeContribution extends ContributionItem {
+ private static final Logger LOGGER = LoggerFactory.getLogger(SwitchComponentTypeContribution.class);
+
+ private static class SwitchGroup implements Comparable<SwitchGroup> {
+ final String label;
+ final ArrayList<Alternative> alternatives = new ArrayList<Alternative>();
+
+ public SwitchGroup(String label) {
+ this.label = label;
+ }
+
+ @Override
+ public int compareTo(SwitchGroup o) {
+ return label.compareTo(o.label);
+ }
+ }
+
+ private static class Alternative implements Comparable<Alternative> {
+ final String label;
+ final Resource componentType;
+ final boolean isCurrent;
+
+ public Alternative(String label, Resource componentType, boolean isCurrent) {
+ this.label = label;
+ this.componentType = componentType;
+ this.isCurrent = isCurrent;
+ }
+
+ @Override
+ public int compareTo(Alternative o) {
+ return label.compareTo(o.label);
+ }
+ }
+
+ @Override
+ public void fill(Menu menu, int index) {
+ Resource resource = ResourceAdaptionUtils.toSingleWorkbenchResource();
+ if(resource == null)
+ return;
+
+ List<SwitchGroup> groups;
+ try {
+ groups = Simantics.getSession().syncRequest(new ComponentSwitchGroupQuery(resource));
+ } catch (DatabaseException e) {
+ LOGGER.error("Retrieval of switch groups failed.", e);
+ return;
+ }
+
+ if(!groups.isEmpty()) {
+ SelectionAdapter switchAction = new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ Resource newComponentType = (Resource)e.widget.getData();
+ Simantics.getSession().asyncRequest(new WriteRequest() {
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ MigrateModel.changeComponentType(graph, elementToComponent(graph, resource), newComponentType);
+ }
+ });
+ }
+ };
+ for(SwitchGroup group : groups) {
+ MenuItem item = new MenuItem(menu, SWT.CASCADE);
+ item.setText(group.label);
+
+ Menu subMenu = new Menu(menu);
+ item.setMenu(subMenu);
+
+ for(Alternative alternative : group.alternatives) {
+ MenuItem subItem = new MenuItem(subMenu, SWT.PUSH);
+ subItem.setText(alternative.label);
+ subItem.setData(alternative.componentType);
+ if(alternative.isCurrent)
+ subItem.setEnabled(false);
+ else
+ subItem.addSelectionListener(switchAction);
+ }
+ }
+ }
+ }
+
+ private static class ComponentSwitchGroupQuery extends UnaryRead<Resource, List<SwitchGroup>> {
+ public ComponentSwitchGroupQuery(Resource parameter) {
+ super(parameter);
+ }
+
+ @Override
+ public List<SwitchGroup> perform(ReadGraph graph) throws DatabaseException {
+ StructuralResource2 STR = StructuralResource2.getInstance(graph);
+ ModelingResources MOD = ModelingResources.getInstance(graph);
+ Resource component = elementToComponent(graph, parameter);
+
+ Resource componentType = graph.getPossibleType(component, STR.Component);
+ if(componentType == null)
+ return Collections.emptyList();
+
+ Layer0 L0 = Layer0.getInstance(graph);
+ ArrayList<SwitchGroup> result = new ArrayList<SwitchGroup>();
+ for(Resource myAlt : graph.getObjects(componentType, MOD.BelongsToComponentSwitchGroup)) {
+ Resource group = graph.getSingleObject(myAlt, MOD.ComponentSwitchGroup_alternative_Inverse);
+
+ SwitchGroup groupObj;
+ {
+ String label = graph.getPossibleRelatedValue(group, L0.HasLabel);
+ if(label == null) {
+ label = graph.getPossibleRelatedValue(group, L0.HasName);
+ if(label == null)
+ label = "Alternative types";
+ }
+ groupObj = new SwitchGroup(label);
+ }
+
+ for(Resource alt : graph.getObjects(group, MOD.ComponentSwitchGroup_alternative)) {
+ Resource altComponentType = graph.getSingleObject(alt, MOD.ComponentSwitchAlternative_componentType);
+ String label = graph.getPossibleRelatedValue(alt, L0.HasLabel);
+ if(label == null) {
+ label = graph.getPossibleRelatedValue(alt, L0.HasName);
+ if(label == null) {
+ label = graph.getPossibleRelatedValue(altComponentType, L0.HasLabel);
+ if(label == null)
+ label = graph.getRelatedValue(altComponentType, L0.HasName);
+ }
+ }
+ groupObj.alternatives.add(new Alternative(label, altComponentType, altComponentType.equals(componentType)));
+ }
+ Collections.sort(groupObj.alternatives);
+ result.add(groupObj);
+ }
+ Collections.sort(result);
+ return result;
+ }
+ }
+
+ private static Resource elementToComponent(ReadGraph graph, Resource element) throws DatabaseException {
+ ModelingResources MOD = ModelingResources.getInstance(graph);
+ Resource component = graph.getPossibleObject(element, MOD.ElementToComponent);
+ if(component != null)
+ return component;
+ else
+ return element;
+ }
+
+}