001: /* uDig - User Friendly Desktop Internet GIS client
002: * http://udig.refractions.net
003: * (C) 2004, Refractions Research Inc.
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation;
008: * version 2.1 of the License.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: */
015: package net.refractions.udig.tools.internal;
016:
017: import java.util.ArrayList;
018:
019: import net.refractions.udig.project.command.NavCommand;
020: import net.refractions.udig.project.command.factory.NavigationCommandFactory;
021: import net.refractions.udig.project.internal.command.navigation.NavComposite;
022: import net.refractions.udig.project.ui.commands.TransformDrawCommand;
023: import net.refractions.udig.project.ui.tool.IToolContext;
024:
025: /**
026: * Waits 1 second after the most recent request before running operation.
027: *
028: * @author Jesse
029: * @since 1.1.0
030: */
031: public class UpdateThread implements Runnable {
032:
033: private static final int PAN_AMOUNT = 30;
034: private static final double FACTOR = 1.01;
035: private static volatile long request = Long.MAX_VALUE;
036: private static Thread thread;
037:
038: private static TransformDrawCommand command;
039: private static final UpdateThread updater = new UpdateThread();
040: private NavigationCommandFactory factory = NavigationCommandFactory
041: .getInstance();
042: int amount = 0;
043: private int vertical = 0;
044: private int horizontal = 0;
045: private IToolContext context;
046:
047: private UpdateThread() {
048: }
049:
050: /**
051: * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
052: */
053: public final void run() {
054: synchronized (UpdateThread.class) {
055: if (thread != Thread.currentThread())
056: return;
057: }
058: while (getElapsedTimeSinceLastRequest() < 1000) {
059: synchronized (UpdateThread.class) {
060: if (thread != Thread.currentThread())
061: return;
062: }
063: try {
064: Thread.sleep(1000);
065: } catch (InterruptedException e) {
066: ToolsPlugin.log("", e); //$NON-NLS-1$
067: synchronized (UpdateThread.class) {
068: if (thread != Thread.currentThread())
069: return;
070: thread = null;
071: }
072: cancel();
073: return;
074: }
075: }
076: synchronized (UpdateThread.class) {
077: if (thread != Thread.currentThread())
078: return;
079: thread = null;
080: }
081: performChange();
082: }
083:
084: /**
085: * @return
086: */
087: private synchronized long getElapsedTimeSinceLastRequest() {
088: return System.currentTimeMillis() - request;
089: }
090:
091: public synchronized void requestStart() {
092: request = System.currentTimeMillis();
093: synchronized (UpdateThread.class) {
094: if (thread == null) {
095: thread = new Thread(this );
096: thread.setName(Messages.ScrollZoom_scroll_zoom);
097: thread.start();
098: }
099: }
100: }
101:
102: public synchronized void left(IToolContext context) {
103: horizontal++;
104: update(context);
105: }
106:
107: public synchronized void right(IToolContext context) {
108: horizontal--;
109: update(context);
110: }
111:
112: public synchronized void up(IToolContext context) {
113: vertical++;
114: update(context);
115: }
116:
117: public synchronized void down(IToolContext context) {
118: vertical--;
119: update(context);
120: }
121:
122: private void update(IToolContext context) {
123: synchronized (UpdateThread.class) {
124: this .context = context;
125: if (command == null) {
126: TransformDrawCommand transformDrawCommand = new TransformDrawCommand();
127: command = transformDrawCommand;
128: transformDrawCommand.pan(horizontal * PAN_AMOUNT,
129: vertical * PAN_AMOUNT);
130: context.sendASyncCommand(transformDrawCommand);
131: } else {
132: command.pan(horizontal * PAN_AMOUNT, vertical
133: * PAN_AMOUNT);
134: context.getViewportPane().repaint();
135: }
136: }
137: requestStart();
138: }
139:
140: public void zoom(int change, IToolContext context) {
141: amount += change;
142:
143: double zoom = Math.abs(Math.pow(FACTOR, amount));
144:
145: synchronized (UpdateThread.class) {
146: if (command == null) {
147: TransformDrawCommand transformDrawCommand = new TransformDrawCommand();
148: command = transformDrawCommand;
149: transformDrawCommand.zoom(zoom, zoom);
150: context.sendASyncCommand(transformDrawCommand);
151: } else {
152: command.zoom(zoom, zoom);
153: context.getViewportPane().repaint();
154: }
155: }
156:
157: this .context = context;
158:
159: requestStart();
160: }
161:
162: protected synchronized void performChange() {
163:
164: double zoom = Math.abs(Math.pow(FACTOR, amount));
165: ArrayList<NavCommand> commands = new ArrayList<NavCommand>();
166: if (horizontal != 0 || vertical != 0) {
167: commands.add(factory.createPanCommandUsingScreenCoords(
168: horizontal * -PAN_AMOUNT, vertical * -PAN_AMOUNT));
169: }
170: if (zoom > 0.00000001) {
171: commands.add(factory.createZoomCommand(zoom));
172: }
173: if (commands.size() > 0) {
174: context.sendASyncCommand(new NavComposite(commands));
175: }
176: amount = 0;
177: command.setValid(false);
178: command = null;
179: horizontal = 0;
180: vertical = 0;
181: }
182:
183: protected void cancel() {
184: amount = 0;
185: command.setValid(false);
186: command = null;
187: horizontal = 0;
188: vertical = 0;
189: context.getViewportPane().repaint();
190: }
191:
192: /**
193: * @return Returns the updater.
194: */
195: public static UpdateThread getUpdater() {
196: return updater;
197: }
198:
199: }
|