package com.vaadin.addon.spreadsheet.client;
/*
* #%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.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Event.NativePreviewHandler;
import com.google.gwt.user.client.ui.TextArea;
/**
* TextArea that handles cut, copy and paste events inside the spreadsheet.
* <p>
* It works by intercepting the keyboard shortcuts for cut, copy and paste and
* moving focus to a hidden textfield. In the textfield we can listen to oncopy
* and oncut events, and put our string into the HTML clipboard instead of the
* normal one.
*
* @author Thomas Mattsson / Vaadin Ltd.
*/
public class CopyPasteTextBox extends TextArea implements NativePreviewHandler {
/**
* Handler interface for dealing with the data that is transferred in copy,
* cut and paste operations.
*
* @author Thomas Mattsson / Vaadin Ltd.
*/
public interface CopyPasteHandler {
/**
* Called when user has performed a copy operation.
*/
public void onCut();
/**
* Called when user has performed a copy operation.
*/
public void onCopy();
/**
* Called when the user has performed a paste operation.
*
* @param text
* the pasted text
*/
public void onPaste(String text);
/**
* @return Textual representation to be put on the systems text
* clipboard.
*/
public String getClipboardText();
}
private SheetWidget widget;
private CopyPasteHandler handler;
public CopyPasteTextBox(SheetWidget widget, CopyPasteHandler handler) {
this.widget = widget;
this.handler = handler;
Event.addNativePreviewHandler(this);
getElement().getStyle().setPosition(Position.ABSOLUTE);
getElement().getStyle().setZIndex(100);
getElement().getStyle().setLeft(-1000, Unit.PX);
// gets round browser security (field must be 'visible' when copying)
getElement().getStyle().setOpacity(0);
}
@Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
final NativeEvent nativeEvent = event.getNativeEvent();
switch (Event.getTypeInt(nativeEvent.getType())) {
case Event.ONKEYDOWN:
onKeyDown(nativeEvent);
break;
default:
break;
}
}
private void onKeyDown(final NativeEvent event) {
boolean metaOrCtrlPressed = (!widget.isMac() && event.getCtrlKey())
|| event.getMetaKey();
Element cast = event.getEventTarget().cast();
boolean sheetFocused = widget.isSheetElement(cast);
if (!metaOrCtrlPressed || !sheetFocused) {
return;
}
// copy
if (event.getKeyCode() == 67 || event.getKeyCode() == 88) { // C or X
// before copy goes through, move the focus and selection to this
// field
setFocus(true);
this.setValue(handler.getClipboardText());
selectAll();
// also, we need to move the field into the visible area of the
// browser
getElement().getStyle().setLeft(100, Unit.PX);
Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
@Override
public boolean execute() {
// after copy, move focus back
widget.focusSheet();
// hide element
getElement().getStyle().setLeft(-1000, Unit.PX);
if (event.getKeyCode() == 67) {
handler.onCopy();
} else if (event.getKeyCode() == 88) {
handler.onCut();
}
return false;
}
}, 100);
// browser copy happens here
}
// paste
if (event.getKeyCode() == 86) {// V
setText("");
setFocus(true);
Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
@Override
public boolean execute() {
// get pasted data
String data = getValue();
handler.onPaste(data);
// .. and move focus back
widget.focusSheet();
return false;
}
}, 100);
// paste happens here
}
}
}