X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Felement%2Fhandler%2Fimpl%2FAbstractClickable.java;h=d3d3946860fb27bfce561889d9423aa3086390d6;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hp=ecd1d4c22b79ccbd6490b69752770cdc66cdbf01;hpb=24e2b34260f219f0d1644ca7a138894980e25b14;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/element/handler/impl/AbstractClickable.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/element/handler/impl/AbstractClickable.java index ecd1d4c22..d3d394686 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/element/handler/impl/AbstractClickable.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/element/handler/impl/AbstractClickable.java @@ -1,198 +1,198 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * 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: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.g2d.element.handler.impl; - -import java.awt.geom.Point2D; -import java.lang.reflect.Method; -import java.util.Map; - -import org.simantics.g2d.canvas.ICanvasContext; -import org.simantics.g2d.diagram.participant.DiagramParticipant; -import org.simantics.g2d.element.ElementUtils; -import org.simantics.g2d.element.IElement; -import org.simantics.g2d.element.handler.Clickable; -import org.simantics.scenegraph.g2d.events.MouseEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseExitEvent; -import org.simantics.utils.datastructures.hints.IHintContext.Key; -import org.simantics.utils.datastructures.hints.IHintContext.KeyOf; -import org.simantics.utils.threads.Executable; -import org.simantics.utils.threads.IThreadWorkQueue; -import org.simantics.utils.threads.SyncListenerList; -import org.simantics.utils.threads.ThreadUtils; - -/** - * Base implementation for button handlers - * - * - * @author Toni Kalajainen - */ -public abstract class AbstractClickable extends AbstractGrabbable implements Clickable { - - private static final long serialVersionUID = -8329973386869163106L; - - public static Key HOVER_KEY = new KeyOf(Boolean.class, "HOVER"); - public static Key PRESS_STATUS_KEY = new KeyOf(PressStatus.class, "PRESS_STATUS"); - - public AbstractClickable(Double strayDistance) { - super(1000.0); - } - - public AbstractClickable() { - super(); - } - - /** - * Get element press status - * @param e - * @param ctx - * @return - */ - public PressStatus getPressStatus(IElement e, ICanvasContext ctx) - { - Map gis = getGrabs(e, ctx); - if (gis==null || gis.size()==0) { - Boolean hover = e.getHint(HOVER_KEY); - if (hover != null && hover) - return PressStatus.HOVER; - return PressStatus.NORMAL; - } - - // is held down - boolean held = false; - boolean pressing = false; - - for (GrabInfo gi : gis.values()) { - held = true; - pressing |= onPickCheck(e, ctx, gi.pointerId, gi.dragPosElement); - if (pressing) break; - } - - if (pressing) return PressStatus.PRESSED; - if (held) return PressStatus.HELD; - Boolean hover = e.getHint(HOVER_KEY); - if (hover != null && hover) - return PressStatus.HOVER; - - return PressStatus.NORMAL; - } - - - @Override - public boolean handleMouseEvent(IElement e, ICanvasContext ctx, - MouseEvent me) { - //System.out.println("AbstractClickable.hME element:" + e + " me:" + me); - boolean b = super.handleMouseEvent(e, ctx, me); - Boolean hovering; - // DND drag starts causes DragBegin + ButtonReleasedEvents, and hovering must be set false - if (!(me instanceof MouseExitEvent || me instanceof MouseDragBegin || me instanceof MouseButtonReleasedEvent)) - hovering = Boolean.valueOf(onPickCheck(e, ctx, me.mouseId, ElementUtils.controlToElementCoordinate(e, ctx, me.controlPosition, null))); - else - hovering = false; - if (!hovering.equals(e.getHint(HOVER_KEY))) { - e.setHint(HOVER_KEY, hovering); - } - - // hackety hack - PressStatus newStatus = getPressStatus(e, ctx); - if (!newStatus.equals(e.getHint(PRESS_STATUS_KEY))) - e.setHint(PRESS_STATUS_KEY, newStatus) ; - return b; - } - - @Override - protected void onDrag(GrabInfo gi, ICanvasContext ctx) { - - } - - @Override - protected void onGrab(GrabInfo gi, ICanvasContext ctx) { - } - - @Override - protected void onGrabCancel(GrabInfo gi, ICanvasContext ctx) { - } - - @Override - protected void onRelease(GrabInfo gi, ICanvasContext ctx) { - // pick is pick until last mouse releases - if (getGrabCount(gi.e, ctx)>0) return; - - boolean pick = onPickCheck(gi.e, ctx, gi.pointerId, gi.dragPosElement); - if (pick) { - onClicked(gi, ctx); - fireClicked(gi.e, ctx); - } - } - - protected boolean onGrabCheck(IElement e, ICanvasContext ctx, int pointerId, Point2D pickPos) - { - Point2D elementPos = ElementUtils.controlToElementCoordinate(e, ctx, pickPos, null); - return onPickCheck(e, ctx, pointerId, elementPos); - } - - protected abstract void onClicked(GrabInfo gi, ICanvasContext ctx); - - /** - * Pick check in element coordinates - * @param e - * @param ctx - * @param pointerId - * @param pickPos - * @return - */ - protected abstract boolean onPickCheck(IElement e, ICanvasContext ctx, int pointerId, Point2D pickPos); - - - private static final Key KEY_CLICK_LISTENERS = new KeyOf(SyncListenerList.class); - - @Override - public void addListener(final IElement e, final ICanvasContext ctx, final IThreadWorkQueue thread, final ClickListener listener) { - ThreadUtils.syncExec(ctx.getThreadAccess(), new Runnable() { - @Override - public void run() { - DiagramParticipant dp = ctx.getSingleItem(DiagramParticipant.class); - SyncListenerList list = dp.getElementHint(e, KEY_CLICK_LISTENERS); - if (list==null) { - list = new SyncListenerList(ClickListener.class); - dp.setElementHint(e, KEY_CLICK_LISTENERS, list); - } - list.add(thread, listener); - }}); - } - - @Override - public void removeListener(final IElement e, final ICanvasContext ctx, final IThreadWorkQueue thread, final ClickListener listener) { - ThreadUtils.syncExec(ctx.getThreadAccess(), new Runnable() { - @Override - public void run() { - DiagramParticipant dp = ctx.getSingleItem(DiagramParticipant.class); - SyncListenerList list = dp.getElementHint(e, KEY_CLICK_LISTENERS); - if (list==null) return; - list.remove(thread, listener); - if (list.isEmpty()) - dp.removeElementHint(e, KEY_CLICK_LISTENERS); - }}); - } - - private final static Method onClick = SyncListenerList.getMethod(ClickListener.class, "onClick"); - public void fireClicked(IElement e, ICanvasContext ctx) - { - DiagramParticipant dp = ctx.getSingleItem(DiagramParticipant.class); - SyncListenerList list = dp.getElementHint(e, KEY_CLICK_LISTENERS); - if (list==null) return; - Executable exes[] = list.getExecutables(onClick, e, ctx); - ThreadUtils.multiSyncExec(exes); - } - -} +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * 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: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.g2d.element.handler.impl; + +import java.awt.geom.Point2D; +import java.lang.reflect.Method; +import java.util.Map; + +import org.simantics.g2d.canvas.ICanvasContext; +import org.simantics.g2d.diagram.participant.DiagramParticipant; +import org.simantics.g2d.element.ElementUtils; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.handler.Clickable; +import org.simantics.scenegraph.g2d.events.MouseEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseExitEvent; +import org.simantics.utils.datastructures.hints.IHintContext.Key; +import org.simantics.utils.datastructures.hints.IHintContext.KeyOf; +import org.simantics.utils.threads.Executable; +import org.simantics.utils.threads.IThreadWorkQueue; +import org.simantics.utils.threads.SyncListenerList; +import org.simantics.utils.threads.ThreadUtils; + +/** + * Base implementation for button handlers + * + * + * @author Toni Kalajainen + */ +public abstract class AbstractClickable extends AbstractGrabbable implements Clickable { + + private static final long serialVersionUID = -8329973386869163106L; + + public static Key HOVER_KEY = new KeyOf(Boolean.class, "HOVER"); + public static Key PRESS_STATUS_KEY = new KeyOf(PressStatus.class, "PRESS_STATUS"); + + public AbstractClickable(Double strayDistance) { + super(1000.0); + } + + public AbstractClickable() { + super(); + } + + /** + * Get element press status + * @param e + * @param ctx + * @return + */ + public PressStatus getPressStatus(IElement e, ICanvasContext ctx) + { + Map gis = getGrabs(e, ctx); + if (gis==null || gis.size()==0) { + Boolean hover = e.getHint(HOVER_KEY); + if (hover != null && hover) + return PressStatus.HOVER; + return PressStatus.NORMAL; + } + + // is held down + boolean held = false; + boolean pressing = false; + + for (GrabInfo gi : gis.values()) { + held = true; + pressing |= onPickCheck(e, ctx, gi.pointerId, gi.dragPosElement); + if (pressing) break; + } + + if (pressing) return PressStatus.PRESSED; + if (held) return PressStatus.HELD; + Boolean hover = e.getHint(HOVER_KEY); + if (hover != null && hover) + return PressStatus.HOVER; + + return PressStatus.NORMAL; + } + + + @Override + public boolean handleMouseEvent(IElement e, ICanvasContext ctx, + MouseEvent me) { + //System.out.println("AbstractClickable.hME element:" + e + " me:" + me); + boolean b = super.handleMouseEvent(e, ctx, me); + Boolean hovering; + // DND drag starts causes DragBegin + ButtonReleasedEvents, and hovering must be set false + if (!(me instanceof MouseExitEvent || me instanceof MouseDragBegin || me instanceof MouseButtonReleasedEvent)) + hovering = Boolean.valueOf(onPickCheck(e, ctx, me.mouseId, ElementUtils.controlToElementCoordinate(e, ctx, me.controlPosition, null))); + else + hovering = false; + if (!hovering.equals(e.getHint(HOVER_KEY))) { + e.setHint(HOVER_KEY, hovering); + } + + // hackety hack + PressStatus newStatus = getPressStatus(e, ctx); + if (!newStatus.equals(e.getHint(PRESS_STATUS_KEY))) + e.setHint(PRESS_STATUS_KEY, newStatus) ; + return b; + } + + @Override + protected void onDrag(GrabInfo gi, ICanvasContext ctx) { + + } + + @Override + protected void onGrab(GrabInfo gi, ICanvasContext ctx) { + } + + @Override + protected void onGrabCancel(GrabInfo gi, ICanvasContext ctx) { + } + + @Override + protected void onRelease(GrabInfo gi, ICanvasContext ctx) { + // pick is pick until last mouse releases + if (getGrabCount(gi.e, ctx)>0) return; + + boolean pick = onPickCheck(gi.e, ctx, gi.pointerId, gi.dragPosElement); + if (pick) { + onClicked(gi, ctx); + fireClicked(gi.e, ctx); + } + } + + protected boolean onGrabCheck(IElement e, ICanvasContext ctx, int pointerId, Point2D pickPos) + { + Point2D elementPos = ElementUtils.controlToElementCoordinate(e, ctx, pickPos, null); + return onPickCheck(e, ctx, pointerId, elementPos); + } + + protected abstract void onClicked(GrabInfo gi, ICanvasContext ctx); + + /** + * Pick check in element coordinates + * @param e + * @param ctx + * @param pointerId + * @param pickPos + * @return + */ + protected abstract boolean onPickCheck(IElement e, ICanvasContext ctx, int pointerId, Point2D pickPos); + + + private static final Key KEY_CLICK_LISTENERS = new KeyOf(SyncListenerList.class); + + @Override + public void addListener(final IElement e, final ICanvasContext ctx, final IThreadWorkQueue thread, final ClickListener listener) { + ThreadUtils.syncExec(ctx.getThreadAccess(), new Runnable() { + @Override + public void run() { + DiagramParticipant dp = ctx.getSingleItem(DiagramParticipant.class); + SyncListenerList list = dp.getElementHint(e, KEY_CLICK_LISTENERS); + if (list==null) { + list = new SyncListenerList(ClickListener.class); + dp.setElementHint(e, KEY_CLICK_LISTENERS, list); + } + list.add(thread, listener); + }}); + } + + @Override + public void removeListener(final IElement e, final ICanvasContext ctx, final IThreadWorkQueue thread, final ClickListener listener) { + ThreadUtils.syncExec(ctx.getThreadAccess(), new Runnable() { + @Override + public void run() { + DiagramParticipant dp = ctx.getSingleItem(DiagramParticipant.class); + SyncListenerList list = dp.getElementHint(e, KEY_CLICK_LISTENERS); + if (list==null) return; + list.remove(thread, listener); + if (list.isEmpty()) + dp.removeElementHint(e, KEY_CLICK_LISTENERS); + }}); + } + + private final static Method onClick = SyncListenerList.getMethod(ClickListener.class, "onClick"); + public void fireClicked(IElement e, ICanvasContext ctx) + { + DiagramParticipant dp = ctx.getSingleItem(DiagramParticipant.class); + SyncListenerList list = dp.getElementHint(e, KEY_CLICK_LISTENERS); + if (list==null) return; + Executable exes[] = list.getExecutables(onClick, e, ctx); + ThreadUtils.multiSyncExec(exes); + } + +}