(refs #7568) Reinitialize diagram editor when element is switched
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / actions / SwitchComponentTypeContribution.java
1 /*******************************************************************************
2  * Copyright (c) 2017 Association for Decentralized Information Management in
3  * Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     Semantum Oy - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.modeling.ui.actions;
13
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.List;
17
18 import org.eclipse.jface.action.ContributionItem;
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.events.SelectionAdapter;
21 import org.eclipse.swt.events.SelectionEvent;
22 import org.eclipse.swt.widgets.Menu;
23 import org.eclipse.swt.widgets.MenuItem;
24 import org.simantics.Simantics;
25 import org.simantics.db.ReadGraph;
26 import org.simantics.db.Resource;
27 import org.simantics.db.WriteGraph;
28 import org.simantics.db.common.request.UnaryRead;
29 import org.simantics.db.common.request.WriteRequest;
30 import org.simantics.db.exception.DatabaseException;
31 import org.simantics.layer0.Layer0;
32 import org.simantics.modeling.MigrateModel;
33 import org.simantics.modeling.ModelingResources;
34 import org.simantics.modeling.ui.diagramEditor.DiagramEditor;
35 import org.simantics.structural.stubs.StructuralResource2;
36 import org.simantics.ui.utils.ResourceAdaptionUtils;
37 import org.simantics.utils.ui.SWTUtils;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 /**
42  * @author Hannu Niemist√∂
43  * @since 1.31.0
44  */
45 public class SwitchComponentTypeContribution extends ContributionItem {
46     private static final Logger LOGGER = LoggerFactory.getLogger(SwitchComponentTypeContribution.class);
47     
48     private static class SwitchGroup implements Comparable<SwitchGroup> {
49         final String label;
50         final ArrayList<Alternative> alternatives = new ArrayList<Alternative>();
51         
52         public SwitchGroup(String label) {
53             this.label = label;
54         }
55
56         @Override
57         public int compareTo(SwitchGroup o) {
58             return label.compareTo(o.label);
59         }
60     }
61     
62     private static class Alternative implements Comparable<Alternative> {
63         final String label;
64         final Resource componentType;
65         final boolean isCurrent;
66         
67         public Alternative(String label, Resource componentType, boolean isCurrent) {
68             this.label = label;
69             this.componentType = componentType;
70             this.isCurrent = isCurrent;
71         }
72         
73         @Override
74         public int compareTo(Alternative o) {
75             return label.compareTo(o.label);
76         }
77     }
78     
79     @Override
80     public void fill(Menu menu, int index) {
81         Resource resource = ResourceAdaptionUtils.toSingleWorkbenchResource();
82         if(resource == null)
83             return;
84         
85         List<SwitchGroup> groups;
86         try {
87             groups = Simantics.getSession().syncRequest(new ComponentSwitchGroupQuery(resource));
88         } catch (DatabaseException e) {
89             LOGGER.error("Retrieval of switch groups failed.", e);
90             return;
91         }
92         
93         if(!groups.isEmpty()) {
94             SelectionAdapter switchAction = new SelectionAdapter() {
95                 @Override
96                 public void widgetSelected(SelectionEvent e) {
97                     Resource newComponentType = (Resource)e.widget.getData();
98                     Simantics.getSession().asyncRequest(new WriteRequest() {
99                         @Override
100                         public void perform(WriteGraph graph) throws DatabaseException {
101                             Resource component = elementToComponent(graph, resource);
102                             MigrateModel.changeComponentType(graph, component, newComponentType);
103
104                             Layer0 L0 = Layer0.getInstance(graph);
105                             Resource composite = graph.getPossibleObject(component, L0.PartOf);
106                             if (composite == null)
107                                 return;
108                             ModelingResources MOD = ModelingResources.getInstance(graph);
109                             Resource diagram = graph.getPossibleObject(composite, MOD.CompositeToDiagram);
110                             if (diagram == null)
111                                 return;
112                             SWTUtils.asyncExec(menu, () -> DiagramEditor.reinitializeDiagram(diagram));
113                         }
114                     });
115                 }
116             };
117             for(SwitchGroup group : groups) {
118                 MenuItem item = new MenuItem(menu, SWT.CASCADE);
119                 item.setText(group.label);
120
121                 Menu subMenu = new Menu(menu);
122                 item.setMenu(subMenu);
123
124                 for(Alternative alternative : group.alternatives) {
125                     MenuItem subItem = new MenuItem(subMenu, SWT.PUSH);
126                     subItem.setText(alternative.label);
127                     subItem.setData(alternative.componentType);
128                     if(alternative.isCurrent)
129                         subItem.setEnabled(false);
130                     else
131                         subItem.addSelectionListener(switchAction);
132                 }
133             }
134         }
135     }
136     
137     private static class ComponentSwitchGroupQuery extends UnaryRead<Resource, List<SwitchGroup>> {
138         public ComponentSwitchGroupQuery(Resource parameter) {
139             super(parameter);
140         }
141
142         @Override
143         public List<SwitchGroup> perform(ReadGraph graph) throws DatabaseException {
144             StructuralResource2 STR = StructuralResource2.getInstance(graph);
145             ModelingResources MOD = ModelingResources.getInstance(graph);
146             Resource component = elementToComponent(graph, parameter);
147             
148             Resource componentType = graph.getPossibleType(component, STR.Component);
149             if(componentType == null)
150                 return Collections.emptyList();
151             
152             Layer0 L0 = Layer0.getInstance(graph);
153             ArrayList<SwitchGroup> result = new ArrayList<SwitchGroup>();
154             for(Resource myAlt : graph.getObjects(componentType, MOD.BelongsToComponentSwitchGroup)) {
155                 Resource group = graph.getSingleObject(myAlt, MOD.ComponentSwitchGroup_alternative_Inverse);
156                 
157                 SwitchGroup groupObj;
158                 {
159                     String label = graph.getPossibleRelatedValue(group, L0.HasLabel);
160                     if(label == null) {
161                         label = graph.getPossibleRelatedValue(group, L0.HasName);
162                         if(label == null)
163                             label = "Alternative types";
164                     }
165                     groupObj = new SwitchGroup(label);
166                 }
167                 
168                 for(Resource alt : graph.getObjects(group, MOD.ComponentSwitchGroup_alternative)) {
169                     Resource altComponentType = graph.getSingleObject(alt, MOD.ComponentSwitchAlternative_componentType);
170                     String label = graph.getPossibleRelatedValue(alt, L0.HasLabel);
171                     if(label == null) {
172                         label = graph.getPossibleRelatedValue(alt, L0.HasName);
173                         if(label == null) {
174                             label = graph.getPossibleRelatedValue(altComponentType, L0.HasLabel);
175                             if(label == null)
176                                 label = graph.getRelatedValue(altComponentType, L0.HasName);
177                         }
178                     }
179                     groupObj.alternatives.add(new Alternative(label, altComponentType, altComponentType.equals(componentType)));
180                 }
181                 Collections.sort(groupObj.alternatives);
182                 result.add(groupObj);
183             }
184             Collections.sort(result);
185             return result;
186         }
187     }
188
189     private static Resource elementToComponent(ReadGraph graph, Resource element) throws DatabaseException {
190         ModelingResources MOD = ModelingResources.getInstance(graph);
191         Resource component = graph.getPossibleObject(element, MOD.ElementToComponent);
192         if(component != null)
193             return component;
194         else
195             return element;
196     }
197     
198 }