/******************************************************************************* * Copyright (c) 2011, 2012 Red Hat, Inc. * All rights reserved. * This program is 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: * Red Hat, Inc. - initial API and implementation * * @author Bob Brodt ******************************************************************************/ package org.eclipse.bpmn2.modeler.core.merrimac.dialogs; import java.util.ArrayList; import java.util.Collections; import java.util.Hashtable; import java.util.Map.Entry; import org.eclipse.bpmn2.modeler.core.Activator; import org.eclipse.bpmn2.modeler.core.IConstants; import org.eclipse.bpmn2.modeler.core.adapters.AdapterRegistry; import org.eclipse.bpmn2.modeler.core.adapters.ExtendedPropertiesAdapter; import org.eclipse.bpmn2.modeler.core.adapters.ExtendedPropertiesProvider; import org.eclipse.bpmn2.modeler.core.merrimac.clad.AbstractDetailComposite; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.util.EObjectEList; import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; /** * @author Bob Brodt * */ public class ComboObjectEditor extends MultivalueObjectEditor { protected ComboViewer comboViewer; protected Composite buttons = null; protected boolean keyPressed = false; protected Button editButton = null; protected Button createButton = null; protected Hashtable<String,Object> choices = null; // cache choices /** * @param parent * @param object * @param feature */ public ComboObjectEditor(AbstractDetailComposite parent, EObject object, EStructuralFeature feature) { this(parent, object, feature, null); } public ComboObjectEditor(AbstractDetailComposite parent, EObject object, EStructuralFeature feature, EClass featureEType) { super(parent, object, feature, featureEType); } /* (non-Javadoc) * @see org.eclipse.bpmn2.modeler.ui.property.editors.ObjectEditor#createControl(org.eclipse.swt.widgets.Composite, java.lang.String, int) */ @Override protected Control createControl(Composite composite, String label, int style) { if (label==null) label = ExtendedPropertiesProvider.getLabel(object,feature); createLabel(composite, label); boolean canEdit = canEdit(); boolean canEditInline = canEditInline(); boolean canCreateNew = canCreateNew(); if (style == SWT.READ_ONLY) { canEdit = false; canEditInline = false; canCreateNew = false; } if (!canEditInline) style |= SWT.READ_ONLY; comboViewer = createComboViewer(composite, AdapterRegistry.getLabelProvider(), style); Combo combo = comboViewer.getCombo(); combo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, (canEdit || canCreateNew) ? 1 : 2, 1)); combo.addDisposeListener(new DisposeListener() { @Override public void widgetDisposed(DisposeEvent e) { comboViewer = null; } }); if (canEditInline) { combo.addKeyListener( new KeyListener() { @Override public void keyPressed(KeyEvent e) { keyPressed = true; } @Override public void keyReleased(KeyEvent e) { } }); combo.addFocusListener( new FocusListener() { @Override public void focusGained(FocusEvent e) { } @Override public void focusLost(FocusEvent e) { if (keyPressed) { keyPressed = false; String text = comboViewer.getCombo().getText(); comboViewer.setSelection(new StructuredSelection(text)); } } }); } buttons = null; if (canEdit || canCreateNew) { buttons = getToolkit().createComposite(composite); buttons.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); buttons.setLayout(new FillLayout(SWT.HORIZONTAL)); if (canCreateNew) { createButton = getToolkit().createButton(buttons, null, SWT.PUSH); createButton.setImage( Activator.getDefault().getImage(IConstants.ICON_ADD_20)); createButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { buttonClicked(ID_CREATE_BUTTON); fillCombo(); } }); } if (canEdit) { editButton = getToolkit().createButton(buttons, null, SWT.PUSH); editButton.setImage( Activator.getDefault().getImage(IConstants.ICON_EDIT_20)); editButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { buttonClicked(ID_EDIT_BUTTON); fillCombo(); } }); editButton.setEnabled(canEdit()); } } fillCombo(); comboViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { if (!isWidgetUpdating) { ISelection selection = comboViewer.getSelection(); if (selection instanceof StructuredSelection) { String firstElement = (String) ((StructuredSelection) selection).getFirstElement(); if(firstElement!=null && comboViewer.getData(firstElement)!=null) setValue(comboViewer.getData(firstElement)); else { if (firstElement!=null && firstElement.isEmpty()) firstElement = null; if (firstElement==null) firstElement = comboViewer.getCombo().getText(); setValue(firstElement); fillCombo(); } if (editButton!=null) editButton.setEnabled(canEdit() && firstElement!=null && !firstElement.isEmpty()); } } } }); return combo; } protected void buttonClicked(int buttonId) { if (buttonId==ID_CREATE_BUTTON) { // create a new target object try { EObject value = createObject(); setValue(value); fillCombo(); } catch (OperationCanceledException ex1) { } catch (Exception ex2) { Activator.logError(ex2); } } else if (buttonId==ID_EDIT_BUTTON) { ISelection selection = comboViewer.getSelection(); if (selection instanceof StructuredSelection) { String firstElement = (String) ((StructuredSelection) selection).getFirstElement(); if ((firstElement != null && firstElement.isEmpty())) { // nothing to edit firstElement = null; } if (firstElement != null && comboViewer.getData(firstElement) instanceof EObject) { EObject value = (EObject) comboViewer.getData(firstElement); try { value = editObject(value); setValue(value); fillCombo(); } catch (OperationCanceledException ex1) { } catch (Exception ex2) { Activator.logError(ex2); } } } } } protected EObject createObject() throws Exception { FeatureEditingDialog dialog = createFeatureEditingDialog(null); dialog.setFeatureEType(featureEType); if ( dialog.open() == Window.OK) return dialog.getNewObject(); throw new OperationCanceledException("Dialog Cancelled"); //$NON-NLS-1$ } protected EObject editObject(EObject value) throws Exception { FeatureEditingDialog dialog = createFeatureEditingDialog(value); dialog.setFeatureEType(featureEType); if ( dialog.open() == Window.OK) return dialog.getNewObject(); throw new OperationCanceledException("Dialog Cancelled"); //$NON-NLS-1$ } @Override public boolean setValue(Object result) { keyPressed = false; return super.setValue(result); } @Override public Object getValue() { Object v = object.eGet(feature); // hack to deal with List features: use the first element in the list to // determine which item to select as active in the combobox if (v instanceof EObjectEList) { EObjectEList list = (EObjectEList)v; if (list.size()>0) v = list.get(0); } return v; } /** * @deprecated * @return */ public String getTextValue() { ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object); if (adapter!=null) { return adapter.getFeatureDescriptor(feature).getTextValue(); } return getValue().toString(); } public String getChoiceString(Object value) { if (value==null) return ""; ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object); if (adapter!=null) { return adapter.getFeatureDescriptor(feature).getChoiceString(value); } return value.toString(); } protected void fillCombo() { try { isWidgetUpdating = true; if (comboViewer!=null) { comboViewer.getCombo().setRedraw(false); Object oldValue = getValue(); String oldTextValue = getTextValue(); //System.out.println("ComboObjectEditor: "+getLabel().getText()+"\n old value="+oldTextValue+"\n "+oldValue+"\n"); //getChoiceString(oldValue); while (comboViewer.getElementAt(0) != null) comboViewer.remove(comboViewer.getElementAt(0)); choices = getChoiceOfValues(object, feature); if (canSetNull()) { // selecting this one will set the target's value to null comboViewer.add(""); //$NON-NLS-1$ } // add all other possible selections ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(oldValue); StructuredSelection currentSelection = null; if (choices!=null) { ArrayList<String> list = new ArrayList<String>(choices.keySet()); Collections.sort(list); for (String key : list) { comboViewer.add(key); // try to find selection using current value of this feature Object newValue = choices.get(key); if (newValue!=null) { comboViewer.setData(key, newValue); if (currentSelection==null) { if (newValue.equals(oldValue) || key.equals(oldValue) || key.equals(oldTextValue)) { currentSelection = new StructuredSelection(key); } else if (adapter!=null) { if (adapter.getObjectDescriptor().equals(newValue)) { currentSelection = new StructuredSelection(key); } } } } } } if (currentSelection!=null) comboViewer.setSelection(currentSelection); if (editButton!=null) editButton.setEnabled(canEdit() && currentSelection!=null); } } finally { if (comboViewer!=null) comboViewer.getCombo().setRedraw(true); isWidgetUpdating = false; } } private boolean itemsChanged() { if (comboViewer==null) return false; Object newValue = getValue(); ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(newValue); // isWidgetUpdating = false; // Hashtable<String,Object> choices = new Hashtable<String,Object>(); // int index = 0; // while (comboViewer.getElementAt(index) != null) { // String key = (String)comboViewer.getElementAt(index); // if (!key.isEmpty()) { // Object value = comboViewer.getData(key); // choices.put(key, value); // } // ++index; // } // isWidgetUpdating = false; Hashtable<String,Object> newChoices = getChoiceOfValues(object, feature); if (choices==null || choices.size()!=newChoices.size()) return true; StructuredSelection oldSelection = (StructuredSelection)comboViewer.getSelection(); Object oldValue = oldSelection.getFirstElement(); if (oldValue instanceof String) oldValue = comboViewer.getData((String)oldValue); if (oldValue==null) { if (newValue!=null) return true; else return false; } else if (adapter!=null) { if (!adapter.getObjectDescriptor().equals(oldValue)) return true; } else if (!oldValue.equals(newValue)) return true; for (Entry<String, Object> entry : newChoices.entrySet()) { oldValue = choices.get(entry.getKey()); newValue = entry.getValue(); adapter = ExtendedPropertiesAdapter.adapt(newValue); if (newValue==null) { if (oldValue!=null) return true; } else if (adapter!=null) { if (!adapter.getObjectDescriptor().equals(oldValue)) return true; } else if (!newValue.equals(oldValue)) return true; } return false; } private ComboViewer createComboViewer(Composite parent, AdapterFactoryLabelProvider labelProvider, int style) { ComboViewer comboViewer = new ComboViewer(parent, style); comboViewer.setLabelProvider(labelProvider); return comboViewer; } @Override public void notifyChanged(Notification notification) { super.notifyChanged(notification); if ((notification.getEventType() == -1 || notification.getFeature()==feature) && itemsChanged()) { fillCombo(); } } public void setVisible(boolean visible) { super.setVisible(visible); comboViewer.getCombo().setVisible(visible); GridData data = (GridData)comboViewer.getCombo().getLayoutData(); data.exclude = !visible; if (buttons!=null) { buttons.setVisible(visible); data = (GridData)buttons.getLayoutData(); data.exclude = !visible; } } public void dispose() { super.dispose(); if (comboViewer!=null && !comboViewer.getCombo().isDisposed()) { comboViewer.getCombo().dispose(); comboViewer = null; } if (editButton!=null && !editButton.isDisposed()) { editButton.dispose(); editButton = null; } if (createButton!=null && !createButton.isDisposed()) { createButton.dispose(); createButton = null; } if (buttons!=null && !buttons.isDisposed()) { buttons.dispose(); buttons = null; } } public Control getControl() { return comboViewer.getCombo(); } }