/******************************************************************************* * Copyright (c) 2017 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: * Semantum Oy - initial API and implementation *******************************************************************************/ 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.modeling.ui.diagramEditor.DiagramEditor; import org.simantics.structural.stubs.StructuralResource2; import org.simantics.ui.utils.ResourceAdaptionUtils; import org.simantics.utils.ui.SWTUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Hannu Niemistö * @since 1.31.0 */ public class SwitchComponentTypeContribution extends ContributionItem { private static final Logger LOGGER = LoggerFactory.getLogger(SwitchComponentTypeContribution.class); private static class SwitchGroup implements Comparable { final String label; final ArrayList alternatives = new ArrayList(); public SwitchGroup(String label) { this.label = label; } @Override public int compareTo(SwitchGroup o) { return label.compareTo(o.label); } } private static class Alternative implements Comparable { 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 groups; try { groups = Simantics.getSession().syncRequest(new ComponentSwitchGroupQuery(resource)); } catch (DatabaseException e) { LOGGER.error("Retrieval of switch groups failed.", e); //$NON-NLS-1$ 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 { Resource component = elementToComponent(graph, resource); MigrateModel.changeComponentType(graph, component, newComponentType); Layer0 L0 = Layer0.getInstance(graph); Resource composite = graph.getPossibleObject(component, L0.PartOf); if (composite == null) return; ModelingResources MOD = ModelingResources.getInstance(graph); Resource diagram = graph.getPossibleObject(composite, MOD.CompositeToDiagram); if (diagram == null) return; SWTUtils.asyncExec(menu, () -> DiagramEditor.reinitializeDiagram(diagram)); } }); } }; 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> { public ComponentSwitchGroupQuery(Resource parameter) { super(parameter); } @Override public List 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 result = new ArrayList(); 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 = Messages.SwitchComponentTypeContribution_AlternativeTypes; } 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; } }