1 // ******************************************************************************
2 //
3 // Title: Force Field X.
4 // Description: Force Field X - Software for Molecular Biophysics.
5 // Copyright: Copyright (c) Michael J. Schnieders 2001-2025.
6 //
7 // This file is part of Force Field X.
8 //
9 // Force Field X is free software; you can redistribute it and/or modify it
10 // under the terms of the GNU General Public License version 3 as published by
11 // the Free Software Foundation.
12 //
13 // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 // details.
17 //
18 // You should have received a copy of the GNU General Public License along with
19 // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20 // Place, Suite 330, Boston, MA 02111-1307 USA
21 //
22 // Linking this library statically or dynamically with other modules is making a
23 // combined work based on this library. Thus, the terms and conditions of the
24 // GNU General Public License cover the whole combination.
25 //
26 // As a special exception, the copyright holders of this library give you
27 // permission to link this library with independent modules to produce an
28 // executable, regardless of the license terms of these independent modules, and
29 // to copy and distribute the resulting executable under terms of your choice,
30 // provided that you also meet, for each linked independent module, the terms
31 // and conditions of the license of that module. An independent module is a
32 // module which is not derived from or based on this library. If you modify this
33 // library, you may extend this exception to your version of the library, but
34 // you are not obligated to do so. If you do not wish to do so, delete this
35 // exception statement from your version.
36 //
37 // ******************************************************************************
38 package ffx.ui.behaviors;
39
40 import java.awt.AWTEvent;
41 import java.awt.event.MouseEvent;
42 import java.util.Iterator;
43 import org.jogamp.java3d.Behavior;
44 import org.jogamp.java3d.Bounds;
45 import org.jogamp.java3d.BranchGroup;
46 import org.jogamp.java3d.Canvas3D;
47 import org.jogamp.java3d.TransformGroup;
48 import org.jogamp.java3d.WakeupCriterion;
49 import org.jogamp.java3d.WakeupOnAWTEvent;
50 import org.jogamp.java3d.WakeupOr;
51 import org.jogamp.java3d.utils.picking.PickCanvas;
52
53 /**
54 * The PickMouseBehavior class is the base class for mouse picking behaviors.
55 *
56 * @author Michael J. Schnieders
57 */
58 public abstract class PickMouseBehavior extends Behavior {
59
60 static int count = 0;
61 protected PickCanvas pickCanvas;
62 protected WakeupCriterion[] conditions;
63 protected WakeupOr wakeupCondition;
64 protected boolean buttonPress = false;
65 protected boolean shiftButton = false;
66 protected boolean controlButton = false;
67 protected TransformGroup currGrp;
68 protected MouseEvent mevent;
69
70 /**
71 * Creates a PickMouseBehavior given current canvas, root of the tree to operate on, and the
72 * bounds.
73 *
74 * @param canvas a {@link org.jogamp.java3d.Canvas3D} object.
75 * @param root a {@link org.jogamp.java3d.BranchGroup} object.
76 * @param bounds a {@link org.jogamp.java3d.Bounds} object.
77 */
78 public PickMouseBehavior(Canvas3D canvas, BranchGroup root, Bounds bounds) {
79 super();
80 setSchedulingBounds(bounds);
81 currGrp = new TransformGroup();
82 currGrp.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
83 currGrp.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
84 root.addChild(currGrp);
85 pickCanvas = new PickCanvas(canvas, root);
86 pickCanvas.setMode(PickCanvas.GEOMETRY);
87 pickCanvas.setTolerance(10.0f);
88 }
89
90 /** initialize */
91 public void initialize() {
92 conditions = new WakeupCriterion[1];
93 // conditions[0] = new WakeupOnAWTEvent(Event.MOUSE_DOWN);
94 conditions[0] = new WakeupOnAWTEvent(AWTEvent.MOUSE_EVENT_MASK);
95 wakeupCondition = new WakeupOr(conditions);
96 wakeupOn(wakeupCondition);
97 }
98
99 /** {@inheritDoc} */
100 @Override
101 public void processStimulus(Iterator<WakeupCriterion> criteria) {
102 AWTEvent[] evt = null;
103 while (criteria.hasNext()) {
104 WakeupCriterion wakeup = criteria.next();
105 if (wakeup instanceof WakeupOnAWTEvent) {
106 evt = ((WakeupOnAWTEvent) wakeup).getAWTEvent();
107 }
108 }
109 int xpos = 0, ypos = 0;
110 if (evt != null && evt[0] instanceof MouseEvent) {
111 mevent = (MouseEvent) evt[0];
112 processMouseEvent((MouseEvent) evt[0]);
113 xpos = mevent.getPoint().x;
114 ypos = mevent.getPoint().y;
115 }
116 if (buttonPress) {
117 updateScene(xpos, ypos);
118 }
119 wakeupOn(wakeupCondition);
120 }
121
122 /**
123 * setTolerance
124 *
125 * @param tol a float.
126 */
127 public void setTolerance(float tol) {
128 if (pickCanvas != null) {
129 pickCanvas.setTolerance(tol);
130 }
131 }
132
133 /**
134 * Subclasses shall implement this update function.
135 *
136 * @param xpos a int.
137 * @param ypos a int.
138 */
139 public abstract void updateScene(int xpos, int ypos);
140
141 private void processMouseEvent(MouseEvent evt) {
142 buttonPress =
143 evt.getID() == MouseEvent.MOUSE_PRESSED
144 | evt.getID() == MouseEvent.MOUSE_CLICKED
145 | evt.getID() == MouseEvent.MOUSE_RELEASED;
146 controlButton = evt.isControlDown();
147 shiftButton = evt.isShiftDown();
148 }
149 }