/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.ui.tools;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.SharedCursors;
import org.eclipse.gef.tools.SimpleDragTracker;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Cursor;
import org.whole.lang.ui.editor.IGEFEditorKit;
import org.whole.lang.ui.editparts.IEntityPart;
import org.whole.lang.ui.editparts.ITextualEntityPart;
import org.whole.lang.ui.figures.ITextualFigure;
import org.whole.lang.ui.keys.IKeyHandler;
import org.whole.lang.ui.util.CaretUpdater;
import org.whole.lang.ui.viewers.IEntityPartViewer;
/**
* @author Enrico Persiani
*/
public class TextualDragTracker extends SimpleDragTracker {
private static final int STATE_SELECT = SimpleDragTracker.MAX_STATE << 1;
private static final int STATE_SWIPE = SimpleDragTracker.MAX_STATE << 2;
private ITextualEntityPart beginPart;
private ITextualEntityPart endPart;
private int start;
private int end;
public TextualDragTracker() {
}
@Override
protected List<IEntityPart> createOperationSet() {
IEntityPartViewer viewer = (IEntityPartViewer) getCurrentViewer();
return Collections.<IEntityPart>singletonList(viewer.getFocusEntityPart());
}
@Override
protected Cursor calculateCursor() {
return SharedCursors.IBEAM;
}
@Override
protected String getCommandName() {
return "Drop Text";
}
protected ITextualEntityPart getTextualEntityPart() {
if (beginPart != null)
return beginPart;
EditPart target = getCurrentViewer().findObjectAt(getLocation());
if (!(target instanceof ITextualEntityPart))
return null;
return (ITextualEntityPart) target;
}
@Override
protected boolean handleButtonDown(int button) {
ITextualEntityPart textualEntityPart = getTextualEntityPart();
if (button != 1 || textualEntityPart == null) {
beginPart = endPart = null;
start = end = 0;
setState(STATE_INVALID);
return handleInvalidInput();
} else {
beginPart = endPart = textualEntityPart;
CaretUpdater.sheduleSyncUpdate(getCurrentViewer(), beginPart.getModelEntity(), getLocation(), true);
start = textualEntityPart.getCaretPosition();
return stateTransition(STATE_INITIAL, STATE_SELECT);
}
}
protected boolean handleTripleClick(int button) {
ITextualEntityPart textualEntityPart = getTextualEntityPart();
if (button == 1 && textualEntityPart != null) {
IGEFEditorKit editorkit = (IGEFEditorKit) textualEntityPart.getModelEntity().wGetEditorKit();
EditPoint editPoint = new EditPoint(textualEntityPart, textualEntityPart.getCaretPosition());
IKeyHandler keyHandler = editorkit.getKeyHandler();
IWholeSelection selection = keyHandler.calculateTripleClickSelection(editPoint);
performSelectionUpdate(selection, true);
return true;
}
return false;
}
@Override
protected boolean handleDoubleClick(int button) {
ITextualEntityPart textualEntityPart = getTextualEntityPart();
if (button == 1 && textualEntityPart != null) {
IGEFEditorKit editorkit = (IGEFEditorKit) textualEntityPart.getModelEntity().wGetEditorKit();
EditPoint editPoint = new EditPoint(textualEntityPart, textualEntityPart.getCaretPosition());
IKeyHandler keyHandler = editorkit.getKeyHandler();
IWholeSelection selection = keyHandler.calculateDoubleClickSelection(editPoint);
performSelectionUpdate(selection, true);
return true;
}
return super.handleDoubleClick(button);
}
@Override
protected boolean handleDragStarted() {
return stateTransition(STATE_SELECT, STATE_SWIPE);
}
@Override
protected boolean handleDragInProgress() {
EditPartViewer viewer = getCurrentViewer();
ITextualEntityPart textualEntityPart = getTextualEntityPart();
if (textualEntityPart == null)
return false;
EditPart overPart = viewer.findObjectAt(getLocation());
if (overPart == endPart) {
end = textualEntityPart.getCaretPosition();
if (start <= end)
performSelectionUpdate(new SelectionRange(textualEntityPart, start, end), false);
else {
performSelectionUpdate(new SelectionRange(textualEntityPart, end, start), false);
}
} else {
ITextualFigure textualFigure = textualEntityPart.getTextualFigure();
Rectangle textBounds = textualFigure.getTextBounds();
textualFigure.translateToAbsolute(textBounds);
Point mouseLocation = getLocation();
mouseLocation.x = Math.max(mouseLocation.x, textBounds.x);
mouseLocation.x = Math.min(mouseLocation.x, textBounds.right()-1);
mouseLocation.y = Math.max(mouseLocation.y, textBounds.y);
mouseLocation.y = Math.min(mouseLocation.y, textBounds.bottom()-1);
textualEntityPart.updateCaret(mouseLocation);
end = textualEntityPart.getCaretPosition();
if (start <= end)
performSelectionUpdate(new SelectionRange(textualEntityPart, start, end), mouseLocation, false);
else {
performSelectionUpdate(new SelectionRange(textualEntityPart, end, start), mouseLocation, false);
}
}
return super.handleDragInProgress();
}
private void performSelectionUpdate(IWholeSelection selection, boolean caretOnSelectionEnd) {
performSelectionUpdate(selection, null, caretOnSelectionEnd);
}
private void performSelectionUpdate(IWholeSelection selection, Point location, boolean caretOnSelectionEnd) {
EditPartViewer viewer = getCurrentViewer();
IEntityPart focusPart = null;
if (selection.size() > 0) {
IWholeSelection last = selection.get(selection.size()-1);
int caretPosition = -1;
switch (last.getKind()) {
case RANGE:
caretPosition = last.getEndPosition();
case PART:
IEntityPart lastPart = last.getPart();
if (lastPart instanceof ITextualEntityPart) {
ITextualEntityPart caretPart = (ITextualEntityPart) lastPart;
if (caretOnSelectionEnd) {
caretPosition = caretPosition < 0 ? caretPart.getCaretPositions(): caretPosition;
CaretUpdater.sheduleSyncUpdate(getCurrentViewer(), lastPart.getModelEntity(), caretPosition, true);
} else
CaretUpdater.sheduleSyncUpdate(getCurrentViewer(), lastPart.getModelEntity(), location != null ? location : getLocation(), true);
// update focus only if instance of ICaretEntityPart
focusPart = lastPart;
}
default:
break;
}
}
List<IEntityPart> partList = new ArrayList<IEntityPart>();
for (int i=0; i<selection.size(); i++) {
IWholeSelection sel = selection.get(i);
switch (sel.getKind()) {
case RANGE:
((ITextualEntityPart)sel.getPart()).setSelectionRange(sel.getStartPosition(), sel.getEndPosition());
partList.add(sel.getPart());
break;
case PART:
IEntityPart part = sel.getPart();
if (part instanceof ITextualEntityPart)
((ITextualEntityPart)part).setSelectionRange(0, ((ITextualEntityPart)part).getCaretPositions());
partList.add(sel.getPart());
break;
default:
break;
}
}
viewer.setSelection(new StructuredSelection(partList));
viewer.setFocus(focusPart);
}
public void mouseTripleClick(MouseEvent me, EditPartViewer viewer) {
if (me.button > 5 || !isViewerImportant(viewer))
return;
setViewer(viewer);
getCurrentInput().setInput(me);
handleTripleClick(me.button);
}
}