1
/*FreeMind - A Program for creating and viewing Mindmaps
2
*Copyright (C) 2000-2001 Joerg Mueller <joergmueller@bigfoot.com>
3
*See COPYING for Details
5
*This program is free software; you can redistribute it and/or
6
*modify it under the terms of the GNU General Public License
7
*as published by the Free Software Foundation; either version 2
8
*of the License, or (at your option) any later version.
10
*This program is distributed in the hope that it will be useful,
11
*but WITHOUT ANY WARRANTY; without even the implied warranty of
12
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
*GNU General Public License for more details.
15
*You should have received a copy of the GNU General Public License
16
*along with this program; if not, write to the Free Software
17
*Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
/* $Id: CommonNodeMouseMotionListener.java,v 1.1.2.1.2.5 2007/08/03 17:24:01 dpolivaev Exp $ */
21
package freemind.modes.common.listeners;
23
import java.awt.Component;
24
import java.awt.EventQueue;
25
import java.awt.Rectangle;
26
import java.awt.event.MouseEvent;
27
import java.awt.geom.Point2D;
28
import java.lang.reflect.InvocationTargetException;
29
import java.util.Timer;
30
import java.util.TimerTask;
32
import javax.swing.JOptionPane;
33
import javax.swing.SwingUtilities;
35
import freemind.controller.NodeMouseMotionListener.NodeMouseMotionObserver;
36
import freemind.main.Tools;
37
import freemind.modes.ModeController;
38
import freemind.view.mindmapview.MainView;
39
import freemind.view.mindmapview.NodeView;
42
* The MouseMotionListener which belongs to every NodeView
44
public class CommonNodeMouseMotionListener implements NodeMouseMotionObserver {
46
private final ModeController c;
49
private static java.util.logging.Logger logger;
51
/** time in ms, overwritten by property time_for_delayed_selection */
52
private static Tools.IntHolder timeForDelayedSelection;
54
/** overwritten by property delayed_selection_enabled */
55
private static Tools.BooleanHolder delayedSelectionEnabled;
58
* And a static method to reread this holder. This is used when the
59
* selection method is changed via the option menu.
61
public void updateSelectionMethod() {
62
if (timeForDelayedSelection == null) {
63
timeForDelayedSelection = new Tools.IntHolder();
65
delayedSelectionEnabled = new Tools.BooleanHolder();
66
delayedSelectionEnabled.setValue(c.getFrame().getProperty(
67
"selection_method").equals("selection_method_direct") ? false
70
* set time for delay to infinity, if selection_method equals
71
* selection_method_by_click.
73
if (c.getFrame().getProperty("selection_method").equals(
74
"selection_method_by_click")) {
75
timeForDelayedSelection.setValue(Integer.MAX_VALUE);
77
timeForDelayedSelection.setValue(Integer.parseInt(c.getFrame()
78
.getProperty("time_for_delayed_selection")));
82
private Timer timerForDelayedSelection;
85
* The mouse has to stay in this region to enable the selection after a
88
private Rectangle controlRegionForDelayedSelection;
90
public CommonNodeMouseMotionListener(ModeController controller) {
93
logger = c.getFrame().getLogger(this.getClass().getName());
94
if (delayedSelectionEnabled == null)
95
updateSelectionMethod();
98
public void mouseMoved(MouseEvent e) {
99
logger.finest("Event: mouseMoved");
100
// Invoked when the mouse button has been moved on a component (with no
102
MainView node = ((MainView) e.getComponent());
103
boolean isLink = (node).updateCursor(e.getX());
104
// links are displayed in the status bar:
106
c.getFrame().out(c.getLinkShortText(node.getNodeView().getModel()));
108
// test if still in selection region:
109
if (controlRegionForDelayedSelection != null
110
&& delayedSelectionEnabled.getValue()) {
111
if (!controlRegionForDelayedSelection.contains(e.getPoint())) {
112
// point is not in the region. start timer again and adjust
113
// region to the current point:
119
/** Invoked when a mouse button is pressed on a component and then dragged. */
120
public void mouseDragged(MouseEvent e) {
121
logger.fine("Event: mouseDragged");
122
// first stop the timer and select the node:
123
stopTimerForDelayedSelection();
124
NodeView nodeV = ((MainView) e.getComponent()).getNodeView();
126
// if dragged for the first time, select the node:
127
if (!c.getView().isSelected(nodeV))
128
c.extendSelection(e);
131
public void mouseClicked(MouseEvent e) {
134
public void mouseEntered(MouseEvent e) {
135
logger.finest("Event: mouseEntered");
136
if(! JOptionPane.getFrameForComponent(e.getComponent()).isFocused())
142
public void mousePressed(MouseEvent e) {
143
logger.fine("Event: mousePressed");
148
public void mouseExited(MouseEvent e) {
149
logger.finest("Event: mouseExited");
150
stopTimerForDelayedSelection();
153
public void mouseReleased(MouseEvent e) {
154
logger.fine("Event: mouseReleased");
155
// handling click in mouseReleased rather than in mouseClicked
156
// provides better interaction. If mouse was slightly moved
157
// between pressed and released events, the event clicked
159
// The behavior is not tested on Linux.
161
// first stop the timer and select the node:
162
stopTimerForDelayedSelection();
163
c.extendSelection(e);
164
// Right mouse <i>press</i> is <i>not</i> a popup trigger for Windows.
165
// Only Right mouse release is a popup trigger!
166
// OK, but Right mouse <i>press</i> <i>is</i> a popup trigger on Linux.
168
if (e.isConsumed()) {
172
if (e.getModifiers() == MouseEvent.BUTTON1_MASK) {
173
// FIXME Dimitry: Double Click comes after Plain Click combining (un)folding with editing
174
// if (e.getClickCount() % 2 == 0) {
183
protected Rectangle getControlRegion(Point2D p) {
184
// Create a small square around the given point.
186
return new Rectangle((int) (p.getX() - side / 2),
187
(int) (p.getY() - side / 2), side, side);
190
public void createTimer(MouseEvent e) {
191
// stop old timer if present.*/
192
stopTimerForDelayedSelection();
193
/* Region to check for in the sequel. */
194
controlRegionForDelayedSelection = getControlRegion(e.getPoint());
195
timerForDelayedSelection = new Timer();
196
timerForDelayedSelection.schedule(new timeDelayedSelection(c, e),
198
* if the new selection method is not enabled we put 0 to get direct
201
(delayedSelectionEnabled.getValue()) ? timeForDelayedSelection
205
protected void stopTimerForDelayedSelection() {
207
if (timerForDelayedSelection != null)
208
timerForDelayedSelection.cancel();
209
timerForDelayedSelection = null;
210
controlRegionForDelayedSelection = null;
213
protected class timeDelayedSelection extends TimerTask {
214
private final ModeController c;
216
private final MouseEvent e;
218
timeDelayedSelection(ModeController c, MouseEvent e) {
223
/** TimerTask method to enable the selection after a given time. */
226
* formerly in ControllerAdapter. To guarantee, that point-to-select
227
* does not change selection if any meta key is pressed.
229
SwingUtilities.invokeLater(new Runnable() {
231
if (e.getModifiers() == 0 && !c.isBlocked()
232
&& c.getView().getSelecteds().size() <= 1) {
233
c.extendSelection(e);