Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 78ff2e44dcaa9fbb26443d8bf3d8a4cb8f9b704b (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
282
283
284
285
286
287
288
289
290
291
292
293
/*****************************************************************************
 * Copyright (c) 2011 Atos Origin.
 *
 *    
 * 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:
 *   Atos Origin - Initial API and implementation
 *
 *****************************************************************************/
package org.eclipse.papyrus.diagram.common.groups.core.ui;

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.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.editparts.CompartmentEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
import org.eclipse.papyrus.diagram.common.groups.Messages;
import org.eclipse.papyrus.diagram.common.groups.commands.ChangeGraphicalParentCommand;
import org.eclipse.papyrus.diagram.common.groups.core.PendingGroupNotificationsManager;
import org.eclipse.papyrus.diagram.common.groups.core.ui.utils.CreatorUtils;
import org.eclipse.papyrus.ui.toolbox.notification.ICompositeCreator;
import org.eclipse.papyrus.ui.toolbox.notification.builders.IContext;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.forms.widgets.FormText;
import org.eclipse.ui.forms.widgets.FormToolkit;

/**
 * Create a IComposite creator to ask the user to choose the graphical parent of a list of possible children
 * and then run the command to change the graphical parent
 * 
 * @author arthur daussy
 * 
 */
public class ChooseChildrenNotificationConfigurator extends NotificationConfigurator {

	/**
	 * EditPart of the parent
	 */
	private IGraphicalEditPart parentEditPart;

	/**
	 * All possible graphical children
	 */
	protected List<IGraphicalEditPart> allChildren;

	/**
	 * All children which are automatically chosen as graphical child
	 */
	protected List<IGraphicalEditPart> automaticChildren;

	/**
	 * buttons for children
	 */
	private Map<Button, IGraphicalEditPart> childCheckBoxes;

	/**
	 * {@link EditPart} hosting the {@link EditPolicy}
	 */
	protected IGraphicalEditPart host;


	/**
	 * Construct a {@link ICompositeCreator} in order to asked the user to choose children among a given list
	 * Constructor.
	 * 
	 * @param parentEditPart
	 *        EditPart of the parent (This part can be the {@link CompartmentEditPart} or the main {@link EditPart} of the element
	 * @param allChildren
	 * @see {@link #allChildren}
	 * @param automaticChildren
	 * @see {@link #automaticChildren}
	 */
	public ChooseChildrenNotificationConfigurator(IGraphicalEditPart parentEditPart, List<IGraphicalEditPart> allChildren, List<IGraphicalEditPart> automaticChildren, IGraphicalEditPart host, PendingGroupNotificationsManager manager) {
		super(parentEditPart, manager, Messages.ChooseChildrenICompositeCreator_ChooseChildren, Mode.QUESTION_MODE);
		this.parentEditPart = parentEditPart;
		this.allChildren = allChildren;
		this.automaticChildren = automaticChildren;
		this.host = host;
		this.childCheckBoxes = new HashMap<Button, IGraphicalEditPart>();
	}

	/**
	 * Run the notification and create a changeGrazphicalParent for each selected element
	 * 
	 * @see org.eclipse.papyrus.ui.toolbox.notification.NotificationRunnable#run(org.eclipse.papyrus.ui.toolbox.notification.builders.IContext)
	 * @param context
	 */
	public void run(IContext context) {
		TransactionalEditingDomain editingDomain = mainEditPart.getEditingDomain();
		Set<IGraphicalEditPart> childrenUpdated = new HashSet<IGraphicalEditPart>();
		for(Button checkBoxButton : childCheckBoxes.keySet()) {
			if(checkBoxButton.getSelection() && checkBoxButton.isEnabled()) {
				IGraphicalEditPart childPart = childCheckBoxes.get(checkBoxButton);
				if(!childrenUpdated.contains(childPart)) {
					changeGraphicalParentOf(editingDomain, childPart);
					childrenUpdated.add(childPart);
				}
			}
		}
		closeNotitfication(context);
	}

	/**
	 * @param editingDomain
	 * @param childPart
	 */
	private void changeGraphicalParentOf(TransactionalEditingDomain editingDomain, IGraphicalEditPart childPart) {
		String label = "Change graphical parent" + " of " + CreatorUtils.getLabel(childPart) + " to " + CreatorUtils.getLabel(mainEditPart);
		ChangeGraphicalParentCommand cmd = new ChangeGraphicalParentCommand(editingDomain, label, mainEditPart, childPart, host);
		if(cmd != null && cmd.canExecute()) {
			//Execute the command
			editingDomain.getCommandStack().execute(new GMFtoEMFCommandWrapper(cmd));
		}
	}

	/**
	 * 
	 * @see org.eclipse.papyrus.ui.toolbox.notification.ICompositeCreator#createComposite(org.eclipse.swt.widgets.Composite,
	 *      org.eclipse.ui.forms.widgets.FormToolkit)
	 * 
	 * @param parent
	 * @param toolkit
	 * @return
	 */
	public Composite createComposite(Composite parent, FormToolkit toolkit) {
		if(toolkit == null) {
			toolkit = new FormToolkit(parent.getDisplay());
		}
		Composite top = toolkit.createComposite(parent, SWT.NONE);
		top.setLayout(new FormLayout());
		FormText textLabel = toolkit.createFormText(top, false);
		textLabel.setText(Messages.ChooseParentNotificationCommand_ChooseGraphicalChildrenMessage + CreatorUtils.getLabel(mainEditPart) + " :", false, true);
		FormData data = new FormData();
		textLabel.setLayoutData(data);
		Control previousElement = textLabel;
		/*
		 * Create for each parents a checkbox
		 */
		createCheckBoxes(toolkit, top, previousElement);


		return top;
	}

	/**
	 * Create all the check boxes needed.
	 * If child is automatically assign to this parent then it appeares but it is disable
	 * If a child has already a parent:
	 * If its parent is the current EditPart then it is selected
	 * If not then it is not selected
	 * 
	 * @param toolkit
	 * @see {@link ICompositeCreator}
	 * @param top
	 * @see {@link ICompositeCreator}
	 * @param previousElement
	 *        A control element under which the check boxes bill be displayed
	 */
	private void createCheckBoxes(FormToolkit toolkit, Composite top, Control previousElement) {
		FormData data;
		for(final IGraphicalEditPart child : allChildren) {
			String label = CreatorUtils.getLabel(child);
			Button checkBox = toolkit.createButton(top, label, SWT.CHECK);
			//FIXME finish the MouseTrackLMistenner
			//			checkBox.addMouseTrackListener(new CheckboxIGraphicalFocusListenner(child));
			//If the child has already parentEditPart as graphical parent the notification will not display it
			if(!child.getParent().equals(mainEditPart)) {
				if(automaticChildren.contains(child)) {
					checkBox.setSelection(true);
					checkBox.setEnabled(false);

				} else {
					checkBox.setSelection(false);
				}
				data = CreatorUtils.getFormDataUnder(previousElement);
				checkBox.setLayoutData(data);
				previousElement = checkBox;
				childCheckBoxes.put(checkBox, child);
			}
			// add dispose listener to remove from handled widgets
			checkBox.addDisposeListener(new DisposeListener() {

				/**
				 * Remove widget from handled ones
				 * 
				 * @param e
				 *        the dispose event
				 */
				public void widgetDisposed(DisposeEvent e) {
					childCheckBoxes.remove(e.widget);
				}
			});

			checkBox.addSelectionListener(new SelectionAdapter() {

				@Override
				public void widgetSelected(SelectionEvent e) {
					Widget check = e.widget;
					if(check instanceof Button) {
						boolean selection = ((Button)check).getSelection();
						for(Button b : getAllButtonFor(child)) {
							b.setSelection(selection);
						}
					}
				}

				/**
				 * This method will return a list of all button referencing a {@link IGraphicalEditPart}
				 * 
				 * @param child
				 *        The {@link IGraphicalEditPart} of which you want to find the {@link Button}
				 * @return List of all button
				 */
				private List<Button> getAllButtonFor(IGraphicalEditPart child) {
					List<Button> result = new ArrayList<Button>();
					for(Button childButton : childCheckBoxes.keySet()) {
						IGraphicalEditPart childEdipart = childCheckBoxes.get(childButton);
						if(childEdipart.equals(child)) {
							result.add(childButton);
						}
					}
					return result;
				}
			});
		}
	}


	/**
	 * This method check if the {@link ChooseChildrenNotificationConfigurator} create with all the following parameters would be different from the
	 * current one
	 * 
	 * @param _parentEditPart
	 * @see {@link #mainEditPart}
	 * @param _allChildren
	 * @see {@link #allChildren}
	 * @param _automaticChildren
	 * @see {@link #automaticChildren}
	 * @param _host
	 * @see {@link #host}
	 * @return true the notification would be different
	 */
	public boolean isThereAnyModification(IGraphicalEditPart _parentEditPart, List<IGraphicalEditPart> _allChildren, List<IGraphicalEditPart> _automaticChildren, IGraphicalEditPart _host) {
		boolean sameParentEditPart = mainEditPart.equals(_parentEditPart);
		boolean sameHost = host.equals(_host);
		boolean sameAllChildren = containsSameElements(allChildren, _allChildren);
		boolean sameAutomaticChildren = containsSameElements(automaticChildren, _automaticChildren);
		return !(sameParentEditPart && sameHost && sameAllChildren && sameAutomaticChildren);
	}

	/**
	 * Compare two list of {@link IGraphicalEditPart} elements and return true if it contains the same elements
	 * 
	 * @param list1
	 *        List of {@link IGraphicalEditPart}
	 * @param list2
	 *        List of {@link IGraphicalEditPart}
	 * @return true is contains same elements
	 */
	private boolean containsSameElements(List<IGraphicalEditPart> list1, List<IGraphicalEditPart> list2) {
		return list1.containsAll(list2) && list2.containsAll(list1);
	}

	@Override
	protected void closeNotitfication(IContext context) {
		papyrusNotificationView.dispose();
		notification.delete();
		manager.removeChooseChildrenNotification(mainEditPart);
	}

}

Back to the top