//
// MouseHelper.java
//
/*
VisAD system for interactive analysis and visualization of numerical
data. Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/
package visad;
import java.awt.event.*;
import java.rmi.*;
import java.awt.*;
import visad.browser.Convert;
/**
MouseHelper is the VisAD helper class for MouseBehaviorJ3D
and MouseBehaviorJ2D.
MouseHelper is preferred by cats everywhere.
*/
public class MouseHelper
implements RendererSourceListener
{
MouseBehavior behavior;
/** DisplayRenderer for Display */
DisplayRenderer display_renderer;
/** Display */
DisplayImpl display;
/** ProjectionControl for Display */
private ProjectionControl proj;
/** DataRenderer for direct manipulation */
protected DataRenderer direct_renderer = null;
/** matrix from ProjectionControl when mousePressed1 (left) */
protected double[] tstart;
/** screen location when mousePressed1 or mousePressed3 */
protected int start_x, start_y;
protected double xmul, ymul;
protected double xymul;
//protected double[] xtrans = new double[3];
//protected double[] ytrans = new double[3];
/** mouse in window (not used) */
private boolean mouseEntered;
/** ((InputEvent) event).getModifiers() when mouse pressed */
protected int mouseModifiers;
/** flag for 2-D mode */
private boolean mode2D;
// start of variables for table-driven mapping from mouse buttons and
// keys to functons
// index values for functions
public static final int NONE = -1, ROTATE = 0, ZOOM = 1, TRANSLATE = 2,
CURSOR_TRANSLATE = 3, CURSOR_ZOOM = 4, CURSOR_ROTATE = 5, DIRECT = 6;
/* Number of functions */
//protected int NFUNCTIONS = 7;
// index values for mouse buttons
public static final int LEFT = 0, CENTER = 1, RIGHT = 2;
// actual mouse buttons pressed
protected boolean[] actual_button = {false, false, false};
// mouse button pressed accounting for combos
protected int virtual_button = -1;
// array of enables for functions
protected boolean[] function = {false, false, false, false, false, false, false};
// save previous function to compute function change
protected boolean[] old_function = {false, false, false, false, false, false, false};
// enable any two mouse buttons = the third
private boolean enable_combos = true;
// mapping from buttons/keys to function
// function_map[button][CTRL][SHIFT] where
// button = 0, 1, 2
// CTRL = 0, 1
// SHIFT = 0, 1
// initialize with defaults
int[][][] function_map =
{{{ROTATE, ZOOM}, {TRANSLATE, NONE}},
{{CURSOR_TRANSLATE, CURSOR_ZOOM}, {CURSOR_ROTATE, NONE}},
{{DIRECT, DIRECT}, {DIRECT, DIRECT}}};
// end of variables for table-driven mapping from mouse buttons
// and keys to functons
public MouseHelper(DisplayRenderer r, MouseBehavior b) {
behavior = b;
display_renderer = r;
display = display_renderer.getDisplay();
proj = display.getProjectionControl();
mode2D = display_renderer.getMode2D();
// track Display's DataRenderers in case direct_renderer is removed
display.addRendererSourceListener(this);
//function =
// new boolean[] {false, false, false, false, false, false, false};
//enable_combos = true;
}
/**
* Get the MouseBehavior for this Helper
* @return MouseBehavior
*/
public MouseBehavior getMouseBehavior() { return behavior; }
/**
* Get the Display for this Helper
* @return Display
*/
public DisplayImpl getDisplay() { return display; }
/**
* Get the DisplayRenderer for this Helper
* @return DisplayRenderer
*/
public DisplayRenderer getDisplayRenderer() { return display_renderer; }
/**
* Get the ProjectionControl for this Helper
* @return ProjectionControl
*/
public ProjectionControl getProjectionControl() { return proj; }
/**
* Get whether we're in 2D mode
* @return true if 2D mode
*/
public boolean getMode2D() { return mode2D; }
/**
* Process the given event treating it as a local event.
* @param event event to process.
*/
public void processEvent(AWTEvent event) {
processEvent(event, VisADEvent.LOCAL_SOURCE);
}
// WLH 17 Aug 2000 (no longer used)
private boolean first = true;
/**
* Process the given event, treating it as coming from a remote source
* if remote flag is set.
* @param event event to process.
* @param remoteId id of remote source.
*/
public void processEvent(AWTEvent event, int remoteId) {
if (getMouseBehavior() == null) return;
// WLH 13 May 2003
// if (first) {
if (event instanceof MouseEvent &&
((MouseEvent) event).getID() == MouseEvent.MOUSE_PRESSED) {
start_x = 0;
start_y = 0;
VisADRay start_ray = getMouseBehavior().findRay(start_x, start_y);
VisADRay start_ray_x = getMouseBehavior().findRay(start_x + 1, start_y);
VisADRay start_ray_y = getMouseBehavior().findRay(start_x, start_y + 1);
if (start_ray != null && start_ray_x != null && start_ray_y != null) {
double[] tstart = getProjectionControl().getMatrix();
double[] rot = new double[3];
double[] scale = new double[3];
double[] trans = new double[3];
getMouseBehavior().instance_unmake_matrix(rot, scale, trans, tstart);
double[] trot = getMouseBehavior().make_matrix(rot[0], rot[1], rot[2],
scale[0], scale[1], scale[2],
0.0, 0.0, 0.0);
double[] xmat = getMouseBehavior().make_translate(
start_ray_x.position[0] - start_ray.position[0],
start_ray_x.position[1] - start_ray.position[1],
start_ray_x.position[2] - start_ray.position[2]);
double[] ymat = getMouseBehavior().make_translate(
start_ray_y.position[0] - start_ray.position[0],
start_ray_y.position[1] - start_ray.position[1],
start_ray_y.position[2] - start_ray.position[2]);
double[] xmatmul = getMouseBehavior().multiply_matrix(trot, xmat);
double[] ymatmul = getMouseBehavior().multiply_matrix(trot, ymat);
getMouseBehavior().instance_unmake_matrix(rot, scale, trans, xmatmul);
//double xmul = trans[0];
xmul = trans[0];
getMouseBehavior().instance_unmake_matrix(rot, scale, trans, ymatmul);
//double ymul = trans[1];
ymul = trans[1];
xymul = Math.sqrt(xmul * xmul + ymul * ymul);
// System.out.println("xymul = " + xymul);
first = false;
}
}
if (!(event instanceof MouseEvent)) {
System.out.println("MouseHelper.processStimulus: non-MouseEvent");
return;
}
MouseEvent mouse_event = (MouseEvent) event;
int event_id = event.getID();
if (event_id == MouseEvent.MOUSE_ENTERED) {
mouseEntered = true;
try {
DisplayEvent e = new DisplayEvent(getDisplay(),
DisplayEvent.MOUSE_ENTERED, mouse_event, remoteId);
getDisplay().notifyListeners(e);
}
catch (VisADException e) {
}
catch (RemoteException e) {
}
return;
}
else if (event_id == MouseEvent.MOUSE_EXITED) {
mouseEntered = false;
try {
DisplayEvent e = new DisplayEvent(getDisplay(),
DisplayEvent.MOUSE_EXITED, mouse_event, remoteId);
getDisplay().notifyListeners(e);
}
catch (VisADException e) {
}
catch (RemoteException e) {
}
return;
}
else if (event_id == MouseEvent.MOUSE_MOVED) {
try {
DisplayEvent e = new DisplayEvent(getDisplay(),
DisplayEvent.MOUSE_MOVED, mouse_event, remoteId);
getDisplay().notifyListeners(e);
}
catch (VisADException e) {
}
catch (RemoteException e) {
}
return;
}
else if (event_id == MouseEvent.MOUSE_PRESSED ||
event_id == MouseEvent.MOUSE_RELEASED) {
int m = ((InputEvent) event).getModifiers();
int m1 = m & InputEvent.BUTTON1_MASK;
int m2 = m & InputEvent.BUTTON2_MASK;
int m3 = m & InputEvent.BUTTON3_MASK;
int mctrl = m & InputEvent.CTRL_MASK;
int mshift = m & InputEvent.SHIFT_MASK;
if (event_id == MouseEvent.MOUSE_PRESSED) {
getDisplay().updateBusyStatus();
if (m1 != 0) {
actual_button[LEFT] = true;
}
if (m2 != 0) {
actual_button[CENTER] = true;
}
if (m3 != 0) {
actual_button[RIGHT] = true;
}
mouseModifiers = m;
}
else { // event_id == MouseEvent.MOUSE_RELEASED
getDisplay().updateBusyStatus();
if (m1 != 0) {
actual_button[LEFT] = false;
}
if (m2 != 0) {
actual_button[CENTER] = false;
}
if (m3 != 0) {
actual_button[RIGHT] = false;
}
mouseModifiers = 0;
}
// compute button combos
int n = 0, sum = 0;
for (int i=0; i<3; i++) {
if (actual_button[i]) {
n++;
sum += i;
}
}
if (n == 1) {
virtual_button = sum;
}
else if (n == 2 && getEnableCombos()) {
virtual_button = 3 - sum;
}
else { // n == 0 || n == 3 || (n == 2 && !getEnableCombos())
virtual_button = -1;
}
// compute old and new functions
for (int i=0; i= 0) function[f] = true;
boolean cursor_off = enableFunctions((MouseEvent) event);
if (event_id == MouseEvent.MOUSE_PRESSED) {
try {
DisplayEvent e = new DisplayEvent(getDisplay(),
DisplayEvent.MOUSE_PRESSED, mouse_event, remoteId);
getDisplay().notifyListeners(e);
}
catch (VisADException e) {
}
catch (RemoteException e) {
}
if (m1 != 0) {
try {
DisplayEvent e = new DisplayEvent(getDisplay(),
DisplayEvent.MOUSE_PRESSED_LEFT, mouse_event, remoteId);
getDisplay().notifyListeners(e);
}
catch (VisADException e) {
}
catch (RemoteException e) {
}
}
if (m2 != 0) {
try {
DisplayEvent e = new DisplayEvent(getDisplay(),
DisplayEvent.MOUSE_PRESSED_CENTER, mouse_event, remoteId);
getDisplay().notifyListeners(e);
}
catch (VisADException e) {
}
catch (RemoteException e) {
}
}
if (m3 != 0) {
try {
DisplayEvent e = new DisplayEvent(getDisplay(),
DisplayEvent.MOUSE_PRESSED_RIGHT, mouse_event, remoteId);
getDisplay().notifyListeners(e);
}
catch (VisADException e) {
}
catch (RemoteException e) {
}
}
}
else { // event_id == MouseEvent.MOUSE_RELEASED
try {
DisplayEvent e = new DisplayEvent(getDisplay(),
DisplayEvent.MOUSE_RELEASED, mouse_event, remoteId);
getDisplay().notifyListeners(e);
}
catch (VisADException e) {
}
catch (RemoteException e) {
}
if (m1 != 0) {
try {
DisplayEvent e = new DisplayEvent(getDisplay(),
DisplayEvent.MOUSE_RELEASED_LEFT, mouse_event, remoteId);
getDisplay().notifyListeners(e);
}
catch (VisADException e) {
}
catch (RemoteException e) {
}
}
if (m2 != 0) {
try {
DisplayEvent e = new DisplayEvent(getDisplay(),
DisplayEvent.MOUSE_RELEASED_CENTER, mouse_event, remoteId);
getDisplay().notifyListeners(e);
}
catch (VisADException e) {
}
catch (RemoteException e) {
}
}
if (m3 != 0) {
try {
DisplayEvent e = new DisplayEvent(getDisplay(),
DisplayEvent.MOUSE_RELEASED_RIGHT, mouse_event, remoteId);
getDisplay().notifyListeners(e);
}
catch (VisADException e) {
}
catch (RemoteException e) {
}
}
}
if (cursor_off) getDisplayRenderer().setCursorOn(false);
}
else if (event_id == MouseEvent.MOUSE_DRAGGED) {
handleMouseDragged(mouse_event, remoteId);
try {
DisplayEvent e = new DisplayEvent(getDisplay(),
DisplayEvent.MOUSE_DRAGGED, mouse_event, remoteId);
getDisplay().notifyListeners(e);
}
catch (VisADException e) {
}
catch (RemoteException e) {
}
}
}
protected void handleMouseDragged(MouseEvent event, int remoteId) {
MouseBehavior mouseBehavior = getMouseBehavior();
boolean cursor = function[CURSOR_TRANSLATE] ||
function[CURSOR_ZOOM] ||
function[CURSOR_ROTATE];
boolean matrix = function[ROTATE] ||
function[ZOOM] ||
function[TRANSLATE];
if (cursor || matrix || function[DIRECT]) {
getDisplay().updateBusyStatus();
Dimension d = event.getComponent().getSize();
int current_x = event.getX();
int current_y = event.getY();
if (matrix) {
double[] t1 = null;
double[] t2 = null;
if (function[ZOOM]) {
// current_y -> scale
double scale =
Math.exp((start_y-current_y) / (double) d.height);
t1 = getMouseBehavior().make_matrix(0.0, 0.0, 0.0, scale, 0.0, 0.0, 0.0);
}
if (function[TRANSLATE]) {
// current_x, current_y -> translate
// WLH 9 Aug 2000
double transx = xmul * (start_x - current_x);
double transy = ymul * (start_y - current_y);
// System.out.println("xmul = " + xmul + " ymul = " + ymul);
// System.out.println("transx = " + transx + " transy = " + transy);
t1 = getMouseBehavior().make_translate(-transx, -transy);
}
double [] myMatrix = tstart;
if (function[ROTATE]) {
if (getMode2D()) {
double transx = xmul * (start_x - current_x);
double transy = ymul * (start_y - current_y);
t1 = getMouseBehavior().make_translate(-transx, -transy);
}
else {
// don't do 3-D rotation in 2-D mode
double angley =
- (current_x - start_x) * 100.0 / (double) d.width;
double anglex =
- (current_y - start_y) * 100.0 / (double) d.height;
double[] transA = { 0.0, 0.0, 0.0 };
double[] rotA = { 0.0, 0.0, 0.0 };
double[] scaleA = { 0.0, 0.0, 0.0 };
mouseBehavior.instance_unmake_matrix(rotA, scaleA, transA, myMatrix);
if(display_renderer.getScaleRotation()) {
angley = angley/scaleA[0];
anglex = anglex/scaleA[0];
}
if(display_renderer.getRotateAboutCenter()) {
myMatrix = mouseBehavior.multiply_matrix(mouseBehavior.make_translate(-transA[0], -transA[1], -transA[2]), myMatrix);
t2 = mouseBehavior.make_translate(transA[0], transA[1], transA[2]);
}
t1 = mouseBehavior.make_matrix(anglex, angley,
0.0, 1.0, 0.0, 0.0, 0.0);
}
}
if (t1 != null) {
t1 = mouseBehavior.multiply_matrix(t1, myMatrix);
if(t2!=null) {
t1 = mouseBehavior.multiply_matrix(t2,t1);
}
try {
getProjectionControl().setMatrix(t1);
} catch (VisADException e) {}
catch (RemoteException e) {}
}
return;
} // end if (matrix)
if (function[CURSOR_ZOOM]) {
if (!getMode2D()) {
// don't do cursor Z in 2-D mode
// current_y -> 3-D cursor Z
float diff =
(start_y - current_y) * 4.0f / (float) d.height;
getDisplayRenderer().drag_depth(diff);
}
}
if (function[CURSOR_ROTATE]) {
if (!getMode2D()) {
// don't do 3-D rotation in 2-D mode
double angley =
- (current_x - start_x) * 100.0 / (double) d.width;
double anglex =
- (current_y - start_y) * 100.0 / (double) d.height;
double[] t1 = getMouseBehavior().make_matrix(anglex, angley,
0.0, 1.0, 0.0, 0.0, 0.0);
t1 = getMouseBehavior().multiply_matrix(t1, tstart);
try {
getProjectionControl().setMatrix(t1);
}
catch (VisADException e) {
}
catch (RemoteException e) {
}
}
}
if(function[CURSOR_TRANSLATE]) {
// current_x, current_y -> 3-D cursor X and Y
VisADRay cursor_ray = getMouseBehavior().findRay(current_x, current_y);
if (cursor_ray != null) {
getDisplayRenderer().drag_cursor(cursor_ray, false);
}
}
if (function[DIRECT]) {
if (direct_renderer != null) {
VisADRay direct_ray = getMouseBehavior().findRay(current_x, current_y);
if (direct_ray != null) {
direct_renderer.setLastMouseModifiers(mouseModifiers);
direct_renderer.drag_direct(direct_ray, false, mouseModifiers);
}
}
}
}
}
/**
* Enable the functions for this mouse helper
* @param event The MouseEvent
*/
protected boolean enableFunctions(MouseEvent event) {
boolean cursor_off = false;
if (event == null) {
for (int i=0; i= function.length) {
throw new DisplayException("bad map array value: " + map[i][j][k]);
}
}
}
}
for (int i=0; i<3; i++) {
for (int j=0; j<2; j++) {
for (int k=0; k<2; k++) {
function_map[i][j][k] = map[i][j][k];
}
}
}
enableFunctions(null);
}
/**
* Print out a readable form of a matrix. Useful for
* debugging.
* @param title title to prepend to output.
* @param m matrix to print.
*/
public void print_matrix(String title, double[] m) {
if (getMouseBehavior() == null) return;
double[] rot = new double[3];
double[] scale = new double[3];
double[] trans = new double[3];
getMouseBehavior().instance_unmake_matrix(rot, scale, trans, m);
StringBuffer buf = new StringBuffer(title);
buf.append(" = (");
buf.append(Convert.shortString(rot[0]));
buf.append(", ");
buf.append(Convert.shortString(rot[1]));
buf.append(", ");
buf.append(Convert.shortString(rot[2]));
buf.append("), ");
if (scale[0] == scale[1] && scale[0] == scale[2]) {
buf.append(Convert.shortString(scale[0]));
buf.append(", (");
} else {
buf.append("(");
buf.append(Convert.shortString(scale[0]));
buf.append(", ");
buf.append(Convert.shortString(scale[1]));
buf.append(", ");
buf.append(Convert.shortString(scale[2]));
buf.append("), (");
}
buf.append(Convert.shortString(trans[0]));
buf.append(", ");
buf.append(Convert.shortString(trans[1]));
buf.append(", ");
buf.append(Convert.shortString(trans[2]));
buf.append(")");
System.out.println(buf.toString());
}
/**
* Implementation for RendererSourceListener. Notifies that the
* renderer has been deleted.
* @param renderer DataRenderer that was deleted.
*/
public void rendererDeleted(DataRenderer renderer)
{
if (direct_renderer != null) {
if (direct_renderer == renderer || direct_renderer.equals(renderer)) {
direct_renderer = null;
}
}
}
}
Ads help maintain this website.