| 194 | | final StringBuilder text = new StringBuilder(); |
| 195 | | String name = osm.getDisplayName(DefaultNameFormatter.getInstance()); |
| 196 | | if (osm.getId() == 0 || osm.isModified()) { |
| 197 | | name = "<i><b>"+ osm.getDisplayName(DefaultNameFormatter.getInstance())+"*</b></i>"; |
| 198 | | } |
| 199 | | text.append(name); |
| 200 | | if (osm.getId() != 0) { |
| 201 | | text.append("<br>id="+osm.getId()); |
| 202 | | } |
| 203 | | for (Entry<String, String> e : osm.entrySet()) { |
| 204 | | text.append("<br>"+e.getKey()+"="+e.getValue()); |
| 205 | | } |
| 206 | | final JLabel l = new JLabel( |
| 207 | | "<html>"+text.toString()+"</html>", |
| 208 | | ImageProvider.get(OsmPrimitiveType.from(osm)), |
| 209 | | JLabel.HORIZONTAL |
| 210 | | ); |
| 211 | | l.setFont(l.getFont().deriveFont(Font.PLAIN)); |
| 212 | | l.setVerticalTextPosition(JLabel.TOP); |
| 213 | | l.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); |
| 214 | | l.addMouseListener(new MouseAdapter(){ |
| 215 | | @Override public void mouseEntered(MouseEvent e) { |
| 216 | | l.setText("<html><u color='blue'>"+text.toString()+"</u></html>"); |
| 217 | | } |
| 218 | | @Override public void mouseExited(MouseEvent e) { |
| 219 | | l.setText("<html>"+text.toString()+"</html>"); |
| 220 | | } |
| 221 | | @Override public void mouseClicked(MouseEvent e) { |
| 222 | | Main.main.getCurrentDataSet().setSelected(osm); |
| 223 | | mv.repaint(); |
| 224 | | } |
| 225 | | }); |
| 226 | | c.add(l, GBC.eol()); |
| | 220 | JLabel l = popupBuildPrimitiveLabels(osm); |
| | 221 | lbls.add(l); |
| | 222 | c.add(l, GBC.eol().fill(GBC.HORIZONTAL).insets(2, 0, 2, 2)); |
| | 238 | |
| | 239 | /** |
| | 240 | * Creates a popup for the given content next to the cursor. Tries to |
| | 241 | * keep the popup on screen. |
| | 242 | * @param content |
| | 243 | * @param ms |
| | 244 | * @return popup |
| | 245 | */ |
| | 246 | private final Popup popupCreatePopup(Component content, MouseState ms) { |
| | 247 | Point p = mv.getLocationOnScreen(); |
| | 248 | Dimension scrn = Toolkit.getDefaultToolkit().getScreenSize(); |
| | 249 | Dimension dim = content.getPreferredSize(); |
| | 250 | |
| | 251 | int xPos = p.x + ms.mousePos.x + 16; |
| | 252 | // Display the popup to the left of the cursor if it would be cut |
| | 253 | // off on its right |
| | 254 | if(xPos + dim.width > scrn.width) { |
| | 255 | xPos = p.x + ms.mousePos.x - 4 - dim.width; |
| | 256 | } |
| | 257 | int yPos = p.y + ms.mousePos.y + 16; |
| | 258 | // Move the popup up if it would be cut off at its bottom |
| | 259 | if(yPos + dim.height > scrn.height - 5) { |
| | 260 | yPos = scrn.height - dim.height - 5; |
| | 261 | } |
| | 262 | |
| | 263 | PopupFactory pf = PopupFactory.getSharedInstance(); |
| | 264 | return pf.getPopup(mv, content, xPos, yPos); |
| | 265 | } |
| | 266 | |
| | 267 | /** |
| | 268 | * Calls this to update the element that is shown in the statusbar |
| | 269 | * @param ms |
| | 270 | */ |
| | 271 | private final void statusBarElementUpdate(MouseState ms) { |
| | 272 | final OsmPrimitive osmNearest = mv.getNearest(ms.mousePos); |
| | 273 | if (osmNearest != null) { |
| | 274 | nameText.setText(osmNearest.getDisplayName(DefaultNameFormatter.getInstance())); |
| | 275 | } else { |
| | 276 | nameText.setText(tr("(no object)")); |
| | 277 | } |
| | 278 | } |
| | 279 | |
| | 280 | /** |
| | 281 | * Call this with a set of primitives to cycle through them. Method |
| | 282 | * will automatically select the next item and update the map |
| | 283 | * @param osms |
| | 284 | */ |
| | 285 | private final void popupCycleSelection(Collection<OsmPrimitive> osms) { |
| | 286 | // Find some items that are required for cycling through |
| | 287 | OsmPrimitive firstItem = null; |
| | 288 | OsmPrimitive firstSelected = null; |
| | 289 | OsmPrimitive nextSelected = null; |
| | 290 | for (final OsmPrimitive osm : osms) { |
| | 291 | if(firstItem == null) { |
| | 292 | firstItem = osm; |
| | 293 | } |
| | 294 | if(firstSelected != null && nextSelected == null) { |
| | 295 | nextSelected = osm; |
| | 296 | } |
| | 297 | if(firstSelected == null && osm.isSelected()) { |
| | 298 | firstSelected = osm; |
| | 299 | } |
| | 300 | } |
| | 301 | |
| | 302 | // This will cycle through the available items. |
| | 303 | if(firstSelected == null) { |
| | 304 | firstItem.setSelected(true); |
| | 305 | } else { |
| | 306 | firstSelected.setSelected(false); |
| | 307 | if(nextSelected != null) { |
| | 308 | nextSelected.setSelected(true); |
| | 309 | } |
| | 310 | } |
| | 311 | mv.repaint(); |
| | 312 | } |
| | 313 | |
| | 314 | /** |
| | 315 | * Tries to hide the given popup |
| | 316 | * @param popup |
| | 317 | */ |
| | 318 | private final void popupHidePopup() { |
| | 319 | popupLabels = null; |
| | 320 | if(popup == null) |
| | 321 | return; |
| | 322 | final Popup staticPopup = popup; |
| | 323 | popup = null; |
| | 324 | EventQueue.invokeLater(new Runnable(){ |
| | 325 | public void run() { staticPopup.hide(); }}); |
| | 326 | } |
| | 327 | |
| | 328 | /** |
| | 329 | * Tries to show the given popup, can be hidden using popupHideOldPopup |
| | 330 | * If an old popup exists, it will be automatically hidden |
| | 331 | * @param popup |
| | 332 | */ |
| | 333 | private final void popupShowPopup(Popup newPopup, List<JLabel> lbls) { |
| | 334 | final Popup staticPopup = newPopup; |
| | 335 | if(this.popup != null) { |
| | 336 | // If an old popup exists, remove it when the new popup has been |
| | 337 | // drawn to keep flickering to a minimum |
| | 338 | final Popup staticOldPopup = this.popup; |
| | 339 | EventQueue.invokeLater(new Runnable(){ |
| | 340 | public void run() { |
| | 341 | staticPopup.show(); |
| | 342 | staticOldPopup.hide(); |
| | 343 | } |
| | 344 | }); |
| | 345 | } else { |
| | 346 | // There is no old popup |
| | 347 | EventQueue.invokeLater(new Runnable(){ |
| | 348 | public void run() { staticPopup.show(); }}); |
| | 349 | } |
| | 350 | this.popupLabels = lbls; |
| | 351 | this.popup = newPopup; |
| | 352 | } |
| | 353 | |
| | 354 | /** |
| | 355 | * This method should be called if the selection may have changed from |
| | 356 | * outside of this class. This is the case when CTRL is pressed and the |
| | 357 | * user clicks on the map instead of the popup. |
| | 358 | */ |
| | 359 | private final void popupUpdateLabels() { |
| | 360 | if(this.popup == null || this.popupLabels == null) |
| | 361 | return; |
| | 362 | for(JLabel l : this.popupLabels) { |
| | 363 | l.validate(); |
| | 364 | } |
| | 365 | } |
| | 366 | |
| | 367 | /** |
| | 368 | * Sets the colors for the given label depending on the selected status of |
| | 369 | * the given OsmPrimitive |
| | 370 | * |
| | 371 | * @param lbl The label to color |
| | 372 | * @param osm The primitive to derive the colors from |
| | 373 | */ |
| | 374 | private final void popupSetLabelColors(JLabel lbl, OsmPrimitive osm) { |
| | 375 | if(osm.isSelected()) { |
| | 376 | lbl.setBackground(SystemColor.textHighlight); |
| | 377 | lbl.setForeground(SystemColor.textHighlightText); |
| | 378 | } else { |
| | 379 | lbl.setBackground(SystemColor.control); |
| | 380 | lbl.setForeground(SystemColor.controlText); |
| | 381 | } |
| | 382 | } |
| | 383 | |
| | 384 | /** |
| | 385 | * Builds the labels with all necessary listeners for the info popup for the |
| | 386 | * given OsmPrimitive |
| | 387 | * @param osm The primitive to create the label for |
| | 388 | * @return |
| | 389 | */ |
| | 390 | private final JLabel popupBuildPrimitiveLabels(final OsmPrimitive osm) { |
| | 391 | final StringBuilder text = new StringBuilder(); |
| | 392 | String name = osm.getDisplayName(DefaultNameFormatter.getInstance()); |
| | 393 | if (osm.getId() == 0 || osm.isModified()) { |
| | 394 | name = "<i><b>"+ osm.getDisplayName(DefaultNameFormatter.getInstance())+"*</b></i>"; |
| | 395 | } |
| | 396 | text.append(name); |
| | 397 | if (osm.getId() != 0) { |
| | 398 | text.append("<br>id="+osm.getId()); |
| | 399 | } |
| | 400 | for (Entry<String, String> e1 : osm.entrySet()) { |
| | 401 | text.append("<br>"+e1.getKey()+"="+e1.getValue()); |
| | 402 | } |
| | 403 | |
| | 404 | final JLabel l = new JLabel( |
| | 405 | "<html>"+text.toString()+"</html>", |
| | 406 | ImageProvider.get(OsmPrimitiveType.from(osm)), |
| | 407 | JLabel.HORIZONTAL |
| | 408 | ) { |
| | 409 | // This is necessary so the label updates its colors when the |
| | 410 | // selection is changed from the outside |
| | 411 | @Override public void validate() { |
| | 412 | super.validate(); |
| | 413 | popupSetLabelColors(this, osm); |
| | 414 | } |
| | 415 | }; |
| | 416 | l.setOpaque(true); |
| | 417 | popupSetLabelColors(l, osm); |
| | 418 | l.setFont(l.getFont().deriveFont(Font.PLAIN)); |
| | 419 | l.setVerticalTextPosition(JLabel.TOP); |
| | 420 | l.setHorizontalAlignment(JLabel.LEFT); |
| | 421 | l.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); |
| | 422 | l.addMouseListener(new MouseAdapter(){ |
| | 423 | @Override public void mouseEntered(MouseEvent e) { |
| | 424 | l.setBackground(SystemColor.info); |
| | 425 | l.setForeground(SystemColor.infoText); |
| | 426 | } |
| | 427 | @Override public void mouseExited(MouseEvent e) { |
| | 428 | popupSetLabelColors(l, osm); |
| | 429 | } |
| | 430 | @Override public void mouseClicked(MouseEvent e) { |
| | 431 | // Let the user toggle the selection |
| | 432 | osm.setSelected(!osm.isSelected()); |
| | 433 | mv.repaint(); |
| | 434 | l.validate(); |
| | 435 | } |
| | 436 | }); |
| | 437 | // Sometimes the mouseEntered event is not catched, thus the label |
| | 438 | // will not be highlighted, making it confusing. The MotionListener |
| | 439 | // can correct this defect. |
| | 440 | l.addMouseMotionListener(new MouseMotionListener() { |
| | 441 | public void mouseMoved(MouseEvent e) { |
| | 442 | l.setBackground(SystemColor.info); |
| | 443 | l.setForeground(SystemColor.infoText); |
| | 444 | } |
| | 445 | public void mouseDragged(MouseEvent e) { |
| | 446 | l.setBackground(SystemColor.info); |
| | 447 | l.setForeground(SystemColor.infoText); |
| | 448 | } |
| | 449 | }); |
| | 450 | return l; |
| | 451 | } |