diff --git a/plugins/org.eclipse.fordiac.ide.application/META-INF/MANIFEST.MF b/plugins/org.eclipse.fordiac.ide.application/META-INF/MANIFEST.MF index 42f053ac25..c40b25de84 100644 --- a/plugins/org.eclipse.fordiac.ide.application/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.fordiac.ide.application/META-INF/MANIFEST.MF @@ -37,3 +37,5 @@ Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.fordiac.ide.application;singleton:=true Bundle-RequiredExecutionEnvironment: JavaSE-21 Automatic-Module-Name: org.eclipse.fordiac.ide.application +Import-Package: org.eclipse.ltk.core.refactoring, + org.eclipse.ltk.ui.refactoring diff --git a/plugins/org.eclipse.fordiac.ide.application/plugin.xml b/plugins/org.eclipse.fordiac.ide.application/plugin.xml index 69921a425a..b712937441 100644 --- a/plugins/org.eclipse.fordiac.ide.application/plugin.xml +++ b/plugins/org.eclipse.fordiac.ide.application/plugin.xml @@ -1857,4 +1857,18 @@ type="java.lang.Object"> + + + + + + + + + + diff --git a/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/actions/FBNetworkSelectAllAction.java b/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/actions/FBNetworkSelectAllAction.java index c3171d6e34..9e4ae23f35 100644 --- a/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/actions/FBNetworkSelectAllAction.java +++ b/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/actions/FBNetworkSelectAllAction.java @@ -10,6 +10,8 @@ * Contributors: * Alois Zoitl, Filip Andren * - initial API and implementation and/or initial documentation + * Martin Schwarz + * - Build fixes *******************************************************************************/ package org.eclipse.fordiac.ide.application.actions; @@ -22,6 +24,7 @@ import org.eclipse.gef.EditPart; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gef.GraphicalViewer; +import org.eclipse.gef.editparts.AbstractGraphicalEditPart; import org.eclipse.gef.ui.actions.SelectAllAction; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.ui.IWorkbenchPart; @@ -48,7 +51,7 @@ private static List getSelectableEditParts(final GraphicalViewer viewe for (final Object child : children) { if ((child instanceof AbstractFBNElementEditPart) || (child instanceof GroupEditPart)) { - final GraphicalEditPart childPart = (GraphicalEditPart) child; + final EditPart childPart = (EditPart) child; if (childPart.isSelectable()) { selectableChildren.add(childPart); addConnectionsTo(selectableChildren, childPart); @@ -58,14 +61,19 @@ private static List getSelectableEditParts(final GraphicalViewer viewe return Collections.unmodifiableList(selectableChildren); } - private static void addConnectionsTo(final List selectableChildren, final GraphicalEditPart child) { + private static void addConnectionsTo(final List selectableChildren, final EditPart child) { // the editparts are in charge of managing the connections if we take all source // connections // from one edit part we should get all connections in the end. - for (final GraphicalEditPart elementChild : child.getChildren()) { - elementChild.getSourceConnections().stream().filter(EditPart::isSelectable) - .forEach(selectableChildren::add); + final List elementChildren = child.getChildren(); + for (final Object elementChild : elementChildren) { + if (elementChild instanceof AbstractGraphicalEditPart) { + final List connections = ((AbstractGraphicalEditPart) elementChild) + .getSourceConnections(); + connections.stream().filter(EditPart::isSelectable).forEach(selectableChildren::add); + } + } } diff --git a/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/commands/ResizeGroupOrSubappCommand.java b/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/commands/ResizeGroupOrSubappCommand.java index 827153ca2b..ef7fd53336 100644 --- a/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/commands/ResizeGroupOrSubappCommand.java +++ b/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/commands/ResizeGroupOrSubappCommand.java @@ -9,6 +9,7 @@ * * Contributors: * Fabio Gandolfi - initial implementation and/or documentation + * Martin Schwarz - Build fixes *******************************************************************************/ package org.eclipse.fordiac.ide.application.commands; diff --git a/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/editors/ApplicationEditor.java b/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/editors/ApplicationEditor.java index b2a589c32b..80d67eba60 100644 --- a/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/editors/ApplicationEditor.java +++ b/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/editors/ApplicationEditor.java @@ -37,6 +37,7 @@ public void notifyChanged(final Notification notification) { @Override public void setInput(final IEditorInput input) { + System.out.println("ApplicationEditorInput called"); if (input instanceof final ApplicationEditorInput appInput) { final Application app = appInput.getContent(); setModel(app.getFBNetwork()); diff --git a/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/editors/FBNetworkEditor.java b/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/editors/FBNetworkEditor.java index d61a9482bd..165c55fa87 100644 --- a/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/editors/FBNetworkEditor.java +++ b/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/editors/FBNetworkEditor.java @@ -99,6 +99,8 @@ public FBNetwork getModel() { * Instantiates a new fB network editor. */ public FBNetworkEditor() { + System.out.println("FBNetworkEditor called"); + // empty constructor } diff --git a/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/policies/ContainerContentLayoutPolicy.java b/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/policies/ContainerContentLayoutPolicy.java index 28c0f2e53b..bbcc056aaa 100644 --- a/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/policies/ContainerContentLayoutPolicy.java +++ b/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/application/policies/ContainerContentLayoutPolicy.java @@ -14,6 +14,7 @@ * Alois Zoitl - extracted most code into common base class for group * infrastructure * - extracted this policy from the AbstractContainerContentEditPart + * Martin Schwarz - Build fixes *******************************************************************************/ package org.eclipse.fordiac.ide.application.policies; diff --git a/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/applications/previews/ProjectChangePreviewViewer.java b/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/applications/previews/ProjectChangePreviewViewer.java new file mode 100644 index 0000000000..99516b32f6 --- /dev/null +++ b/plugins/org.eclipse.fordiac.ide.application/src/org/eclipse/fordiac/ide/applications/previews/ProjectChangePreviewViewer.java @@ -0,0 +1,189 @@ +/******************************************************************************* + * Copyright (c) 2024 Johannes Kepler University + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Martin Schwarz - initial implementation + *******************************************************************************/ +package org.eclipse.fordiac.ide.applications.previews; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.draw2d.ColorConstants; +import org.eclipse.draw2d.FigureCanvas; +import org.eclipse.draw2d.IFigure; +import org.eclipse.draw2d.Polyline; +import org.eclipse.draw2d.geometry.Point; +import org.eclipse.draw2d.geometry.Rectangle; +import org.eclipse.fordiac.ide.application.editparts.ElementEditPartFactory; +import org.eclipse.fordiac.ide.model.libraryElement.AutomationSystem; +import org.eclipse.fordiac.ide.model.libraryElement.FBNetwork; +import org.eclipse.fordiac.ide.model.libraryElement.FBNetworkElement; +import org.eclipse.fordiac.ide.model.ui.editors.AdvancedScrollingGraphicalViewer; +import org.eclipse.fordiac.ide.systemmanagement.SystemManager; +import org.eclipse.fordiac.ide.typemanagement.refactoring.UpdateInstancesChange; +import org.eclipse.gef.EditPart; +import org.eclipse.gef.editparts.AbstractGraphicalEditPart; +import org.eclipse.gef.editparts.ScalableFreeformRootEditPart; +import org.eclipse.gef.ui.parts.GraphicalEditor; +import org.eclipse.ltk.ui.refactoring.ChangePreviewViewerInput; +import org.eclipse.ltk.ui.refactoring.IChangePreviewViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; + +@SuppressWarnings("restriction") +public class ProjectChangePreviewViewer implements IChangePreviewViewer { + + private SashForm control; + private Composite parent; + + private AdvancedScrollingGraphicalViewer graphicalViewer; + + @Override + public void createControl(final Composite parent) { + parent.setLayout(new GridLayout(1, false)); + + this.parent = parent; + + resetControl(); + } + + private void resetControl() { + if (control != null) { + control.dispose(); + } + + control = new SashForm(parent, SWT.VERTICAL); + control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + final Composite compl = new Composite(control, SWT.NONE); + compl.setLayout(new GridLayout()); + final Label labell = new Label(compl, SWT.NONE); + graphicalViewer = new AdvancedScrollingGraphicalViewer(); + graphicalViewer.createControl(compl); + graphicalViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + parent.layout(true, true); + } + + @Override + public Control getControl() { + return control; + } + + @Override + public void setInput(final ChangePreviewViewerInput input) { + if (!(input.getChange() instanceof UpdateInstancesChange)) { + return; + } + + final UpdateInstancesChange change = (UpdateInstancesChange) input.getChange(); + + final AutomationSystem system = SystemManager.INSTANCE.getProjectSystems(change.getProject()).getFirst(); + + final FBNetwork network = system.getApplication().getFirst().getFBNetwork(); + + final GraphicalEditor mockEditor = new GraphicalEditor() { + + @Override + protected void initializeGraphicalViewer() { + // No initialization needed for mock + } + + @Override + public void doSave(final IProgressMonitor monitor) { + // No save final operation needed for mock + + } + + }; + + resetControl(); + + graphicalViewer.setRootEditPart(new ScalableFreeformRootEditPart()); + graphicalViewer.setEditPartFactory(new ElementEditPartFactory(mockEditor)); + graphicalViewer.setContents(network); // exception here + + drawRedRectangleForElement(graphicalViewer, change.getFBNetworkElement()); + } + + private void resetGraphicalViewer(final AdvancedScrollingGraphicalViewer viewer) { + if (viewer != null) { + viewer.setContents(null); + if (viewer.getControl() != null) { + viewer.getControl().setRedraw(false); + viewer.getControl().dispose(); + } + } + } + + private void drawRedRectangleForElement(final AdvancedScrollingGraphicalViewer viewer, final FBNetworkElement fb) { + if (viewer != null && fb != null) { + final EditPart editPart = viewer.getEditPartRegistry().get(fb); + + if (editPart != null) { + final IFigure figure = ((AbstractGraphicalEditPart) editPart).getFigure(); + if (figure != null) { + // Ensure layout is complete before accessing bounds + viewer.getControl().getDisplay().asyncExec(() -> { + final Rectangle bounds = figure.getBounds(); + + figure.translateToAbsolute(bounds); + + createRedBorder(viewer, bounds); + + final FigureCanvas canvas = (FigureCanvas) viewer.getControl(); + if (canvas != null) { + canvas.scrollTo(bounds.x - 10, bounds.y - 10); + } + + }); + } + } + } + } + + private void createRedBorder(final AdvancedScrollingGraphicalViewer viewer, final Rectangle bounds) { + final int padding = 5; + + final Polyline topLine = new Polyline(); + topLine.addPoint(new Point(bounds.x - padding, bounds.y - padding)); + topLine.addPoint(new Point(bounds.x + bounds.width + padding, bounds.y - padding)); + topLine.setForegroundColor(ColorConstants.red); + topLine.setLineWidth(2); + + final Polyline bottomLine = new Polyline(); + bottomLine.addPoint(new Point(bounds.x - padding, bounds.y + bounds.height + padding)); + bottomLine.addPoint(new Point(bounds.x + bounds.width + padding, bounds.y + bounds.height + padding)); + bottomLine.setForegroundColor(ColorConstants.red); + bottomLine.setLineWidth(2); + + final Polyline leftLine = new Polyline(); + leftLine.addPoint(new Point(bounds.x - padding, bounds.y - padding)); + leftLine.addPoint(new Point(bounds.x - padding, bounds.y + bounds.height + padding)); + leftLine.setForegroundColor(ColorConstants.red); + leftLine.setLineWidth(2); + + final Polyline rightLine = new Polyline(); + rightLine.addPoint(new Point(bounds.x + bounds.width + padding, bounds.y - padding)); + rightLine.addPoint(new Point(bounds.x + bounds.width + padding, bounds.y + bounds.height + padding)); + rightLine.setForegroundColor(ColorConstants.red); + rightLine.setLineWidth(2); + + final FigureCanvas canvas = (FigureCanvas) viewer.getControl(); + if (canvas != null) { + canvas.getContents().add(topLine); + canvas.getContents().add(bottomLine); + canvas.getContents().add(leftLine); + canvas.getContents().add(rightLine); + } + } +} \ No newline at end of file diff --git a/plugins/org.eclipse.fordiac.ide.debug.ui/src/org/eclipse/fordiac/ide/debug/ui/view/editparts/FBDebugViewRootEditPart.java b/plugins/org.eclipse.fordiac.ide.debug.ui/src/org/eclipse/fordiac/ide/debug/ui/view/editparts/FBDebugViewRootEditPart.java index 852a4f6668..ca9a0c1c6d 100644 --- a/plugins/org.eclipse.fordiac.ide.debug.ui/src/org/eclipse/fordiac/ide/debug/ui/view/editparts/FBDebugViewRootEditPart.java +++ b/plugins/org.eclipse.fordiac.ide.debug.ui/src/org/eclipse/fordiac/ide/debug/ui/view/editparts/FBDebugViewRootEditPart.java @@ -11,6 +11,7 @@ * Contributors: * Alois Zoitl - initial API and implementation and/or initial documentation * Martin Jobst - refactor evaluator API + * Martin Schwarz - Build fixes *******************************************************************************/ package org.eclipse.fordiac.ide.debug.ui.view.editparts; diff --git a/plugins/org.eclipse.fordiac.ide.fbtypeeditor/META-INF/MANIFEST.MF b/plugins/org.eclipse.fordiac.ide.fbtypeeditor/META-INF/MANIFEST.MF index 0439f18f36..242af2f476 100644 --- a/plugins/org.eclipse.fordiac.ide.fbtypeeditor/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.fordiac.ide.fbtypeeditor/META-INF/MANIFEST.MF @@ -30,7 +30,8 @@ Require-Bundle: org.eclipse.ui, org.eclipse.xtext.ui, org.eclipse.nebula.widgets.nattable.core, org.eclipse.fordiac.ide.model.search, - org.eclipse.fordiac.ide.typeeditor + org.eclipse.fordiac.ide.typeeditor, + org.eclipse.ltk.ui.refactoring Bundle-Vendor: Eclipse 4diac Bundle-ActivationPolicy: lazy Bundle-Version: 3.0.0.qualifier diff --git a/plugins/org.eclipse.fordiac.ide.fbtypeeditor/plugin.xml b/plugins/org.eclipse.fordiac.ide.fbtypeeditor/plugin.xml index c7d6bd6b57..29fc391ace 100644 --- a/plugins/org.eclipse.fordiac.ide.fbtypeeditor/plugin.xml +++ b/plugins/org.eclipse.fordiac.ide.fbtypeeditor/plugin.xml @@ -175,5 +175,19 @@ + + + + + + + + + + diff --git a/plugins/org.eclipse.fordiac.ide.fbtypeeditor/src/org/eclipse/fordiac/ide/fbtypeeditor/editparts/FBInterfaceEditPartFactory.java b/plugins/org.eclipse.fordiac.ide.fbtypeeditor/src/org/eclipse/fordiac/ide/fbtypeeditor/editparts/FBInterfaceEditPartFactory.java index 40fbc464d8..ceaa2a8a52 100644 --- a/plugins/org.eclipse.fordiac.ide.fbtypeeditor/src/org/eclipse/fordiac/ide/fbtypeeditor/editparts/FBInterfaceEditPartFactory.java +++ b/plugins/org.eclipse.fordiac.ide.fbtypeeditor/src/org/eclipse/fordiac/ide/fbtypeeditor/editparts/FBInterfaceEditPartFactory.java @@ -34,6 +34,7 @@ public FBInterfaceEditPartFactory(final GraphicalEditor editor, final TypeLibrar @Override protected EditPart getPartForElement(final EditPart context, final Object modelElement) { + System.out.println("Loaded editor for:" + modelElement.getClass()); if (modelElement instanceof FBType && context == null) { return new FBTypeRootEditPart(); } diff --git a/plugins/org.eclipse.fordiac.ide.fbtypeeditor/src/org/eclipse/fordiac/ide/fbtypeeditor/previews/InterfaceDataTypeChangePreviewViewer.java b/plugins/org.eclipse.fordiac.ide.fbtypeeditor/src/org/eclipse/fordiac/ide/fbtypeeditor/previews/InterfaceDataTypeChangePreviewViewer.java new file mode 100644 index 0000000000..e286a9449d --- /dev/null +++ b/plugins/org.eclipse.fordiac.ide.fbtypeeditor/src/org/eclipse/fordiac/ide/fbtypeeditor/previews/InterfaceDataTypeChangePreviewViewer.java @@ -0,0 +1,258 @@ +/******************************************************************************* + * Copyright (c) 2024 Johannes Kepler University + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Martin Schwarz - initial implementation + *******************************************************************************/ +package org.eclipse.fordiac.ide.fbtypeeditor.previews; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.draw2d.ColorConstants; +import org.eclipse.draw2d.FigureCanvas; +import org.eclipse.draw2d.IFigure; +import org.eclipse.draw2d.Polyline; +import org.eclipse.draw2d.geometry.Point; +import org.eclipse.draw2d.geometry.Rectangle; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.fordiac.ide.fbtypeeditor.editparts.FBInterfaceEditPartFactory; +import org.eclipse.fordiac.ide.fbtypeeditor.editparts.InterfaceEditPart; +import org.eclipse.fordiac.ide.model.libraryElement.FBType; +import org.eclipse.fordiac.ide.model.typelibrary.TypeEntry; +import org.eclipse.fordiac.ide.model.ui.editors.AdvancedScrollingGraphicalViewer; +import org.eclipse.fordiac.ide.typemanagement.refactoring.InterfaceDataTypeChange; +import org.eclipse.gef.GraphicalEditPart; +import org.eclipse.gef.editparts.ScalableRootEditPart; +import org.eclipse.gef.ui.parts.GraphicalEditor; +import org.eclipse.ltk.ui.refactoring.ChangePreviewViewerInput; +import org.eclipse.ltk.ui.refactoring.IChangePreviewViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.ScrollBar; + +@SuppressWarnings("restriction") +public class InterfaceDataTypeChangePreviewViewer implements IChangePreviewViewer { + + private SashForm control; + private Composite parent; + + private AdvancedScrollingGraphicalViewer graphicalViewerLeft; + private AdvancedScrollingGraphicalViewer graphicalViewerRight; + + @Override + public void createControl(final Composite parent) { + parent.setLayout(new GridLayout(1, false)); + + this.parent = parent; + + resetControl(); + } + + private void resetControl() { + if (control != null) { + control.dispose(); + } + + control = new SashForm(parent, SWT.VERTICAL); + control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + final Composite compl = new Composite(control, SWT.NONE); + compl.setLayout(new GridLayout()); + final Label labell = new Label(compl, SWT.NONE); + labell.setText("Before refactor"); + graphicalViewerLeft = new AdvancedScrollingGraphicalViewer(); + graphicalViewerLeft.createControl(compl); + graphicalViewerLeft.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + final Composite compr = new Composite(control, SWT.NONE); + compr.setLayout(new GridLayout()); + final Label labelr = new Label(compr, SWT.NONE); + labelr.setText("After refactor"); + graphicalViewerRight = new AdvancedScrollingGraphicalViewer(); + graphicalViewerRight.createControl(compr); + graphicalViewerRight.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + parent.layout(true, true); + } + + @Override + public Control getControl() { + return control; + } + + @Override + public void setInput(final ChangePreviewViewerInput input) { + if (!(input.getChange() instanceof InterfaceDataTypeChange)) { + return; + } + + final InterfaceDataTypeChange change = (InterfaceDataTypeChange) input.getChange(); + + final String newName = change.getNewName(); + final TypeEntry oldTypeEntry = change.getOldTypeEntry(); + final FBType originalFbType = (FBType) change.getModifiedElement(); + + final FBType refactoredFbType = EcoreUtil.copy(originalFbType); + + refactoredFbType.getInterfaceList().getInputs() + .filter(var -> var.getTypeName().equals(oldTypeEntry.getTypeName())).forEach(var -> { + var.setType(EcoreUtil.copy(var.getType())); + var.getType().setName(newName); + }); + + refactoredFbType.getInterfaceList().getOutputs() + .filter(var -> var.getTypeName().equals(oldTypeEntry.getTypeName())).forEach(var -> { + var.setType(EcoreUtil.copy(var.getType())); + var.getType().setName(newName); + }); + + final GraphicalEditor mockEditor = new GraphicalEditor() { + + @Override + protected void initializeGraphicalViewer() { + // No initialization needed for mock + } + + @Override + public void doSave(final IProgressMonitor monitor) { + // No save operation needed for mock + } + + }; + + resetControl(); + + graphicalViewerLeft.setRootEditPart(new ScalableRootEditPart()); + graphicalViewerLeft.setEditPartFactory( + new FBInterfaceEditPartFactory(mockEditor, change.getOldTypeEntry().getTypeLibrary())); + graphicalViewerLeft.setContents(change.getModifiedElement()); + + graphicalViewerRight.setRootEditPart(new ScalableRootEditPart()); + graphicalViewerRight.setEditPartFactory( + new FBInterfaceEditPartFactory(mockEditor, change.getOldTypeEntry().getTypeLibrary())); + graphicalViewerRight.setContents(refactoredFbType); + + synchronizeScrolling(graphicalViewerLeft, graphicalViewerRight); + synchronizeScrolling(graphicalViewerRight, graphicalViewerLeft); + + final GraphicalEditPart gEditPartR = (GraphicalEditPart) graphicalViewerRight.getContents(); + + gEditPartR.setLayoutConstraint(gEditPartR.getChildren().get(0), gEditPartR.getChildren().get(0).getFigure(), + new Rectangle(400, 50, -1, -1)); + + final GraphicalEditPart gEditPartL = (GraphicalEditPart) graphicalViewerLeft.getContents(); + + gEditPartL.setLayoutConstraint(gEditPartL.getChildren().get(0), gEditPartL.getChildren().get(0).getFigure(), + new Rectangle(400, 50, -1, -1)); + + drawRedRectangleForElement(graphicalViewerLeft, oldTypeEntry.getTypeName()); + + } + + private void synchronizeScrolling(final AdvancedScrollingGraphicalViewer source, + final AdvancedScrollingGraphicalViewer target) { + if (source.getControl() instanceof FigureCanvas && target.getControl() instanceof FigureCanvas) { + final FigureCanvas sourceCanvas = (FigureCanvas) source.getControl(); + final FigureCanvas targetCanvas = (FigureCanvas) target.getControl(); + + final ScrollBar sourceHBar = sourceCanvas.getHorizontalBar(); + if (sourceHBar != null) { + sourceHBar.addListener(SWT.Selection, event -> { + final ScrollBar targetHBar = targetCanvas.getHorizontalBar(); + if (targetHBar != null) { + targetHBar.setSelection(sourceHBar.getSelection()); + targetCanvas.scrollTo(sourceCanvas.getHorizontalBar().getSelection(), + sourceCanvas.getVerticalBar().getSelection()); + } + }); + } + + final ScrollBar sourceVBar = sourceCanvas.getVerticalBar(); + if (sourceVBar != null) { + sourceVBar.addListener(SWT.Selection, event -> { + final ScrollBar targetVBar = targetCanvas.getVerticalBar(); + if (targetVBar != null) { + targetVBar.setSelection(sourceVBar.getSelection()); + targetCanvas.scrollTo(sourceCanvas.getHorizontalBar().getSelection(), + sourceCanvas.getVerticalBar().getSelection()); + } + }); + } + } + } + + private void drawRedRectangleForElement(final AdvancedScrollingGraphicalViewer viewer, + final String originalTypeName) { + if (viewer != null) { + viewer.getEditPartRegistry().forEach((key, val) -> { + + if ((val instanceof final InterfaceEditPart part) + && part.getCastedModel().getFullTypeName().equals(originalTypeName)) { + + final IFigure figure = part.getFigure(); + if (figure != null) { + // Ensure layout is complete before accessing bounds + viewer.getControl().getDisplay().asyncExec(() -> { + final Rectangle bounds = figure.getBounds(); + figure.translateToAbsolute(bounds); + + createRedBorder(viewer, bounds); + + final FigureCanvas canvas = (FigureCanvas) viewer.getControl(); + if (canvas != null) { + canvas.scrollTo(bounds.x - 10, bounds.y - 10); + } + }); + } + } + }); + } + } + + private void createRedBorder(final AdvancedScrollingGraphicalViewer viewer, final Rectangle bounds) { + final int padding = 2; + + final Polyline topLine = new Polyline(); + topLine.addPoint(new Point(bounds.x - padding, bounds.y - padding)); + topLine.addPoint(new Point(bounds.x + bounds.width + padding, bounds.y - padding)); + topLine.setForegroundColor(ColorConstants.red); + topLine.setLineWidth(2); + + final Polyline bottomLine = new Polyline(); + bottomLine.addPoint(new Point(bounds.x - padding, bounds.y + bounds.height + padding)); + bottomLine.addPoint(new Point(bounds.x + bounds.width + padding, bounds.y + bounds.height + padding)); + bottomLine.setForegroundColor(ColorConstants.red); + bottomLine.setLineWidth(2); + + final Polyline leftLine = new Polyline(); + leftLine.addPoint(new Point(bounds.x - padding, bounds.y - padding)); + leftLine.addPoint(new Point(bounds.x - padding, bounds.y + bounds.height + padding)); + leftLine.setForegroundColor(ColorConstants.red); + leftLine.setLineWidth(2); + + final Polyline rightLine = new Polyline(); + rightLine.addPoint(new Point(bounds.x + bounds.width + padding, bounds.y - padding)); + rightLine.addPoint(new Point(bounds.x + bounds.width + padding, bounds.y + bounds.height + padding)); + rightLine.setForegroundColor(ColorConstants.red); + rightLine.setLineWidth(2); + + final FigureCanvas canvas = (FigureCanvas) viewer.getControl(); + if (canvas != null) { + canvas.getContents().add(topLine); + canvas.getContents().add(bottomLine); + canvas.getContents().add(leftLine); + canvas.getContents().add(rightLine); + } + } + +} \ No newline at end of file diff --git a/plugins/org.eclipse.fordiac.ide.gef/src/org/eclipse/fordiac/ide/gef/utilities/ElementSelector.java b/plugins/org.eclipse.fordiac.ide.gef/src/org/eclipse/fordiac/ide/gef/utilities/ElementSelector.java index dbf941d338..96dd9ff8d0 100644 --- a/plugins/org.eclipse.fordiac.ide.gef/src/org/eclipse/fordiac/ide/gef/utilities/ElementSelector.java +++ b/plugins/org.eclipse.fordiac.ide.gef/src/org/eclipse/fordiac/ide/gef/utilities/ElementSelector.java @@ -12,6 +12,7 @@ * Filip Adren, Alois Zoitl * - initial API and implementation and/or initial documentation * Fabio Gandolfi - added doubleclickevent for pin jumps + * Martin Schwarz - Build fixes *******************************************************************************/ package org.eclipse.fordiac.ide.gef.utilities; diff --git a/plugins/org.eclipse.fordiac.ide.model.commands/src/org/eclipse/fordiac/ide/model/commands/change/UpdatePinInTypeDeclarationCommand.java b/plugins/org.eclipse.fordiac.ide.model.commands/src/org/eclipse/fordiac/ide/model/commands/change/UpdatePinInTypeDeclarationCommand.java new file mode 100644 index 0000000000..a550177791 --- /dev/null +++ b/plugins/org.eclipse.fordiac.ide.model.commands/src/org/eclipse/fordiac/ide/model/commands/change/UpdatePinInTypeDeclarationCommand.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2023 Johannes Kepler University + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Dario Romano - initial API and implementation and/or initial documentation + *******************************************************************************/ +package org.eclipse.fordiac.ide.model.commands.change; + +import org.eclipse.fordiac.ide.model.libraryElement.FBType; +import org.eclipse.fordiac.ide.model.libraryElement.VarDeclaration; +import org.eclipse.fordiac.ide.model.typelibrary.DataTypeEntry; +import org.eclipse.gef.commands.Command; + +/** UpdateFBTypeCommand triggers an update of the type for an FB instance */ +public class UpdatePinInTypeDeclarationCommand extends Command { + private final DataTypeEntry dataTypeEntry; + private final FBType fbType; + + public UpdatePinInTypeDeclarationCommand(final FBType fbnElement, final DataTypeEntry type) { + this.fbType = fbnElement; + this.dataTypeEntry = type; + } + + @Override + public boolean canExecute() { + return true; + } + + @Override + public void execute() { + fbType.getInterfaceList().getAllInterfaceElements().stream().filter(VarDeclaration.class::isInstance) + .map(VarDeclaration.class::cast).filter(i -> i.getType().getTypeEntry() == dataTypeEntry) + .forEach(el -> { + el.setType(dataTypeEntry.getTypeEditable()); + }); + } +} \ No newline at end of file diff --git a/plugins/org.eclipse.fordiac.ide.structuredtextcore.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.fordiac.ide.structuredtextcore.ui/META-INF/MANIFEST.MF index 92a9dbf59d..94ab0bd68a 100644 --- a/plugins/org.eclipse.fordiac.ide.structuredtextcore.ui/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.fordiac.ide.structuredtextcore.ui/META-INF/MANIFEST.MF @@ -28,6 +28,7 @@ Require-Bundle: org.eclipse.fordiac.ide.model, org.eclipse.fordiac.ide.globalconstantseditor.model, org.eclipse.fordiac.ide.typemanagement Import-Package: org.apache.log4j, + org.eclipse.fordiac.ide.typemanagement.refactoring, org.eclipse.xtext.ui.codemining;resolution:=optional Bundle-RequiredExecutionEnvironment: JavaSE-21 Export-Package: org.eclipse.fordiac.ide.structuredtextcore.ui, diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/META-INF/MANIFEST.MF b/plugins/org.eclipse.fordiac.ide.typemanagement/META-INF/MANIFEST.MF index e5cba77092..2994050bec 100644 --- a/plugins/org.eclipse.fordiac.ide.typemanagement/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/META-INF/MANIFEST.MF @@ -19,6 +19,10 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.ltk.ui.refactoring, org.eclipse.fordiac.ide.model.search, org.eclipse.fordiac.ide.model.commands, + org.eclipse.compare, + org.eclipse.emf.compare, + org.eclipse.emf.compare.edit, + org.eclipse.emf.compare.ide.ui, org.eclipse.fordiac.ide.model.ui Bundle-Vendor: Eclipse 4diac Bundle-ActivationPolicy: lazy @@ -36,4 +40,6 @@ Export-Package: org.eclipse.fordiac.ide.typemanagement, org.eclipse.fordiac.ide.typemanagement.util, org.eclipse.fordiac.ide.typemanagement.wizards Automatic-Module-Name: org.eclipse.fordiac.ide.typemanagement -Import-Package: org.eclipse.fordiac.ide.model.ui.editors +Import-Package: org.eclipse.emf.compare, + org.eclipse.fordiac.ide.model.ui.editors, + org.eclipse.fordiac.ide.model.ui.widgets diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/plugin.xml b/plugins/org.eclipse.fordiac.ide.typemanagement/plugin.xml index f64a81e0ee..0781e794ef 100644 --- a/plugins/org.eclipse.fordiac.ide.typemanagement/plugin.xml +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/plugin.xml @@ -700,7 +700,7 @@ @@ -713,6 +713,16 @@ + + + + + + + diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/Messages.java b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/Messages.java index 4cada9a9d8..dc42d9dbc7 100644 --- a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/Messages.java +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/Messages.java @@ -16,6 +16,8 @@ * - Externalized all translatable strings * Martin Jobst * - add strings for Build Path property page + * Martin Schwarz + * - add/modify strings for rename refactoring *******************************************************************************/ package org.eclipse.fordiac.ide.typemanagement; @@ -155,7 +157,9 @@ public final class Messages extends NLS { public static String typeManagementPreferencePageDescription; public static String Refactoring_RenameFromTo; + public static String Refactoring_AffectedFuctionBlock; public static String Refactoring_AffectedStruct; + public static String Refactoring_AffectedFbInstances; public static String Refactoring_AffectedInstancesOfFB; public static String Refactoring_UpdateTypeEntryChange; diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/messages.properties b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/messages.properties index 064c0cf942..78dd5e12f8 100644 --- a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/messages.properties +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/messages.properties @@ -13,6 +13,7 @@ # Jose Cabral - Add preferences for information about new types # Andrea Zoitl - Externalized all translatable strings # Martin Jobst - add strings for Build Path property page + # Martin Schwarz - add/modify strings for rename refactoring ############################################################################### AbstractCommandChange_CannotExecuteCommand=Cannot execute command {0} in {1} for element at ''{2}'' @@ -103,7 +104,8 @@ RenameElementRefactoringProcessor_Name=Rename element to {0} RenameElementRefactoringProcessor_RenamePinInType=Rename Pin in type: {0} RenameElementRefactoringWizardPage_Name=Name RenameType_Name=Rename IEC 61499 Type -RenameType_TypeExists=The type {0} is already included in the library +RenameType_TypeExists=The type ''{0}'' is already included in the library +OldTypeLibVersionCouldNotBeDeleted= There was a problem while importing the new Type Library version, old one could not be deleted! OpenTypeHandler_EDITOR_OPEN_ERROR_MESSAGE=Could not open according editor OpenTypeHandler_NO_FILES_IN_WORKSPACE=There are no files in your workspace OpenTypeHandler_NO_FILES_SELECTED=No file selected @@ -115,9 +117,13 @@ typeManagementPreferencePageIdentificationTitle=Identification information typeManagementPreferencePageVersionTitle=Version information typeManagementPreferencePageDescription=Default values for created Function Blocks Warning=Warning +Refactoring_RenameFromTo=Rename Type from ''{0}'' to ''{1}'' +Refactoring_AffectedFuctionBlock=Update affected Function Blocks +Refactoring_AffectedFbInstances=Update affected Function Block instances Refactoring_RenameFromTo=Rename Type from {0} to : {1} -Refactoring_AffectedStruct=Affected Struct {0} that contain struct {1} as member +Refactoring_AffectedStruct=Update affected Structs Refactoring_AffectedInstancesOfFB=Affected Instances of this FB Type +UpdatedInstances=Instances which have been updated with the new type library version Refactoring_UpdateTypeEntryChange=Update type entry and editors PreviewChange_DeleteChoice=Delete PreviewChange_ChangeToAnyStruct=Change to ANY_STRUCT diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/wizards/ChangeConfigurationViewer.java b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/previews/ChangeConfigurationViewer.java similarity index 97% rename from plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/wizards/ChangeConfigurationViewer.java rename to plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/previews/ChangeConfigurationViewer.java index 5afc2d2e45..5f1e4dadbe 100644 --- a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/wizards/ChangeConfigurationViewer.java +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/previews/ChangeConfigurationViewer.java @@ -12,8 +12,10 @@ * - initial API and implementation and/or initial documentation * Dario Romano * - add correct preservation of selection and ui initialization from change state + * Martin Schwarz + * - moved file *******************************************************************************/ -package org.eclipse.fordiac.ide.typemanagement.wizards; +package org.eclipse.fordiac.ide.typemanagement.previews; import java.util.HashMap; import java.util.Map; @@ -67,7 +69,6 @@ public void widgetSelected(final SelectionEvent e) { } } }); - } @Override diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/previews/InterfaceDataTypeChangePreviewViewer.java b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/previews/InterfaceDataTypeChangePreviewViewer.java new file mode 100644 index 0000000000..334eb30c5b --- /dev/null +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/previews/InterfaceDataTypeChangePreviewViewer.java @@ -0,0 +1,118 @@ +/******************************************************************************* + * Copyright (c) 2024 Johannes Kepler University + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Martin Schwarz - initial implementation + *******************************************************************************/ +package org.eclipse.fordiac.ide.typemanagement.previews; + +import java.util.Objects; + +import org.eclipse.compare.CompareConfiguration; +import org.eclipse.compare.CompareEditorInput; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.compare.Comparison; +import org.eclipse.emf.compare.EMFCompare; +import org.eclipse.emf.compare.domain.ICompareEditingDomain; +import org.eclipse.emf.compare.domain.impl.EMFCompareEditingDomain; +import org.eclipse.emf.compare.ide.ui.internal.configuration.EMFCompareConfiguration; +import org.eclipse.emf.compare.ide.ui.internal.editor.ComparisonEditorInput; +import org.eclipse.emf.compare.scope.DefaultComparisonScope; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.edit.provider.ComposedAdapterFactory; +import org.eclipse.fordiac.ide.model.libraryElement.FBType; +import org.eclipse.fordiac.ide.model.typelibrary.TypeEntry; +import org.eclipse.fordiac.ide.typemanagement.refactoring.InterfaceDataTypeChange; +import org.eclipse.ltk.ui.refactoring.ChangePreviewViewerInput; +import org.eclipse.ltk.ui.refactoring.IChangePreviewViewer; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +@SuppressWarnings("restriction") +public class InterfaceDataTypeChangePreviewViewer implements IChangePreviewViewer { + + private static Composite parent; + private static Control previewControl; + private EMFCompareConfiguration emfCompareConfiguration; + private AdapterFactory adapterFactory; + private EMFCompare emfCompare; + + @Override + public void createControl(final Composite parent) { + parent.setSize(500, 500); + this.emfCompareConfiguration = new EMFCompareConfiguration(new CompareConfiguration()); + this.emfCompareConfiguration.setLeftEditable(false); + this.emfCompareConfiguration.setLeftLabel("Before Refactor"); + this.emfCompareConfiguration.setRightEditable(false); + this.emfCompareConfiguration.setRightLabel("After Refactor"); + + this.adapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE); + this.emfCompare = EMFCompare.builder().build(); + if (Objects.nonNull(previewControl)) { + previewControl.dispose(); + previewControl = null; + InterfaceDataTypeChangePreviewViewer.parent.dispose(); + } + InterfaceDataTypeChangePreviewViewer.parent = parent; + + } + + @Override + public Control getControl() { + return previewControl; + } + + @Override + public void setInput(final ChangePreviewViewerInput input) { + if (!(input.getChange() instanceof InterfaceDataTypeChange)) { + return; + } + + final InterfaceDataTypeChange change = (InterfaceDataTypeChange) input.getChange(); + final TypeEntry oldTypeEntry = change.getOldTypeEntry(); + final FBType originalFbType = (FBType) change.getModifiedElement(); + final FBType refactoredFbType = EcoreUtil.copy(originalFbType); + final String newName = change.getNewName(); + + refactoredFbType.getInterfaceList().getInputs() + .filter(var -> var.getTypeName().equals(oldTypeEntry.getTypeName())).forEach(var -> { + var.setType(EcoreUtil.copy(var.getType())); + var.getType().setName(newName); + }); + + refactoredFbType.getInterfaceList().getOutputs() + .filter(var -> var.getTypeName().equals(oldTypeEntry.getTypeName())).forEach(var -> { + var.setType(EcoreUtil.copy(var.getType())); + var.getType().setName(newName); + }); + + final Comparison comparison = this.emfCompare + .compare(new DefaultComparisonScope(originalFbType, refactoredFbType, null)); + + final ICompareEditingDomain editingDomain = EMFCompareEditingDomain.create(originalFbType, refactoredFbType, + null); + + final CompareEditorInput compareEditorInput = new ComparisonEditorInput(this.emfCompareConfiguration, + comparison, editingDomain, this.adapterFactory); + + try { + + compareEditorInput.run(new NullProgressMonitor()); + compareEditorInput.setTitle("Refactor comparison"); + previewControl = compareEditorInput.createContents(parent); + + } catch (final Exception e) { + System.out.println("Comparison failure"); + e.printStackTrace(); + } + + } + +} diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/previews/StructChangePreviewViewer.java b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/previews/StructChangePreviewViewer.java new file mode 100644 index 0000000000..25bf910d9a --- /dev/null +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/previews/StructChangePreviewViewer.java @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (c) 2024 Johannes Kepler University + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Martin Schwarz - initial implementation + *******************************************************************************/ +package org.eclipse.fordiac.ide.typemanagement.previews; + +import java.util.Objects; + +import org.eclipse.compare.CompareConfiguration; +import org.eclipse.compare.CompareEditorInput; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.compare.Comparison; +import org.eclipse.emf.compare.EMFCompare; +import org.eclipse.emf.compare.domain.ICompareEditingDomain; +import org.eclipse.emf.compare.domain.impl.EMFCompareEditingDomain; +import org.eclipse.emf.compare.ide.ui.internal.configuration.EMFCompareConfiguration; +import org.eclipse.emf.compare.ide.ui.internal.editor.ComparisonEditorInput; +import org.eclipse.emf.compare.scope.DefaultComparisonScope; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.edit.provider.ComposedAdapterFactory; +import org.eclipse.fordiac.ide.model.data.StructuredType; +import org.eclipse.fordiac.ide.typemanagement.refactoring.rename.StructuredTypeMemberChange; +import org.eclipse.ltk.ui.refactoring.ChangePreviewViewerInput; +import org.eclipse.ltk.ui.refactoring.IChangePreviewViewer; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +@SuppressWarnings("restriction") +public class StructChangePreviewViewer implements IChangePreviewViewer { + + private static Composite parent; + private static Control previewControl; + private EMFCompareConfiguration emfCompareConfiguration; + private AdapterFactory adapterFactory; + private EMFCompare emfCompare; + + @Override + public void createControl(final Composite parent) { + parent.setSize(500, 500); + this.emfCompareConfiguration = new EMFCompareConfiguration(new CompareConfiguration()); + this.emfCompareConfiguration.setLeftEditable(false); + this.emfCompareConfiguration.setLeftLabel("Before Refactor"); + this.emfCompareConfiguration.setRightEditable(false); + this.emfCompareConfiguration.setRightLabel("After Refactor"); + + this.adapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE); + this.emfCompare = EMFCompare.builder().build(); + if (Objects.nonNull(previewControl)) { + previewControl.dispose(); + previewControl = null; + StructChangePreviewViewer.parent.dispose(); + } + StructChangePreviewViewer.parent = parent; + + } + + @Override + public Control getControl() { + return previewControl; + } + + @Override + public void setInput(final ChangePreviewViewerInput input) { + if (!(input.getChange() instanceof StructuredTypeMemberChange)) { + return; + } + + final StructuredTypeMemberChange change = (StructuredTypeMemberChange) input.getChange(); + final StructuredType originalStructuredType = change.getModifiedElement(); + final StructuredType refactoredStructuredType = EcoreUtil.copy(originalStructuredType); + + refactoredStructuredType.getMemberVariables().stream() + .filter(var -> var.getType().getTypeEntry() == change.getModifiedTypeEntry()).forEach(var -> { + var.setType(EcoreUtil.copy(var.getType())); + var.getType().setName(change.getNewTypeEntryName()); + }); + + final Comparison comparison = this.emfCompare + .compare(new DefaultComparisonScope(originalStructuredType, refactoredStructuredType, null)); + + final ICompareEditingDomain editingDomain = EMFCompareEditingDomain.create(originalStructuredType, + refactoredStructuredType, null); + + final CompareEditorInput compareEditorInput = new ComparisonEditorInput(this.emfCompareConfiguration, + comparison, editingDomain, this.adapterFactory); + + try { + + compareEditorInput.run(new NullProgressMonitor()); + compareEditorInput.setTitle("Refactor comparison"); + previewControl = compareEditorInput.createContents(parent); + + } catch (final Exception e) { + System.out.println("Comparison failure"); + e.printStackTrace(); + } + + } + +} diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/previews/UpdateInstancesChangePreviewViewer.java b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/previews/UpdateInstancesChangePreviewViewer.java new file mode 100644 index 0000000000..5075c1e42a --- /dev/null +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/previews/UpdateInstancesChangePreviewViewer.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2024 Johannes Kepler University + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Martin Schwarz - initial implementation + *******************************************************************************/ +package org.eclipse.fordiac.ide.typemanagement.previews; + +import org.eclipse.fordiac.ide.typemanagement.refactoring.UpdateInstancesChange; +import org.eclipse.ltk.ui.refactoring.ChangePreviewViewerInput; +import org.eclipse.ltk.ui.refactoring.IChangePreviewViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Table; + +@SuppressWarnings("restriction") +public class UpdateInstancesChangePreviewViewer implements IChangePreviewViewer { + + private Composite parent; + private Control previewControl; + + @Override + public void createControl(final Composite parent) { + parent.setSize(500, 500); + + final Composite control = new Composite(parent, SWT.NONE); + control.setLayoutData(new FillLayout()); + + final Table table = new Table(control, SWT.CHECK | SWT.BORDER); + + } + + @Override + public Control getControl() { + return previewControl; + } + + @Override + public void setInput(final ChangePreviewViewerInput input) { + if (!(input.getChange() instanceof UpdateInstancesChange)) { + return; + } + + } + +} diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/InterfaceDataTypeChange.java b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/InterfaceDataTypeChange.java new file mode 100644 index 0000000000..6b0de600ba --- /dev/null +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/InterfaceDataTypeChange.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2023 Primetals Technologies Austria GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Michael Oberlehner - initial API and implementation and/or initial documentation + * Martin Schwarz - added additional information to refactoring preview + *******************************************************************************/ +package org.eclipse.fordiac.ide.typemanagement.refactoring; + +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.fordiac.ide.model.libraryElement.FBType; +import org.eclipse.fordiac.ide.model.libraryElement.IInterfaceElement; +import org.eclipse.fordiac.ide.model.search.AbstractLiveSearchContext; +import org.eclipse.fordiac.ide.model.typelibrary.DataTypeEntry; +import org.eclipse.fordiac.ide.model.typelibrary.TypeEntry; +import org.eclipse.fordiac.ide.typemanagement.util.FBUpdater; +import org.eclipse.gef.commands.Command; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; + +public class InterfaceDataTypeChange extends Change { + + private final FBType fbType; + private final TypeEntry oldTypeEntry; + private final String newName; + private final List inputPinNames; + private final List outputPinNames; + + public InterfaceDataTypeChange(final FBType fbType, final TypeEntry oldTypeEntry, final String newName) { + + this.fbType = fbType; + this.newName = newName; + this.oldTypeEntry = oldTypeEntry; + this.inputPinNames = fbType.getInterfaceList().getInputs() + .filter(input -> input.getTypeName().equals(oldTypeEntry.getTypeName())).map(IInterfaceElement::getName) + .toList(); + + this.outputPinNames = fbType.getInterfaceList().getOutputs() + .filter(output -> output.getTypeName().equals(oldTypeEntry.getTypeName())) + .map(IInterfaceElement::getName).toList(); + + } + + @Override + public String getName() { + return "Update Interface Pins - Inputs: " + this.inputPinNames.toString() + " / Outputs: " //$NON-NLS-1$//$NON-NLS-2$ + + this.outputPinNames.toString(); + } + + @Override + public void initializeValidationData(final IProgressMonitor pm) { + // Unused + } + + private Command getUpdatePinInTypeDeclarationCommand() { + return FBUpdater.createUpdatePinInTypeDeclarationCommand(fbType, (DataTypeEntry) this.oldTypeEntry); + + } + + @Override + public RefactoringStatus isValid(final IProgressMonitor pm) throws CoreException, OperationCanceledException { + return new RefactoringStatus(); + } + + @Override + public Change perform(final IProgressMonitor pm) throws CoreException { + // we have to execute in UI thread, otherwise SWT crashes if the editor of the + // type is open + final Command cmd = getUpdatePinInTypeDeclarationCommand(); + AbstractLiveSearchContext.executeAndSave(cmd, fbType, pm); + return null; + } + + @Override + public Object getModifiedElement() { + return fbType; + } + + public TypeEntry getOldTypeEntry() { + return oldTypeEntry; + } + + public String getNewName() { + return newName; + } + +} diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/UpdateInstancesChange.java b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/UpdateInstancesChange.java new file mode 100644 index 0000000000..1ab9f7a4ad --- /dev/null +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/UpdateInstancesChange.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2023 Johannes Kepler University + * Primetals Technologies Austria GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Dario Romano - initial API and implementation and/or initial documentation + * Fabio Gandolfi - added FB type update + * Martin Schwarz - moved file and refactored for new preview grouping + *******************************************************************************/ +package org.eclipse.fordiac.ide.typemanagement.refactoring; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.fordiac.ide.model.commands.change.ChangeStructCommand; +import org.eclipse.fordiac.ide.model.commands.change.UpdateFBTypeCommand; +import org.eclipse.fordiac.ide.model.commands.change.UpdateInternalFBCommand; +import org.eclipse.fordiac.ide.model.commands.change.UpdateUntypedSubAppInterfaceCommand; +import org.eclipse.fordiac.ide.model.data.StructuredType; +import org.eclipse.fordiac.ide.model.libraryElement.BaseFBType; +import org.eclipse.fordiac.ide.model.libraryElement.FB; +import org.eclipse.fordiac.ide.model.libraryElement.FBNetworkElement; +import org.eclipse.fordiac.ide.model.libraryElement.LibraryElement; +import org.eclipse.fordiac.ide.model.libraryElement.StructManipulator; +import org.eclipse.fordiac.ide.model.libraryElement.SubApp; +import org.eclipse.fordiac.ide.model.typelibrary.DataTypeEntry; +import org.eclipse.fordiac.ide.model.typelibrary.TypeEntry; +import org.eclipse.gef.commands.Command; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; + +public class UpdateInstancesChange extends Change { + + private final FBNetworkElement instance; + private final TypeEntry typeEntry; + private final IProject project; + + public UpdateInstancesChange(final FBNetworkElement instance, final TypeEntry typeEntry, final IProject project) { + this.instance = instance; + this.typeEntry = typeEntry; + this.project = project; + } + + @Override + public String getName() { + return "Update FB instance: " + instance.getName(); //$NON-NLS-1$ + } + + @Override + public void initializeValidationData(final IProgressMonitor pm) { + // can't think of a way to validate an update + } + + private Command getCommand(final FBNetworkElement instance) { + if (instance instanceof final SubApp subApp && !subApp.isTyped()) { + return new UpdateUntypedSubAppInterfaceCommand(instance, (DataTypeEntry) typeEntry); + } + + if (instance instanceof final StructManipulator muxer) { + final LibraryElement structuredType = typeEntry.getTypeEditable(); + Assert.isTrue(structuredType instanceof StructuredType); + return new ChangeStructCommand(muxer, (StructuredType) structuredType); + } + if (instance.eContainer() instanceof BaseFBType && instance instanceof final FB fb) { + return new UpdateInternalFBCommand(fb, typeEntry); + } + + return new UpdateFBTypeCommand(instance, typeEntry); + } + + @Override + public RefactoringStatus isValid(final IProgressMonitor pm) throws CoreException, OperationCanceledException { + return new RefactoringStatus(); + } + + @Override + public Change perform(final IProgressMonitor pm) throws CoreException { + ChangeExecutionHelper.executeChange(getCommand(instance), instance, pm); + return null; + } + + @Override + public Object getModifiedElement() { + return null; + } + + public IProject getProject() { + return project; + } + + public FBNetworkElement getFBNetworkElement() { + return instance; + } + +} diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/FbInstanceChange.java b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/FbInstanceChange.java new file mode 100644 index 0000000000..37c8ef8ac3 --- /dev/null +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/FbInstanceChange.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2024 Johannes Kepler University + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Martin Schwarz - initial implementation + *******************************************************************************/ +package org.eclipse.fordiac.ide.typemanagement.refactoring.rename; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.fordiac.ide.model.libraryElement.impl.BasicFBTypeImpl; +import org.eclipse.fordiac.ide.model.libraryElement.impl.FBImpl; +import org.eclipse.fordiac.ide.model.libraryElement.impl.InterfaceListImpl; +import org.eclipse.fordiac.ide.model.search.types.BlockTypeInstanceSearch; +import org.eclipse.fordiac.ide.model.search.types.DataTypeInstanceSearch; +import org.eclipse.fordiac.ide.model.typelibrary.DataTypeEntry; +import org.eclipse.fordiac.ide.model.typelibrary.TypeEntry; +import org.eclipse.fordiac.ide.model.typelibrary.TypeLibraryManager; +import org.eclipse.fordiac.ide.typemanagement.Messages; +import org.eclipse.fordiac.ide.typemanagement.refactoring.UpdateInstancesChange; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.CompositeChange; + +public class FbInstanceChange extends CompositeChange { + + private final IFile file; + private final TypeEntry oldTypeEntry; + + public FbInstanceChange(final IFile file) { + super(Messages.Refactoring_AffectedFbInstances); + this.file = file; + this.oldTypeEntry = TypeLibraryManager.INSTANCE.getTypeEntryForFile(file); + buildChanges(); + } + + private void buildChanges() { + buildSubChanges().forEach(this::add); + } + + private List buildSubChanges() { + final Map> affectedStructChanges = new HashMap<>(); + + searchAffectedStructuredType().forEach(impactedStructuredType -> { + final IProject project = impactedStructuredType.getTypeEntry().getFile().getProject(); + + if (!affectedStructChanges.containsKey(project)) { + affectedStructChanges.put(project, new HashSet<>()); + } + + affectedStructChanges.get(project) + .add(new UpdateInstancesChange(impactedStructuredType, oldTypeEntry, project)); + }); + + return affectedStructChanges.entrySet().stream().map(entry -> { + final ProjectFbInstanceChange fbChange = new ProjectFbInstanceChange(file, entry.getKey()); + + entry.getValue().stream().forEach(fbChange::add); + + return fbChange; + }).toList(); + } + + private List searchAffectedStructuredType() { + final List affectedFbInstances = new ArrayList<>(); + + final DataTypeInstanceSearch affectedFbSearch = new DataTypeInstanceSearch((DataTypeEntry) oldTypeEntry); + final List results = affectedFbSearch.performSearch(); + + final List affectedFbs = results.stream() + .filter(r -> InterfaceListImpl.class.isInstance(r.eContainer())) + .filter(r -> BasicFBTypeImpl.class.isInstance(r.eContainer().eContainer())) + .map(r -> BasicFBTypeImpl.class.cast(r.eContainer().eContainer())).distinct().toList(); + + for (final BasicFBTypeImpl fbType : affectedFbs) { + final BlockTypeInstanceSearch affectedFbInstanceSearch = new BlockTypeInstanceSearch(fbType.getTypeEntry()); + final List affectedFbInstanceSearchResults = affectedFbInstanceSearch.performSearch(); + + for (final EObject object : affectedFbInstanceSearchResults) { + affectedFbInstances.add((FBImpl) object); + } + + } + + return affectedFbInstances; + } + +} diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/FbTypeChange.java b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/FbTypeChange.java new file mode 100644 index 0000000000..3d766df05d --- /dev/null +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/FbTypeChange.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2024 Johannes Kepler University + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Martin Schwarz - initial implementation + *******************************************************************************/ +package org.eclipse.fordiac.ide.typemanagement.refactoring.rename; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.resources.IFile; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.fordiac.ide.model.libraryElement.FBType; +import org.eclipse.fordiac.ide.model.libraryElement.InterfaceList; +import org.eclipse.fordiac.ide.model.search.types.DataTypeInstanceSearch; +import org.eclipse.fordiac.ide.model.typelibrary.DataTypeEntry; +import org.eclipse.fordiac.ide.model.typelibrary.TypeEntry; +import org.eclipse.fordiac.ide.model.typelibrary.TypeLibraryManager; +import org.eclipse.fordiac.ide.typemanagement.Messages; +import org.eclipse.fordiac.ide.typemanagement.refactoring.InterfaceDataTypeChange; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.CompositeChange; + +public class FbTypeChange extends CompositeChange { + + private final IFile file; + private final String newName; + private final TypeEntry oldTypeEntry; + + public FbTypeChange(final IFile targetFile, final String newName) { + super(Messages.Refactoring_AffectedFuctionBlock); + this.file = targetFile; + this.newName = newName; + this.oldTypeEntry = TypeLibraryManager.INSTANCE.getTypeEntryForFile(this.file); + buildChanges(); + } + + private void buildChanges() { + buildSubChanges().forEach(this::add); + } + + private List buildSubChanges() { + final List affectedFBs = searchAffectedFBs(); + + final Map> functionBlockChangeMap = new HashMap<>(); + + affectedFBs.forEach(functionBlockType -> { + final String label = buildLabel(functionBlockType.getTypeEntry().getFile().getName(), + functionBlockType.getTypeEntry().getFile().getProject().getName()); + + if (!functionBlockChangeMap.containsKey(label)) { + functionBlockChangeMap.put(label, new HashSet<>()); + } + + functionBlockChangeMap.get(label) + .add(new InterfaceDataTypeChange(functionBlockType, oldTypeEntry, newName)); + }); + + return functionBlockChangeMap.entrySet().stream().map(entry -> { + final CompositeChange fbChange = new CompositeChange(entry.getKey()); + entry.getValue().stream().forEach(fbChange::add); + return fbChange; + }).toList(); + } + + private List searchAffectedFBs() { + final DataTypeInstanceSearch nsearch = new DataTypeInstanceSearch((DataTypeEntry) oldTypeEntry); + final List res = nsearch.performSearch(); + + return res.stream().filter(r -> InterfaceList.class.isInstance(r.eContainer())) + .filter(r -> FBType.class.isInstance(r.eContainer().eContainer())) + .map(r -> FBType.class.cast(r.eContainer().eContainer())).distinct().toList(); + } + + private String buildLabel(final String fbFileName, final String projectName) { + return fbFileName + " [" + projectName + "]"; //$NON-NLS-1$ + } + +} diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/ProjectFbInstanceChange.java b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/ProjectFbInstanceChange.java new file mode 100644 index 0000000000..4e311f2a5f --- /dev/null +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/ProjectFbInstanceChange.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2024 Johannes Kepler University + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Martin Schwarz - initial implementation + *******************************************************************************/ +package org.eclipse.fordiac.ide.typemanagement.refactoring.rename; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.fordiac.ide.model.typelibrary.TypeEntry; +import org.eclipse.fordiac.ide.model.typelibrary.TypeLibraryManager; +import org.eclipse.ltk.core.refactoring.CompositeChange; + +public class ProjectFbInstanceChange extends CompositeChange { + + private final IFile file; + private final IProject project; + private final TypeEntry oldTypeEntry; + + public ProjectFbInstanceChange(final IFile file, final IProject project) { + super(project.getName()); + this.file = file; + this.project = project; + this.oldTypeEntry = TypeLibraryManager.INSTANCE.getTypeEntryForFile(file); + } + + public IProject getProject() { + return project; + } + +} diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/RenameTypeRefactoringParticipant.java b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/RenameTypeRefactoringParticipant.java index 30316014ed..e1ba68aa77 100644 --- a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/RenameTypeRefactoringParticipant.java +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/RenameTypeRefactoringParticipant.java @@ -10,54 +10,41 @@ * Contributors: * Fabio Gandolfi, Michael Oberlehner - * initial API and implementation and/or initial documentation + * Martin Schwarz - refactored for proper change grouping *******************************************************************************/ package org.eclipse.fordiac.ide.typemanagement.refactoring.rename; import java.text.MessageFormat; -import java.util.HashSet; import java.util.List; -import java.util.Set; import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.fordiac.ide.model.data.StructuredType; import org.eclipse.fordiac.ide.model.libraryElement.FBNetworkElement; import org.eclipse.fordiac.ide.model.libraryElement.FBType; import org.eclipse.fordiac.ide.model.libraryElement.LibraryElement; -import org.eclipse.fordiac.ide.model.libraryElement.StructManipulator; -import org.eclipse.fordiac.ide.model.libraryElement.VarDeclaration; import org.eclipse.fordiac.ide.model.search.types.BlockTypeInstanceSearch; -import org.eclipse.fordiac.ide.model.search.types.DataTypeInstanceSearch; import org.eclipse.fordiac.ide.model.search.types.IEC61499ElementSearch; -import org.eclipse.fordiac.ide.model.typelibrary.DataTypeEntry; import org.eclipse.fordiac.ide.model.typelibrary.TypeEntry; import org.eclipse.fordiac.ide.model.typelibrary.TypeLibraryManager; import org.eclipse.fordiac.ide.typemanagement.Messages; -import org.eclipse.fordiac.ide.typemanagement.refactoring.UpdateFBInstanceChange; -import org.eclipse.fordiac.ide.typemanagement.refactoring.UpdateFBTypeInterfaceChange; +import org.eclipse.fordiac.ide.typemanagement.refactoring.UpdateInstancesChange; import org.eclipse.fordiac.ide.typemanagement.refactoring.UpdateTypeEntryChange; -import org.eclipse.fordiac.ide.typemanagement.refactoring.delete.UpdateStructDataTypeMemberVariableChange; import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.CompositeChange; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; import org.eclipse.ltk.core.refactoring.participants.RenameParticipant; -/** - * A participant for type rename refactorings triggered within a model context, - * such as file rename. - */ public class RenameTypeRefactoringParticipant extends RenameParticipant { - private IFile file; - private TypeEntry typeEntry; - private String oldName; - private String newName; + IFile file; + TypeEntry typeEntry; + String oldName; + String newName; @Override protected boolean initialize(final Object element) { @@ -84,7 +71,7 @@ public RefactoringStatus checkConditions(final IProgressMonitor monitor, final C try { monitor.beginTask("Checking preconditions...", 1); //$NON-NLS-1$ checkFileEnding(status); - checkFileName(status); + } finally { monitor.done(); } @@ -97,21 +84,6 @@ protected void checkFileEnding(final RefactoringStatus result) { } } - protected void checkFileName(final RefactoringStatus result) { - if (!oldName.equalsIgnoreCase(newName)) { - try { - final String name = getArguments().getNewName(); - for (final IResource resource : file.getParent().members()) { - if (name.equalsIgnoreCase(resource.getName())) { - result.addFatalError("File already exists!"); //$NON-NLS-1$ - } - } - } catch (final CoreException e) { - // do nothing - } - } - } - @Override public Change createChange(final IProgressMonitor monitor) throws CoreException, OperationCanceledException { try { @@ -119,7 +91,7 @@ public Change createChange(final IProgressMonitor monitor) throws CoreException, final LibraryElement type = typeEntry.getType(); if (type instanceof StructuredType) { - return createStructDataChange((DataTypeEntry) typeEntry); + return createStructDataChange(); } if (type instanceof FBType) { return createFBDataChange(); @@ -131,30 +103,29 @@ public Change createChange(final IProgressMonitor monitor) throws CoreException, } } - private CompositeChange createStructDataChange(final DataTypeEntry dataTypeEntry) { - + private CompositeChange createStructDataChange() { final CompositeChange parentChange = new CompositeChange( MessageFormat.format(Messages.Refactoring_RenameFromTo, typeEntry.getTypeName(), newName)); - parentChange.add(new UpdateTypeEntryChange(file, typeEntry, newName, oldName)); - final CompositeChange structUsageChanges = new CompositeChange("Refactoring struct users:"); - parentChange.add(structUsageChanges); - createStructChanges(dataTypeEntry, structUsageChanges); + final Change typeLibraryChange = new UpdateTypeEntryChange(file, typeEntry, newName, oldName); + parentChange.add(typeLibraryChange); - return parentChange; - } + final CompositeChange fbTypeChange = new FbTypeChange(file, newName); + if (fbTypeChange.getChildren().length != 0) { + parentChange.add(fbTypeChange); + } - private static void createStructChanges(final DataTypeEntry dataTypeEntry, - final CompositeChange structUsageChanges) { - final DataTypeInstanceSearch dataTypeInstanceSearch = new DataTypeInstanceSearch(dataTypeEntry); - final Set rootElements = new HashSet<>(); - dataTypeInstanceSearch.performSearch().forEach(obj -> { - if (obj instanceof final VarDeclaration varDecl) { - structUsageChanges.add(createSubChange(varDecl, dataTypeEntry, rootElements)); - } else if (obj instanceof final StructManipulator structMan) { - structUsageChanges.add(new UpdateFBInstanceChange(structMan, dataTypeEntry)); - } - }); + final CompositeChange structChange = new StructTypeChange(file, newName); + if (structChange.getChildren().length != 0) { + parentChange.add(structChange); + } + + final CompositeChange fbInstanceChange = new FbInstanceChange(file); + if (fbInstanceChange.getChildren().length != 0) { + parentChange.add(fbInstanceChange); + } + + return parentChange; } private CompositeChange createFBDataChange() { @@ -166,7 +137,8 @@ private CompositeChange createFBDataChange() { final IEC61499ElementSearch search = new BlockTypeInstanceSearch(typeEntry); final List searchResults = search.performSearch(); searchResults.stream().filter(FBNetworkElement.class::isInstance).map(FBNetworkElement.class::cast) - .map(fbn -> new UpdateFBInstanceChange(fbn, typeEntry)).forEach(change::add); + .map(fbn -> new UpdateInstancesChange(fbn, typeEntry, typeEntry.getFile().getProject())) + .forEach(change::add); if (!searchResults.isEmpty()) { parentChange.add(change); @@ -174,28 +146,21 @@ private CompositeChange createFBDataChange() { return parentChange; } - private static Change createSubChange(final VarDeclaration varDecl, final DataTypeEntry dataTypeEntry, - final Set rootElements) { - if (varDecl.getFBNetworkElement() != null) { - if (rootElements.add(varDecl.getFBNetworkElement())) { - return new UpdateFBInstanceChange(varDecl.getFBNetworkElement(), dataTypeEntry); - } - } else { - final EObject rootContainer = EcoreUtil.getRootContainer(varDecl); - if (rootElements.add(rootContainer)) { - if (rootContainer instanceof final StructuredType stElement) { - final CompositeChange change = new CompositeChange(MessageFormat.format( - Messages.Refactoring_AffectedStruct, stElement.getName(), dataTypeEntry.getTypeName())); - change.add(new UpdateStructDataTypeMemberVariableChange(varDecl)); - createStructChanges((DataTypeEntry) stElement.getTypeEntry(), change); - return change; - } - if (rootContainer instanceof final FBType fbType - && dataTypeEntry.getType() instanceof final StructuredType type) { - return new UpdateFBTypeInterfaceChange(fbType, type); - } - } - } - return null; - } + /* + * private static Change createSubChange(final VarDeclaration varDecl, final + * DataTypeEntry dataTypeEntry, final Set rootElements) { if + * (varDecl.getFBNetworkElement() != null) { if + * (rootElements.add(varDecl.getFBNetworkElement())) { return new + * UpdateFBInstanceChange(varDecl.getFBNetworkElement(), dataTypeEntry); } } + * else { final EObject rootContainer = EcoreUtil.getRootContainer(varDecl); if + * (rootElements.add(rootContainer)) { if (rootContainer instanceof final + * StructuredType stElement) { final CompositeChange change = new + * CompositeChange(MessageFormat.format( Messages.Refactoring_AffectedStruct, + * stElement.getName(), dataTypeEntry.getTypeName())); change.add(new + * UpdateStructDataTypeMemberVariableChange(varDecl)); + * createStructChanges((DataTypeEntry) stElement.getTypeEntry(), change); return + * change; } if (rootContainer instanceof final FBType fbType && + * dataTypeEntry.getType() instanceof final StructuredType type) { return new + * UpdateFBTypeInterfaceChange(fbType, type); } } } return null; } + */ } diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/StructTypeChange.java b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/StructTypeChange.java new file mode 100644 index 0000000000..8521effcb4 --- /dev/null +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/StructTypeChange.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2024 Johannes Kepler University + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Martin Schwarz - initial implementation + *******************************************************************************/ +package org.eclipse.fordiac.ide.typemanagement.refactoring.rename; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.resources.IFile; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.fordiac.ide.model.data.StructuredType; +import org.eclipse.fordiac.ide.model.search.types.DataTypeInstanceSearch; +import org.eclipse.fordiac.ide.model.typelibrary.DataTypeEntry; +import org.eclipse.fordiac.ide.model.typelibrary.TypeEntry; +import org.eclipse.fordiac.ide.model.typelibrary.TypeLibraryManager; +import org.eclipse.fordiac.ide.typemanagement.Messages; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.CompositeChange; + +public class StructTypeChange extends CompositeChange { + + private final IFile file; + private final String newName; + private final TypeEntry oldTypeEntry; + + public StructTypeChange(final IFile file, final String newName) { + super(Messages.Refactoring_AffectedStruct); + this.file = file; + this.oldTypeEntry = TypeLibraryManager.INSTANCE.getTypeEntryForFile(file); + this.newName = newName; + buildChanges(); + } + + private void buildChanges() { + buildSubChanges().forEach(this::add); + } + + private List buildSubChanges() { + final Map> affectedStructChanges = new HashMap<>(); + + searchAffectedStructuredType().forEach(impactedStructuredType -> { + final String label = buildLabel(impactedStructuredType.getTypeEntry().getFile().getName(), + impactedStructuredType.getTypeEntry().getFile().getProject().getName()); + + if (!affectedStructChanges.containsKey(label)) { + affectedStructChanges.put(label, new HashSet<>()); + } + + affectedStructChanges.get(label) + .add(new StructuredTypeMemberChange(impactedStructuredType, oldTypeEntry, newName)); + }); + + return affectedStructChanges.entrySet().stream().map(entry -> { + final CompositeChange fbChange = new CompositeChange(entry.getKey()); + + entry.getValue().stream().forEach(fbChange::add); + + return fbChange; + }).toList(); + } + + private List searchAffectedStructuredType() { + final DataTypeInstanceSearch nsearch = new DataTypeInstanceSearch((DataTypeEntry) oldTypeEntry); + final List res = nsearch.performSearch(); + + return res.stream().filter(r -> StructuredType.class.isInstance(r.eContainer())) + .map(r -> StructuredType.class.cast(r.eContainer())).distinct().toList(); + } + + private String buildLabel(final String fbFileName, final String projectName) { + return fbFileName + " [" + projectName + "]"; //$NON-NLS-1$ + } +} diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/StructuredTypeMemberChange.java b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/StructuredTypeMemberChange.java new file mode 100644 index 0000000000..a0b95d73fc --- /dev/null +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/refactoring/rename/StructuredTypeMemberChange.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2024 Johannes Kepler University + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Martin Schwarz - initial implementation + *******************************************************************************/ +package org.eclipse.fordiac.ide.typemanagement.refactoring.rename; + +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.fordiac.ide.model.commands.change.ChangeDataTypeCommand; +import org.eclipse.fordiac.ide.model.data.DataType; +import org.eclipse.fordiac.ide.model.data.StructuredType; +import org.eclipse.fordiac.ide.model.libraryElement.VarDeclaration; +import org.eclipse.fordiac.ide.model.typelibrary.TypeEntry; +import org.eclipse.gef.commands.CompoundCommand; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; + +public class StructuredTypeMemberChange extends Change { + + private final StructuredType affectedStruct; + private final TypeEntry oldTypeEntry; + private final List affectedMembers; + private final String newStructMemberName; + + private final CompoundCommand cmd = new CompoundCommand(); + + public StructuredTypeMemberChange(final StructuredType affectedStruct, final TypeEntry oldTypeEntry, + final String newStructMemberName) { + + this.affectedStruct = affectedStruct; + this.oldTypeEntry = oldTypeEntry; + this.newStructMemberName = newStructMemberName; + this.affectedMembers = affectedStruct.getMemberVariables().stream() + .filter(var -> var.getType().equals(oldTypeEntry.getType())).map(VarDeclaration::getName).toList(); + + this.buildRefactoringChange(); + + } + + public void buildRefactoringChange() { + final StructuredType structuredTypeEditable = (StructuredType) affectedStruct.getTypeEntry().getTypeEditable(); + for (final VarDeclaration varDeclaration : structuredTypeEditable.getMemberVariables()) { + final String typeName = varDeclaration.getTypeName(); + if (typeName.equals(this.oldTypeEntry.getTypeName())) { + cmd.add(ChangeDataTypeCommand.forDataType(varDeclaration, + (DataType) this.oldTypeEntry.getTypeEditable())); + } + } + + } + + @Override + public String getName() { + return "Update Struct Members: " + this.affectedMembers.toString(); //$NON-NLS-1$ + } + + @Override + public void initializeValidationData(final IProgressMonitor pm) { + + } + + @Override + public RefactoringStatus isValid(final IProgressMonitor pm) throws CoreException, OperationCanceledException { + return new RefactoringStatus(); + } + + @Override + public Change perform(final IProgressMonitor pm) throws CoreException { + + final StructuredType structuredTypeEditable = (StructuredType) affectedStruct.getTypeEntry().getTypeEditable(); + + cmd.execute(); + structuredTypeEditable.getTypeEntry().save(structuredTypeEditable, pm); + + return null; + } + + @Override + public StructuredType getModifiedElement() { + return this.affectedStruct; + } + + public CompoundCommand getRefactoringCommand() { + return cmd; + } + + public TypeEntry getModifiedTypeEntry() { + return this.oldTypeEntry; + } + + public String getNewTypeEntryName() { + return this.newStructMemberName; + } + +} diff --git a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/util/FBUpdater.java b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/util/FBUpdater.java index 08292efe21..c3f1c64f9c 100644 --- a/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/util/FBUpdater.java +++ b/plugins/org.eclipse.fordiac.ide.typemanagement/src/org/eclipse/fordiac/ide/typemanagement/util/FBUpdater.java @@ -23,10 +23,12 @@ import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.fordiac.ide.model.commands.change.ChangeStructCommand; import org.eclipse.fordiac.ide.model.commands.change.UpdateFBTypeCommand; +import org.eclipse.fordiac.ide.model.commands.change.UpdatePinInTypeDeclarationCommand; import org.eclipse.fordiac.ide.model.commands.change.UpdateUntypedSubAppInterfaceCommand; import org.eclipse.fordiac.ide.model.data.StructuredType; import org.eclipse.fordiac.ide.model.libraryElement.AutomationSystem; import org.eclipse.fordiac.ide.model.libraryElement.FBNetworkElement; +import org.eclipse.fordiac.ide.model.libraryElement.FBType; import org.eclipse.fordiac.ide.model.libraryElement.INamedElement; import org.eclipse.fordiac.ide.model.libraryElement.StructManipulator; import org.eclipse.fordiac.ide.model.libraryElement.SubApp; @@ -71,6 +73,23 @@ public static Command createUpdateUntypedSubappInterfaceCommand(final Collection return cmd; } + public static Command createUpdatePinInTypeDeclarationCommand(final List types, + final List dataTypeEntries) { + final List commands = new ArrayList<>(); + types.forEach(type -> commands + .add(createUpdatePinInTypeDeclarationCommand(type, dataTypeEntries.get(types.indexOf(type))))); + Command cmd = new CompoundCommand(); + for (final Command subCmd : commands) { + cmd = cmd.chain(subCmd); + } + return cmd; + } + + public static Command createUpdatePinInTypeDeclarationCommand(final FBType type, + final DataTypeEntry dataTypeEntry) { + return new UpdatePinInTypeDeclarationCommand(type, dataTypeEntry); + } + public static Command createStructManipulatorsUpdateCommand(final List muxes, final List dataTypeEntries) { final List commands = new ArrayList<>();