/*******************************************************************************
* 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
*******************************************************************************/
package org.eclipse.bpmn2.modeler.core.merrimac.clad;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import org.eclipse.bpmn2.modeler.core.adapters.ExtendedPropertiesProvider;
import org.eclipse.bpmn2.modeler.core.merrimac.providers.ColumnTableProvider;
import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;
import org.eclipse.core.runtime.Assert;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.edit.ui.provider.PropertyDescriptor.EDataTypeCellEditor;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.graphiti.ui.editor.DiagramEditor;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.ICellEditorValidator;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
public class TableColumn extends ColumnTableProvider.Column implements ILabelProvider, ICellModifier {
protected AbstractListComposite listComposite;
// the underlying EObject of the table row
protected EObject object;
// the EStructuralFeature being managed for this table column
protected EStructuralFeature feature;
// The column cell editor
protected boolean editable = true;
protected String headerText = null;
public TableColumn(EObject o) {
this(o,(EStructuralFeature)null);
}
public TableColumn(EObject o, EStructuralFeature f) {
this(null,o,f);
}
public TableColumn(AbstractListComposite abstractListComposite, EObject o, EStructuralFeature f) {
this.listComposite = abstractListComposite;
object = o;
feature = f;
}
public TableColumn(EObject o, String f) {
this(null,o,f);
}
public TableColumn(AbstractListComposite abstractListComposite, EObject o, String f) {
this.listComposite = abstractListComposite;
object = o;
feature = o.eClass().getEStructuralFeature(f);
}
public void setOwner(AbstractListComposite abstractListComposite) {
this.listComposite = abstractListComposite;
}
public void setHeaderText(String text) {
headerText = text;
}
public Resource getResource() {
return (Resource) listComposite.getDiagramEditor().getAdapter(Resource.class);
}
@Override
public String getHeaderText() {
if (headerText!=null)
return headerText;
String text = ""; //$NON-NLS-1$
if (feature!=null) {
if (feature.eContainer() instanceof EClass) {
EClass eclass = this.listComposite.getListItemClass();
text = ExtendedPropertiesProvider.getLabel(getResource(), eclass, feature);
}
else
text = ModelUtil.toCanonicalString(feature.getName());
}
return text;
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.merrimac.providers.ColumnTableProvider.Column#getProperty()
* NOTE: You may want to override this method if feature==null and provide a unique string value
* for each column in the table, otherwise it will use the Header Text string.
*/
@Override
public String getProperty() {
if (feature!=null)
return feature.getName(); //$NON-NLS-1$
return this.getHeaderText(); //$NON-NLS-1$
}
@Override
public int getInitialWeight() {
return 10;
}
public String getText(Object element) {
if (element instanceof EObject) {
return ExtendedPropertiesProvider.getTextValue((EObject)element,feature);
}
return element.toString();
}
protected int getColumnIndex() {
return listComposite.getColumnProvider().getColumns().indexOf(this);
}
protected Composite getParent() {
return tableViewer.getTable();
}
protected void setCellEditor(CellEditor ce) {
CellEditor[] cellEditors = tableViewer.getCellEditors();
int index = getColumnIndex();
if (index>=0 && index<cellEditors.length) {
CellEditor oldCe = cellEditors[index];
if (oldCe!=null && oldCe!=ce)
oldCe.dispose();
cellEditors[index] = ce;
}
}
protected CellEditor getCellEditor() {
CellEditor[] cellEditors = tableViewer.getCellEditors();
int index = getColumnIndex();
if (index>=0 && index<cellEditors.length) {
return cellEditors[index];
}
return null;
}
public CellEditor createCellEditor (Composite parent) {
CellEditor ce = null;
if (editable && feature!=null) {
EClassifier ec = feature.getEType();
Class ic = ec.getInstanceClass();
if (boolean.class.equals(ic)) {
ce = new CustomCheckboxCellEditor(parent);
}
else if (ec instanceof EEnum) {
ce = new CustomComboBoxCellEditor(parent, feature);
}
else if (ExtendedPropertiesProvider.isMultiChoice(getResource(), (EClass)feature.eContainer(), feature)) {
ce = new CustomComboBoxCellEditor(parent, feature);
}
else if (ec instanceof EDataType) {
ce = new EDataTypeCellEditor((EDataType)ec, parent);
ce.setValidator(new CustomDataTypeValidator());
}
else if (ic==EObject.class) {
ce = new StringWrapperCellEditor(parent);
}
}
return ce;
}
public class CustomDataTypeValidator implements ICellEditorValidator {
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ICellEditorValidator#isValid(java.lang.Object)
*/
@Override
public String isValid(Object value) {
// TODO Auto-generated method stub
return null;
}
}
public void setEditable(boolean editable) {
this.editable = editable;
}
public boolean canModify(Object element, String property) {
// This is the only point in the cell editor lifecycle where we have access to the
// cell object being edited.
if (editable && listComposite.getColumnProvider().canModify(object, feature, (EObject)element)) {
CellEditor ce = getCellEditor();
return ce!=null;
}
return false;
}
public void modify(Object element, String property, Object value) {
modify((EObject)element, feature, value);
}
protected void modify(final EObject object, EStructuralFeature feature, Object value) {
CellEditor ce = getCellEditor();
if (ce instanceof CustomComboBoxCellEditor) {
value = ((CustomComboBoxCellEditor)ce).getChoice(value);
}
boolean result = ExtendedPropertiesProvider.setValue(object, feature, value);
// if (result==false || getDiagramEditor().getDiagnostics()!=null) {
// // revert the change and display error errorList message.
// ErrorUtils.showErrorMessage(getDiagramEditor().getDiagnostics().getMessage());
// }
// else {
// ErrorUtils.showErrorMessage(null);
// tableViewer.refresh();
// }
if (result) {
tableViewer.refresh(object);
}
}
@Override
public Object getValue(Object element, String property) {
CellEditor ce = getCellEditor();
if (element instanceof EObject) {
if (ce instanceof CustomCheckboxCellEditor) {
return ce.getValue();
}
else if (ce instanceof CustomComboBoxCellEditor) {
// for combobox cell editors, the returned value is a list of strings
return ce.getValue();
}
else {
// all other types of cell editors accept the object/feature value
EObject object = (EObject)element;
return object.eGet(feature);
}
}
return getText(element);
}
protected DiagramEditor getDiagramEditor() {
return listComposite.getDiagramEditor();
}
protected TransactionalEditingDomain getEditingDomain() {
return getDiagramEditor().getEditingDomain();
}
public static class CustomCheckboxCellEditor extends ComboBoxCellEditor {
private static String[] items = new String[] { "false", "true" }; //$NON-NLS-1$ //$NON-NLS-2$
public CustomCheckboxCellEditor(Composite parent) {
super(parent, items,SWT.READ_ONLY);
}
@Override
public String[] getItems() {
return items;
}
@Override
public void setItems(String[] items) {
super.setItems(this.items);
}
@Override
protected Object doGetValue() {
Integer value = (Integer)super.doGetValue();
return new Boolean(value.intValue()!=0);
}
@Override
protected void doSetValue(Object value) {
if (value instanceof Boolean) {
value = new Integer( ((Boolean)value).booleanValue() ? 1 : 0 );
}
else if (value instanceof String) {
for (int i=0; i<items.length; ++i) {
if (value.equals(items[i])) {
value = new Integer(i);
break;
}
}
}
super.doSetValue(value);
}
}
public class CustomComboBoxCellEditor extends ComboBoxCellEditor {
// list of choices as constructed by ExtendedPropertiesAdapter.FeatureDescriptor#getChoiceOfValues()
protected Hashtable<String,Object> choices = null;
public CustomComboBoxCellEditor(Composite parent, EStructuralFeature feature) {
super(parent, new String[] {""}, SWT.READ_ONLY); //$NON-NLS-1$
}
public void activate(ColumnViewerEditorActivationEvent activationEvent) {
Object source = activationEvent.getSource();
if (source instanceof ViewerCell) {
Object element = ((ViewerCell)source).getElement();
if (element instanceof EObject) {
EObject object = (EObject)element;
Object current = object.eGet(feature);
setValue(object, feature, current);
}
}
}
public void setValue(EObject object, EStructuralFeature feature, Object current) {
// build the list of valid choices for this object/feature and cache it;
// we'll need it again later in modify()
// NOTE: This list should be rebuilt every time before we activate this
// cell editor since the choices may have changed.
List<String> items = new ArrayList<String>();
choices = ExtendedPropertiesProvider.getChoiceOfValues(object, feature);
if (ExtendedPropertiesProvider.canSetNull(object,feature))
items.add(""); //$NON-NLS-1$
items.addAll(choices.keySet());
Collections.sort(items);
this.setItems(items.toArray(new String[items.size()]));
// find the index of the current value in the choices list
// need to handle both cases where current value matches the
// choices key (a String) or an EObject
int index = -1;
for (int i=0; i<items.size(); ++i) {
if (current == choices.get(items.get(i))) {
index = i;
break;
}
if (current instanceof String) {
if (current.equals(items.get(i))) {
index = i;
break;
}
}
}
this.setValue(new Integer(index));
}
public Object getChoice(Object value) {
// for combobox cell editors, getValue() returns an Integer
Assert.isTrue(choices!=null && value instanceof Integer);
int index = ((Integer)value).intValue();
if (index>=0) {
// look up the real value from the list of choices created by getValue()
String[] items = ((ComboBoxCellEditor)getCellEditor()).getItems();
value = choices.get(items[index]);
}
else
value = null;
return value;
}
}
public class StringWrapperCellEditor extends TextCellEditor {
public StringWrapperCellEditor(Composite parent) {
super(parent);
}
@Override
protected Object doGetValue() {
String value = (String)super.doGetValue();
return ModelUtil.createStringWrapper(value);
}
@Override
protected void doSetValue(Object value) {
if (value==null)
value = ""; //$NON-NLS-1$
else
value = ModelUtil.getStringWrapperTextValue(value);
super.doSetValue(value);
}
}
}