/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.gef.event;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.LightweightSystem;
import org.eclipse.draw2d.RangeModel;
import org.eclipse.draw2d.ToolTipHelper;
import org.eclipse.draw2d.Viewport;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.AccessibleControlEvent;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.xmind.gef.EditDomain;
import org.xmind.gef.GEF;
import org.xmind.gef.GraphicalViewer;
import org.xmind.gef.IGraphicalViewer;
import org.xmind.gef.acc.IAccessible;
import org.xmind.gef.dnd.DndData;
import org.xmind.gef.dnd.IDndClient;
import org.xmind.gef.dnd.IDndSupport;
import org.xmind.gef.draw2d.KeepVisibleToolTipHelper;
import org.xmind.gef.part.GraphicalEditPart;
import org.xmind.gef.part.IGraphicalEditPart;
import org.xmind.gef.part.IGraphicalPart;
import org.xmind.gef.part.IPart;
import org.xmind.gef.status.IStatusMachine;
import org.xmind.gef.tool.AbstractTool;
import org.xmind.gef.tool.IDragDropHandler;
import org.xmind.gef.tool.IGraphicalTool;
import org.xmind.gef.tool.ITool;
/**
* @author Brian Sun
*/
public class PartsEventDispatcher extends ViewerEventDispatcher implements
DropTargetListener {
protected class PartAccessibilityDispatcher extends AccessibilityDispatcher {
private IAccessible get(int childID) {
if (childID == ACC.CHILDID_SELF || childID == ACC.CHILDID_NONE) {
IPart focused = getFocusedPart();
if (focused != null) {
IAccessible acc = (IAccessible) focused
.getAdapter(IAccessible.class);
if (acc != null)
return acc;
}
IPart contents = getViewer().getRootPart().getContents();
if (contents == null)
return null;
return (IAccessible) contents.getAdapter(IAccessible.class);
}
return getViewer().getAccessibleRegistry().getAccessible(childID);
}
public void getChildAtPoint(AccessibleControlEvent e) {
IPart part = findPart(e.x, e.y);
if (part == null)
return;
IAccessible acc = (IAccessible) part.getAdapter(IAccessible.class);
if (acc != null) {
e.childID = acc.getAccessibleId();
}
}
public void getChildCount(AccessibleControlEvent e) {
e.detail = getViewer().getAccessibleRegistry().getNumAccessibles();
}
public void getChildren(AccessibleControlEvent e) {
e.children = getViewer().getAccessibleRegistry()
.getAllAccessibleIDs();
}
public void getDefaultAction(AccessibleControlEvent e) {
IAccessible acc = get(e.childID);
if (acc != null) {
String defaultAction = acc.getDefaultAction();
if (defaultAction != null)
e.result = defaultAction;
}
}
public void getFocus(AccessibleControlEvent e) {
if (control.isFocusControl()) {
IPart focusedPart = getFocusedPart();
if (focusedPart != null) {
IAccessible acc = (IAccessible) focusedPart
.getAdapter(IAccessible.class);
if (acc != null) {
e.childID = acc.getAccessibleId();
return;
}
}
e.childID = ACC.CHILDID_SELF;
} else {
e.childID = ACC.CHILDID_NONE;
}
}
private IPart getFocusedPart() {
Object focused = getViewer().getFocused();
return focused == null ? null : getViewer().getSelectionSupport()
.findSelectablePart(focused);
}
public void getLocation(AccessibleControlEvent e) {
IAccessible acc = get(e.childID);
if (acc != null) {
Rectangle r = acc.getLocation();
if (r != null) {
e.x = r.x;
e.y = r.y;
if (r.width >= 0)
e.width = r.width;
if (r.height >= 0)
e.height = r.height;
}
}
}
public void getRole(AccessibleControlEvent e) {
IAccessible acc = get(e.childID);
if (acc != null) {
int role = acc.getRole();
if (role >= 0) {
e.detail = role;
}
}
}
public void getSelection(AccessibleControlEvent e) {
List<IPart> selectedParts = getViewer().getSelectionSupport()
.getPartSelection();
if (selectedParts.isEmpty()) {
if (getViewer().getControl().isFocusControl()) {
e.childID = ACC.CHILDID_SELF;
} else {
e.childID = ACC.CHILDID_NONE;
}
return;
}
List<Integer> childIds = new ArrayList<Integer>(
selectedParts.size());
for (IPart p : selectedParts) {
IAccessible acc = (IAccessible) p.getAdapter(IAccessible.class);
if (acc != null) {
childIds.add(acc.getAccessibleId());
}
}
if (childIds.isEmpty()) {
e.childID = ACC.CHILDID_NONE;
} else {
e.childID = ACC.CHILDID_MULTIPLE;
e.children = childIds.toArray();
}
}
public void getState(AccessibleControlEvent e) {
IAccessible acc = get(e.childID);
if (acc != null) {
int state = acc.getState();
if (state >= 0) {
e.detail = state;
}
}
}
public void getValue(AccessibleControlEvent e) {
IAccessible acc = get(e.childID);
if (acc != null) {
String value = acc.getValue();
if (value != null) {
e.result = value;
}
}
}
public void getDescription(AccessibleEvent e) {
IAccessible acc = get(e.childID);
if (acc != null) {
String description = acc.getDescription();
if (description != null) {
e.result = description;
}
}
}
public void getHelp(AccessibleEvent e) {
IAccessible acc = get(e.childID);
if (acc != null) {
String help = acc.getHelp();
if (help != null) {
e.result = help;
}
}
}
public void getKeyboardShortcut(AccessibleEvent e) {
IAccessible acc = get(e.childID);
if (acc != null) {
String keyboardShortcut = acc.getKeyboardShortcut();
if (keyboardShortcut != null)
e.result = keyboardShortcut;
}
}
public void getName(AccessibleEvent e) {
IAccessible acc = get(e.childID);
if (acc != null) {
String name = acc.getName();
if (name != null) {
e.result = name;
}
}
}
}
private static int LONG_PRESSING_ACTIVATION_TIME = 500;
private ToolTipHelper toolTipHelper;
private Shell shell = null;
private DropTarget dropTarget = null;
private boolean ignoreDoubleClicking = false;
private boolean ignoreLongPressing = false;
private boolean ignoreDragging = false;
private boolean ignoreNextMouseUp = false;
private MouseDragEvent lastDragEvent = null;
private MouseEvent currentMouseEvent = null;
private DragDropEvent currentDropEvent = null;
private IDragDropHandler dropHandler = null;
private int pressedMouseButton = 0;
private PartAccessibilityDispatcher accDispatcher = null;
private PropertyChangeListener viewportScrollListener = null;
private RangeModel horizontalRangeModel = null;
private RangeModel verticalRangeModel = null;
private boolean mouseHovering = false;
/**
* @param domain
*/
public PartsEventDispatcher(IGraphicalViewer viewer) {
super(viewer);
}
public EditDomain getDomain() {
return getViewer().getEditDomain();
}
protected void onActivated() {
super.onActivated();
setIgnoreDoubleClicking(false);
}
protected void onDeactivated() {
hideToolTip();
cancelLongPressing();
lastDragEvent = null;
currentMouseEvent = null;
currentDropEvent = null;
dropHandler = null;
setIgnoreDoubleClicking(true);
}
@Override
public void setControl(Control c) {
if (c == control)
return;
if (control != null && !control.isDisposed())
throw new RuntimeException(
"Can not set control again once it has been set"); //$NON-NLS-1$
if (c != null)
c.addDisposeListener(new org.eclipse.swt.events.DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
if (toolTipHelper != null)
toolTipHelper.dispose();
}
});
control = c;
createDropTarget(c);
}
protected void createDropTarget(Control c) {
if (dropTarget != null) {
dropTarget.dispose();
dropTarget = null;
}
if (getDndSupport() != null) {
dropTarget = new DropTarget(c, getDndSupport().getStyle());
dropTarget.setTransfer(getDndSupport().getTransfers());
dropTarget.addDropListener(this);
c.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
disposeDropTarget();
}
});
}
}
/*
* (non-Javadoc)
*
* @see
* org.xmind.gef.event.ViewerEventDispatcher#dndSupportChanged(org.xmind
* .gef.dnd.IDndSupport, org.xmind.gef.dnd.IDndSupport)
*/
@Override
protected void dndSupportChanged(IDndSupport oldDndSupport,
IDndSupport newDndSupport) {
super.dndSupportChanged(oldDndSupport, newDndSupport);
if (control != null && !control.isDisposed()) {
createDropTarget(control);
}
}
protected DropTarget getDropTarget() {
return dropTarget;
}
protected void disposeDropTarget() {
if (dropTarget != null) {
if (!dropTarget.isDisposed()) {
dropTarget.removeDropListener(this);
}
dropTarget.dispose();
dropTarget = null;
}
}
/**
* @param controlX
* @param controlY
* @return
*/
protected Point convertPoint(int controlX, int controlY) {
Point p = new Point(controlX, controlY);
if (getViewer().getControl() != null
&& !getViewer().getControl().isDisposed()) {
// if (isScaleLocation()) {
p = getViewer().computeToLayer(p, true);
// } else {
// p.translate(getViewer().getScrollPosition());
// }
}
return p;
}
/**
* @param me
* @return
*/
protected MouseEvent convertMouse(org.eclipse.swt.events.MouseEvent me) {
Point pos = convertPoint(me.x, me.y);
return MouseEvent.createEvent(me, findPart(me.x, me.y), pos);
}
protected MouseEvent convertMouse(org.eclipse.swt.events.MouseEvent me,
IPart host) {
Point pos = convertPoint(me.x, me.y);
return MouseEvent.createEvent(me, host, pos);
}
/**
* @param me
* @return
*/
protected MouseDragEvent convertDrag(org.eclipse.swt.events.MouseEvent me) {
Point pos = convertPoint(me.x, me.y);
return MouseDragEvent.createEvent(me, lastDragEvent, pos,
findPart(me.x, me.y));
}
protected MouseDragEvent convertDrag(org.eclipse.swt.events.MouseEvent me,
IPart host) {
Point pos = convertPoint(me.x, me.y);
return MouseDragEvent.createEvent(me, lastDragEvent, pos, host);
}
protected MouseDragEvent convertDrag(org.eclipse.swt.events.MouseEvent me,
MouseEvent current) {
return MouseDragEvent.createEvent(me, lastDragEvent,
current.cursorLocation, current.target);
}
/**
* @param ke
* @return
*/
protected KeyEvent convertKey(org.eclipse.swt.events.KeyEvent ke) {
return KeyEvent.createEvent(ke, isImeOpened());
}
protected MouseWheelEvent convertWheel(org.eclipse.swt.widgets.Event e) {
return MouseWheelEvent.createEvent(findPart(e.x, e.y), e);
}
/**
* @param me
* @return
*/
protected MouseDragEvent createDragEvent(
org.eclipse.swt.events.MouseEvent me) {
Point startPoint = convertPoint(me.x, me.y);
return MouseDragEvent.createEvent(me, findPart(me.x, me.y), startPoint);
}
public PartAccessibilityDispatcher getPartAccessibilityDispatcher() {
if (accDispatcher == null)
accDispatcher = new PartAccessibilityDispatcher();
return accDispatcher;
}
@Override
protected AccessibilityDispatcher getAccessibilityDispatcher() {
return getPartAccessibilityDispatcher();
}
protected IPart findPart(int controlX, int controlY) {
IPart part = getViewer().findPart(controlX, controlY);
return part == null ? getViewer().getRootPart() : part;
}
// /**
// * @param position
// */
// protected IPart findPart(Point position) {
// return findPart(getViewer().getRootPart(), position);
// }
//
// protected IPart findPart(IPart parent, Point position) {
// if (parent == null)
// return null;
// if (parent instanceof IGraphicalEditPart) {
// return (((IGraphicalEditPart) parent).findAt(position));
// }
// for (IPart p : parent.getChildren()) {
// IPart ret = findPart(p, position);
// if (ret != null)
// return ret;
// }
// return null;
// }
protected ITool getActiveTool() {
EditDomain domain = getDomain();
return domain != null && !domain.isDisposed() ? domain.getActiveTool()
: null;
}
protected boolean isImeOpened() {
if (shell == null) {
if (control != null & !control.isDisposed()) {
shell = control.getShell();
} else {
Control viewerControl = getViewer().getControl();
if (viewerControl != null && !viewerControl.isDisposed())
shell = viewerControl.getShell();
}
}
return shell == null ? false : shell.getImeInputMode() != SWT.NONE;
}
/**
* @see org.eclipse.draw2d.SWTEventDispatcher#dispatchFocusGained(org.eclipse.swt.events.FocusEvent)
*/
@Override
public void dispatchFocusGained(FocusEvent e) {
if (!isActive())
return;
// super.dispatchFocusGained(e);
ITool tool = getActiveTool();
if (tool != null) {
tool.focusGained(getViewer());
MouseEvent me = currentMouseEvent;
if (me != null) {
updateCursor(me.cursorLocation, me.target);
}
} else {
super.dispatchFocusGained(e);
}
updateFocus();
}
/**
* @see org.eclipse.draw2d.SWTEventDispatcher#dispatchFocusLost(org.eclipse.swt.events.FocusEvent)
*/
@Override
public void dispatchFocusLost(FocusEvent e) {
cancelLongPressing();
if (!isActive())
return;
// super.dispatchFocusLost(e);
ITool tool = getActiveTool();
if (tool != null) {
tool.focusLost(getViewer());
MouseEvent me = currentMouseEvent;
if (me != null) {
updateCursor(me.cursorLocation, me.target);
}
} else {
super.dispatchFocusLost(e);
}
}
/**
* @see org.eclipse.draw2d.SWTEventDispatcher#dispatchKeyPressed(org.eclipse.swt.events.KeyEvent)
*/
@Override
public void dispatchKeyPressed(org.eclipse.swt.events.KeyEvent e) {
if (!isActive())
return;
// super.dispatchKeyPressed(e);
ITool tool = getActiveTool();
if (tool != null) {
KeyEvent ke = convertKey(e);
tool.keyDown(ke, getViewer());
e.doit = !ke.isConsumed();
MouseEvent me = currentMouseEvent;
if (me != null && isValidGraphicalPart(me.target)) {
updateCursor(me.cursorLocation, me.target);
}
} else {
super.dispatchKeyPressed(e);
}
if ((e.keyCode & SWT.ESC) != 0) {
lastDragEvent = null;
}
updateFocus();
}
/**
* @see org.eclipse.draw2d.SWTEventDispatcher#dispatchKeyReleased(org.eclipse.swt.events.KeyEvent)
*/
@Override
public void dispatchKeyReleased(org.eclipse.swt.events.KeyEvent e) {
if (!isActive())
return;
// super.dispatchKeyReleased(e);
ITool tool = getActiveTool();
if (tool != null) {
KeyEvent ke = convertKey(e);
tool.keyUp(ke, getViewer());
e.doit = !ke.isConsumed();
MouseEvent me = currentMouseEvent;
if (me != null && isValidGraphicalPart(me.target)) {
updateCursor(me.cursorLocation, me.target);
}
} else {
super.dispatchKeyReleased(e);
}
updateFocus();
}
/**
* @see org.eclipse.draw2d.SWTEventDispatcher#dispatchKeyTraversed(org.eclipse.swt.events.TraverseEvent)
*/
@Override
public void dispatchKeyTraversed(TraverseEvent e) {
if (!isActive())
return;
// super.dispatchKeyTraversed(e);
ITool tool = getActiveTool();
if (tool != null) {
KeyEvent ke = convertKey(e);
tool.keyTraversed(ke, getViewer());
e.doit = !ke.isConsumed();
e.detail = ke.traverse;
MouseEvent me = currentMouseEvent;
if (me != null && isValidGraphicalPart(me.target)) {
updateCursor(me.cursorLocation, me.target);
}
} else {
super.dispatchKeyTraversed(e);
}
updateFocus();
}
/**
* @see org.eclipse.draw2d.SWTEventDispatcher#dispatchMouseDoubleClicked(org.eclipse.swt.events.MouseEvent)
*/
@Override
public void dispatchMouseDoubleClicked(org.eclipse.swt.events.MouseEvent me) {
if (!isActive())
return;
// super.dispatchMouseDoubleClicked(me);
cancelToolTipShowing();
if (ignoresDoubleClicking()) {
setIgnoreDoubleClicking(false);
return;
}
receive(me);
ITool tool = getActiveTool();
if (tool != null) {
MouseEvent e = currentMouseEvent;
if (tool instanceof IGraphicalTool) {
((IGraphicalTool) tool).setCursorPosition(e.cursorLocation);
}
tool.mouseDoubleClick(e, getViewer());
updateCursor(e.cursorLocation, e.target);
ignoreDragging = e.isConsumed() && pressedMouseButton != 0;
} else {
super.dispatchMouseDoubleClicked(me);
}
updateFocus();
}
/**
* @see org.eclipse.draw2d.SWTEventDispatcher#dispatchMouseEntered(org.eclipse.swt.events.MouseEvent)
*/
@Override
public void dispatchMouseEntered(org.eclipse.swt.events.MouseEvent me) {
if (!isActive())
return;
// super.dispatchMouseEntered(me);
mouseHovering = false;
hookScrollBars();
cancelToolTipShowing();
receive(me);
ITool tool = getActiveTool();
if (tool != null) {
MouseEvent e = currentMouseEvent;
if (tool instanceof IGraphicalTool) {
((IGraphicalTool) tool).setCursorPosition(e.cursorLocation);
}
tool.mouseEntered(e, getViewer());
updateCursor(e.cursorLocation, e.target);
} else {
super.dispatchMouseEntered(me);
}
updateFocus();
}
/**
* @see org.eclipse.draw2d.SWTEventDispatcher#dispatchMouseExited(org.eclipse.swt.events.MouseEvent)
*/
@Override
public void dispatchMouseExited(org.eclipse.swt.events.MouseEvent me) {
unhookScrollBars();
if (!isActive())
return;
// super.dispatchMouseExited(me);
mouseHovering = false;
cancelToolTipShowing();
hideToolTip();
receive(me);
ITool tool = getActiveTool();
if (tool != null) {
MouseEvent e = currentMouseEvent;
if (tool instanceof IGraphicalTool) {
((IGraphicalTool) tool).setCursorPosition(e.cursorLocation);
}
tool.mouseExited(e, getViewer());
updateCursor(e.cursorLocation, e.target);
} else {
super.dispatchMouseExited(me);
}
updateFocus();
}
private void hookScrollBars() {
Viewport viewport = getViewer().getCanvas().getViewport();
horizontalRangeModel = viewport.getHorizontalRangeModel();
horizontalRangeModel
.addPropertyChangeListener(getViewportScrollListener());
verticalRangeModel = viewport.getVerticalRangeModel();
verticalRangeModel
.addPropertyChangeListener(getViewportScrollListener());
}
private void unhookScrollBars() {
if (horizontalRangeModel != null) {
horizontalRangeModel
.removePropertyChangeListener(getViewportScrollListener());
horizontalRangeModel = null;
}
if (verticalRangeModel != null) {
verticalRangeModel
.removePropertyChangeListener(getViewportScrollListener());
verticalRangeModel = null;
}
}
private PropertyChangeListener getViewportScrollListener() {
if (viewportScrollListener == null) {
viewportScrollListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
dispatchViewerScrolled(evt);
}
};
}
return viewportScrollListener;
}
protected void dispatchViewerScrolled(PropertyChangeEvent evt) {
if (lastDragEvent != null
|| currentDropEvent != null
|| Boolean.TRUE.equals(getViewer().getProperties().get(
IGraphicalViewer.VIEWER_IGNORE_SCROLL_EVENT)))
return;
Display currentDisplay = Display.getCurrent();
org.eclipse.swt.graphics.Point loc = currentDisplay.getCursorLocation();
loc = control.toControl(loc);
org.eclipse.swt.graphics.Rectangle bounds = control.getBounds();
if (bounds.contains(loc)) {
org.eclipse.swt.widgets.Event event = new org.eclipse.swt.widgets.Event();
org.eclipse.swt.events.MouseEvent last = currentMouseEvent == null ? null
: currentMouseEvent.currentSWTEvent;
if (last != null) {
event.button = last.button;
event.count = last.count;
event.data = last.data;
event.display = last.display;
event.stateMask = last.stateMask;
event.widget = last.widget;
} else {
event.display = currentDisplay;
event.widget = control;
}
event.time = (int) System.currentTimeMillis();
event.x = loc.x;
event.y = loc.y;
dispatchMouseMoved(new org.eclipse.swt.events.MouseEvent(event));
}
}
/**
* @see org.eclipse.draw2d.SWTEventDispatcher#dispatchMouseHover(org.eclipse.swt.events.MouseEvent)
*/
@Override
public void dispatchMouseHover(org.eclipse.swt.events.MouseEvent me) {
if (!isActive())
return;
// super.dispatchMouseHover(me);
mouseHovering = true;
cancelToolTipShowing();
receive(me);
ITool tool = getActiveTool();
if (tool != null) {
MouseEvent e = currentMouseEvent;
if (tool instanceof IGraphicalTool) {
((IGraphicalTool) tool).setCursorPosition(e.cursorLocation);
}
tool.mouseHover(e, getViewer());
updateCursor(e.cursorLocation, e.target);
updateToolTip(e);
} else {
super.dispatchMouseHover(me);
}
updateFocus();
}
public void cancelToolTipShowing() {
// if ( tooltipTimer != null ) {
// tooltipTimer.cancel();
// tooltipTimer = null;
// }
}
public void updateToolTip() {
if (control == null || control.isDisposed())
return;
hideToolTip();
if (mouseHovering && currentMouseEvent != null) {
updateToolTip(currentMouseEvent, false);
}
}
protected void updateToolTip(MouseEvent me, boolean useEventTarget) {
Point cp = null;
org.eclipse.swt.events.MouseEvent e = me.getCurrentSWTEvent();
if (e != null) {
cp = new Point(e.x, e.y);
} else {
cp = getViewer().computeToControl(me.cursorLocation, true);
}
IPart target = useEventTarget ? me.target : findPart(cp.x, cp.y);
if (target != null && target instanceof IGraphicalPart) {
ITool tool = getActiveTool();
IFigure tooltip = null;
if (tool instanceof IGraphicalTool) {
tooltip = ((IGraphicalTool) tool).getToolTip(target,
me.cursorLocation);
}
if (tooltip == null && target instanceof IGraphicalEditPart) {
tooltip = ((IGraphicalEditPart) target)
.findTooltipAt(me.cursorLocation);
}
if (tooltip != null) {
Point absolute = new Point(control.toDisplay(cp.x, cp.y));
getToolTipHelper().displayToolTipNear(
((IGraphicalPart) target).getFigure(), tooltip,
absolute.x, absolute.y);
return;
}
}
hideToolTip();
}
protected ToolTipHelper getToolTipHelper() {
if (toolTipHelper == null) {
if (currentMouseEvent != null) {
IPart target = currentMouseEvent.target;
if (target != null && target instanceof GraphicalEditPart) {
String actionId = ((GraphicalEditPart) target)
.getActionId();
if (actionId != null
&& (actionId.equals("org.xmind.ui.editNotes") || actionId //$NON-NLS-1$
.equals("org.xmind.ui.editComments"))) { //$NON-NLS-1$
toolTipHelper = new KeepVisibleToolTipHelper(control);
} else {
toolTipHelper = new ToolTipHelper(control);
}
}
}
} else {
if (currentMouseEvent != null) {
IPart target = currentMouseEvent.target;
if (target != null && target instanceof GraphicalEditPart) {
String actionId = ((GraphicalEditPart) target)
.getActionId();
if (actionId != null
&& (actionId.equals("org.xmind.ui.editNotes") || actionId //$NON-NLS-1$
.equals("org.xmind.ui.editComments"))) { //$NON-NLS-1$
if (!(toolTipHelper instanceof KeepVisibleToolTipHelper)) {
toolTipHelper.dispose();
toolTipHelper = new KeepVisibleToolTipHelper(
control);
}
} else {
if (toolTipHelper instanceof KeepVisibleToolTipHelper) {
toolTipHelper.dispose();
toolTipHelper = new ToolTipHelper(control);
}
}
}
}
}
if (toolTipHelper == null) {
toolTipHelper = new ToolTipHelper(control);
}
return toolTipHelper;
}
/**
* @param me
*/
protected void updateToolTip(MouseEvent me) {
updateToolTip(me, true);
}
protected boolean isValidGraphicalPart(IPart host) {
return host != null && host instanceof IGraphicalPart
&& host.getStatus().isActive();
}
protected void updateFocus() {
IFigure focusableFigure = null;
IPart focusedPart = getViewer().getFocusedPart();
if (focusedPart instanceof IGraphicalPart) {
IFigure fig = ((IGraphicalPart) focusedPart).getFigure();
if (fig.isRequestFocusEnabled()) {
focusableFigure = fig;
}
}
setFocus(focusableFigure);
}
/**
* @see org.eclipse.draw2d.SWTEventDispatcher#dispatchMouseMoved(org.eclipse.swt.events.MouseEvent)
*/
@Override
public void dispatchMouseMoved(org.eclipse.swt.events.MouseEvent me) {
if (!isActive())
return;
/*
* IMPORTANT: IF brainy is running on JDK 1.6beta, the sentence below
* will fix a huge bug.
*/
if (me.x > 0x8fff) {
me.x -= 65536;
}
/* IMPORTANT: end IF. */
// super.dispatchMouseMoved(me);
mouseHovering = false;
cancelToolTipShowing();
receive(me);
ITool tool = getActiveTool();
if (tool != null) {
MouseEvent e = currentMouseEvent;
if (tool instanceof IGraphicalTool) {
((IGraphicalTool) tool).setCursorPosition(e.cursorLocation);
}
if ((me.stateMask & SWT.BUTTON_MASK) != 0 && lastDragEvent != null
&& !ignoreDragging) {
lastDragEvent = convertDrag(me, e);
tool.mouseDrag(lastDragEvent, getViewer());
} else if ((me.stateMask & SWT.BUTTON_MASK) == 0) {
tool.mouseMove(e, getViewer());
}
updateCursor(e.cursorLocation, e.target);
if (getToolTipHelper().isShowing())
updateToolTip(e);
} else {
super.dispatchMouseMoved(me);
}
updateFocus();
}
private void receive(org.eclipse.swt.events.MouseEvent me) {
readStateMask(me);
MouseEvent current = convertMouse(me);
ITool tool;
if (currentMouseEvent == null
|| current.target != currentMouseEvent.target) {
if (currentMouseEvent != null) {
tool = getActiveTool();
if (tool != null)
tool.mouseExited(currentMouseEvent, getViewer());
hideToolTip();
}
if (current.target != null) {
tool = getActiveTool();
if (tool != null)
tool.mouseEntered(current, getViewer());
}
}
currentMouseEvent = current;
}
protected void readStateMask(org.eclipse.swt.events.MouseEvent me) {
ITool tool = getActiveTool();
if (tool != null && tool instanceof AbstractTool) {
IStatusMachine statusMachine = ((AbstractTool) tool).getStatus();
int stateMask = me.stateMask;
statusMachine.setStatus(GEF.ST_CONTROL_PRESSED,
(stateMask & SWT.MOD1) != 0);
statusMachine.setStatus(GEF.ST_SHIFT_PRESSED,
(stateMask & SWT.MOD2) != 0);
statusMachine.setStatus(GEF.ST_ALT_PRESSED,
(stateMask & SWT.MOD3) != 0);
}
}
/**
*
*/
public void hideToolTip() {
if (control != null && !control.isDisposed()) {
getToolTipHelper().updateToolTip(null, null, 0, 0);
}
}
/**
* @param pos
* @param host
*/
protected void updateCursor(Point pos, IPart host) {
if (!isActive())
return;
Cursor currentCursor = null;
ITool tool = getActiveTool();
if (tool instanceof IGraphicalTool) {
currentCursor = ((IGraphicalTool) tool).getCurrentCursor(pos, host);
}
if (currentCursor == null && host != null
&& host instanceof IGraphicalEditPart
&& host.getStatus().isActive()) {
currentCursor = ((IGraphicalEditPart) host).getCursor(pos);
}
setCursor(currentCursor);
}
protected int getLongPressingActivationTime() {
return LONG_PRESSING_ACTIVATION_TIME;
}
/**
* @see org.eclipse.draw2d.SWTEventDispatcher#dispatchMousePressed(org.eclipse.swt.events.MouseEvent)
*/
@Override
public void dispatchMousePressed(org.eclipse.swt.events.MouseEvent me) {
pressedMouseButton = me.button;
if (!isActive())
return;
// super.dispatchMousePressed(me);
cancelToolTipShowing();
lastDragEvent = createDragEvent(me);
receive(me);
ITool tool = getActiveTool();
if (tool != null) {
final MouseEvent e = currentMouseEvent;
if (tool instanceof IGraphicalTool) {
((IGraphicalTool) tool).setCursorPosition(e.cursorLocation);
}
tool.mouseDown(e, getViewer());
if (e.isConsumed()) {
ignoreNextMouseUp = true;
}
updateCursor(e.cursorLocation, e.target);
if (getToolTipHelper().isShowing())
updateToolTip(e);
ignoreLongPressing = false;
setIgnoreDoubleClicking(e.isConsumed());
Display.getCurrent().timerExec(getLongPressingActivationTime(),
new Runnable() {
public void run() {
dispatchMouseLongPressed(e);
}
});
} else {
super.dispatchMousePressed(me);
setIgnoreDoubleClicking(getCurrentEvent() != null
&& getCurrentEvent().isConsumed());
}
updateFocus();
}
/**
* @return the mousePressed
*/
public boolean isMousePressed() {
return pressedMouseButton != 0;
}
public int getPressedMouseButton() {
return pressedMouseButton;
}
public boolean ignoresDoubleClicking() {
return ignoreDoubleClicking;
}
public void setIgnoreDoubleClicking(boolean ignore) {
this.ignoreDoubleClicking = ignore;
}
public void cancelLongPressing() {
this.ignoreLongPressing = true;
}
public boolean ignoresLongPressing() {
return ignoreLongPressing;
}
/**
* @param mouseEvent
*/
public void dispatchMouseLongPressed(MouseEvent me) {
if (!isActive())
return;
if (!ignoresLongPressing() && me == currentMouseEvent && me != null
&& !me.isConsumed()) {
ITool tool = getActiveTool();
if (tool != null) {
if (tool instanceof IGraphicalTool) {
((IGraphicalTool) tool)
.setCursorPosition(me.cursorLocation);
}
tool.mouseLongPressed(me, getViewer());
updateCursor(me.cursorLocation, me.target);
}
}
}
/**
* @see org.eclipse.draw2d.SWTEventDispatcher#dispatchMouseReleased(org.eclipse.swt.events.MouseEvent)
*/
@Override
public void dispatchMouseReleased(org.eclipse.swt.events.MouseEvent me) {
if (ignoreNextMouseUp) {
ignoreNextMouseUp = false;
return;
}
pressedMouseButton = 0;
ignoreDragging = false;
if (!isActive())
return;
// super.dispatchMouseReleased(me);
cancelToolTipShowing();
lastDragEvent = null;
receive(me);
ITool tool = getActiveTool();
if (tool != null) {
MouseEvent e = currentMouseEvent;
if (tool instanceof IGraphicalTool) {
((IGraphicalTool) tool).setCursorPosition(e.cursorLocation);
}
tool.mouseUp(e, getViewer());
updateCursor(e.cursorLocation, e.target);
} else {
super.dispatchMouseReleased(me);
}
updateFocus();
}
/**
* @see org.eclipse.draw2d.EventDispatcher#dispatchMouseWheelScrolled(org.eclipse.swt.widgets.Event)
*/
@Override
public void dispatchMouseWheelScrolled(org.eclipse.swt.widgets.Event event) {
if (!isActive())
return;
// super.dispatchMouseWheelScrolled(event);
cancelToolTipShowing();
ITool tool = getActiveTool();
if (tool != null) {
MouseEvent e = currentMouseEvent;
if (e != null && tool instanceof IGraphicalTool) {
((IGraphicalTool) tool).setCursorPosition(e.cursorLocation);
}
MouseWheelEvent mwe = convertWheel(event);
tool.mouseWheelScrolled(mwe, getViewer());
if (e != null) {
updateCursor(e.cursorLocation, e.target);
}
event.doit = mwe.doIt;
} else {
super.dispatchMouseWheelScrolled(event);
}
}
protected DragDropEvent createDropEvent(DropTargetEvent e, boolean drop) {
TransferData[] dataTypes;
if (drop && e.currentDataType != null) {
dataTypes = new TransferData[] { e.currentDataType };
} else {
dataTypes = e.dataTypes;
}
DndData dndData = getDndSupport().parseData(dataTypes, getDropTarget(),
!drop);
if (dndData == null)
return null;
Point p = new Point(control.toControl(e.x, e.y));
Point location = convertPoint(p.x, p.y);
IPart host = findPart(p.x, p.y);
DragDropEvent event = DragDropEvent.createFrom(e, host, location);
event.dndData = dndData;
IDndClient client = getDndSupport().getDndClient(dndData.clientId);
if (event.detail == DND.DROP_DEFAULT)
event.detail = event.operations;
if ((event.detail & DND.DROP_LINK) != 0
&& !client.canLink(dndData.dataType, getViewer(), location,
host)) {
event.detail &= ~DND.DROP_LINK;
}
if ((event.detail & DND.DROP_MOVE) != 0
&& !client.canMove(dndData.dataType, getViewer(), location,
host)) {
event.detail &= ~DND.DROP_MOVE;
}
if ((event.detail & DND.DROP_COPY) != 0
&& !client.canCopy(dndData.dataType, getViewer(), location,
host)) {
event.detail &= ~DND.DROP_COPY;
}
return event;
}
protected void feedback(DragDropEvent de, DropTargetEvent swtEvent) {
swtEvent.detail = de.detail;
swtEvent.currentDataType = de.dndData.dataType;
updateControl();
}
/**
*
*/
private void updateControl() {
LightweightSystem lws;
if (control instanceof FigureCanvas) {
lws = ((FigureCanvas) control).getLightweightSystem();
} else if (getViewer() instanceof GraphicalViewer) {
lws = ((GraphicalViewer) getViewer()).getLightweightSystem();
} else if (getViewer().getCanvas() != null
&& !getViewer().getCanvas().isDisposed()) {
lws = getViewer().getCanvas().getLightweightSystem();
} else {
return;
}
lws.getUpdateManager().performUpdate();
}
protected IDragDropHandler getDragDropHandler() {
IDragDropHandler handler = null;
ITool tool = getActiveTool();
if (tool instanceof IDragDropHandler) {
handler = (IDragDropHandler) tool;
}
return handler;
}
public void dragEnter(DropTargetEvent event) {
if (!isActive())
return;
dropHandler = null;
currentDropEvent = createDropEvent(event, false);
if (currentDropEvent == null) {
event.detail = DND.DROP_NONE;
return;
}
IDragDropHandler handler = getDragDropHandler();
if (handler != null) {
if (handler instanceof IGraphicalTool) {
((IGraphicalTool) handler)
.setCursorPosition(currentDropEvent.location);
}
handler.dragStarted(currentDropEvent, getViewer());
handler.dragEntered(currentDropEvent, getViewer());
feedback(currentDropEvent, event);
}
}
public void dragLeave(DropTargetEvent event) {
if (!isActive())
return;
if (currentDropEvent == null) {
event.detail = DND.DROP_NONE;
return;
}
final IDragDropHandler handler = getDragDropHandler();
if (handler != null) {
if (handler instanceof IGraphicalTool) {
((IGraphicalTool) handler)
.setCursorPosition(currentDropEvent.location);
}
// The passed-in DropTargetEvent object's contents
// may be invalid, such as position and detail, so we use
// the last DragDropEvent object instead of creating
// a new one, and thus achieve a correct effect that
// the drag operation 'LEAVE' off that every last part
// it ever stayed over.
handler.dragExited(currentDropEvent, getViewer());
handler.dragDismissed(currentDropEvent, getViewer());
feedback(currentDropEvent, event);
dropHandler = handler;
}
}
public void dragOperationChanged(DropTargetEvent event) {
if (!isActive())
return;
currentDropEvent = createDropEvent(event, false);
if (currentDropEvent == null) {
event.detail = DND.DROP_NONE;
return;
}
IDragDropHandler handler = getDragDropHandler();
if (handler != null) {
if (handler instanceof IGraphicalTool) {
((IGraphicalTool) handler)
.setCursorPosition(currentDropEvent.location);
}
handler.dragOperationChanged(currentDropEvent, getViewer());
feedback(currentDropEvent, event);
}
}
public void dragOver(DropTargetEvent event) {
if (!isActive())
return;
DragDropEvent prevDropEvent = currentDropEvent;
currentDropEvent = createDropEvent(event, false);
if (currentDropEvent == null) {
event.detail = DND.DROP_NONE;
return;
}
IDragDropHandler handler = getDragDropHandler();
if (handler != null) {
if (handler instanceof IGraphicalTool) {
((IGraphicalTool) handler)
.setCursorPosition(currentDropEvent.location);
}
// test if the cursor leaves a part and enters another
if (prevDropEvent != null
&& prevDropEvent.target != currentDropEvent.target) {
handler.dragExited(prevDropEvent, getViewer());
handler.dragEntered(currentDropEvent, getViewer());
}
handler.dragOver(currentDropEvent, getViewer());
feedback(currentDropEvent, event);
}
}
public void drop(DropTargetEvent event) {
if (!isActive())
return;
currentDropEvent = createDropEvent(event, true);
if (currentDropEvent == null) {
event.detail = DND.DROP_NONE;
return;
}
IDragDropHandler handler = dropHandler;
if (handler == null)
handler = getDragDropHandler();
if (handler != null) {
if (handler instanceof IGraphicalTool) {
((IGraphicalTool) handler)
.setCursorPosition(currentDropEvent.location);
}
handler.drop(currentDropEvent, getViewer());
feedback(currentDropEvent, event);
dropHandler = null;
}
}
public void dropAccept(DropTargetEvent event) {
if (!isActive())
return;
currentDropEvent = createDropEvent(event, false);
if (currentDropEvent == null) {
event.detail = DND.DROP_NONE;
return;
}
IDragDropHandler handler = dropHandler;
if (handler == null)
handler = getDragDropHandler();
if (handler != null) {
if (handler instanceof IGraphicalTool) {
((IGraphicalTool) handler)
.setCursorPosition(currentDropEvent.location);
}
handler.dropAccept(currentDropEvent, getViewer());
feedback(currentDropEvent, event);
}
}
}