/******************************************************************************* * Copyright (c) 2006-2013 The RCP Company and others. * 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: * The RCP Company - initial API and implementation *******************************************************************************/ package com.rcpcompany.uibindings.grid.internal; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.NotificationChain; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.impl.ENotificationImpl; import org.eclipse.emf.ecore.impl.EObjectImpl; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.CellEditor.LayoutData; import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent; import org.eclipse.jface.viewers.ICellEditorListener; import org.eclipse.nebula.widgets.grid.GridEditor; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import com.rcpcompany.uibindings.Constants; import com.rcpcompany.uibindings.ICellEditorFactory; import com.rcpcompany.uibindings.ICellEditorFactoryContext; import com.rcpcompany.uibindings.IValueBindingCell; import com.rcpcompany.uibindings.grid.IGridBinding; import com.rcpcompany.uibindings.grid.IGridBindingCellEditor; import com.rcpcompany.uibindings.grid.IGridBindingCellInformation; import com.rcpcompany.uibindings.grid.IGridPackage; import com.rcpcompany.uibindings.internal.Activator; import com.rcpcompany.uibindings.internal.cellEditors.SimpleCellEditorFactory; import com.rcpcompany.utils.logging.LogUtils; /** * <!-- begin-user-doc --> An implementation of the model object ' * <em><b>Binding Cell Editor</b></em>'. <!-- end-user-doc --> * <p> * The following features are implemented: * <ul> * <li>{@link com.rcpcompany.uibindings.grid.internal.GridBindingCellEditorImpl#getGrid <em>Grid * </em>}</li> * <li>{@link com.rcpcompany.uibindings.grid.internal.GridBindingCellEditorImpl#getGridEditor <em> * Grid Editor</em>}</li> * <li>{@link com.rcpcompany.uibindings.grid.internal.GridBindingCellEditorImpl#getActiveEditCell * <em>Active Edit Cell</em>}</li> * </ul> * </p> * * @generated */ public class GridBindingCellEditorImpl extends EObjectImpl implements IGridBindingCellEditor { /** * The cached value of the '{@link #getGrid() <em>Grid</em>}' reference. <!-- begin-user-doc --> * <!-- end-user-doc --> * * @see #getGrid() * @generated * @ordered */ protected IGridBinding grid; /** * The default value of the '{@link #getGridEditor() <em>Grid Editor</em>}' attribute. <!-- * begin-user-doc --> <!-- end-user-doc --> * * @see #getGridEditor() * @generated * @ordered */ protected static final GridEditor GRID_EDITOR_EDEFAULT = null; /** * The cached value of the '{@link #getGridEditor() <em>Grid Editor</em>}' attribute. <!-- * begin-user-doc --> <!-- end-user-doc --> * * @see #getGridEditor() * @generated * @ordered */ protected GridEditor gridEditor = GRID_EDITOR_EDEFAULT; /** * The cached value of the '{@link #getActiveEditCell() <em>Active Edit Cell</em>}' reference. * <!-- begin-user-doc --> <!-- end-user-doc --> * * @see #getActiveEditCell() * @generated * @ordered */ protected IGridBindingCellInformation activeEditCell; /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ private static final int EOFFSET_CORRECTION_GRID_OPPOSITE = IGridPackage.Literals.GRID_BINDING .getFeatureID(IGridPackage.Literals.GRID_BINDING__CELL_EDITOR) - IGridPackage.GRID_BINDING__CELL_EDITOR; /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ public GridBindingCellEditorImpl() { super(); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ @Override protected EClass eStaticClass() { return IGridPackage.Literals.GRID_BINDING_CELL_EDITOR; } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ @Override public IGridBinding getGrid() { return grid; } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated NOT */ public NotificationChain basicSetGrid(IGridBinding newGrid, NotificationChain msgs) { if (gridEditor != null) { gridEditor.dispose(); gridEditor = null; } if (newGrid != null) { gridEditor = new GridEditor(newGrid.getGrid()); } return basicSetGridGen(newGrid, msgs); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ public NotificationChain basicSetGridGen(IGridBinding newGrid, NotificationChain msgs) { final IGridBinding oldGrid = grid; grid = newGrid; if (eNotificationRequired()) { final ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, IGridPackage.GRID_BINDING_CELL_EDITOR__GRID, oldGrid, newGrid); if (msgs == null) { msgs = notification; } else { msgs.add(notification); } } return msgs; } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated NOT */ private static final int EOFFSET_CORRECTION_CELL_EDITOR_OPPOSITE = IGridPackage.Literals.GRID_BINDING .getFeatureID(IGridPackage.Literals.GRID_BINDING__NO_COLUMN_HEADERS) - IGridPackage.GRID_BINDING__NO_COLUMN_HEADERS; /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ @Override public void setGrid(IGridBinding newGrid) { if (newGrid != grid) { NotificationChain msgs = null; if (grid != null) { msgs = ((InternalEObject) grid).eInverseRemove(this, IGridPackage.GRID_BINDING__CELL_EDITOR + EOFFSET_CORRECTION_GRID_OPPOSITE, IGridBinding.class, msgs); } if (newGrid != null) { msgs = ((InternalEObject) newGrid).eInverseAdd(this, IGridPackage.GRID_BINDING__CELL_EDITOR + EOFFSET_CORRECTION_GRID_OPPOSITE, IGridBinding.class, msgs); } msgs = basicSetGrid(newGrid, msgs); if (msgs != null) { msgs.dispatch(); } } else if (eNotificationRequired()) { eNotify(new ENotificationImpl(this, Notification.SET, IGridPackage.GRID_BINDING_CELL_EDITOR__GRID, newGrid, newGrid)); } } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ @Override public GridEditor getGridEditor() { return gridEditor; } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ @Override public IGridBindingCellInformation getActiveEditCell() { return activeEditCell; } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ @Override public void setActiveEditCell(IGridBindingCellInformation newActiveEditCell) { final IGridBindingCellInformation oldActiveEditCell = activeEditCell; activeEditCell = newActiveEditCell; if (eNotificationRequired()) { eNotify(new ENotificationImpl(this, Notification.SET, IGridPackage.GRID_BINDING_CELL_EDITOR__ACTIVE_EDIT_CELL, oldActiveEditCell, activeEditCell)); } } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ @Override public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, NotificationChain msgs) { switch (featureID) { case IGridPackage.GRID_BINDING_CELL_EDITOR__GRID: if (grid != null) { msgs = ((InternalEObject) grid).eInverseRemove(this, IGridPackage.GRID_BINDING__CELL_EDITOR + EOFFSET_CORRECTION_GRID_OPPOSITE, IGridBinding.class, msgs); } return basicSetGrid((IGridBinding) otherEnd, msgs); } return super.eInverseAdd(otherEnd, featureID, msgs); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ @Override public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) { switch (featureID) { case IGridPackage.GRID_BINDING_CELL_EDITOR__GRID: return basicSetGrid(null, msgs); } return super.eInverseRemove(otherEnd, featureID, msgs); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ @Override public Object eGet(int featureID, boolean resolve, boolean coreType) { switch (featureID) { case IGridPackage.GRID_BINDING_CELL_EDITOR__GRID: return getGrid(); case IGridPackage.GRID_BINDING_CELL_EDITOR__GRID_EDITOR: return getGridEditor(); case IGridPackage.GRID_BINDING_CELL_EDITOR__ACTIVE_EDIT_CELL: return getActiveEditCell(); } return super.eGet(featureID, resolve, coreType); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ @Override public void eSet(int featureID, Object newValue) { switch (featureID) { case IGridPackage.GRID_BINDING_CELL_EDITOR__GRID: setGrid((IGridBinding) newValue); return; case IGridPackage.GRID_BINDING_CELL_EDITOR__ACTIVE_EDIT_CELL: setActiveEditCell((IGridBindingCellInformation) newValue); return; } super.eSet(featureID, newValue); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ @Override public void eUnset(int featureID) { switch (featureID) { case IGridPackage.GRID_BINDING_CELL_EDITOR__GRID: setGrid((IGridBinding) null); return; case IGridPackage.GRID_BINDING_CELL_EDITOR__ACTIVE_EDIT_CELL: setActiveEditCell((IGridBindingCellInformation) null); return; } super.eUnset(featureID); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ @Override public boolean eIsSet(int featureID) { switch (featureID) { case IGridPackage.GRID_BINDING_CELL_EDITOR__GRID: return grid != null; case IGridPackage.GRID_BINDING_CELL_EDITOR__GRID_EDITOR: return GRID_EDITOR_EDEFAULT == null ? gridEditor != null : !GRID_EDITOR_EDEFAULT.equals(gridEditor); case IGridPackage.GRID_BINDING_CELL_EDITOR__ACTIVE_EDIT_CELL: return activeEditCell != null; } return super.eIsSet(featureID); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated */ @Override public String toString() { if (eIsProxy()) return super.toString(); final StringBuffer result = new StringBuffer(super.toString()); result.append(" (gridEditor: "); result.append(gridEditor); result.append(')'); return result.toString(); } /** * The cell editor used in the current edit session. */ private CellEditor myCE; @Override public void editCell(final IGridBindingCellInformation cell, final ColumnViewerEditorActivationEvent event) { if (getActiveEditCell() == cell) return; if (getActiveEditCell() != null) { cancelEdit(); } setActiveEditCell(cell); // LogUtils.debug(this, "cell=" + cell); final GridEditor editorControl = getGridEditor(); myCE = createCellEditor(cell); final Control control = myCE.getControl(); // Layout the cell final LayoutData layoutData = myCE.getLayoutData(); gridEditor.grabHorizontal = layoutData.grabHorizontal; gridEditor.horizontalAlignment = layoutData.horizontalAlignment; gridEditor.minimumWidth = layoutData.minimumWidth; gridEditor.verticalAlignment = layoutData.verticalAlignment; gridEditor.minimumHeight = layoutData.minimumHeight; // Set the grid editor editorControl.setEditor(control, cell.getRow().getGridItem(), getGrid().getGrid().indexOf(cell.getColumn().getGridColumn())); /* * Activation */ myCE.activate(event); /* * Set focus - after the binding */ myCE.setFocus();// ??? myMouseListener = new MouseAdapter() { final int activationTime = event.time + Display.getCurrent().getDoubleClickTime(); @Override public void mouseDown(MouseEvent e) { if (control.isDisposed()) return; // time wrap? // check for expiration of doubleClickTime if (shouldFireDoubleClick(activationTime, e.time, event) && e.button == 1) { control.removeMouseListener(this); cancelEdit(); // handleDoubleClickEvent(); } else { control.removeMouseListener(this); } } private boolean shouldFireDoubleClick(int activationTime, int mouseTime, ColumnViewerEditorActivationEvent activationEvent) { return mouseTime <= activationTime && activationEvent.eventType != ColumnViewerEditorActivationEvent.KEY_PRESSED && activationEvent.eventType != ColumnViewerEditorActivationEvent.PROGRAMMATIC && activationEvent.eventType != ColumnViewerEditorActivationEvent.TRAVERSAL; } }; control.addTraverseListener(myTabEditingListener); control.addMouseListener(myMouseListener); control.addDisposeListener(myDisposeListener); myCE.addListener(myCellEditorListener); } protected CellEditor createCellEditor(final IGridBindingCellInformation cell) { if (Activator.getDefault().TRACE_LIFECYCLE_COLUMN_EDITORS) { LogUtils.debug(this, "cell=" + cell); } /* * Find the cell editor to use form the binding. Defaults to a text widget */ final ICellEditorFactory factory = cell.getLabelBinding().getArgument( Constants.ARG_PREFERRED_CELL_EDITOR_FACTORY, ICellEditorFactory.class, SimpleCellEditorFactory.Factory.getFactory()); /* * Context used for the editor creation. */ final ICellEditorFactoryContext context = new ICellEditorFactoryContext() { @Override public IValueBindingCell getCell() { return cell; } @Override public Composite getParent() { return cell.getColumn().getGrid().getGrid(); } }; return factory.create(context); } /** * Ends the current edit session. */ protected void endEditing() { // LogUtils.debug(this, "commit=" + commitChanges); final IGridBindingCellInformation cell = getActiveEditCell(); if (cell == null) return; setActiveEditCell(null); if (myCE == null) return; final Control control = myCE.getControl(); // Deactivate myCE.deactivate(); if (getGrid().getGrid().isDisposed()) { getGridEditor().setEditor(null, null, 0); } control.removeTraverseListener(myTabEditingListener); control.removeMouseListener(myMouseListener); myMouseListener = null; control.removeDisposeListener(myDisposeListener); myCE.removeListener(myCellEditorListener); myCE.dispose(); myCE = null; } @Override public void acceptEdit() { endEditing(); } @Override public void cancelEdit() { endEditing(); } /** * Traverse listener for the edit control. */ protected final TraverseListener myTabEditingListener = new TraverseListener() { @Override public void keyTraversed(TraverseEvent e) { if (!e.doit) return; switch (e.detail) { case SWT.TRAVERSE_ESCAPE: break; default: acceptEdit(); break; } // final IGridBinding g = getGrid(); // final IGridBindingCellInformation currentCell = g.getFocusCell(); // g.getGrid().traverse(e.detail); // final IGridBindingCellInformation newCell = g.getFocusCell(); // if (newCell != currentCell) { // editCell(newCell, new ColumnViewerEditorActivationEvent(MyViewerCell.INSTANCE, e)); // } } }; /** * Dispose listener for the edit control. */ protected final DisposeListener myDisposeListener = new DisposeListener() { @Override public void widgetDisposed(DisposeEvent e) { cancelEdit(); } }; /** * Mouse listener used to weed out double clicks. Recreated for each editor. */ protected MouseListener myMouseListener; /** * Cell Editor Listener. */ protected ICellEditorListener myCellEditorListener = new ICellEditorListener() { @Override public void editorValueChanged(boolean oldValidState, boolean newValidState) { // NOP } @Override public void cancelEditor() { cancelEdit(); } @Override public void applyEditorValue() { acceptEdit(); } }; } // GridBindingCellEditorImpl