Package org.eclipse.nebula.widgets.nattable.edit.command

Source Code of org.eclipse.nebula.widgets.nattable.edit.command.EditUtils

/*******************************************************************************
* Copyright (c) 2012, 2013 Original authors 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:
*     Original authors and others - initial API and implementation
******************************************************************************/
package org.eclipse.nebula.widgets.nattable.edit.command;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.nebula.widgets.nattable.NatTable;
import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes;
import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
import org.eclipse.nebula.widgets.nattable.config.IEditableRule;
import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
import org.eclipse.nebula.widgets.nattable.data.convert.IDisplayConverter;
import org.eclipse.nebula.widgets.nattable.edit.ActiveCellEditorRegistry;
import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes;
import org.eclipse.nebula.widgets.nattable.edit.editor.ICellEditor;
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
import org.eclipse.nebula.widgets.nattable.layer.LabelStack;
import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
import org.eclipse.nebula.widgets.nattable.selection.IRowSelectionModel;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum;
import org.eclipse.nebula.widgets.nattable.style.DisplayMode;

/**
* Helper class for retrieving information regarding editing of selected cells.
*/
public class EditUtils {

    /**
     *
     * @param selectionLayer
     *            The {@link SelectionLayer} to retrieve the current selection
     *            from.
     * @return The last cell of the current selection in the specified
     *         {@link SelectionLayer}. Will return <code>null</code> if there is
     *         no selection.
     */
    public static ILayerCell getLastSelectedCell(SelectionLayer selectionLayer) {
        PositionCoordinate selectionAnchor = selectionLayer.getSelectionAnchor();
        return selectionLayer.getCellByPosition(selectionAnchor.columnPosition, selectionAnchor.rowPosition);
    }

    /**
     *
     * @param selectionLayer
     *            The {@link SelectionLayer} to retrieve the current selectio
     *            from.
     * @param configRegistry
     *            The {@link IConfigRegistry} needed to access the configured
     *            {@link ICellEditor}.
     * @return The {@link ICellEditor} of the last cell of the current selection
     *         in the specified {@link SelectionLayer}. Will return
     *         <code>null</code> if there is no selection.
     */
    public static ICellEditor getLastSelectedCellEditor(SelectionLayer selectionLayer, IConfigRegistry configRegistry) {
        ILayerCell lastSelectedCell = EditUtils.getLastSelectedCell(selectionLayer);
        if (lastSelectedCell != null) {
            final List<String> lastSelectedCellLabelsArray = lastSelectedCell.getConfigLabels().getLabels();
            return configRegistry.getConfigAttribute(
                    EditConfigAttributes.CELL_EDITOR,
                    DisplayMode.EDIT,
                    lastSelectedCellLabelsArray);
        }
        return null;
    }

    /**
     *
     * @param selectionLayer
     *            The {@link SelectionLayer} to retrieve the current selection.
     * @param configRegistry
     *            The {@link IConfigRegistry} needed to access the configured
     *            {@link ICellEditor}.
     * @param byTraversal
     *            <code>true</code> if the activation is triggered by traversal,
     *            <code>false</code> if not
     * @return <code>true</code> if the current selected cell contains an editor
     *         that should be activated, <code>false</code> if not
     */
    public static boolean activateLastSelectedCellEditor(SelectionLayer selectionLayer, IConfigRegistry configRegistry, boolean byTraversal) {
        ILayerCell lastSelectedCell = EditUtils.getLastSelectedCell(selectionLayer);
        if (lastSelectedCell != null) {
            final List<String> lastSelectedCellLabelsArray = lastSelectedCell.getConfigLabels().getLabels();
            ICellEditor editor = configRegistry.getConfigAttribute(
                    EditConfigAttributes.CELL_EDITOR,
                    DisplayMode.EDIT,
                    lastSelectedCellLabelsArray);
            if (editor != null) {
                return (!byTraversal || editor.activateOnTraversal(configRegistry, lastSelectedCellLabelsArray));
            }
        }
        return false;
    }

    /**
     * For every cell that is selected it is checked whether the cell is
     * editable or not.
     *
     * <p>
     * In case a {@link IRowSelectionModel} is in use, only the selection anchor
     * is checked.
     * </p>
     *
     * @param selectionLayer
     *            The {@link SelectionLayer} to retrieve the current selection.
     * @param configRegistry
     *            The {@link IConfigRegistry} needed to access the configured
     *            {@link IEditableRule}s.
     * @return <code>true</code> if all selected cells are editable,
     *         <code>false</code> if at least one cell is not editable.
     */
    public static boolean allCellsEditable(SelectionLayer selectionLayer, IConfigRegistry configRegistry) {
        return allCellsEditable(getSelectedCellsForEditing(selectionLayer), configRegistry);
    }

    /**
     * For every selected cell it is checked whether the cell is editable or
     * not. If the collection of selected cells is <code>null</code> or empty,
     * this method will also return <code>true</code>.
     *
     * @param selectedCells
     *            The collection of selected cells that should be checked.
     * @param configRegistry
     *            The {@link IConfigRegistry} needed to access the configured
     *            {@link IEditableRule}s.
     * @return <code>true</code> if all selected cells are editable,
     *         <code>false</code> if at least one cell is not editable.
     */
    public static boolean allCellsEditable(Collection<ILayerCell> selectedCells, IConfigRegistry configRegistry) {
        if (selectedCells != null) {
            for (ILayerCell layerCell : selectedCells) {
                LabelStack labelStack = layerCell.getConfigLabels();
                IEditableRule editableRule = configRegistry.getConfigAttribute(
                        EditConfigAttributes.CELL_EDITABLE_RULE,
                        DisplayMode.EDIT,
                        labelStack.getLabels());

                if (editableRule == null
                        || !editableRule.isEditable(layerCell, configRegistry)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Checks if the cell at the specified coordinates is editable or not.
     * <p>
     * Note: The coordinates need to be related to the given SelectionLayer,
     * otherwise the wrong cell will be used for the check.
     *
     * @param layer
     *            The {@link ILayer} to check the cell coordinates against.
     * @param configRegistry
     *            The {@link IConfigRegistry} needed to access the configured
     *            {@link IEditableRule}s.
     * @param cellCoords
     *            The coordinates of the cell to check the editable state,
     *            related to the given {@link ILayer}
     * @return <code>true</code> if the cell is editable, <code>false</code> if
     *         not
     */
    public static boolean isCellEditable(ILayer layer,
            IConfigRegistry configRegistry, PositionCoordinate cellCoords) {
        ILayerCell layerCell = layer.getCellByPosition(cellCoords.columnPosition, cellCoords.rowPosition);
        LabelStack labelStack = layerCell.getConfigLabels();

        IEditableRule editableRule = configRegistry.getConfigAttribute(
                EditConfigAttributes.CELL_EDITABLE_RULE,
                DisplayMode.EDIT,
                labelStack.getLabels());
        if (editableRule == null) {
            return false;
        }

        return editableRule.isEditable(layerCell, configRegistry);
    }

    /**
     * Checks if all selected cells have the same {@link ICellEditor}
     * configured. This is needed for the multi edit feature to determine if a
     * multi edit is possible.
     *
     * @param selectionLayer
     *            The {@link SelectionLayer} to retrieve the current selection.
     * @param configRegistry
     *            The {@link IConfigRegistry} needed to access the configured
     *            {@link ICellEditor}s.
     * @return <code>true</code> if all selected cells have the same
     *         {@link ICellEditor} configured, <code>false</code> if at least
     *         one cell has another {@link ICellEditor} configured.
     */
    public static boolean isEditorSame(SelectionLayer selectionLayer, IConfigRegistry configRegistry) {
        return isEditorSame(getSelectedCellsForEditing(selectionLayer), configRegistry);
    }

    /**
     * Checks if all selected cells have the same {@link ICellEditor}
     * configured. This is needed for the multi edit feature to determine if a
     * multi edit is possible. If the collection of selected cells is
     * <code>null</code> or empty, this method will also return
     * <code>true</code>.
     *
     * @param selectedCells
     *            The collection of selected cells that should be checked.
     * @param configRegistry
     *            The {@link IConfigRegistry} needed to access the configured
     *            {@link ICellEditor}s.
     * @return <code>true</code> if all selected cells have the same
     *         {@link ICellEditor} configured, <code>false</code> if at least
     *         one cell has another {@link ICellEditor} configured.
     */
    public static boolean isEditorSame(Collection<ILayerCell> selectedCells, IConfigRegistry configRegistry) {
        if (selectedCells != null) {
            ICellEditor lastSelectedCellEditor = null;
            for (ILayerCell selectedCell : selectedCells) {
                LabelStack labelStack = selectedCell.getConfigLabels();
                ICellEditor cellEditor = configRegistry.getConfigAttribute(
                        EditConfigAttributes.CELL_EDITOR,
                        DisplayMode.EDIT,
                        labelStack.getLabels());

                // The first time we get here we need to remember the editor so
                // further checks can use it.
                // Getting the editor before by getLastSelectedCellEditor()
                // might cause issues in case there is no active selection
                // anchor
                if (lastSelectedCellEditor == null) {
                    lastSelectedCellEditor = cellEditor;
                }
                if (cellEditor != lastSelectedCellEditor) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Checks if all selected cells have the same {@link IDisplayConverter}
     * configured. This is needed for the multi edit feature to determine if a
     * multi edit is possible.
     * <p>
     * Let's assume there are two columns, one containing an Integer, the other
     * a Date. Both have a TextCellEditor configured, so if only the editor is
     * checked, the multi edit dialog would open. On committing a changed value
     * an error would occur because of wrong conversion.
     * </p>
     *
     * @param selectionLayer
     *            The {@link SelectionLayer} to retrieve the current selection.
     * @param configRegistry
     *            The {@link IConfigRegistry} needed to access the configured
     *            {@link IDisplayConverter}s.
     * @return <code>true</code> if all selected cells have the same
     *         {@link IDisplayConverter} configured, <code>false</code> if at
     *         least one cell has another {@link IDisplayConverter} configured.
     */
    public static boolean isConverterSame(SelectionLayer selectionLayer, IConfigRegistry configRegistry) {
        return isConverterSame(getSelectedCellsForEditing(selectionLayer), configRegistry);
    }

    /**
     * Checks if all selected cells have the same {@link IDisplayConverter}
     * configured. This is needed for the multi edit feature to determine if a
     * multi edit is possible. If the collection of selected cells is
     * <code>null</code> or empty, this method will also return
     * <code>true</code>.
     * <p>
     * Let's assume there are two columns, one containing an Integer, the other
     * a Date. Both have a TextCellEditor configured, so if only the editor is
     * checked, the multi edit dialog would open. On committing a changed value
     * an error would occur because of wrong conversion.
     * </p>
     *
     * @param selectedCells
     *            The collection of selected cells that should be checked.
     * @param configRegistry
     *            The {@link IConfigRegistry} needed to access the configured
     *            {@link IDisplayConverter}s.
     * @return <code>true</code> if all selected cells have the same
     *         {@link IDisplayConverter} configured, <code>false</code> if at
     *         least one cell has another {@link IDisplayConverter} configured.
     */
    @SuppressWarnings("rawtypes")
    public static boolean isConverterSame(Collection<ILayerCell> selectedCells, IConfigRegistry configRegistry) {
        if (selectedCells != null) {
            Set<Class> converterSet = new HashSet<Class>();

            for (ILayerCell selectedCell : selectedCells) {
                LabelStack labelStack = selectedCell.getConfigLabels();
                IDisplayConverter dataTypeConverter = configRegistry.getConfigAttribute(
                        CellConfigAttributes.DISPLAY_CONVERTER,
                        DisplayMode.EDIT,
                        labelStack.getLabels());
                if (dataTypeConverter != null) {
                    converterSet.add(dataTypeConverter.getClass());
                }
                if (converterSet.size() > 1)
                    return false;
            }
        }
        return true;
    }

    /**
     * Checks if all selected cells contain the same canonical value. This is
     * needed for multi edit to know if the editor should be initialised with
     * the value that is shared amongst all cells.
     *
     * @param selectionLayer
     *            The {@link SelectionLayer} to retrieve the current selection.
     * @return <code>true</code> if all cells contain the same value,
     *         <code>false</code> if at least one cell contains another value.
     */
    public static boolean isValueSame(SelectionLayer selectionLayer) {
        return isValueSame(getSelectedCellsForEditing(selectionLayer));
    }

    /**
     * Checks if all selected cells contain the same canonical value. This is
     * needed for multi edit to know if the editor should be initialized with
     * the value that is shared amongst all cells. If the collection of selected
     * cells is <code>null</code> or empty, this method will also return
     * <code>true</code>.
     *
     * @param selectedCells
     *            The collection of selected cells that should be checked.
     * @return <code>true</code> if all cells contain the same value,
     *         <code>false</code> if at least one cell contains another value.
     */
    public static boolean isValueSame(Collection<ILayerCell> selectedCells) {
        if (selectedCells != null) {
            Object lastSelectedValue = null;
            for (ILayerCell layerCell : selectedCells) {
                Object cellValue = layerCell.getDataValue();
                if (lastSelectedValue == null) {
                    lastSelectedValue = cellValue;
                }
                if ((cellValue != null && !cellValue.equals(lastSelectedValue))
                        || cellValue == null && lastSelectedValue != null) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Returns the collection of selected {@link ILayerCell}s that are eligible
     * for editing. This method is used for multi edit support, to ensure the
     * editing also with row selection.
     * <p>
     * In case of cell selection, simply all selected cells are returned.
     * </p>
     * <p>
     * In case a {@link IRowSelectionModel} is configured, the selected cells in
     * correlation to the selection anchor are returned. This means, in case
     * only one row is selected, the selection anchor is returned. In case
     * multiple rows are selected, the cells at the column position of the
     * selection anchor for all selected rows are returned.
     * </p>
     *
     * @param selectionLayer
     *            The {@link SelectionLayer} to retrieve the current selection.
     * @return The selected {@link ILayerCell}s that are eligible for editing.
     */
    public static Collection<ILayerCell> getSelectedCellsForEditing(SelectionLayer selectionLayer) {
        Collection<ILayerCell> selectedCells = null;
        if (selectionLayer.getSelectionModel() instanceof IRowSelectionModel) {
            selectedCells = new ArrayList<ILayerCell>();

            if (selectionLayer.getSelectionModel().getSelectedRowCount() == 1) {
                selectedCells.add(getLastSelectedCell(selectionLayer));
            }
            else {
                ILayerCell anchor = getLastSelectedCell(selectionLayer);
                for (ILayerCell cell : selectionLayer.getSelectedCells()) {
                    if (cell.getColumnPosition() == anchor.getColumnPosition()) {
                        selectedCells.add(cell);
                    }
                }
            }
        }
        else {
            selectedCells = selectionLayer.getSelectedCells();
        }
        return selectedCells;
    }

    /**
     * Checks if there is an active editor registered. If there is one, it is
     * tried to commit the value that is currently entered there.
     *
     * @deprecated Has been replaced by
     *             {@link NatTable#commitAndCloseActiveCellEditor()}. The active
     *             editor is now managed by the table itself. Therefore the
     *             static helpers to access the editor should not be used any
     *             more.
     *
     * @return <code>false</code> if there is an open editor that can not be
     *         committed because of conversion/validation errors,
     *         <code>true</code> if there is no active open editor or it could
     *         be closed after committing the value.
     */
    @Deprecated
    public static boolean commitAndCloseActiveEditor() {
        ICellEditor activeCellEditor = ActiveCellEditorRegistry.getActiveCellEditor();
        if (activeCellEditor != null) {
            return activeCellEditor.commit(MoveDirectionEnum.NONE, true);
        }
        return true;
    }

}
TOP

Related Classes of org.eclipse.nebula.widgets.nattable.edit.command.EditUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.