/***************************************************************************** * 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.uml.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.infra.widgets.toolbox.notification.ICompositeCreator; import org.eclipse.papyrus.infra.widgets.toolbox.notification.builders.IContext; import org.eclipse.papyrus.uml.diagram.common.groups.Messages; import org.eclipse.papyrus.uml.diagram.common.groups.commands.ChangeGraphicalParentCommand; import org.eclipse.papyrus.uml.diagram.common.groups.core.PendingGroupNotificationsManager; import org.eclipse.papyrus.uml.diagram.common.groups.core.ui.utils.CreatorUtils; 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); } }