/***************************************************************************** * Copyright (c) 2011 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: * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation *****************************************************************************/ package org.eclipse.papyrus.uml.table.widget.celleditors.composite; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.facet.widgets.celleditors.AbstractCellEditorComposite; import org.eclipse.emf.facet.widgets.celleditors.internal.Messages; import org.eclipse.emf.facet.widgets.internal.CustomizableLabelProvider; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.fieldassist.ComboContentAdapter; import org.eclipse.jface.fieldassist.ContentProposalAdapter; import org.eclipse.jface.fieldassist.SimpleContentProposalProvider; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.papyrus.infra.widgets.editors.ReferenceCombo; import org.eclipse.papyrus.infra.widgets.editors.TreeSelectorDialog; import org.eclipse.papyrus.uml.tools.providers.UMLContentProvider; import org.eclipse.papyrus.uml.tools.providers.UMLLabelProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; 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.graphics.Font; import org.eclipse.swt.graphics.FontData; 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.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; public class UnaryReferencePapyrusCellEditorComposite extends AbstractCellEditorComposite<EObject> { private static final int GRID_DATA_HEIGHT = 50; private final Button button; private final Combo combo; private final ReferenceCombo referenceCombo; private final Control parentControl; private EObject source; private final Map<String, EObject> fElements = new TreeMap<String, EObject>(); private EObject semanticRoot; private EStructuralFeature feature; /** * @param parent * the parent composite * @param eObjects * the possible choices */ public UnaryReferencePapyrusCellEditorComposite(final Composite parent, final List<EObject> eObjects, final EObject source, final EStructuralFeature feature) { super(parent); this.source = source; this.feature = feature; this.parentControl = parent; final CustomizableLabelProvider customizableLabelProvider = new CustomizableLabelProvider(); for(EObject eObject : eObjects) { String label = customizableLabelProvider.getText(eObject); // find a unique label if(this.fElements.get(label) != null) { int suffix = 2; while(this.fElements.get(label + " (" + suffix + ")") != null) { //$NON-NLS-1$ //$NON-NLS-2$ suffix++; } this.fElements.put(label + " (" + suffix + ")", eObject); //$NON-NLS-1$//$NON-NLS-2$ } else { this.fElements.put(label, eObject); } } GridLayout compositeLayout = new GridLayout(2, false); compositeLayout.marginHeight = 0; compositeLayout.marginWidth = 0; compositeLayout.horizontalSpacing = 0; setLayout(compositeLayout); this.combo = new Combo(this, SWT.DROP_DOWN); this.referenceCombo = null; // reduce the font so that the Combo fits in the cell FontData[] fontData = Display.getDefault().getSystemFont().getFontData(); fontData[0].setHeight(fontData[0].getHeight()/* - 2 */); Font font = new Font(Display.getDefault(), fontData); this.combo.setFont(font); for(String label : this.fElements.keySet()) { this.combo.add(label); } GridData comboGridData = new GridData(SWT.FILL, SWT.FILL, true, true); this.combo.setLayoutData(comboGridData); addCompletionHandler(this.combo, this.fElements.keySet()); this.combo.addKeyListener(new KeyAdapter() { @Override public void keyPressed(final KeyEvent event) { // Enter key pressed if((event.keyCode == SWT.CR && event.stateMask == 0) || (event.keyCode == SWT.KEYPAD_CR && event.stateMask == 0)) { if(isValid()) { commit(); } else { MessageDialog.openWarning(parent.getShell(), Messages.UnaryReferenceCellEditorComposite_0, Messages.UnaryReferenceCellEditorComposite_1); } } else if(event.keyCode == SWT.ESC && event.stateMask == 0) { // Escape key pressed close(); } } }); this.button = new Button(this, SWT.PUSH); this.button.setText("..."); //$NON-NLS-1$ GridData buttonGridData = new GridData(SWT.FILL, SWT.FILL, false, true); buttonGridData.heightHint = UnaryReferencePapyrusCellEditorComposite.GRID_DATA_HEIGHT; this.button.setLayoutData(buttonGridData); this.button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { final UMLContentProvider provider = new UMLContentProvider(source, feature); ILabelProvider labelProvider = new UMLLabelProvider(); TreeSelectorDialog dialog = new TreeSelectorDialog(Display.getCurrent().getActiveShell()) { @Override public void okPressed() { Object selectedElements[] = new Object[this.getResult().length]; Object result[] = this.getResult(); for(int i = 0; i < result.length; i++) { Object adapted = provider.getAdaptedValue(result[i]); selectedElements[i] = adapted; } String selectedElementLabel = null; if(selectedElements.length > 0) { Set<Entry<String, EObject>> entrySet = UnaryReferencePapyrusCellEditorComposite.this.getfElements().entrySet(); for(Entry<String, EObject> entry : entrySet) { if(entry.getValue() == selectedElements[0]) { selectedElementLabel = entry.getKey(); break; } } } UnaryReferencePapyrusCellEditorComposite.this.getCombo().setText(selectedElementLabel); commit(); super.okPressed(); super.close(); } }; dialog.setLabelProvider(labelProvider); dialog.setContentProvider(provider); if(source != null) { dialog.setInitialElementSelections(Collections.singletonList(source.eGet(feature))); } dialog.setTitle(feature.getEType().getName()); dialog.open(); } }); // commit the cell editor when the mouse is clicked // anywhere outside the text field final Listener clickListener = new Listener() { public void handleEvent(final Event event) { if(event.widget instanceof Control) { Control control = (Control)event.widget; if(control.getShell() == UnaryReferencePapyrusCellEditorComposite.this.getParentControl().getShell() && event.widget != UnaryReferencePapyrusCellEditorComposite.this.getButton() && event.widget != UnaryReferencePapyrusCellEditorComposite.this.getCombo()) { if(isValid()) { commit(); } } } } }; Display.getDefault().addFilter(SWT.MouseDown, clickListener); // this listener is only here to remove // the other listener from the Display addDisposeListener(new DisposeListener() { public void widgetDisposed(final DisposeEvent e) { Display.getDefault().removeFilter(SWT.MouseDown, clickListener); } }); this.combo.addModifyListener(new ModifyListener() { public void modifyText(final ModifyEvent e) { fireChanged(); } }); this.combo.forceFocus(); } protected boolean isValid() { return this.fElements.get(this.combo.getText()) != null; } private static void addCompletionHandler(final Combo comboBox, final Collection<String> completions) { String[] completionsArray = completions.toArray(new String[completions.size()]); SimpleContentProposalProvider contentProposalProvider = new SimpleContentProposalProvider(completionsArray); contentProposalProvider.setFiltering(true); ContentProposalAdapter adapter = new ContentProposalAdapter(comboBox, new ComboContentAdapter(), contentProposalProvider, null, null); // adapter.setFilterStyle(ContentProposalAdapter.FILTER_CHARACTER); adapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE); } public EObject getValue() { EObject eObject = this.fElements.get(this.combo.getText()); return eObject; } protected void commit() { fireCommit(); } public void setValue(final EObject value) { // int d = 0; d++; } protected Button getButton() { return this.button; } protected Combo getCombo() { return this.combo; } protected Control getParentControl() { return this.parentControl; } protected Map<String, EObject> getfElements() { return this.fElements; } }