com.vaadin.addon.spreadsheet.SpreadsheetHandlerImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.vaadin.addon.spreadsheet.SpreadsheetHandlerImpl.java

Source

package com.vaadin.addon.spreadsheet;

/*
 * #%L
 * Vaadin Spreadsheet
 * %%
 * Copyright (C) 2013 - 2015 Vaadin Ltd
 * %%
 * This program is available under Commercial Vaadin Add-On License 3.0
 * (CVALv3).
 * 
 * See the file license.html distributed with this software for more
 * information about licensing.
 * 
 * You should have received a copy of the CVALv3 along with this program.
 * If not, see <http://vaadin.com/license/cval-3>.
 * #L%
 */

import com.vaadin.addon.spreadsheet.Spreadsheet.CellValueChangeEvent;
import com.vaadin.addon.spreadsheet.Spreadsheet.ProtectedEditEvent;
import com.vaadin.addon.spreadsheet.client.SpreadsheetServerRpc;
import com.vaadin.addon.spreadsheet.command.CellValueCommand;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

/**
 * Implementation of the Spreadsheet Server RPC interface.
 */
@SuppressWarnings("serial")
public class SpreadsheetHandlerImpl implements SpreadsheetServerRpc {

    private Spreadsheet spreadsheet;

    public SpreadsheetHandlerImpl(Spreadsheet spreadsheet) {
        this.spreadsheet = spreadsheet;
    }

    @Override
    public void onSheetScroll(int firstRow, int firstColumn, int lastRow, int lastColumn) {
        spreadsheet.onSheetScroll(firstRow, firstColumn, lastRow, lastColumn);
    }

    @Override
    public void cellSelected(int row, int column, boolean discardOldRangeSelection) {
        spreadsheet.getCellSelectionManager().onCellSelected(row, column, discardOldRangeSelection);
    }

    @Override
    public void sheetAddressChanged(String value) {
        spreadsheet.getCellSelectionManager().onSheetAddressChanged(value, false);
    }

    @Override
    public void cellRangeSelected(int row1, int col1, int row2, int col2) {
        spreadsheet.getCellSelectionManager().onCellRangeSelected(row1, col1, row2, col2);
    }

    /* */
    @Override
    public void cellRangePainted(int selectedCellRow, int selectedCellColumn, int row1, int col1, int row2,
            int col2) {
        spreadsheet.getCellSelectionManager().onCellRangePainted(selectedCellRow, selectedCellColumn, row1, col1,
                row2, col2);
    }

    @Override
    public void cellAddedToSelectionAndSelected(int row, int column) {
        spreadsheet.getCellSelectionManager().onCellAddToSelectionAndSelected(row, column);
    }

    @Override
    public void cellsAddedToRangeSelection(int row1, int col1, int row2, int col2) {
        spreadsheet.getCellSelectionManager().onCellsAddedToRangeSelection(row1, col1, row2, col2);
    }

    @Override
    public void rowSelected(int row, int firstColumnIndex) {
        spreadsheet.getCellSelectionManager().onRowSelected(row, firstColumnIndex);
    }

    @Override
    public void rowAddedToRangeSelection(int row, int firstColumnIndex) {
        spreadsheet.getCellSelectionManager().onRowAddedToRangeSelection(row, firstColumnIndex);
    }

    @Override
    public void columnSelected(int col, int firstRowIndex) {
        spreadsheet.getCellSelectionManager().onColumnSelected(firstRowIndex, col);
    }

    @Override
    public void columnAddedToSelection(int firstRowIndex, int column) {
        spreadsheet.getCellSelectionManager().onColumnAddedToSelection(firstRowIndex, column);
    }

    /* the actual selected cell hasn't changed */
    @Override
    public void selectionIncreasePainted(int r1, int c1, int r2, int c2) {
        spreadsheet.getCellShifter().onSelectionIncreasePainted(r1, c1, r2, c2);
    }

    /* the actual selected cell hasn't changed */
    @Override
    public void selectionDecreasePainted(int r, int c) {
        spreadsheet.getCellShifter().onSelectionDecreasePainted(r, c);
    }

    @Override
    public void cellValueEdited(int row, int col, String value) {
        spreadsheet.getCellValueManager().onCellValueChange(col, row, value);
    }

    @Override
    public void sheetSelected(int tabIndex, int scrollLeft, int scrollTop) {
        spreadsheet.onSheetSelected(tabIndex, scrollLeft, scrollTop);
    }

    @Override
    public void sheetRenamed(int sheetIndex, String sheetName) {
        spreadsheet.onSheetRename(sheetIndex, sheetName);
    }

    @Override
    public void sheetCreated(int scrollLeft, int scrollTop) {
        spreadsheet.onNewSheetCreated(scrollLeft, scrollTop);
    }

    @Override
    public void deleteSelectedCells() {
        spreadsheet.getCellValueManager().onDeleteSelectedCells();
    }

    @Override
    public void linkCellClicked(int row, int column) {
        spreadsheet.onLinkCellClick(row, column);
    }

    @Override
    public void contextMenuOpenOnSelection(int row, int column) {
        spreadsheet.getContextMenuManager().onContextMenuOpenOnSelection(row, column);
    }

    @Override
    public void rowHeaderContextMenuOpen(int rowIndex) {
        spreadsheet.getContextMenuManager().onRowHeaderContextMenuOpen(rowIndex);
    }

    @Override
    public void columnHeaderContextMenuOpen(int columnIndex) {
        spreadsheet.getContextMenuManager().onColumnHeaderContextMenuOpen(columnIndex);
    }

    @Override
    public void actionOnCurrentSelection(String actionKey) {
        spreadsheet.getContextMenuManager().onActionOnCurrentSelection(actionKey);
    }

    @Override
    public void actionOnRowHeader(String actionKey) {
        spreadsheet.getContextMenuManager().onActionOnRowHeader(actionKey);
    }

    @Override
    public void actionOnColumnHeader(String actionKey) {
        spreadsheet.getContextMenuManager().onActionOnColumnHeader(actionKey);
    }

    @Override
    public void rowsResized(Map<Integer, Float> newRowSizes, int row1, int col1, int row2, int col2) {
        spreadsheet.onRowResized(newRowSizes, row1, col1, row2, col2);
    }

    @Override
    public void columnResized(Map<Integer, Integer> newColumnSizes, int row1, int col1, int row2, int col2) {
        spreadsheet.onColumnResized(newColumnSizes, row1, col1, row2, col2);
    }

    @Override
    public void onColumnAutofit(int columnIndex) {
        spreadsheet.onColumnAutofit(columnIndex - 1);
    }

    @Override
    public void onUndo() {
        spreadsheet.getSpreadsheetHistoryManager().undo();
    }

    @Override
    public void onRedo() {
        spreadsheet.getSpreadsheetHistoryManager().redo();
    }

    @Override
    public void setCellStyleWidthRatios(HashMap<Integer, Float> cellStyleWidthRatioMap) {
        spreadsheet.getCellValueManager().onCellStyleWidthRatioUpdate(cellStyleWidthRatioMap);
    }

    @Override
    public void onConnectorInit() {
        spreadsheet.onConnectorInit();
    }

    @Override
    public void protectedCellWriteAttempted() {
        spreadsheet.fireEvent(new ProtectedEditEvent(spreadsheet));
    }

    @Override
    public void onPaste(String text) {
        Workbook workbook = spreadsheet.getWorkbook();
        Sheet activesheet = workbook.getSheetAt(workbook.getActiveSheetIndex());

        CellReference selectedCellReference = spreadsheet.getSelectedCellReference();

        String[] lines;
        if (text.indexOf("\r\n") > -1) {
            lines = text.split("\r\n");
        } else if (text.indexOf("\n") > -1) {
            lines = text.split("\n");
        } else {
            lines = text.split("\r");
        }

        int pasteHeight = lines.length;
        int pasteWidth = 1;
        for (String line : lines) {
            String[] tokens = splitOnTab(line);
            pasteWidth = Math.max(pasteWidth, tokens.length);
        }

        int rowIndex = selectedCellReference.getRow();
        int colIndex = selectedCellReference.getCol();

        // Check for protected cells at target
        for (int i = 0; i < pasteHeight; i++) {
            Row row = activesheet.getRow(rowIndex + i);
            if (row != null) {
                for (int j = 0; j < pasteWidth; j++) {
                    Cell cell = row.getCell(colIndex + j);
                    if (spreadsheet.isCellLocked(cell)) {
                        protectedCellWriteAttempted();
                        return;
                    }
                }
            }
        }

        CellValueCommand command = new CellValueCommand(spreadsheet);
        CellRangeAddress affectedRange = new CellRangeAddress(rowIndex, rowIndex + pasteHeight - 1, colIndex,
                colIndex + pasteWidth - 1);
        command.captureCellRangeValues(affectedRange);

        for (int i = 0; i < pasteHeight; i++) {
            String line = lines[i];
            Row row = activesheet.getRow(rowIndex + i);
            if (row == null) {
                row = activesheet.createRow(rowIndex + i);
            }
            String[] tokens = splitOnTab(line);
            for (int j = 0; j < pasteWidth; j++) {
                Cell cell = row.getCell(colIndex + j);
                if (cell == null) {
                    cell = row.createCell(colIndex + j);
                }
                if (j < tokens.length) {
                    String cellContent = tokens[j];
                    Double numVal = SpreadsheetUtil.parseNumber(cell, cellContent, spreadsheet.getLocale());
                    if (numVal != null) {
                        cell.setCellType(Cell.CELL_TYPE_NUMERIC);
                        cell.setCellValue(numVal);
                    } else {
                        cell.setCellValue(cellContent);
                    }
                } else {
                    cell.setCellType(Cell.CELL_TYPE_BLANK);
                    spreadsheet.markCellAsDeleted(cell, true);
                }

                spreadsheet.getCellValueManager().markCellForUpdate(cell);
                spreadsheet.getCellValueManager().getFormulaEvaluator().notifyUpdateCell(cell);
            }
        }

        spreadsheet.getSpreadsheetHistoryManager().addCommand(command);
        spreadsheet.updateMarkedCells();
        // re-set selection to copied area
        spreadsheet.setSelectionRange(rowIndex, colIndex, rowIndex + pasteHeight - 1, colIndex + pasteWidth - 1);

        fireCellValueChangeEvent(affectedRange);
    }

    private void fireCellValueChangeEvent(CellRangeAddress region) {
        Set<CellReference> cells = new HashSet<CellReference>();
        for (int x = region.getFirstColumn(); x <= region.getLastColumn(); x++) {
            for (int y = region.getFirstRow(); y <= region.getLastRow(); y++) {
                cells.add(new CellReference(y, x));
            }
        }
        fireCellValueChangeEvent(cells);
    }

    private void fireCellValueChangeEvent(Set<CellReference> cells) {
        spreadsheet.fireEvent(new CellValueChangeEvent(spreadsheet, cells));
    }

    /**
     * Splits tab-delimited string into an array of Strings, inserting empty
     * strings between any tab characters and the beginning and end of the line
     * if it would be a tab. Length of array will equal number of tabs + 1.
     * <p>
     * E.g.<br/>
     * "1\t2" - {"1","2"}<br/>
     * "\t\t" - {"","",""}<br/>
     * 
     * @param line
     *            input
     * @return output string parts split at tabs
     */
    private static String[] splitOnTab(String line) {

        List<String> list = new LinkedList<String>();
        StringTokenizer tokenizer = new StringTokenizer(line, "\t", true);

        // marker for when last token is a tab, meaning we need one
        // additional empty string
        boolean lastCharWasTab = false;

        while (tokenizer.hasMoreTokens()) {

            String content = tokenizer.nextToken();

            if (content.equals("\t")) {
                // empty content; insert empty string here
                content = "";

                if (!tokenizer.hasMoreTokens()) {
                    lastCharWasTab = true;
                }

            } else {
                // normal cell content, value in 'content'

                // skip to next content by skipping tab token
                // (we process 'content\t' on the same loop)
                if (tokenizer.countTokens() > 1) {
                    tokenizer.nextToken();
                } else if (tokenizer.countTokens() == 1) {
                    // if the tab is the last char we need to mark it
                    tokenizer.nextToken();
                    lastCharWasTab = true;
                }
            }

            list.add(content);

            if (lastCharWasTab) {
                list.add("");
            }
        }

        return list.toArray(new String[list.size()]);
    }

    @Override
    public void clearSelectedCellsOnCut() {
        // clear ranges
        List<Cell> targetCells = new ArrayList<Cell>();
        List<CellRangeAddress> cellRangeAddresses = spreadsheet.getCellSelectionManager().getCellRangeAddresses();
        for (CellRangeAddress a : cellRangeAddresses) {
            for (int row = a.getFirstRow(); row <= a.getLastRow(); row++) {
                for (int col = a.getFirstColumn(); col <= a.getLastColumn(); col++) {
                    Cell cell = spreadsheet.getCell(row, col);
                    if (cell != null) {
                        if (spreadsheet.isCellLocked(cell)) {
                            protectedCellWriteAttempted();
                            return;
                        }
                        targetCells.add(cell);
                    }
                }
            }
        }

        // clear single cell
        CellReference reference = spreadsheet.getCellSelectionManager().getSelectedCellReference();
        Cell cell = spreadsheet.getCell(reference.getRow(), reference.getCol());
        if (cell != null) {
            if (spreadsheet.isCellLocked(cell)) {
                protectedCellWriteAttempted();
                return;
            }
            targetCells.add(cell);
        }
        CellValueCommand command = new CellValueCommand(spreadsheet);
        if (reference != null) {
            command.captureCellValues(reference);
        }
        for (CellRangeAddress range : cellRangeAddresses) {
            command.captureCellRangeValues(range);
        }
        spreadsheet.getSpreadsheetHistoryManager().addCommand(command);

        for (Cell targetCell : targetCells) {
            targetCell.setCellType(Cell.CELL_TYPE_BLANK);
            spreadsheet.markCellAsDeleted(targetCell, true);
        }

        fireCellValueChangeEvent(spreadsheet.getSelectedCellReferences());
        spreadsheet.refreshAllCellValues();
    }

    @Override
    public void updateCellComment(String text, int col, int row) {
        CreationHelper factory = spreadsheet.getWorkbook().getCreationHelper();
        RichTextString str = factory.createRichTextString(text);
        spreadsheet.getActiveSheet().getCellComment(row - 1, col - 1).setString(str);
    }

    @Override
    public void setGroupingCollapsed(boolean isCols, int colIndex, boolean collapsed) {
        spreadsheet.setGroupingCollapsed(isCols, colIndex, collapsed);
    }

    @Override
    public void levelHeaderClicked(boolean isCols, int level) {
        spreadsheet.levelHeaderClicked(isCols, level);
    }
}