/***************************************************************************** * Copyright (c) 2010 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: * Emilien Perico (Atos Origin) emilien.perico@atosorigin.com - Initial API and implementation * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.activity.edit.dialogs; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.edit.command.AddCommand; import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.papyrus.infra.core.modelsetquery.ModelSetQuery; import org.eclipse.papyrus.infra.core.utils.EditorUtils; import org.eclipse.papyrus.uml.diagram.activity.part.Messages; import org.eclipse.papyrus.uml.diagram.activity.part.UMLDiagramEditorPlugin; import org.eclipse.papyrus.uml.diagram.activity.providers.UMLElementTypes; import org.eclipse.papyrus.uml.diagram.common.actions.LabelHelper; import org.eclipse.papyrus.uml.diagram.common.ui.helper.HelpComponentFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.ElementListSelectionDialog; import org.eclipse.ui.forms.FormDialog; import org.eclipse.ui.forms.IManagedForm; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ImageHyperlink; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.forms.widgets.Section; import org.eclipse.uml2.uml.Activity; import org.eclipse.uml2.uml.NamedElement; import org.eclipse.uml2.uml.Parameter; import org.eclipse.uml2.uml.ParameterDirectionKind; import org.eclipse.uml2.uml.Type; import org.eclipse.uml2.uml.UMLFactory; import org.eclipse.uml2.uml.UMLPackage; /** * DialogBox in order to link a parameter with the new ActivityParameterNode * that will be created * */ public class CreateActivityParameterNodeDialog extends FormDialog { private Button creationRadio; private Button selectionRadio; private Text selectionText; private Button selectionButton; private Text creationNameText; private Text creationTypeText; private Button creationTypeButton; private Parameter selectedParameter = null; private EObject selectedType = null; private Activity activityOwner; private String selectedName = null; private ParameterDirectionKind selectedDirection = null; private ComboViewer directionComboViewer = null; private Combo creationDirectionCombo = null; private ILabelProvider labelProvider; /** * Create a new dialog to initialize an ActivityParameterNode. * * @param shell * parent shell * @param owner * the activity that owns the action */ public CreateActivityParameterNodeDialog(Shell shell, Activity owner) { super(shell); activityOwner = owner; labelProvider = new AdapterFactoryLabelProvider(UMLDiagramEditorPlugin.getInstance().getItemProvidersAdapterFactory()); } /** * Create the form to : * * - ask the user to choose or create an existing element. * * @see org.eclipse.ui.forms.FormDialog#createFormContent(org.eclipse.ui.forms.IManagedForm) */ @Override protected void createFormContent(IManagedForm pForm) { pForm.getForm().setText(Messages.CreateActivityParameterNodeDialog_DialogTitle); ScrolledForm scrolledForm = pForm.getForm(); FormToolkit toolkit = pForm.getToolkit(); Composite parent = scrolledForm.getBody(); parent.setLayout(new GridLayout()); createInvocationCreationSection(scrolledForm.getBody(), toolkit); createInvocationSelectionSection(scrolledForm.getBody(), toolkit); refreshSectionsEnable(false); hookListeners(); // invoked name is set after listeners, since we count on listener to // update it properly setInvokedName(null); scrolledForm.reflow(true); } /** * Adds buttons to this dialog's button bar. * * @param parent * the button bar composite */ @Override protected void createButtonsForButtonBar(Composite parent) { super.createButtonsForButtonBar(parent); refreshOkButton(); } /** * Create the section to ask the user to choose an existing element. * * @param pParent * the section's parent widget * @param pToolkit * the form toolkit */ private void createInvocationSelectionSection(Composite pParent, FormToolkit pToolkit) { // create the section String lSectionTitle = Messages.CreateActivityParameterNodeDialog_ParameterSelectionTitle; Section lSection = pToolkit.createSection(pParent, Section.EXPANDED | Section.TITLE_BAR); lSection.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); if(lSectionTitle != null) { lSection.setText(lSectionTitle); } ImageHyperlink componentHelp = HelpComponentFactory.createHelpComponent(lSection, pToolkit, Messages.CreateActivityParameterNodeDialog_ParameterSelectionHelp); lSection.setTextClient(componentHelp); ScrolledForm lInsideScrolledForm = pToolkit.createScrolledForm(lSection); lInsideScrolledForm.setExpandHorizontal(true); lInsideScrolledForm.setExpandVertical(true); Composite lBody = lInsideScrolledForm.getBody(); GridLayout lLayout = new GridLayout(); lLayout.numColumns = 3; lBody.setLayout(lLayout); // content of the section selectionRadio = pToolkit.createButton(lBody, Messages.CreateActivityParameterNodeDialog_ParameterSelectionLabel, SWT.RADIO); selectionRadio.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1)); // manage parameter selection pToolkit.createLabel(lBody, getParameterFeature().getEReferenceType().getName() + ":", SWT.NONE); selectionText = pToolkit.createText(lBody, "", SWT.BORDER | SWT.READ_ONLY); selectionText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); selectionButton = pToolkit.createButton(lBody, "...", SWT.FLAT); Image image = UMLElementTypes.getImage(getParameterFeature()); selectionButton.setImage(image); selectionButton.setLayoutData(new GridData(SWT.NONE)); lInsideScrolledForm.reflow(true); lSection.setClient(lInsideScrolledForm); } /** * Create the section to ask the user to create an invoked element. * * @param pParent * the section's parent widget * @param pToolkit * the form toolkit */ private void createInvocationCreationSection(Composite pParent, FormToolkit pToolkit) { // create the section String lSectionTitle = Messages.CreateActivityParameterNodeDialog_ParameterCreationTitle; Section lSection = pToolkit.createSection(pParent, Section.EXPANDED | Section.TITLE_BAR); lSection.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); if(lSectionTitle != null) { lSection.setText(lSectionTitle); } ImageHyperlink componentHelp = HelpComponentFactory.createHelpComponent(lSection, pToolkit, Messages.CreateActivityParameterNodeDialog_ParameterCreationHelp); lSection.setTextClient(componentHelp); ScrolledForm lInsideScrolledForm = pToolkit.createScrolledForm(lSection); lInsideScrolledForm.setExpandHorizontal(true); lInsideScrolledForm.setExpandVertical(true); Composite lBody = lInsideScrolledForm.getBody(); GridLayout lLayout = new GridLayout(); lLayout.numColumns = 3; lBody.setLayout(lLayout); // content of the section creationRadio = pToolkit.createButton(lBody, Messages.CreateActivityParameterNodeDialog_ParameterCreationLabel, SWT.RADIO); creationRadio.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1)); pToolkit.createLabel(lBody, Messages.CreateActivityParameterNodeDialog_NameLabel, SWT.NONE); creationNameText = pToolkit.createText(lBody, "", SWT.BORDER); creationNameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); creationNameText.setFocus(); // manage type selection pToolkit.createLabel(lBody, Messages.CreateActivityParameterNodeDialog_TypeLabel, SWT.NONE); creationTypeText = pToolkit.createText(lBody, labelProvider.getText(selectedType), SWT.BORDER | SWT.READ_ONLY); creationTypeText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); creationTypeButton = pToolkit.createButton(lBody, "...", SWT.FLAT); Image image = UMLElementTypes.getImage(UMLPackage.eINSTANCE.getPackage_PackagedElement()); creationTypeButton.setImage(image); creationTypeButton.setLayoutData(new GridData(SWT.NONE)); // manage direction selection pToolkit.createLabel(lBody, Messages.CreateActivityParameterNodeDialog_DirectionLabel, SWT.NONE); creationDirectionCombo = new Combo(lBody, SWT.DROP_DOWN | SWT.READ_ONLY); directionComboViewer = new ComboViewer(creationDirectionCombo); pToolkit.adapt(creationDirectionCombo); creationDirectionCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); directionComboViewer.setLabelProvider(labelProvider); directionComboViewer.add(getDirections()); // initialize selection directionComboViewer.setSelection(new StructuredSelection(getDirections()[0])); selectedDirection = ParameterDirectionKind.getByName(getDirections()[0]); lInsideScrolledForm.reflow(true); lSection.setClient(lInsideScrolledForm); } /** * Set correctly the invoked object, by creating it if needed. Then, * notifies that the ok button of this dialog has been pressed. * * @see org.eclipse.jface.dialogs.Dialog#okPressed() * */ @Override protected void okPressed() { boolean isSelectionSelected = selectionRadio.getSelection(); // create element if needed if(!isSelectionSelected) { selectedParameter = UMLFactory.eINSTANCE.createParameter(); selectedParameter.setName(selectedName); selectedParameter.setType((Type)selectedType); selectedParameter.setDirection(selectedDirection); addParameter(selectedParameter); } super.okPressed(); } /** * Get the invoked object that have been selected or created. * * @return the invoked object to use. */ public EObject getSelectedInvoked() { return selectedParameter; } /** * Add listeners to widgets */ private void hookListeners() { // listener to choose active section SelectionListener selectCreateListener = new SelectionAdapter() { /** * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected(SelectionEvent e) { if(creationRadio.equals(e.getSource())) { refreshSectionsEnable(false); } else { refreshSectionsEnable(true); } refreshOkButton(); } }; selectionRadio.addSelectionListener(selectCreateListener); creationRadio.addSelectionListener(selectCreateListener); // listener to select existing element SelectionListener selectBtnListener = new SelectionAdapter() { /** * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected(SelectionEvent e) { handleChooseParameter(); refreshOkButton(); } }; selectionButton.addSelectionListener(selectBtnListener); if(creationDirectionCombo != null && directionComboViewer != null) { // listener to select direction ModifyListener lTypeListener = new ModifyListener() { /** * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent) */ public void modifyText(ModifyEvent e) { ISelection sel = directionComboViewer.getSelection(); if(sel instanceof StructuredSelection) { String firstElement = ((StructuredSelection)sel).getFirstElement().toString(); selectedDirection = ParameterDirectionKind.getByName(firstElement); } else { selectedDirection = null; } // reset name setInvokedName(null); refreshOkButton(); } }; creationDirectionCombo.addModifyListener(lTypeListener); } // listener to element name ModifyListener lNameListener = new ModifyListener() { /** * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent) */ public void modifyText(ModifyEvent e) { setInvokedName(creationNameText.getText()); } }; creationNameText.addModifyListener(lNameListener); // listener to select new element type SelectionListener selectTypeBtnListener = new SelectionAdapter() { /** * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected(SelectionEvent e) { handleChooseType(); // reset name if not set if(selectedName == null) { setInvokedName(null); } refreshOkButton(); } }; creationTypeButton.addSelectionListener(selectTypeBtnListener); } /** * Set the name chosen for the invoked element * * @param text * the text string or null for auto-initialization */ private void setInvokedName(String text) { String name = text; if(text == null) { name = LabelHelper.INSTANCE.findName(activityOwner, UMLPackage.eINSTANCE.getParameter()); // the name assignment will be performed by listener's call creationNameText.setText(name); } else if(name != null && !"".equals(name.trim())) { selectedName = name.trim(); Color black = creationNameText.getDisplay().getSystemColor(SWT.COLOR_BLACK); creationNameText.setForeground(black); refreshOkButton(); } else { selectedName = null; Color red = creationNameText.getDisplay().getSystemColor(SWT.COLOR_RED); creationNameText.setForeground(red); refreshOkButton(); } } /** * Open the dialog to choose the existing parameter to select * */ private void handleChooseParameter() { Collection<EObject> elements = ModelSetQuery.getObjectsOfType(activityOwner, getParameterFeature().getEType()); // only keep parameter that are children of the activity for(Iterator<EObject> it = elements.iterator(); it.hasNext();) { EObject eObject = (EObject)it.next(); if(!(activityOwner.equals(((Parameter)eObject).getOwner()))) { it.remove(); } } ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), labelProvider); dialog.setMessage(Messages.UMLModelingAssistantProviderMessage); dialog.setTitle(Messages.UMLModelingAssistantProviderTitle); dialog.setFilter("*"); dialog.setMultipleSelection(false); dialog.setElements(elements.toArray(new EObject[elements.size()])); if(dialog.open() == Window.OK) { setParameterSelection((EObject)dialog.getFirstResult()); } } /** * Define the parameter that will be set for the parameter node (if * selection mode is chosen) * * @param invokedElement * the selected element */ private void setParameterSelection(EObject invokedElement) { if(invokedElement instanceof Parameter) { selectedParameter = (Parameter)invokedElement; selectionText.setText(labelProvider.getText(selectedParameter)); } else { selectionText.setText(""); } } /** * Open the dialog to choose the type of element to create * */ private void handleChooseType() { Set<Object> types = getAvailableTypes(); ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), labelProvider); dialog.setFilter("*"); dialog.setMessage(Messages.UMLModelingAssistantProviderMessage); dialog.setTitle(Messages.UMLModelingAssistantProviderTitle); dialog.setMultipleSelection(false); dialog.setElements(types.toArray()); if(dialog.open() == Window.OK) { Object firstResult = dialog.getFirstResult(); if(firstResult instanceof EObject) { setSelectedType((EObject)dialog.getFirstResult()); } else { setSelectedType(null); } } } /** * Define the type of the object that will be created (if creation mode is * chosen) * * @param the * selected parent */ private void setSelectedType(EObject invokedType) { selectedType = invokedType; if(selectedType instanceof NamedElement) { creationTypeText.setText(labelProvider.getText(selectedType)); } else { creationTypeText.setText(""); } } /** * Refresh the enabled and disabled elements in various sections * * @param isSelectionSelected * true if we choose to select an existing element, false if we * choose to create an element */ private void refreshSectionsEnable(boolean isSelectionSelected) { // handle radio button value if(isSelectionSelected) { creationRadio.setSelection(false); if(!selectionRadio.getSelection()) { selectionRadio.setSelection(true); } } else { selectionRadio.setSelection(false); if(!creationRadio.getSelection()) { creationRadio.setSelection(true); } } // handle disabled section selectionText.setEnabled(isSelectionSelected); selectionButton.setEnabled(isSelectionSelected); if(creationDirectionCombo != null) { creationDirectionCombo.setEnabled(!isSelectionSelected); } creationNameText.setEnabled(!isSelectionSelected); creationNameText.setFocus(); creationTypeText.setEnabled(!isSelectionSelected); creationTypeButton.setEnabled(!isSelectionSelected); } /** * Refresh the OK button activation */ private void refreshOkButton() { boolean isSelectionSelected = selectionRadio.getSelection(); if(getButton(IDialogConstants.OK_ID) != null && !getButton(IDialogConstants.OK_ID).isDisposed()) { if(isSelectionSelected) { getButton(IDialogConstants.OK_ID).setEnabled(selectedParameter != null); } else { getButton(IDialogConstants.OK_ID).setEnabled(selectedDirection != null && selectedName != null); } } } /** * Gets the parameter feature. * * @return the parameter feature */ private EReference getParameterFeature() { return UMLPackage.eINSTANCE.getBehavior_OwnedParameter(); } /** * Create the new Parameter */ protected void addParameter(EObject newEObject) { TransactionalEditingDomain editingdomain = EditorUtils.getTransactionalEditingDomain(); // Let the command find the relation on its own. Command addCmd = AddCommand.create(editingdomain, activityOwner, null, Collections.singleton(newEObject)); addCmd.execute(); } /** * Gets the available types for the parameter * * @return the available types */ private Set<Object> getAvailableTypes() { Collection<EObject> types = ModelSetQuery.getObjectsOfType(activityOwner, UMLPackage.eINSTANCE.getTypedElement_Type().getEType()); Set<Object> result = new HashSet<Object>(); result.add(""); result.addAll(types); return result; } /** * Gets the possible directions. * * @return the possible directions */ private String[] getDirections() { List<ParameterDirectionKind> values = ParameterDirectionKind.VALUES; String[] ret = new String[values.size()]; for(int i = 0; i < values.size(); i++) { ret[i] = values.get(i).getName(); } return ret; } }