source: josm/src/org/openstreetmap/josm/gui/MapStatus.java@ 15

Last change on this file since 15 was 15, checked in by imi, 19 years ago

renamed alot (Layer instead of MapView) and removed feature of having
projections on every Layer.

File size: 5.6 KB
Line 
1package org.openstreetmap.josm.gui;
2
3import java.awt.AWTEvent;
4import java.awt.Point;
5import java.awt.Toolkit;
6import java.awt.event.AWTEventListener;
7import java.awt.event.InputEvent;
8import java.awt.event.MouseEvent;
9import java.awt.event.MouseMotionListener;
10import java.util.Map.Entry;
11
12import javax.swing.BorderFactory;
13import javax.swing.BoxLayout;
14import javax.swing.JLabel;
15import javax.swing.JPanel;
16import javax.swing.JTextField;
17import javax.swing.Popup;
18import javax.swing.PopupFactory;
19
20import org.openstreetmap.josm.data.GeoPoint;
21import org.openstreetmap.josm.data.osm.Key;
22import org.openstreetmap.josm.data.osm.OsmPrimitive;
23import org.openstreetmap.josm.data.osm.visitor.SelectionComponentVisitor;
24
25/**
26 * A component that manages some status information display about the map.
27 * It keeps a status line below the map up to date and displays some tooltip
28 * information if the user hold the mouse long enough at some point.
29 *
30 * All this is done in background to not disturb other processes.
31 *
32 * The background thread does not alter any data of the map (read only thread).
33 * Also it is rather fail safe. In case of some error in the data, it just do
34 * nothing instead of whining and complaining.
35 *
36 * @author imi
37 */
38public class MapStatus extends JPanel {
39
40 /**
41 * The Layer this status belongs.
42 */
43 final Layer mv;
44 /**
45 * The position of the mouse cursor.
46 */
47 private JTextField positionText = new JTextField("-000.00000000000000 -000.00000000000000".length());
48 /**
49 * The field holding the name of the object under the mouse.
50 */
51 private JTextField nameText = new JTextField(30);
52 /**
53 * The background thread thats collecting the data.
54 */
55 private Runnable collector;
56
57 /**
58 * The collector class that waits for notification and then update
59 * the display objects.
60 *
61 * @author imi
62 */
63 private final class Collector implements Runnable {
64 /**
65 * The last object displayed in status line.
66 */
67 OsmPrimitive osmStatus;
68 /**
69 * A visitor to retrieve name information about the osm primitive
70 */
71 private SelectionComponentVisitor visitor = new SelectionComponentVisitor();
72 /**
73 * The old modifiers, that was pressed the last time this collector ran.
74 */
75 private int oldModifiers;
76 /**
77 * The popup displayed to show additional information
78 */
79 private Popup popup;
80
81 /**
82 * Execution function for the Collector.
83 */
84 public void run() {
85 for (;;) {
86 MouseState ms = new MouseState();
87 synchronized (this) {
88 try {wait();} catch (InterruptedException e) {}
89 ms.modifiers = mouseState.modifiers;
90 ms.mousePos = mouseState.mousePos;
91 }
92 if ((ms.modifiers & MouseEvent.CTRL_DOWN_MASK) != 0 || ms.mousePos == null)
93 continue; // freeze display when holding down ctrl
94 OsmPrimitive osm = mv.getNearest(ms.mousePos, (ms.modifiers & MouseEvent.ALT_DOWN_MASK) != 0);
95 if (osm == osmStatus && ms.modifiers == oldModifiers)
96 continue;
97 osmStatus = osm;
98 oldModifiers = ms.modifiers;
99 if (osm != null) {
100 osm.visit(visitor);
101 nameText.setText(visitor.name);
102 } else
103 nameText.setText("");
104
105 // Popup Information
106 if ((ms.modifiers & MouseEvent.BUTTON2_DOWN_MASK) != 0 && osm != null) {
107 if (popup != null)
108 popup.hide();
109
110 StringBuilder text = new StringBuilder("<html>");
111 text.append(visitor.name);
112 if (osm.keys != null) {
113 for (Entry<Key, String> e : osm.keys.entrySet()) {
114 text.append("<br>");
115 text.append(e.getKey().name);
116 text.append("=");
117 text.append(e.getValue());
118 }
119 }
120 JLabel l = new JLabel(text.toString(), visitor.icon, JLabel.HORIZONTAL);
121
122 Point p = mv.getLocationOnScreen();
123 popup = PopupFactory.getSharedInstance().getPopup(mv, l, p.x+ms.mousePos.x+16, p.y+ms.mousePos.y+16);
124 popup.show();
125 } else if (popup != null) {
126 popup.hide();
127 popup = null;
128 }
129 }
130 }
131 }
132
133 /**
134 * Everything, the collector is interested of. Access must be synchronized.
135 * @author imi
136 */
137 class MouseState {
138 Point mousePos;
139 int modifiers;
140 }
141 /**
142 * The last sent mouse movement event.
143 */
144 private MouseState mouseState = new MouseState();
145
146 /**
147 * Construct a new MapStatus and attach it to the Layer.
148 * @param mv The Layer the status line is part of.
149 */
150 public MapStatus(final Layer mv) {
151 this.mv = mv;
152
153 // Listen for mouse movements and set the position text field
154 mv.addMouseMotionListener(new MouseMotionListener(){
155 public void mouseDragged(MouseEvent e) {
156 mouseMoved(e);
157 }
158 public void mouseMoved(MouseEvent e) {
159 // Do not update the view, if ctrl is pressed.
160 if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == 0) {
161 GeoPoint p = mv.getPoint(e.getX(),e.getY(),true);
162 positionText.setText(p.lat+" "+p.lon);
163 }
164 }
165 });
166
167 // Listen to keyboard/mouse events for pressing/releasing alt key and
168 // inform the collector.
169 Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener(){
170 public void eventDispatched(AWTEvent event) {
171 synchronized (collector) {
172 mouseState.modifiers = ((InputEvent)event).getModifiersEx();
173 if (event instanceof MouseEvent)
174 mouseState.mousePos = ((MouseEvent)event).getPoint();
175 collector.notify();
176 }
177 }
178 }, AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
179
180 positionText.setEditable(false);
181 nameText.setEditable(false);
182 setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
183 setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
184 add(new JLabel("Lat/Lon "));
185 add(positionText);
186 add(new JLabel(" Object "));
187 add(nameText);
188
189 // The background thread
190 collector = new Collector();
191 new Thread(collector).start();
192 }
193}
Note: See TracBrowser for help on using the repository browser.