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

Source Code of org.eclipse.nebula.widgets.nattable.copy.command.CopyDataCommandHandler

/*******************************************************************************
* 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.copy.command;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler;
import org.eclipse.nebula.widgets.nattable.coordinate.Range;
import org.eclipse.nebula.widgets.nattable.copy.serializing.CopyDataToClipboardSerializer;
import org.eclipse.nebula.widgets.nattable.copy.serializing.CopyFormattedTextToClipboardSerializer;
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.serializing.ISerializer;

/**
* Handler class for copying selected data within the {@link SelectionLayer} to
* the clipboard. This handler is registered by default with the
* {@link SelectionLayer}, without references to the header regions. You can
* override the copy data behaviour by registering an instance of this handler
* to a layer above the {@link SelectionLayer}. This way the registered custom
* instance will consume a {@link CopyDataToClipboardCommand} and the registered
* default handler won't be called.
*/
public class CopyDataCommandHandler extends
        AbstractLayerCommandHandler<CopyDataToClipboardCommand> {

    /**
     * The SelectionLayer needed to retrieve the selected data to copy to the
     * clipboard.
     */
    private final SelectionLayer selectionLayer;
    /**
     * The column header layer of the grid, needed to also copy the column
     * header data.
     */
    private final ILayer columnHeaderDataLayer;
    /**
     * The row header layer of the grid, needed to also copy the row header
     * data.
     */
    private final ILayer rowHeaderDataLayer;
    /**
     * Flag to specify which serializer should be used for copying the data.
     * <code>false</code> will use the CopyDataToClipboardSerializer which
     * simply calls <code>toString()</code> to serialize the data to copy,
     * <code>true</code> will use the CopyFormattedTextToClipboardSerializer
     * which will use the configured IDisplayConverter to get the String
     * representation of the value to copy.
     */
    private boolean copyFormattedText;

    /**
     * Creates an instance that only checks the {@link SelectionLayer} for data
     * to add to the clipboard.
     *
     * @param selectionLayer
     *            The {@link SelectionLayer} within the NatTable. Can not be
     *            <code>null</code>.
     */
    public CopyDataCommandHandler(SelectionLayer selectionLayer) {
        this(selectionLayer, null, null);
    }

    /**
     * Creates an instance that checks the {@link SelectionLayer} and the header
     * layers if they are given.
     *
     * @param selectionLayer
     *            The {@link SelectionLayer} within the NatTable. Can not be
     *            <code>null</code>.
     * @param columnHeaderDataLayer
     *            The column header data layer within the NatTable grid. Can be
     *            <code>null</code>.
     * @param rowHeaderDataLayer
     *            The row header data layer within the NatTable grid. Can be
     *            <code>null</code>.
     */
    public CopyDataCommandHandler(SelectionLayer selectionLayer,
            ILayer columnHeaderDataLayer, ILayer rowHeaderDataLayer) {
        assert selectionLayer != null : "The SelectionLayer can not be null on creating a CopyDataCommandHandler"; //$NON-NLS-1$
        this.selectionLayer = selectionLayer;
        this.columnHeaderDataLayer = columnHeaderDataLayer;
        this.rowHeaderDataLayer = rowHeaderDataLayer;
    }

    /**
     * Specify which serializer to use for copying.
     *
     * @param copyFormattedText
     *            <code>false</code> will use the CopyDataToClipboardSerializer
     *            which simply calls <code>toString()</code> to serialize the
     *            data to copy, <code>true</code> will use the
     *            CopyFormattedTextToClipboardSerializer which will use the
     *            configured IDisplayConverter to get the String representation
     *            of the value to copy
     */
    public void setCopyFormattedText(boolean copyFormattedText) {
        this.copyFormattedText = copyFormattedText;
    }

    @Override
    public boolean doCommand(CopyDataToClipboardCommand command) {
        ISerializer serializer = copyFormattedText ? new CopyFormattedTextToClipboardSerializer(
                assembleCopiedDataStructure(), command)
                : new CopyDataToClipboardSerializer(
                        assembleCopiedDataStructure(), command);
        serializer.serialize();
        return true;
    }

    @Override
    public Class<CopyDataToClipboardCommand> getCommandClass() {
        return CopyDataToClipboardCommand.class;
    }

    /**
     * Collects and assembles the selected data that should be copied to the
     * clipboard.
     *
     * @return A two dimensional array containing the selected cells to copy to
     *         the clipboard. The first level of this array represent the row
     *         positions of the cells, while the second level contains the cells
     *         itself based on the column position.
     */
    protected ILayerCell[][] assembleCopiedDataStructure() {
        final Set<Range> selectedRows = selectionLayer
                .getSelectedRowPositions();
        final ILayerCell[][] copiedCells = assembleColumnHeaders();

        // cleanup the row positions to copy
        // this is needed because taking only the Range.start into account leads
        // to overriding
        // values in the array instead of adding if there are multiple Ranges
        // returned
        List<Integer> selectedRowPositions = new ArrayList<Integer>();
        for (Range range : selectedRows) {
            for (int rowPosition = range.start; rowPosition < range.end; rowPosition++) {
                selectedRowPositions.add(rowPosition);
            }
        }
        // ensure the correct order as a Set is not ordered at all and we want
        // to paste the values
        // in the same order we copied them.
        Collections.sort(selectedRowPositions);

        final int rowOffset = columnHeaderDataLayer != null ? columnHeaderDataLayer
                .getRowCount() : 0;
        for (int i = 0; i < selectedRowPositions.size(); i++) {
            Integer rowPos = selectedRowPositions.get(i);
            copiedCells[i + rowOffset] = assembleBody(rowPos);
        }

        return copiedCells;
    }

    /**
     * Creates the two dimensional array whose dimensions are calculated based
     * on the selection within the {@link SelectionLayer} and the configured
     * column and row headers. If there is a column header configured for this
     * handler, the column header information will be added to the resulting
     * array in here. If there is no column header configured an empty array
     * with the matching dimensions will be returned.
     *
     * @return A two dimensional array with the dimensions to store the selected
     *         data to copy to the clipboard. Will also contain the column
     *         header information for the copy operation if there is one
     *         configured.
     */
    protected ILayerCell[][] assembleColumnHeaders() {
        // Add offset to rows, remember they need to include the column header
        // rows
        final int rowOffset = columnHeaderDataLayer != null ? columnHeaderDataLayer
                .getRowCount() : 0;
        final int columnOffset = rowHeaderDataLayer != null ? rowHeaderDataLayer
                .getColumnCount() : 0;

        final ILayerCell[][] copiedCells = new ILayerCell[selectionLayer
                .getSelectedRowCount() + rowOffset][1];

        if (columnHeaderDataLayer != null) {
            int[] selectedColumnPositions = selectionLayer
                    .getSelectedColumnPositions();
            for (int i = 0; i < rowOffset; i++) {
                final ILayerCell[] cells = new ILayerCell[selectedColumnPositions.length
                        + columnOffset];
                for (int columnPosition = 0; columnPosition < selectedColumnPositions.length; columnPosition++) {
                    // Pad the width of the vertical layer
                    cells[columnPosition + columnOffset] = columnHeaderDataLayer
                            .getCellByPosition(
                                    selectedColumnPositions[columnPosition], i);
                }

                copiedCells[i] = cells;
            }
        }

        return copiedCells;
    }

    /**
     * Collects and assembles the selected data per row position that should be
     * copied to the clipboard. If there is a row header layer configured for
     * this handler, the row header cells of the selected row position are also
     * added to the resulting array.
     *
     * @param currentRowPosition
     *            The row position of which the selected cells should be
     *            collected.
     * @return An array containing the selected cells that should be copied to
     *         the clipboard.
     */
    protected ILayerCell[] assembleBody(int currentRowPosition) {
        final int[] selectedColumns = selectionLayer
                .getSelectedColumnPositions();
        final int columnOffset = rowHeaderDataLayer != null ? rowHeaderDataLayer
                .getColumnCount() : 0;
        final ILayerCell[] bodyCells = new ILayerCell[selectedColumns.length
                + columnOffset];

        if (rowHeaderDataLayer != null) {
            for (int i = 0; i < rowHeaderDataLayer.getColumnCount(); i++) {
                bodyCells[i] = rowHeaderDataLayer.getCellByPosition(i,
                        currentRowPosition);
            }
        }

        for (int columnPosition = 0; columnPosition < selectedColumns.length; columnPosition++) {
            final int selectedColumnPosition = selectedColumns[columnPosition];
            if (selectionLayer.isCellPositionSelected(selectedColumnPosition,
                    currentRowPosition)) {
                bodyCells[columnPosition + columnOffset] = selectionLayer
                        .getCellByPosition(selectedColumnPosition,
                                currentRowPosition);
            }
        }
        return bodyCells;
    }

}
TOP

Related Classes of org.eclipse.nebula.widgets.nattable.copy.command.CopyDataCommandHandler

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.