Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 41cddbbed2dbf3957ad040f23ebb6a3e5b70dc7f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/*****************************************************************************
 * Copyright (c) 2013 CEA LIST.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *  Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
 *  Christian W. Damus (CEA) - refactor for non-workspace abstraction of problem markers (CDO)
 *
 *****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.css.editpolicies;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartListener;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.editpolicies.AbstractEditPolicy;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
import org.eclipse.papyrus.infra.gmfdiag.common.utils.ServiceUtilsForEditPart;
import org.eclipse.papyrus.infra.gmfdiag.css.Activator;
import org.eclipse.papyrus.infra.gmfdiag.css.notation.CSSDiagram;
import org.eclipse.papyrus.infra.gmfdiag.css.notation.StatefulView;
import org.eclipse.papyrus.infra.gmfdiag.css.service.CssMarkerEventManagerService;
import org.eclipse.papyrus.infra.gmfdiag.css.service.MarkerToPseudoSelectorMappingService;
import org.eclipse.papyrus.infra.services.markerlistener.IMarkerEventListener;
import org.eclipse.papyrus.infra.services.markerlistener.IPapyrusMarker;
import org.w3c.dom.Element;

/**
 * An EditPolicy to handle marker events on semantic element associated with EditParts
 *
 */
public class MarkerEventListenerEditPolicy extends AbstractEditPolicy implements EditPolicy, EditPartListener {

	public static final String ROLE = "MARKER_EVENT_LISTENER";

	/**
	 * The marker event manager service to which this edit policy is attached.
	 */
	protected CssMarkerEventManagerService markerEventManagerService;

	public MarkerEventListenerEditPolicy() {
		// Nothing
	}

	/**
	 * Register this edit policy with the marker event manager service.
	 * When an edit policy has to be notified, this must be done through this marker event manager service.
	 *
	 * @see org.eclipse.gef.EditPolicy#activate()
	 */
	@Override
	public void activate() {
		try {
			ServicesRegistry servicesRegistry = ServiceUtilsForEditPart.getInstance().getServiceRegistry(getHost());

			markerEventManagerService = servicesRegistry.getService(CssMarkerEventManagerService.class);
			if (markerEventManagerService != null) {
				markerEventManagerService.registerEditPolicy(this);
			}

			markerToPseudoSelectorMappingService = servicesRegistry.getService(MarkerToPseudoSelectorMappingService.class);
		} catch (Exception e) {
			// Ignored; do nothing
		}
		getHost().addEditPartListener(this);
	}

	/**
	 * Unregister this edit policy from the marker event manager service
	 *
	 * @see org.eclipse.gef.EditPolicy#deactivate()
	 */
	@Override
	public void deactivate() {
		if (markerEventManagerService != null) {
			markerEventManagerService.unregisterEditPolicy(this);
		}
		getHost().removeEditPartListener(this);
		markerStringToMarkerPseudoSelector.clear();
	}

	protected View getSemanticView() {
		return (View) getHost().getModel();
	}

	/**
	 * Updates the css state of the element associated with this edit policy
	 *
	 * @param state
	 *            The css states to be added or removed from the current state
	 * @param addedOrRemoved
	 *            Indicates wheter states have to be added or removed (Possible values are IMarkerEventListener.MARKER_ADDED and
	 *            IMarkerEventListener.MARKER_REMOVED)
	 */
	public void updateState(Set<String> state, int addedOrRemoved) {
		MarkerEventListenerEditPolicy primaryEditPolicy = getPrimaryEditPolicy();

		if (primaryEditPolicy == this) {
			View view = getSemanticView();
			if (view.getDiagram() instanceof CSSDiagram) {
				Element domElement = ((CSSDiagram) view.getDiagram()).getEngine().getElement(view);
				if (domElement instanceof StatefulView) {
					if (addedOrRemoved == IMarkerEventListener.MARKER_ADDED) {
						((StatefulView) domElement).addStates(state);
					} else {
						((StatefulView) domElement).removeStates(state);
					}
				}
			}
		} else if (primaryEditPolicy != null) {
			primaryEditPolicy.updateState(state, addedOrRemoved);
		}
	}

	/**
	 * Returns the primary edit policy
	 *
	 * @return THe primary edit policy
	 */
	private MarkerEventListenerEditPolicy getPrimaryEditPolicy() {
		EditPart current = getHost();
		EditPart parent = current.getParent();

		while (parent != null && semanticCompareEditParts(parent, getHost())) {
			current = parent;
			parent = parent.getParent();
		}

		return (MarkerEventListenerEditPolicy) current.getEditPolicy(ROLE);
	}

	/**
	 * Compares semantically the two given edit parts
	 *
	 * @param one
	 *            The first edit part to be compared
	 * @param other
	 *            The second edit part to be compared
	 * @return True if the two edit parts refer to the same model element, false otherwise
	 */
	private boolean semanticCompareEditParts(EditPart one, EditPart other) {
		if (one.getModel() instanceof View && other.getModel() instanceof View) {
			View view1 = (View) one.getModel();
			View view2 = (View) other.getModel();
			return view1 != null && view2 != null && view1.getElement() == view2.getElement();
		}
		return false;
	}

	// Helper method: casts the host edit part to the right type.
	@Override
	public GraphicalEditPart getHost() {
		return (GraphicalEditPart) super.getHost();
	}

	/*
	 * Events support
	 */
	@Override
	public void selectedStateChanged(EditPart editpart) {
		// Ignore
	}

	/*
	 * Ignored events
	 */
	@Override
	public void childAdded(EditPart child, int index) {
		// Ignore
	}

	@Override
	public void partActivated(EditPart editpart) {
		// Ignore
	}

	@Override
	public void partDeactivated(EditPart editpart) {
		// Ignore
	}

	@Override
	public void removingChild(EditPart child, int index) {
		// Ignore
	}

	/**
	 * Notifies this edit policy about a marker change
	 *
	 * @param marker
	 *            The actual marker
	 * @param addedOrRemoved
	 *            Indicates whether states have to be added or removed (Possible values are IMarkerEventListener.MARKER_ADDED and
	 *            IMarkerEventListener.MARKER_REMOVED)
	 */
	public void notifyMarkerChange(IPapyrusMarker marker, int addedOrRemoved) {
		String cssName = this.getPseudoSelector(marker);
		if (cssName != null && !"".equals(cssName)) {
			Set<String> state = new HashSet<String>();
			state.add(cssName);
			updateState(state, addedOrRemoved);
		}
	}

	/**
	 * Notifies this edit policy about multiple marker changes
	 *
	 * @param markers
	 *            The actual markers
	 * @param addedOrRemoved
	 *            Indicates whether states have to be added or removed (Possible values are IMarkerEventListener.MARKER_ADDED and
	 *            IMarkerEventListener.MARKER_REMOVED)
	 */
	public void notifyMarkerChange(IPapyrusMarker[] markers, int addedOrRemoved) {
		if (markers.length == 0) {
			return;
		}
		String cssName = "";
		Set<String> state = new HashSet<String>();
		for (int i = 0; i < markers.length; i++) {
			cssName = this.getPseudoSelector(markers[i]);
			if (cssName != null && !cssName.equals("")) {
				state.add(cssName);
			}
		}
		updateState(state, addedOrRemoved);
	}

	/**
	 * A mapping between a marker.toString() representation, and corresponding pseudo selector
	 * Elements are added in this mapping when a marker is added.
	 * This mapping is then used to retrieve the pseudo selector for a marker that does not exist anymore (i.e., !marker.exists(), which is the case
	 * when a marker has been removed),
	 * so that this pseudo selector can be removed from the state of the edit part.
	 */
	protected final Map<String, String> markerStringToMarkerPseudoSelector = new HashMap<String, String>();

	/**
	 * The Marker To Pseudo Selector Mapping Service
	 */
	protected MarkerToPseudoSelectorMappingService markerToPseudoSelectorMappingService;

	/**
	 * Convenience method returning the pseudo selector associated with a marker, using the MarkerToPseudoSelectorMappingService
	 *
	 * @param marker
	 *            The marker for which
	 * @return the pseudo selector associated with the given marker
	 */
	protected String getPseudoSelector(IPapyrusMarker marker) {
		try {
			if (!marker.exists()) {
				// Tries to retrieve it from the local map
				String pseudoSelector = this.markerStringToMarkerPseudoSelector.get(marker.toString());
				return pseudoSelector == null ? "" : pseudoSelector;
			}

			if (this.markerToPseudoSelectorMappingService == null) {
				return "";
			}

			String pseudoSelector = this.markerToPseudoSelectorMappingService.getPseudoSelector(marker.getType());
			this.markerStringToMarkerPseudoSelector.put(marker.toString(), pseudoSelector);
			return pseudoSelector;
		} catch (CoreException e) {
			Activator.log.error(e);
		}
		return "";
	}
}

Back to the top