[546244] Allow to consider some graphical changes as requiring a refresh
This commit allows developer to add specific graphical changes as
changes requiring a refresh.
This commit also updates the collapse or uncollapse action on a region
container to launch a refresh of the current diagram even if Sirius is
in manual refresh mode.
Bug: 546244
Cherry-picked-from: 545640
Change-Id: I17ff1ead4c285bed3262d7b2ab3a01b5b504c01f
Signed-off-by: Laurent Redor <laurent.redor@obeo.fr>
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/RegionResizableEditPolicy.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/RegionResizableEditPolicy.java
index bebd0ba..566376b 100644
--- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/RegionResizableEditPolicy.java
+++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/RegionResizableEditPolicy.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013, 2016 THALES GLOBAL SERVICES and others.
+ * Copyright (c) 2013, 2019 THALES GLOBAL SERVICES and others.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
@@ -14,6 +14,7 @@
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Locator;
@@ -22,9 +23,11 @@
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.gef.DragTracker;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gef.requests.AlignmentRequest;
import org.eclipse.gef.requests.ChangeBoundsRequest;
@@ -33,9 +36,13 @@
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IResizableCompartmentEditPart;
import org.eclipse.gmf.runtime.diagram.ui.handles.CompartmentCollapseHandle;
+import org.eclipse.gmf.runtime.diagram.ui.internal.tools.CompartmentCollapseTracker;
import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand;
import org.eclipse.gmf.runtime.gef.ui.figures.DefaultSizeNodeFigure;
import org.eclipse.gmf.runtime.notation.NotationPackage;
+import org.eclipse.sirius.business.api.session.Session;
+import org.eclipse.sirius.business.api.session.SessionManager;
+import org.eclipse.sirius.diagram.DDiagram;
import org.eclipse.sirius.diagram.DDiagramElement;
import org.eclipse.sirius.diagram.DDiagramElementContainer;
import org.eclipse.sirius.diagram.DNodeList;
@@ -52,6 +59,7 @@
import org.eclipse.sirius.ext.base.Option;
import org.eclipse.sirius.ext.base.Options;
import org.eclipse.sirius.ext.gmf.runtime.gef.ui.figures.IContainerLabelOffsets;
+import org.eclipse.sirius.tools.api.ui.RefreshHelper;
import org.eclipse.sirius.viewpoint.LabelAlignment;
import org.eclipse.sirius.viewpoint.LabelStyle;
import org.eclipse.sirius.viewpoint.Style;
@@ -263,9 +271,8 @@
}
/**
- * Complete the given composite command with Region specific resize
- * commands: the commands to report the resize on the RegionContainer or on
- * the sibling regions.
+ * Complete the given composite command with Region specific resize commands: the commands to report the resize on
+ * the RegionContainer or on the sibling regions.
*/
@Override
protected void completeResizeCommand(CompositeTransactionalCommand ctc, ChangeBoundsRequest request) {
@@ -289,11 +296,9 @@
}
/**
- * Return true to add the default {@link AirResizableEditPolicy} behavior in
- * completeResizeCommand: this will add the sub commands to adjust children
- * position: see
- * {@link org.eclipse.sirius.diagram.ui.internal.edit.commands.ChildrenAdjustmentCommand}
- * .
+ * Return true to add the default {@link AirResizableEditPolicy} behavior in completeResizeCommand: this will add
+ * the sub commands to adjust children position: see
+ * {@link org.eclipse.sirius.diagram.ui.internal.edit.commands.ChildrenAdjustmentCommand} .
*
* @param request
* the current change bounds request.
@@ -573,9 +578,8 @@
}
/**
- * Specific {@link CompartmentCollapseHandle} for Regions: it locates the
- * handle on the Region label area and not in its content pane, it takes the
- * label alignment of the Region into account.
+ * Specific {@link CompartmentCollapseHandle} for Regions: it locates the handle on the Region label area and not in
+ * its content pane, it takes the label alignment of the Region into account.
*/
private static class RegionCollapseHandle extends CompartmentCollapseHandle {
@@ -585,14 +589,11 @@
* Constructor.
*
* @param owner
- * the compartment part to collapse (the part whose GMF node
- * has the drawer style)
+ * the compartment part to collapse (the part whose GMF node has the drawer style)
* @param alignment
- * the label alignment to take into account to correctly
- * locate the handle.
+ * the label alignment to take into account to correctly locate the handle.
* @param regionPart
- * the region part to notify when drawer syle is expanded or
- * collapsed.
+ * the region part to notify when drawer syle is expanded or collapsed.
*/
RegionCollapseHandle(IGraphicalEditPart owner, LabelAlignment alignment, AbstractDiagramElementContainerEditPart regionPart) {
super(owner);
@@ -610,6 +611,45 @@
}
}
+ /*
+ * Overriden to force the refresh of the current diagram, even if we are in manual refresh.
+ */
+ @SuppressWarnings("restriction")
+ @Override
+ protected DragTracker createDragTracker() {
+ return new CompartmentCollapseTracker(
+ (IResizableCompartmentEditPart) getOwner()) {
+ @Override
+ protected Command getCommand(Boolean expand) {
+ Command command = super.getCommand(expand);
+ CompoundCommand commandPlusForceRefresh = new CompoundCommand(command.getLabel());
+ // If we are in manual refresh, add a new command to force the refresh of the current diagram.
+ if (!RefreshHelper.isAutoRefresh()) {
+ commandPlusForceRefresh.add(new Command() {
+ @Override
+ public void execute() {
+ Optional<DDiagram> optionalDDiagram = new org.eclipse.sirius.diagram.ui.business.api.query.EditPartQuery(regionPart).getDDiagram();
+ if (optionalDDiagram.isPresent()) {
+ Session session = SessionManager.INSTANCE.getSession(optionalDDiagram.get());
+ if (session != null) {
+ // Set the RefreshEditorsListener in forceRefresh mode
+ session.getRefreshEditorsListener().setForceRefresh(true);
+ }
+ }
+ }
+
+ @Override
+ public void undo() {
+ execute();
+ }
+ });
+ }
+ commandPlusForceRefresh.add(command);
+ return commandPlusForceRefresh;
+ }
+ };
+ }
+
private class RegionCollapseHandleLocator implements Locator {
private boolean isRegionTextLeftAligned;
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src/org/eclipse/sirius/diagram/ui/business/api/query/EditPartQuery.java b/plugins/org.eclipse.sirius.diagram.ui/src/org/eclipse/sirius/diagram/ui/business/api/query/EditPartQuery.java
index 8a8861b..b1ee6ab 100644
--- a/plugins/org.eclipse.sirius.diagram.ui/src/org/eclipse/sirius/diagram/ui/business/api/query/EditPartQuery.java
+++ b/plugins/org.eclipse.sirius.diagram.ui/src/org/eclipse/sirius/diagram/ui/business/api/query/EditPartQuery.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2018 Obeo
+ * Copyright (c) 2018, 2019 Obeo
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
@@ -12,6 +12,8 @@
*******************************************************************************/
package org.eclipse.sirius.diagram.ui.business.api.query;
+import java.util.Optional;
+
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.EditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
@@ -47,6 +49,21 @@
* element exists.
*/
public DiagramDescription getDiagramDescription() {
+ Optional<DDiagram> optionalDDiagram = getDDiagram();
+ if (optionalDDiagram.isPresent()) {
+ return optionalDDiagram.get().getDescription();
+ }
+
+ return null;
+ }
+
+ /**
+ * Return the {@link DDiagram} associated to the edit part or to one of its ancestor.
+ *
+ * @return the {@link DDiagram} associated to the edit part or to one of its ancestor. Empty optional if no such
+ * element exists.
+ */
+ public Optional<DDiagram> getDDiagram() {
IDDiagramEditPart effectiveDiagramEditPart = null;
if (editPart instanceof IDiagramElementEditPart) {
effectiveDiagramEditPart = getDiagramEditPart(editPart);
@@ -56,11 +73,10 @@
if (effectiveDiagramEditPart != null) {
EObject resolvedSemanticElement = effectiveDiagramEditPart.resolveSemanticElement();
if (resolvedSemanticElement instanceof DDiagram) {
- return ((DDiagram) resolvedSemanticElement).getDescription();
+ return Optional.of((DDiagram) resolvedSemanticElement);
}
}
-
- return null;
+ return Optional.empty();
}
/**
diff --git a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html
index 943a4d2..acb3b4a 100644
--- a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html
+++ b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html
@@ -118,6 +118,29 @@
</li>
</ul>
<h3 id="DeveloperVisibleChanges">Developer-Visible Changes</h3>
+ <ul>
+ <li><span class="label label-success">Added</span> It is now possible to consider that some specific graphical changes need a refresh of the representation. Before Sirius 6.1.3, only semantic changes triggers a refresh. Now you can use
+ <code>RefreshHelper.registerImpactingNotification(Predicate<Notification>)</code> to consider a specific graphical changes. An example is the possibility to launch a refresh when the region container is collapsed or uncollapsed.
+ </li>
+ </ul>
+ <p>See
+ <a href="developer/trigger-refresh-graphical-changes.html">Trigger a Sirius refresh on specific graphical changes</a> in the developer documentation for more details.
+ </p>
+ <h4 id="Changesinorg.eclipse.sirius">Changes in
+ <code>org.eclipse.sirius</code>
+ </h4>
+ <ul>
+ <li><span class="label label-success">Added</span> The method
+ <code>org.eclipse.sirius.tools.api.ui.RefreshHelper.isAutoRefresh()</code> has been added to know if Sirius is in automatic refresh mode or in manual mode.
+ </li>
+ <li><span class="label label-success">Added</span> The methods
+ <code>org.eclipse.sirius.tools.api.ui.RefreshHelper.registerImpactingNotification(Predicate<Notification>)</code> and
+ <code>org.eclipse.sirius.tools.api.ui.RefreshHelper.unregisterImpactingNotification(Predicate<Notification>)</code> have been added to allow to consider some graphical modifications as requiring a refresh. By default, only semantic changes are considered as requiring a refresh.
+ </li>
+ <li><span class="label label-danger">Removed</span> The
+ <code>org.eclipse.sirius.business.api.helper.task.NotificationTask</code> class has been removed. It was not used anywhere.
+ </li>
+ </ul>
<h4 id="Changesinorg.eclipse.sirius.common">Changes in
<code>org.eclipse.sirius.common</code>
</h4>
@@ -213,14 +236,6 @@
<code>java.util.Optional<T></code> instead.
</li>
</ul>
- <h4 id="Changesinorg.eclipse.sirius">Changes in
- <code>org.eclipse.sirius</code>
- </h4>
- <ul>
- <li><span class="label label-danger">Removed</span> The
- <code>org.eclipse.sirius.business.api.helper.task.NotificationTask</code> class has been removed. It was not used anywhere.
- </li>
- </ul>
<h4 id="Changesinorg.eclipse.sirius.diagram.layoutdata">Changes in
<code>org.eclipse.sirius.diagram.layoutdata</code>
</h4>
@@ -243,7 +258,7 @@
<code>on()</code> was also added to provide a more fluent API, e.g.
<code>DragAndDropTargetQuery.on(container).getLogicalChildren()</code>.
</li>
- <li><span class="label label-info">Added</span> The extension point org.eclipse.sirius.diagram.customBundledImageShape has been created in order to provide custom shape to the bundled image style. This extension point offers more flexibility on the specification of the svg tags and attributes holding the color, border color and border size information than the extension point org.eclipse.sirius.diagram.bundledImageShape.</li>
+ <li><span class="label label-success">Added</span> The extension point org.eclipse.sirius.diagram.customBundledImageShape has been created in order to provide custom shape to the bundled image style. This extension point offers more flexibility on the specification of the svg tags and attributes holding the color, border color and border size information than the extension point org.eclipse.sirius.diagram.bundledImageShape.</li>
<li><span class="label label-info">Modified</span> The extension point org.eclipse.sirius.diagram.bundledImageShape has been marked as deprecated. Shapes provided by this extension point still work.</li>
<li><span class="label label-info">Modified</span> The method
<code>org.eclipse.sirius.diagram.tools.api.command.IDiagramCommandFactory.buildInsertVerticalBlankSpaceCommand(DDiagram, int, int)</code> has been renamed to
@@ -407,6 +422,10 @@
<code>org.eclipse.sirius.diagram.ui</code>
</h4>
<ul>
+ <li><span class="label label-success">Added</span> The method
+ <code>org.eclipse.sirius.diagram.ui.business.api.query.EditPartQuery.getDDiagram()</code> has been added to retrieve the
+ <code>DDiagram</code> associated to the edit part or to one of its ancestor.
+ </li>
<li><span class="label label-danger">Removed</span> The message
<code>org.eclipse.sirius.diagram.ui.provider.Messages.SynchronizeGMFModelCommand_label</code> has been removed. It has been replaced in
<code>org.eclipse.sirius.diagram.Messages</code>.
diff --git a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile
index 36f3a2a..90860ff 100644
--- a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile
+++ b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile
@@ -16,6 +16,15 @@
h3. Developer-Visible Changes
+* <span class="label label-success">Added</span> It is now possible to consider that some specific graphical changes need a refresh of the representation. Before Sirius 6.1.3, only semantic changes triggers a refresh. Now you can use @RefreshHelper.registerImpactingNotification(Predicate<Notification>)@ to consider a specific graphical changes. An example is the possibility to launch a refresh when the region container is collapsed or uncollapsed.
+See "Trigger a Sirius refresh on specific graphical changes":developer/trigger-refresh-graphical-changes.html in the developer documentation for more details.
+
+h4. Changes in @org.eclipse.sirius@
+
+* <span class="label label-success">Added</span> The method @org.eclipse.sirius.tools.api.ui.RefreshHelper.isAutoRefresh()@ has been added to know if Sirius is in automatic refresh mode or in manual mode.
+* <span class="label label-success">Added</span> The methods @org.eclipse.sirius.tools.api.ui.RefreshHelper.registerImpactingNotification(Predicate<Notification>)@ and @org.eclipse.sirius.tools.api.ui.RefreshHelper.unregisterImpactingNotification(Predicate<Notification>)@ have been added to allow to consider some graphical modifications as requiring a refresh. By default, only semantic changes are considered as requiring a refresh.
+* <span class="label label-danger">Removed</span> The @org.eclipse.sirius.business.api.helper.task.NotificationTask@ class has been removed. It was not used anywhere.
+
h4. Changes in @org.eclipse.sirius.common@
* <span class="label label-success">Added</span> A new interface @org.eclipse.sirius.common.tools.api.interpreter.IConverter@ has been added: it encapsulates the coercion rules used to convert raw results returned by interpreted expressions into the types expected by Sirius (depending on the context of use of the expression).
@@ -37,10 +46,6 @@
* <span class="label label-info">Modified</span> In @org.eclipse.sirius.common.ui.tools.api.dialog.quickoutline.QuickOutlineDescriptor@, the methods @getFirstPage()@ and @getNextPage(QuickOutlinePageDescriptor)@ which used to return a @org.eclipse.sirius.ext.base.Option<T>@ now return standard @java.util.Optional<T>@ instead.
-h4. Changes in @org.eclipse.sirius@
-
-* <span class="label label-danger">Removed</span> The @org.eclipse.sirius.business.api.helper.task.NotificationTask@ class has been removed. It was not used anywhere.
-
h4. Changes in @org.eclipse.sirius.diagram.layoutdata@
* <span class="label label-danger">Removed</span> This plugin has been removed and fully replaced by @org.eclipse.sirius.diagram.formatdata@
@@ -49,7 +54,7 @@
* <span class="label label-success">Added</span> The message @org.eclipse.sirius.diagram.Messages.SynchronizeGMFModelCommand_label@ has been added. It replaces @org.eclipse.sirius.diagram.ui.provider.Messages.SynchronizeGMFModelCommand_label@.
* <span class="label label-success">Added</span> In @org.eclipse.sirius.diagram.business.api.query.DragAndDropTargetQuery@, a new method @getLogicalChildren()@ has been added. It makes it easy to iterate over the logical structure of diagram elements. A static factory method @on()@ was also added to provide a more fluent API, e.g. @DragAndDropTargetQuery.on(container).getLogicalChildren()@.
-* <span class="label label-info">Added</span> The extension point org.eclipse.sirius.diagram.customBundledImageShape has been created in order to provide custom shape to the bundled image style. This extension point offers more flexibility on the specification of the svg tags and attributes holding the color, border color and border size information than the extension point org.eclipse.sirius.diagram.bundledImageShape.
+* <span class="label label-success">Added</span> The extension point org.eclipse.sirius.diagram.customBundledImageShape has been created in order to provide custom shape to the bundled image style. This extension point offers more flexibility on the specification of the svg tags and attributes holding the color, border color and border size information than the extension point org.eclipse.sirius.diagram.bundledImageShape.
* <span class="label label-info">Modified</span> The extension point org.eclipse.sirius.diagram.bundledImageShape has been marked as deprecated. Shapes provided by this extension point still work.
* <span class="label label-info">Modified</span> The method @org.eclipse.sirius.diagram.tools.api.command.IDiagramCommandFactory.buildInsertVerticalBlankSpaceCommand(DDiagram, int, int)@ has been renamed to @org.eclipse.sirius.diagram.tools.api.command.IDiagramCommandFactory.buildInsertOrRemoveVerticalBlankSpaceCommand(DDiagram, int, int)@ because it handles now both addition and removal.
* <span class="label label-info">Modified</span> Method _getAllEdgeMappings_ defined in @org.eclipse.sirius.diagram.business.internal.metamodel.helper.ContentHelper@ has been moved in a new class called @org.eclipse.sirius.diagram.business.internal.metamodel.helper.ContentLayerHelper@ to ensure method to be independent from pure Sirius code.
@@ -91,6 +96,7 @@
h4. Changes in @org.eclipse.sirius.diagram.ui@
+* <span class="label label-success">Added</span> The method @org.eclipse.sirius.diagram.ui.business.api.query.EditPartQuery.getDDiagram()@ has been added to retrieve the @DDiagram@ associated to the edit part or to one of its ancestor.
* <span class="label label-danger">Removed</span> The message @org.eclipse.sirius.diagram.ui.provider.Messages.SynchronizeGMFModelCommand_label@ has been removed. It has been replaced in @org.eclipse.sirius.diagram.Messages@.
* <span class="label label-danger">Removed</span> The extension point @layoutDataManager@, deprecated since Sirius 4.1.0, has been removed. The corresponding plug-in @org.eclipse.sirius.diagram.layoutdata@ has also been removed.
diff --git a/plugins/org.eclipse.sirius.doc/doc/developer/Sirius Developer Manual.html b/plugins/org.eclipse.sirius.doc/doc/developer/Sirius Developer Manual.html
index 86692ef..2ffe064 100644
--- a/plugins/org.eclipse.sirius.doc/doc/developer/Sirius Developer Manual.html
+++ b/plugins/org.eclipse.sirius.doc/doc/developer/Sirius Developer Manual.html
@@ -109,6 +109,16 @@
<strong>Provide custom aird editor pages</strong>
</a>
</li>
+ <li>
+ <a href="extensions-provide_resource_strategy.html">
+ <strong>Provide a resource strategy</strong>
+ </a>
+ </li>
+ <li>
+ <a href="trigger-refresh-graphical-changes.html">
+ <strong>Trigger refresh on specific graphical changes</strong>
+ </a>
+ </li>
</ul>
</li>
</ul>
diff --git a/plugins/org.eclipse.sirius.doc/doc/developer/Sirius Developer Manual.textile b/plugins/org.eclipse.sirius.doc/doc/developer/Sirius Developer Manual.textile
index e9e9ade..8af7751 100644
--- a/plugins/org.eclipse.sirius.doc/doc/developer/Sirius Developer Manual.textile
+++ b/plugins/org.eclipse.sirius.doc/doc/developer/Sirius Developer Manual.textile
@@ -21,3 +21,5 @@
** "*Provide custom widget for the properties view and dialogs*":extensions-properties_provide_custom_widget.html
** "*Provide custom model operation*":extensions-provide_custom_model_operation.html
** "*Provide custom aird editor pages*":extensions-provide_custom_aird_editor_pages.html
+** "*Provide a resource strategy*":extensions-provide_resource_strategy.html
+** "*Trigger refresh on specific graphical changes*":trigger-refresh-graphical-changes.html
\ No newline at end of file
diff --git a/plugins/org.eclipse.sirius.doc/doc/developer/trigger-refresh-graphical-changes.html b/plugins/org.eclipse.sirius.doc/doc/developer/trigger-refresh-graphical-changes.html
new file mode 100644
index 0000000..b19e8a4
--- /dev/null
+++ b/plugins/org.eclipse.sirius.doc/doc/developer/trigger-refresh-graphical-changes.html
@@ -0,0 +1,52 @@
+<?xml version='1.0' encoding='utf-8' ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>trigger-refresh-graphical-changes</title>
+ <link type="text/css" rel="stylesheet" href="../resources/bootstrap.css"/>
+ <link type="text/css" rel="stylesheet" href="../resources/custom.css"/>
+ </head>
+ <body>
+ <h1 id="TriggeraSiriusrefreshonspecificgraphicalchanges">Trigger a Sirius refresh on specific graphical changes</h1>
+ <h2 id="Description">Description</h2>
+ <p>In automatic refresh mode, representations are refreshed as soon as at least one semantic change is done. Graphical changes are not considered as they are not impacting the mapping precondition. In some cases, the mapping can depend on the graphical state. A typical example is the “collapse” state of a
+ <a href="../specifier/diagrams/Diamgram.html#graphical_elements">region</a> to change the mapping according to it. Since Sirius 6.1.3, it is possible to register a new graphical change to trigger a Sirius refresh.
+ </p>
+ <h2 id="RegisteranewgraphicalchangetotriggeraSiriusrefresh">Register a new graphical change to trigger a Sirius refresh</h2>
+ <p>The
+ <code>org.eclipse.sirius.tools.api.ui.RefreshHelper.registerImpactingNotification(Predicate<Notification>)</code> allows to consider some graphical modifications as requiring a refresh. This method is called through the pre-commit listener
+ <code>org.eclipse.sirius.tools.api.ui.RefreshEditorsPrecommitListener</code>. So it is called only if you are in automatic refresh mode or if the “forceRefresh” mode has been activated (
+ <code>org.eclipse.sirius.tools.api.ui.RefreshEditorsPrecommitListener.setForceRefresh(boolean)</code>) with the corresponding representation to refresh (
+ <code>org.eclipse.sirius.tools.api.ui.RefreshEditorsPrecommitListener.addRepresentationToForceRefresh(DRepresentation)</code>).
+ <br/>For the specific case of collapse/uncollapse, current representation is automatically added as a force refresh representation. So the collapse/uncollapse of a region automatically launch a refresh, even in manual refresh mode.
+ </p>
+ <h3 id="Example">Example</h3>
+ <pre>// Register a predicate to consider Collapse/Uncollapse changes as impacting in diagram of kind "MyDiagramDescriptionName".
+RefreshHelper.registerImpactingNotification(new Predicate<Notification>() {
+ @Override
+ public boolean test(Notification notification) {
+ if (notification != null) {
+ if (NotationPackage.eINSTANCE.getDrawerStyle_Collapsed().equals(notification.getFeature())) {
+ if (notification.getNotifier() instanceof EObject) {
+ Option<DDiagram> optionalDDiagram = new EObjectQuery((EObject) notification.getNotifier()).getParentDiagram();
+ if (optionalDDiagram.some()) {
+ return "MyDiagramDescriptionName".equals(optionalDDiagram.get().getDescription().getName);
+ }
+ }
+ }
+ }
+ return false;
+ }
+});
+</pre>
+ <h2 id="Unregisterapreviouslyregistergraphicalchanges">Unregister a previously register graphical changes</h2>
+ <p>You can use
+ <code>org.eclipse.sirius.tools.api.ui.RefreshHelper.unregisterImpactingNotification(Predicate<Notification>)</code> to unregister a previously registered predicate.
+ </p>
+ <h2 id="Recommendation">Recommendation</h2>
+ <p>The
+ <code>RefreshEditorsPrecommitListener</code> is called after each changes. So each predicate added through
+ <code>registerImpactingNotification()</code> will be called on each notification (until one is considered as impacting). These predicates must be efficient.
+ </p>
+ </body>
+</html>
\ No newline at end of file
diff --git a/plugins/org.eclipse.sirius.doc/doc/developer/trigger-refresh-graphical-changes.textile b/plugins/org.eclipse.sirius.doc/doc/developer/trigger-refresh-graphical-changes.textile
new file mode 100644
index 0000000..ef9a840
--- /dev/null
+++ b/plugins/org.eclipse.sirius.doc/doc/developer/trigger-refresh-graphical-changes.textile
@@ -0,0 +1,39 @@
+h1. Trigger a Sirius refresh on specific graphical changes
+
+h2. Description
+
+In automatic refresh mode, representations are refreshed as soon as at least one semantic change is done. Graphical changes are not considered as they are not impacting the mapping precondition. In some cases, the mapping can depend on the graphical state. A typical example is the "collapse" state of a "region":../specifier/diagrams/Diamgram.html#graphical_elements to change the mapping according to it. Since Sirius 6.1.3, it is possible to register a new graphical change to trigger a Sirius refresh.
+
+h2. Register a new graphical change to trigger a Sirius refresh
+
+The @org.eclipse.sirius.tools.api.ui.RefreshHelper.registerImpactingNotification(Predicate<Notification>)@ allows to consider some graphical modifications as requiring a refresh. This method is called through the pre-commit listener @org.eclipse.sirius.tools.api.ui.RefreshEditorsPrecommitListener@. So it is called only if you are in automatic refresh mode or if the "forceRefresh" mode has been activated (@org.eclipse.sirius.tools.api.ui.RefreshEditorsPrecommitListener.setForceRefresh(boolean)@) with the corresponding representation to refresh (@org.eclipse.sirius.tools.api.ui.RefreshEditorsPrecommitListener.addRepresentationToForceRefresh(DRepresentation)@).
+For the specific case of collapse/uncollapse, current representation is automatically added as a force refresh representation. So the collapse/uncollapse of a region automatically launch a refresh, even in manual refresh mode.
+
+h3. Example
+
+pre.
+// Register a predicate to consider Collapse/Uncollapse changes as impacting in diagram of kind "MyDiagramDescriptionName".
+RefreshHelper.registerImpactingNotification(new Predicate<Notification>() {
+ @Override
+ public boolean test(Notification notification) {
+ if (notification != null) {
+ if (NotationPackage.eINSTANCE.getDrawerStyle_Collapsed().equals(notification.getFeature())) {
+ if (notification.getNotifier() instanceof EObject) {
+ Option<DDiagram> optionalDDiagram = new EObjectQuery((EObject) notification.getNotifier()).getParentDiagram();
+ if (optionalDDiagram.some()) {
+ return "MyDiagramDescriptionName".equals(optionalDDiagram.get().getDescription().getName);
+ }
+ }
+ }
+ }
+ return false;
+ }
+});
+
+h2. Unregister a previously register graphical changes
+
+You can use @org.eclipse.sirius.tools.api.ui.RefreshHelper.unregisterImpactingNotification(Predicate<Notification>)@ to unregister a previously registered predicate.
+
+h2. Recommendation
+
+The @RefreshEditorsPrecommitListener@ is called after each changes. So each predicate added through @registerImpactingNotification()@ will be called on each notification (until one is considered as impacting). These predicates must be efficient.
\ No newline at end of file
diff --git a/plugins/org.eclipse.sirius.doc/doc/toc.xml b/plugins/org.eclipse.sirius.doc/doc/toc.xml
index 26fa5e8..5c84389 100644
--- a/plugins/org.eclipse.sirius.doc/doc/toc.xml
+++ b/plugins/org.eclipse.sirius.doc/doc/toc.xml
@@ -248,8 +248,8 @@
<topic href="doc/developer/extensions-properties_provide_custom_widget_basic.html" label="Basic approach" />
<topic href="doc/developer/extensions-properties_provide_custom_widget_advanced.html" label="Advanced approach" />
</topic>
- <topic href="doc/developer/extensions-provide_resource_strategy.html" label="Provide a resource strategy">
- </topic>
+ <topic href="doc/developer/extensions-provide_resource_strategy.html" label="Provide a resource strategy"/>
+ <topic href="doc/developer/trigger-refresh-graphical-changes.html" label="Trigger a Sirius refresh on specific graphical changes" />
<anchor id="moreExtensionPointsRefs" />
</topic>
<anchor id="moreDeveloperRefs" />
diff --git a/plugins/org.eclipse.sirius/plugin.properties b/plugins/org.eclipse.sirius/plugin.properties
index e0d3e92..856c7f9 100644
--- a/plugins/org.eclipse.sirius/plugin.properties
+++ b/plugins/org.eclipse.sirius/plugin.properties
@@ -1,5 +1,5 @@
# ====================================================================
-# Copyright (c) 2007, 2018 THALES GLOBAL SERVICES and others
+# Copyright (c) 2007, 2019 THALES GLOBAL SERVICES and others
# This program and the accompanying materials
# are made available under the terms of the Eclipse Public License 2.0
# which accompanies this distribution, and is available at
@@ -231,6 +231,7 @@
PaneBasedSelectionWizardDescriptionImpl_choiceOfValuesMsg = Choice of values
PaneBasedSelectionWizardDescriptionImpl_selectedValuesMsg = Selected values
PrepareNewAnalysisCommand_label = Prepare new Analysis
+RefreshHelper_notNullPredicate = The predicate cannot be null.
RefreshImpactedElementsCommand_label = Refresh impacted representation elements
RefreshRepresentationsCommand_label = Refresh representation
RemoveElementTask_label = Remove an element
diff --git a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/tools/api/ui/RefreshEditorsPrecommitListener.java b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/tools/api/ui/RefreshEditorsPrecommitListener.java
index 9e36997..5713173 100644
--- a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/tools/api/ui/RefreshEditorsPrecommitListener.java
+++ b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/tools/api/ui/RefreshEditorsPrecommitListener.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2016 THALES GLOBAL SERVICES and others.
+ * Copyright (c) 2011, 2019 THALES GLOBAL SERVICES and others.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
@@ -124,7 +124,8 @@
if (needsRefresh()) {
boolean impactingNotification = RefreshHelper.isImpactingNotification(notifications);
// Do nothing if the notification concern only elements of aird
- // resource and that the representationsToForceRefresh is empty.
+ // resource that are not in the specific graphical notification to consider (see
+ // RefreshHelper.registerImpactingNotification) and that the representationsToForceRefresh is empty.
if (impactingNotification || !representationsToForceRefresh.isEmpty()) {
Option<? extends Command> optionCommand = getRefreshOpenedRepresentationsCommand(impactingNotification);
if (optionCommand.some()) {
diff --git a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/tools/api/ui/RefreshHelper.java b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/tools/api/ui/RefreshHelper.java
index e1bfa3e..301c2bc 100644
--- a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/tools/api/ui/RefreshHelper.java
+++ b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/tools/api/ui/RefreshHelper.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016, 2017 THALES GLOBAL SERVICES.
+ * Copyright (c) 2016, 2019 THALES GLOBAL SERVICES.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
@@ -12,14 +12,30 @@
*******************************************************************************/
package org.eclipse.sirius.tools.api.ui;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
import java.util.Set;
+import java.util.function.Predicate;
+import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.sirius.business.api.preferences.SiriusPreferencesKeys;
+import org.eclipse.sirius.business.api.query.EObjectQuery;
import org.eclipse.sirius.business.api.query.ResourceQuery;
+import org.eclipse.sirius.business.api.session.Session;
+import org.eclipse.sirius.business.api.session.SessionManager;
+import org.eclipse.sirius.ext.base.Option;
+import org.eclipse.sirius.viewpoint.DRepresentation;
+import org.eclipse.sirius.viewpoint.Messages;
+import org.eclipse.sirius.viewpoint.SiriusPlugin;
+
+import com.google.common.base.Preconditions;
/**
* A class providing useful methods for refresh.
@@ -27,6 +43,8 @@
* @author mbats
*/
public final class RefreshHelper {
+ private static List<Predicate<Notification>> impactingNotificationPredicates = new ArrayList<>();
+
/**
* Prevent instantiation.
*/
@@ -34,29 +52,131 @@
}
/**
- * Checks whether the changes we are notified changes semantic models (i.e. not just Sirius representations state).
+ * Checks whether at least one change of which we are notified, concerns a semantic model or a specific graphical
+ * change (registered through {@link #registerImpactingNotification(Predicate)}).
*
* @param notifications
* the model changes.
- * @return <code>true</code> if the changes impact semantic models.
+ * @return <code>true</code> if the changes impact a semantic model or a specific graphical change.
*/
public static boolean isImpactingNotification(final Collection<Notification> notifications) {
- boolean isImpactingNotification = false;
+ // Create caches for the resource of a notifier and for the result of the method "new
+ // ResourceQuery(Resource).isAirdOrSrmResource()". Both of them can be "time consuming".
+ Map<EObject, Boolean> notifierIsInAirdOrSrmResource = new HashMap<>();
+ Map<EObject, Resource> notifierWithResource = new HashMap<>();
Set<EObject> alreadyDoneNotifiers = new HashSet<>();
for (Notification notification : notifications) {
Object notifier = notification.getNotifier();
if (notifier instanceof EObject) {
EObject eObjectNotifier = (EObject) notifier;
- if (!alreadyDoneNotifiers.contains(eObjectNotifier)) {
- alreadyDoneNotifiers.add(eObjectNotifier);
- Resource notifierResource = eObjectNotifier.eResource();
- if (notifierResource != null && !new ResourceQuery(notifierResource).isAirdOrSrmResource()) {
- isImpactingNotification = true;
- break;
- }
+ if (!alreadyDoneNotifiers.contains(eObjectNotifier) && isImpactingNotification(notification, eObjectNotifier, alreadyDoneNotifiers, notifierWithResource, notifierIsInAirdOrSrmResource)) {
+ return true;
}
}
}
+ return false;
+ }
+
+ /**
+ * Checks whether this notification concerns a semantic model change or a specific graphical change (registered
+ * through {@link #registerImpactingNotification(Predicate)}).
+ *
+ * @param notification
+ * the model change.
+ * @param notifier
+ * the EObject which is concerned by this notification
+ * @param alreadyDoneNotifiers
+ * list of notifiers that have already been checked before
+ * @param notifierWithResource
+ * a cache map used to retrieve the resource from a notifier
+ * @param notifierIsInAirdOrSrmResource
+ * a cache map used to retrieve the result of the method
+ * <code>ResourceQuery(Resource).isAirdOrSrmResource()</code> from a notifier
+ * @return <code>true</code> if the change impact a semantic model or a specific graphical change.
+ */
+ protected static boolean isImpactingNotification(Notification notification, EObject notifier, Set<EObject> alreadyDoneNotifiers, Map<EObject, Resource> notifierWithResource,
+ Map<EObject, Boolean> notifierIsInAirdOrSrmResource) {
+ Resource notifierResource = notifierWithResource.get(notifier);
+ Boolean isAirdOrSrmResourceCache = notifierIsInAirdOrSrmResource.get(notifier);
+ boolean isImpactingNotification = false;
+ if (notifierResource != null) {
+ isImpactingNotification = !isAirdOrSrmResourceCache.booleanValue();
+ } else {
+ notifierResource = notifier.eResource();
+ if (notifierResource != null) {
+ if (impactingNotificationPredicates.isEmpty()) {
+ // If the impactingNotificationPredicates is not empty we must check every notification but in other
+ // case, you have only one check by notifier.
+ alreadyDoneNotifiers.add(notifier);
+ }
+ isImpactingNotification = !new ResourceQuery(notifierResource).isAirdOrSrmResource();
+ notifierWithResource.put(notifier, notifierResource);
+ notifierIsInAirdOrSrmResource.put(notifier, !isImpactingNotification);
+ }
+ }
+ if (notifierResource != null && !isImpactingNotification && isSpecificImpactingNotification(notification)) {
+ // The impacting notification is a graphical one, so if we are in manual refresh, we must add
+ // the corresponding representation to the force refresh list
+ if (!isAutoRefresh()) {
+ Option<DRepresentation> optionalDRepresentation = new EObjectQuery(notifier).getRepresentation();
+ if (optionalDRepresentation.some()) {
+ Session session = SessionManager.INSTANCE.getExistingSession(notifierResource.getURI());
+ if (session != null) {
+ session.getRefreshEditorsListener().addRepresentationToForceRefresh(optionalDRepresentation.get());
+ }
+ }
+ }
+ isImpactingNotification = true;
+ }
return isImpactingNotification;
}
+
+ /**
+ * Return true if the automatic refresh mode is activated, false otherwise.
+ *
+ * @return true if the automatic refresh mode is activated, false otherwise.
+ */
+ public static boolean isAutoRefresh() {
+ return Platform.isRunning() && Platform.getPreferencesService().getBoolean(SiriusPlugin.ID, SiriusPreferencesKeys.PREF_AUTO_REFRESH.name(), false, null);
+ }
+
+ /**
+ * Check this notification with all registered predicates.
+ *
+ * @param notification
+ * The notification to check
+ * @return true if at least one predicate consider this notification as impacting, false otherwise.
+ */
+ private static boolean isSpecificImpactingNotification(Notification notification) {
+ // Check graphical modification considered as impacting by customers
+ for (Predicate<Notification> predicate : impactingNotificationPredicates) {
+ if (predicate.test(notification)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Register a predicate to consider a graphical notification (notification concerning the representations file and
+ * not the semantic file) as impacting and requiring a refresh of the diagram.
+ *
+ * @param impactingNotificationPredicate
+ * a predicate to consider a notification as impacting.
+ */
+ public static void registerImpactingNotification(Predicate<Notification> impactingNotificationPredicate) {
+ Preconditions.checkNotNull(impactingNotificationPredicate, Messages.RefreshHelper_notNullPredicate);
+ impactingNotificationPredicates.add(impactingNotificationPredicate);
+ }
+
+ /**
+ * Unregister a predicate, previously register through {@link #registerImpactingNotification(Predicate)}.
+ *
+ * @param impactingNotificationPredicate
+ * a predicate that must no longer consider a notification as impacting.
+ */
+ public static void unregisterImpactingNotification(Predicate<Notification> impactingNotificationPredicate) {
+ Preconditions.checkNotNull(impactingNotificationPredicate, Messages.RefreshHelper_notNullPredicate);
+ impactingNotificationPredicates.remove(impactingNotificationPredicate);
+ }
}
diff --git a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/viewpoint/Messages.java b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/viewpoint/Messages.java
index bdc7f4f..a4c61f3 100644
--- a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/viewpoint/Messages.java
+++ b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/viewpoint/Messages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2015, 2018 Obeo.
+ * Copyright (c) 2015, 2019 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
@@ -477,6 +477,9 @@
public static String PrepareNewAnalysisCommand_label;
@TranslatableMessage
+ public static String RefreshHelper_notNullPredicate;
+
+ @TranslatableMessage
public static String RefreshImpactedElementsCommand_label;
@TranslatableMessage