edu.mines.jtk.sgl.SelectDragMode Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of edu-mines-jtk Show documentation
Show all versions of edu-mines-jtk Show documentation
Java packages for science and engineering
The newest version!
/****************************************************************************
Copyright 2004, Colorado School of Mines and others.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
****************************************************************************/
package edu.mines.jtk.sgl;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import edu.mines.jtk.awt.Mode;
import edu.mines.jtk.awt.ModeManager;
/**
* A mode for selecting and dragging nodes.
* @author Dave Hale, Colorado School of Mines
* @version 2005.07.08
*/
public class SelectDragMode extends Mode {
private static final long serialVersionUID = 1L;
/**
* Constructs a select-drag mode with specified manager.
* @param modeManager the mode manager for this mode.
*/
public SelectDragMode(ModeManager modeManager) {
super(modeManager);
setName("Select");
Class cls = SelectDragMode.class;
setIcon(loadIcon(cls,"SelectDragIcon16.png"));
setCursor(loadCursor(cls,"SelectDragCursor16.png",1,1));
setMnemonicKey(KeyEvent.VK_S);
setAcceleratorKey(KeyStroke.getKeyStroke(KeyEvent.VK_S,0));
setShortDescription("Select/drag");
}
///////////////////////////////////////////////////////////////////////////
// protected
protected void setActive(Component component, boolean active) {
if ((component instanceof ViewCanvas)) {
if (active) {
component.addMouseListener(_ml);
} else {
component.removeMouseListener(_ml);
_selecting = false;
_selectable = null;
_dragable = null;
_dragContext = null;
}
}
}
///////////////////////////////////////////////////////////////////////////
// private
private ViewCanvas _canvas; // canvas when mouse pressed
private View _view; // view when mouse pressed; null, if none
private World _world; // world when mouse pressed; null, if none
private PickResult _pickResult; // pick result when mouse pressed
private Selectable _selectable; // used iff selecting
private Dragable _dragable; // used iff dragging
private DragContext _dragContext; // non-null iff dragging
private boolean _selecting; // true iff mouse moves too little for drag
private MouseListener _ml = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
// Initially, assume we are selecting, not dragging.
_selecting = true;
// Pick and look in the result for dragable and selectable nodes.
_pickResult = pick(e);
if (_pickResult!=null) {
_selectable = _pickResult.getSelectableNode();
_dragable = _pickResult.getDragableNode();
}
// Remember the canvas, view, and world.
_canvas = (ViewCanvas)e.getSource();
_view = _canvas.getView();
if (_view!=null)
_world = _view.getWorld();
// Begin listening for mouse movement.
_canvas.addMouseMotionListener(_mml);
}
public void mouseReleased(MouseEvent e) {
// If dragging, end the drag.
if (_dragable!=null && _dragContext!=null) {
_dragable.dragEnd(_dragContext);
}
// Else if selecting (or deselecting), ...
else if (_selecting) {
// If control select, toggle selection of the picked node.
if (e.isControlDown() || e.isAltDown()) { // Alt/Option for Mac
if (_selectable!=null)
_selectable.setSelected(!_selectable.isSelected());
}
// Else if shift select, extend the selection.
else if (e.isShiftDown()) {
if (_selectable!=null)
_selectable.setSelected(true);
}
// Else, select the picked node, if any, after deselecting others.
else {
if (_selectable!=null) {
_world.clearSelectedExcept(_selectable);
_selectable.setSelected(true);
} else {
if (_world!=null)
_world.clearSelected();
}
}
}
// No longer dragging or selecting.
_dragable = null;
_dragContext = null;
_selectable = null;
_selecting = false;
// End listening for mouse movement.
_canvas.removeMouseMotionListener(_mml);
}
};
private MouseMotionListener _mml = new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
// See if mouse has moved too much for selecting.
_selecting = _dragContext==null;
if (_selecting && _pickResult!=null) {
Point3 pp = _pickResult.getPointPixel();
Point3 pd = new Point3(e.getX(),e.getY(),pp.z);
if (pp.distanceTo(pd)>=2.0)
_selecting = false;
}
// If (1) not selecting, and (2) the picked node is dragable, and
// (3) we are not yet dragging, then initiate dragging.
if (!_selecting && _dragable!=null && _dragContext==null) {
_dragContext = new DragContext(_pickResult);
_dragable.dragBegin(_dragContext);
}
// If we are now dragging, update the drag context and drag.
if (_dragable!=null && _dragContext!=null) {
_dragContext.update(e);
_dragable.drag(_dragContext);
}
}
};
private PickResult pick(MouseEvent event) {
ViewCanvas canvas = (ViewCanvas)event.getSource();
//canvas.addMouseMotionListener(_mml); ??
View view = canvas.getView();
if (view==null)
return null;
World world = view.getWorld();
if (world==null)
return null;
PickContext pc = new PickContext(event);
world.pickApply(pc);
PickResult pickResult = pc.getClosest();
if (pickResult!=null) {
Point3 pointLocal = pickResult.getPointLocal();
Point3 pointWorld = pickResult.getPointWorld();
System.out.println("Pick");
System.out.println(" local="+pointLocal);
System.out.println(" world="+pointWorld);
} else {
System.out.println("Pick nothing");
}
return pickResult;
}
}
/*
Design of selectable and dragable:
dragable and selectable are independent interfaces
nodes may implement dragable, selectable, neither, or both
can drag without selecting
can select without dragging
dragging requires a mouse (a drag context)
selecting requires no mouse or context
e.g., may select a node from a list of nodes
when selected, a node may reveal handles,
which may be used for editing, and
are typically dragable, but
are typically not selectable
selected nodes typically highlight themselves, perhaps
by displaying handles (if editable), or
by changing their rendering in some other way
selectable nodes can have selectable children and parents
selecting a node does not cause children and/or parents to be selected
multiple selections are possible
by default, selection of one node causes deselection of all others
shift-click to extend selection set
control-click to add/subtract node to/from current selection set
each world has a selected set of nodes
when a branch is added/removed to/from a group in a world,
the branch is searched to update the world's selected set
to select (or de-select) a node,
press and release mouse
without dragging significantly (less than two pixels)
call setSelected
to drag a node,
press mouse on the node
drag mouse significantly (at least two pixels)
call drawBegin with new drag context
call drag with current drag context
continue dragging mouse
call drag with current drag context
release mouse anywhere
call dragEnd with final drag context
a significant drag is two or more pixels in any direction
prevents inadvertant dragging when selecting is intended
*/
© 2015 - 2025 Weber Informatics LLC | Privacy Policy