Changeset 15333 in josm for trunk/src/org/openstreetmap
- Timestamp:
- 2019-09-02T22:35:07+02:00 (5 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
r15046 r15333 540 540 if (dp < initialMoveThreshold) 541 541 return; // ignore small drags 542 initialMoveThresholdExceeded = true; //no more i ngnoring uintil nexmouse press542 initialMoveThresholdExceeded = true; //no more ignoring until next mouse press 543 543 } 544 544 if (e.getPoint().equals(lastMousePos)) -
trunk/src/org/openstreetmap/josm/data/ImageData.java
r14590 r15333 1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.data; 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 3 5 4 6 import java.util.ArrayList; 5 7 import java.util.Collections; 6 8 import java.util.List; 9 import java.util.stream.Collectors; 7 10 8 11 import org.openstreetmap.josm.data.coor.LatLon; … … 34 37 private final List<ImageEntry> data; 35 38 36 private int selectedImageIndex = -1;39 private final List<Integer> selectedImagesIndex = new ArrayList<>(); 37 40 38 41 private final ListenerList<ImageDataUpdateListener> listeners = ListenerList.create(); … … 56 59 this.data = new ArrayList<>(); 57 60 } 61 selectedImagesIndex.add(-1); 58 62 } 59 63 … … 107 111 108 112 /** 109 * Return the current selected image 110 * @return the selected image as {@link ImageEntry} or null 113 * Return the first currently selected image 114 * @return the first selected image as {@link ImageEntry} or null 115 * @see #getSelectedImages 111 116 */ 112 117 public ImageEntry getSelectedImage() { 118 int selectedImageIndex = selectedImagesIndex.isEmpty() ? -1 : selectedImagesIndex.get(0); 113 119 if (selectedImageIndex > -1) { 114 120 return data.get(selectedImageIndex); 115 121 } 116 122 return null; 123 } 124 125 /** 126 * Return the current selected images 127 * @return the selected images as list {@link ImageEntry} 128 * @since 15333 129 */ 130 public List<ImageEntry> getSelectedImages() { 131 return selectedImagesIndex.stream().filter(i -> i > -1).map(data::get).collect(Collectors.toList()); 117 132 } 118 133 … … 138 153 */ 139 154 public boolean hasNextImage() { 140 return selectedImageIndex != data.size() - 1;155 return (selectedImagesIndex.size() == 1 && selectedImagesIndex.get(0) != data.size() - 1); 141 156 } 142 157 … … 146 161 public void selectNextImage() { 147 162 if (hasNextImage()) { 148 setSelectedImageIndex(selectedImage Index+ 1);163 setSelectedImageIndex(selectedImagesIndex.get(0) + 1); 149 164 } 150 165 } … … 155 170 */ 156 171 public boolean hasPreviousImage() { 157 return selectedImageIndex - 1 > -1;172 return (selectedImagesIndex.size() == 1 && selectedImagesIndex.get(0) - 1 > -1); 158 173 } 159 174 … … 165 180 return; 166 181 } 167 setSelectedImageIndex(Integer.max(0, selectedImage Index- 1));182 setSelectedImageIndex(Integer.max(0, selectedImagesIndex.get(0) - 1)); 168 183 } 169 184 … … 177 192 178 193 /** 179 * Clear the selected image 194 * Add image to the list of selected images 195 * @param image {@link ImageEntry} the image to add 196 * @since 15333 197 */ 198 public void addImageToSelection(ImageEntry image) { 199 int index = data.indexOf(image); 200 if (selectedImagesIndex.get(0) == -1) { 201 setSelectedImage(image); 202 } else if (!selectedImagesIndex.contains(index)) { 203 selectedImagesIndex.add(index); 204 listeners.fireEvent(l -> l.selectedImageChanged(this)); 205 } 206 } 207 208 /** 209 * Remove the image from the list of selected images 210 * @param image {@link ImageEntry} the image to remove 211 * @since 15333 212 */ 213 public void removeImageToSelection(ImageEntry image) { 214 int index = data.indexOf(image); 215 selectedImagesIndex.remove(selectedImagesIndex.indexOf(index)); 216 if (selectedImagesIndex.isEmpty()) { 217 selectedImagesIndex.add(-1); 218 } 219 listeners.fireEvent(l -> l.selectedImageChanged(this)); 220 } 221 222 /** 223 * Clear the selected image(s) 180 224 */ 181 225 public void clearSelectedImage() { … … 188 232 189 233 private void setSelectedImageIndex(int index, boolean forceTrigger) { 190 if (index == selectedImageIndex && !forceTrigger) { 234 if (selectedImagesIndex.size() > 1) { 235 selectedImagesIndex.clear(); 236 selectedImagesIndex.add(-1); 237 } 238 if (index == selectedImagesIndex.get(0) && !forceTrigger) { 191 239 return; 192 240 } 193 selectedImage Index = index;241 selectedImagesIndex.set(0, index); 194 242 listeners.fireEvent(l -> l.selectedImageChanged(this)); 195 243 } … … 199 247 */ 200 248 public void removeSelectedImage() { 201 data.remove(getSelectedImage()); 202 if (selectedImageIndex == data.size()) { 249 List<ImageEntry> selected = getSelectedImages(); 250 if (selected.size() > 1) { 251 throw new IllegalStateException(tr("Multiple images have been selected")); 252 } 253 if (selected.isEmpty()) { 254 return; 255 } 256 data.remove(getSelectedImages().get(0)); 257 if (selectedImagesIndex.get(0) == data.size()) { 203 258 setSelectedImageIndex(data.size() - 1); 204 259 } else { 205 setSelectedImageIndex(selectedImageIndex, true); 206 } 260 setSelectedImageIndex(selectedImagesIndex.get(0), true); 261 } 262 } 263 264 /** 265 * Determines if the image is selected 266 * @param image the {@link ImageEntry} image 267 * @return {@code true} is the image is selected, {@code false} otherwise 268 * @since 15333 269 */ 270 public boolean isImageSelected(ImageEntry image) { 271 int index = data.indexOf(image); 272 return selectedImagesIndex.contains(index); 207 273 } 208 274 -
trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java
r15007 r15333 99 99 /** Mouse position where the last image was selected. */ 100 100 private Point lastSelPos; 101 /** The mouse point */ 102 private Point startPoint; 101 103 102 104 /** … … 153 155 this.useThumbs = useThumbs; 154 156 this.data.addImageDataUpdateListener(this); 157 } 158 159 private final class ImageMouseListener extends MouseAdapter { 160 private boolean isMapModeOk() { 161 MapMode mapMode = MainApplication.getMap().mapMode; 162 return mapMode == null || isSupportedMapMode(mapMode); 163 } 164 165 @Override 166 public void mousePressed(MouseEvent e) { 167 if (e.getButton() != MouseEvent.BUTTON1) 168 return; 169 if (isVisible() && isMapModeOk()) { 170 cycleModeArmed = true; 171 invalidate(); 172 startPoint = e.getPoint(); 173 } 174 } 175 176 @Override 177 public void mouseReleased(MouseEvent ev) { 178 if (ev.getButton() != MouseEvent.BUTTON1) 179 return; 180 if (!isVisible() || !isMapModeOk()) 181 return; 182 if (!cycleModeArmed) { 183 return; 184 } 185 186 Rectangle hitBoxClick = new Rectangle((int) startPoint.getX() - 10, (int) startPoint.getY() - 10, 15, 15); 187 if (!hitBoxClick.contains(ev.getPoint())) { 188 return; 189 } 190 191 Point mousePos = ev.getPoint(); 192 boolean cycle = cycleModeArmed && lastSelPos != null && lastSelPos.equals(mousePos); 193 final boolean isShift = (ev.getModifiersEx() & MouseEvent.SHIFT_DOWN_MASK) == MouseEvent.SHIFT_DOWN_MASK; 194 final boolean isCtrl = (ev.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == MouseEvent.CTRL_DOWN_MASK; 195 int idx = getPhotoIdxUnderMouse(ev, cycle); 196 if (idx >= 0) { 197 lastSelPos = mousePos; 198 cycleModeArmed = false; 199 ImageEntry img = data.getImages().get(idx); 200 if (isShift) { 201 if (isCtrl && !data.getSelectedImages().isEmpty()) { 202 int idx2 = data.getImages().indexOf(data.getSelectedImages().get(data.getSelectedImages().size() - 1)); 203 int startIndex = Math.min(idx, idx2); 204 int endIndex = Math.max(idx, idx2); 205 for (int i = startIndex; i <= endIndex; i++) { 206 data.addImageToSelection(data.getImages().get(i)); 207 } 208 } else { 209 if (data.isImageSelected(img)) { 210 data.removeImageToSelection(img); 211 } else { 212 data.addImageToSelection(img); 213 } 214 } 215 } else { 216 data.setSelectedImage(img); 217 } 218 } 219 } 155 220 } 156 221 … … 497 562 paintImage(e, mv, clip, tempG); 498 563 } 499 if (data.getSelectedImage() != null) {564 for (ImageEntry img: this.data.getSelectedImages()) { 500 565 // Make sure the selected image is on top in case multiple images overlap. 501 paintImage( data.getSelectedImage(), mv, clip, tempG);566 paintImage(img, mv, clip, tempG); 502 567 } 503 568 updateOffscreenBuffer = false; … … 516 581 } 517 582 518 ImageEntry e = data.getSelectedImage(); 519 if (e != null && e.getPos() != null) { 520 Point p = mv.getPoint(e.getPos()); 521 522 int imgWidth; 523 int imgHeight; 524 if (useThumbs && e.hasThumbnail()) { 525 Dimension d = scaledDimension(e.getThumbnail()); 526 if (d != null) { 527 imgWidth = d.width; 528 imgHeight = d.height; 583 for (ImageEntry e: data.getSelectedImages()) { 584 if (e != null && e.getPos() != null) { 585 Point p = mv.getPoint(e.getPos()); 586 587 int imgWidth; 588 int imgHeight; 589 if (useThumbs && e.hasThumbnail()) { 590 Dimension d = scaledDimension(e.getThumbnail()); 591 if (d != null) { 592 imgWidth = d.width; 593 imgHeight = d.height; 594 } else { 595 imgWidth = -1; 596 imgHeight = -1; 597 } 529 598 } else { 530 imgWidth = -1; 531 imgHeight = -1; 532 } 533 } else { 534 imgWidth = selectedIcon.getIconWidth(); 535 imgHeight = selectedIcon.getIconHeight(); 536 } 537 538 if (e.getExifImgDir() != null) { 539 // Multiplier must be larger than sqrt(2)/2=0.71. 540 double arrowlength = Math.max(25, Math.max(imgWidth, imgHeight) * 0.85); 541 double arrowwidth = arrowlength / 1.4; 542 543 double dir = e.getExifImgDir(); 544 // Rotate 90 degrees CCW 545 double headdir = (dir < 90) ? dir + 270 : dir - 90; 546 double leftdir = (headdir < 90) ? headdir + 270 : headdir - 90; 547 double rightdir = (headdir > 270) ? headdir - 270 : headdir + 90; 548 549 double ptx = p.x + Math.cos(Utils.toRadians(headdir)) * arrowlength; 550 double pty = p.y + Math.sin(Utils.toRadians(headdir)) * arrowlength; 551 552 double ltx = p.x + Math.cos(Utils.toRadians(leftdir)) * arrowwidth/2; 553 double lty = p.y + Math.sin(Utils.toRadians(leftdir)) * arrowwidth/2; 554 555 double rtx = p.x + Math.cos(Utils.toRadians(rightdir)) * arrowwidth/2; 556 double rty = p.y + Math.sin(Utils.toRadians(rightdir)) * arrowwidth/2; 557 558 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 559 g.setColor(new Color(255, 255, 255, 192)); 560 int[] xar = {(int) ltx, (int) ptx, (int) rtx, (int) ltx}; 561 int[] yar = {(int) lty, (int) pty, (int) rty, (int) lty}; 562 g.fillPolygon(xar, yar, 4); 563 g.setColor(Color.black); 564 g.setStroke(new BasicStroke(1.2f)); 565 g.drawPolyline(xar, yar, 3); 566 } 567 568 if (useThumbs && e.hasThumbnail()) { 569 g.setColor(new Color(128, 0, 0, 122)); 570 g.fillRect(p.x - imgWidth / 2, p.y - imgHeight / 2, imgWidth, imgHeight); 571 } else { 572 selectedIcon.paintIcon(mv, g, 573 p.x - imgWidth / 2, 574 p.y - imgHeight / 2); 599 imgWidth = selectedIcon.getIconWidth(); 600 imgHeight = selectedIcon.getIconHeight(); 601 } 602 603 if (e.getExifImgDir() != null) { 604 // Multiplier must be larger than sqrt(2)/2=0.71. 605 double arrowlength = Math.max(25, Math.max(imgWidth, imgHeight) * 0.85); 606 double arrowwidth = arrowlength / 1.4; 607 608 double dir = e.getExifImgDir(); 609 // Rotate 90 degrees CCW 610 double headdir = (dir < 90) ? dir + 270 : dir - 90; 611 double leftdir = (headdir < 90) ? headdir + 270 : headdir - 90; 612 double rightdir = (headdir > 270) ? headdir - 270 : headdir + 90; 613 614 double ptx = p.x + Math.cos(Utils.toRadians(headdir)) * arrowlength; 615 double pty = p.y + Math.sin(Utils.toRadians(headdir)) * arrowlength; 616 617 double ltx = p.x + Math.cos(Utils.toRadians(leftdir)) * arrowwidth/2; 618 double lty = p.y + Math.sin(Utils.toRadians(leftdir)) * arrowwidth/2; 619 620 double rtx = p.x + Math.cos(Utils.toRadians(rightdir)) * arrowwidth/2; 621 double rty = p.y + Math.sin(Utils.toRadians(rightdir)) * arrowwidth/2; 622 623 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 624 g.setColor(new Color(255, 255, 255, 192)); 625 int[] xar = {(int) ltx, (int) ptx, (int) rtx, (int) ltx}; 626 int[] yar = {(int) lty, (int) pty, (int) rty, (int) lty}; 627 g.fillPolygon(xar, yar, 4); 628 g.setColor(Color.black); 629 g.setStroke(new BasicStroke(1.2f)); 630 g.drawPolyline(xar, yar, 3); 631 } 632 633 if (useThumbs && e.hasThumbnail()) { 634 g.setColor(new Color(128, 0, 0, 122)); 635 g.fillRect(p.x - imgWidth / 2, p.y - imgHeight / 2, imgWidth, imgHeight); 636 } else { 637 selectedIcon.paintIcon(mv, g, 638 p.x - imgWidth / 2, 639 p.y - imgHeight / 2); 640 } 575 641 } 576 642 } … … 743 809 @Override 744 810 public void hookUpMapView() { 745 mouseAdapter = new MouseAdapter() { 746 private boolean isMapModeOk() { 747 MapMode mapMode = MainApplication.getMap().mapMode; 748 return mapMode == null || isSupportedMapMode(mapMode); 749 } 750 751 @Override 752 public void mousePressed(MouseEvent e) { 753 if (e.getButton() != MouseEvent.BUTTON1) 754 return; 755 if (isVisible() && isMapModeOk()) { 756 cycleModeArmed = true; 757 invalidate(); 758 } 759 } 760 761 @Override 762 public void mouseReleased(MouseEvent ev) { 763 if (ev.getButton() != MouseEvent.BUTTON1) 764 return; 765 if (!isVisible() || !isMapModeOk()) 766 return; 767 768 Point mousePos = ev.getPoint(); 769 boolean cycle = cycleModeArmed && lastSelPos != null && lastSelPos.equals(mousePos); 770 int idx = getPhotoIdxUnderMouse(ev, cycle); 771 if (idx >= 0) { 772 lastSelPos = mousePos; 773 cycleModeArmed = false; 774 data.setSelectedImage(data.getImages().get(idx)); 775 } 776 } 777 }; 811 mouseAdapter = new ImageMouseListener(); 778 812 779 813 mouseMotionAdapter = new MouseMotionAdapter() { -
trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java
r15204 r15333 67 67 private final ImgDisplayMouseListener imgMouseListener = new ImgDisplayMouseListener(); 68 68 69 private String emptyText; 69 70 private String osdText; 70 71 … … 699 700 700 701 /** 702 * Set the message displayed when there is no image to display. 703 * By default it display a simple No image 704 * @param emptyText the string to display 705 * @since 15333 706 */ 707 public void setEmptyText(String emptyText) { 708 this.emptyText = emptyText; 709 } 710 711 /** 701 712 * Sets the On-Screen-Display text. 702 713 * @param text text to display on top of the image … … 730 741 if (entry == null) { 731 742 g.setColor(Color.black); 732 String noImageStr = tr("No image"); 743 if (emptyText == null) { 744 emptyText = tr("No image"); 745 } 746 String noImageStr = emptyText; 733 747 Rectangle2D noImageSize = g.getFontMetrics(g.getFont()).getStringBounds(noImageStr, g); 734 748 g.drawString(noImageStr, -
trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java
r15219 r15333 14 14 import java.text.DateFormat; 15 15 import java.text.SimpleDateFormat; 16 import java.util.Collections; 17 import java.util.List; 16 18 import java.util.Optional; 17 19 … … 377 379 * @param data geo image data 378 380 * @param entry image entry 379 */ 381 * @deprecated Use {@link #displayImage} 382 */ 383 @Deprecated 380 384 public static void showImage(ImageData data, ImageEntry entry) { 381 385 getInstance().displayImage(data, entry); … … 417 421 418 422 /** 419 * Displays image for the given layer.423 * Displays a single image for the given layer. 420 424 * @param data the image data 421 425 * @param entry image entry 426 * @see #displayImages 422 427 */ 423 428 public void displayImage(ImageData data, ImageEntry entry) { 429 displayImages(data, Collections.singletonList(entry)); 430 } 431 432 /** 433 * Displays images for the given layer. 434 * @param data the image data 435 * @param entries image entries 436 * @since 15333 437 */ 438 public void displayImages(ImageData data, List<ImageEntry> entries) { 424 439 boolean imageChanged; 440 ImageEntry entry = entries != null && entries.size() == 1 ? entries.get(0) : null; 425 441 426 442 synchronized (this) { … … 491 507 btnDeleteFromDisk.setEnabled(false); 492 508 btnCopyPath.setEnabled(false); 509 if (entries != null && entries.size() > 1) { 510 imgDisplay.setEmptyText(tr("Multiple images selected")); 511 btnFirst.setEnabled(!isFirstImageSelected(data)); 512 btnLast.setEnabled(!isLastImageSelected(data)); 513 } 514 imgDisplay.setImage(null); 515 imgDisplay.setOsdText(""); 493 516 return; 494 517 } … … 504 527 } 505 528 529 private static boolean isLastImageSelected(ImageData data) { 530 return data.isImageSelected(data.getImages().get(data.getImages().size() - 1)); 531 } 532 533 private static boolean isFirstImageSelected(ImageData data) { 534 return data.isImageSelected(data.getImages().get(0)); 535 } 536 506 537 /** 507 538 * When an image is closed, really close it and do not pop … … 562 593 ImageData removedData = ((GeoImageLayer) e.getRemovedLayer()).getImageData(); 563 594 if (removedData == currentData) { 564 displayImage (null, null);595 displayImages(null, null); 565 596 } 566 597 removedData.removeImageDataUpdateListener(this); … … 592 623 @Override 593 624 public void selectedImageChanged(ImageData data) { 594 showImage(data, data.getSelectedImage());625 displayImages(data, data.getSelectedImages()); 595 626 } 596 627 597 628 @Override 598 629 public void imageDataUpdated(ImageData data) { 599 showImage(data, data.getSelectedImage());630 displayImages(data, data.getSelectedImages()); 600 631 } 601 632 }
Note:
See TracChangeset
for help on using the changeset viewer.