Ticket #11905: patch_multiple_image_core.patch
File patch_multiple_image_core.patch, 37.8 KB (added by , 5 years ago) |
---|
-
src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
diff --git a/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java b/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java index 48873a20c..e749ed44c 100644
a b public class SelectAction extends MapMode implements ModifierExListener, KeyPres 539 539 int dp = (int) lastMousePos.distance(e.getX(), e.getY()); 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)) 545 545 return; -
src/org/openstreetmap/josm/data/ImageData.java
diff --git a/src/org/openstreetmap/josm/data/ImageData.java b/src/org/openstreetmap/josm/data/ImageData.java index f84bf3ed7..00a65420f 100644
a b 1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.data; 3 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 4 6 import java.util.ArrayList; 5 7 import java.util.Collections; 6 8 import java.util.List; … … public class ImageData { 28 30 * Called when the selection change 29 31 * @param data the image data 30 32 */ 31 void selectedImage Changed(ImageData data);33 void selectedImagesChanged(ImageData data); 32 34 } 33 35 34 36 private final List<ImageEntry> data; 35 37 36 private int selectedImageIndex = -1;38 private List<Integer> selectedImagesIndex = new ArrayList<>(); 37 39 38 40 private final ListenerList<ImageDataUpdateListener> listeners = ListenerList.create(); 39 41 … … public class ImageData { 55 57 } else { 56 58 this.data = new ArrayList<>(); 57 59 } 60 selectedImagesIndex.add(-1); 58 61 } 59 62 60 63 /** … … public class ImageData { 86 89 data.addAll(otherData.getImages()); 87 90 Collections.sort(data); 88 91 89 final ImageEntry selected = otherData.getSelectedImage();90 91 92 // Suppress the double photos. 92 93 if (data.size() > 1) { 93 94 ImageEntry prev = data.get(data.size() - 1); … … public class ImageData { 100 101 } 101 102 } 102 103 } 103 if (selected != null) { 104 setSelectedImageIndex(data.indexOf(selected)); 104 105 final List<ImageEntry> selected = otherData.getSelectedImages(); 106 if (!selected.isEmpty()) { 107 setSelectedImageIndex(data.indexOf(selected.get(0))); 105 108 } 106 109 } 107 110 108 111 /** 109 * Return the current selected image 110 * @return the selected image as {@link ImageEntry} or null112 * Return the current selected images 113 * @return the selected images as list {@link ImageEntry} 111 114 */ 112 public ImageEntry getSelectedImage() { 113 if (selectedImageIndex > -1) { 114 return data.get(selectedImageIndex); 115 public List<ImageEntry> getSelectedImages() { 116 List<ImageEntry> selected = new ArrayList<>(selectedImagesIndex.size()); 117 for (Integer i: selectedImagesIndex) { 118 if (i != -1) { 119 selected.add(data.get(i)); 120 } 115 121 } 116 return null;122 return selected; 117 123 } 118 124 119 125 /** … … public class ImageData { 137 143 * @return {@code true} is there is a next image, {@code false} otherwise 138 144 */ 139 145 public boolean hasNextImage() { 140 return selectedImageIndex != data.size() - 1;146 return (selectedImagesIndex.size() == 1 && selectedImagesIndex.get(0) != data.size() - 1); 141 147 } 142 148 143 149 /** … … public class ImageData { 145 151 */ 146 152 public void selectNextImage() { 147 153 if (hasNextImage()) { 148 setSelectedImageIndex(selectedImage Index+ 1);154 setSelectedImageIndex(selectedImagesIndex.get(0) + 1); 149 155 } 150 156 } 151 157 … … public class ImageData { 154 160 * @return {@code true} is there is a previous image, {@code false} otherwise 155 161 */ 156 162 public boolean hasPreviousImage() { 157 return selectedImageIndex - 1 > -1;163 return (selectedImagesIndex.size() == 1 && selectedImagesIndex.get(0) - 1 > -1); 158 164 } 159 165 160 166 /** … … public class ImageData { 164 170 if (data.isEmpty()) { 165 171 return; 166 172 } 167 setSelectedImageIndex(Integer.max(0, selectedImage Index- 1));173 setSelectedImageIndex(Integer.max(0, selectedImagesIndex.get(0) - 1)); 168 174 } 169 175 170 176 /** … … public class ImageData { 175 181 setSelectedImageIndex(data.indexOf(image)); 176 182 } 177 183 184 /** 185 * Add image to the list of selected images 186 * @param image {@link ImageEntry} the image to add 187 */ 188 public void addImageToSelection(ImageEntry image) { 189 int index = data.indexOf(image); 190 if (selectedImagesIndex.get(0) == -1) { 191 setSelectedImage(image); 192 } else if (!selectedImagesIndex.contains(index)) { 193 selectedImagesIndex.add(index); 194 listeners.fireEvent(l -> l.selectedImagesChanged(this)); 195 } 196 } 197 198 /** 199 * Remove the image from the list of selected images 200 * @param image {@link ImageEntry} the image to remove 201 */ 202 public void removeImageToSelection(ImageEntry image) { 203 int index = data.indexOf(image); 204 selectedImagesIndex.remove(selectedImagesIndex.indexOf(index)); 205 if (selectedImagesIndex.isEmpty()) { 206 selectedImagesIndex.add(-1); 207 } 208 listeners.fireEvent(l -> l.selectedImagesChanged(this)); 209 } 210 178 211 /** 179 212 * Clear the selected image 180 213 */ 181 public void clearSelectedImage () {214 public void clearSelectedImages() { 182 215 setSelectedImageIndex(-1); 183 216 } 184 217 … … public class ImageData { 187 220 } 188 221 189 222 private void setSelectedImageIndex(int index, boolean forceTrigger) { 190 if (index == selectedImageIndex && !forceTrigger) { 223 if (selectedImagesIndex.size() > 1) { 224 selectedImagesIndex.clear(); 225 selectedImagesIndex.add(-1); 226 } 227 if (index == selectedImagesIndex.get(0) && !forceTrigger) { 191 228 return; 192 229 } 193 selectedImage Index = index;194 listeners.fireEvent(l -> l.selectedImage Changed(this));230 selectedImagesIndex.set(0, index); 231 listeners.fireEvent(l -> l.selectedImagesChanged(this)); 195 232 } 196 233 197 234 /** 198 235 * Remove the current selected image from the list 199 236 */ 200 237 public void removeSelectedImage() { 201 data.remove(getSelectedImage()); 202 if (selectedImageIndex == data.size()) { 238 List<ImageEntry> selected = getSelectedImages(); 239 if (selected.size() > 1) { 240 throw new IllegalStateException(tr("Multiple images have been selected")); 241 } 242 if (selected.isEmpty()) { 243 return; 244 } 245 data.remove(getSelectedImages().get(0)); 246 if (selectedImagesIndex.get(0) == data.size()) { 203 247 setSelectedImageIndex(data.size() - 1); 204 248 } else { 205 setSelectedImageIndex(selectedImage Index, true);249 setSelectedImageIndex(selectedImagesIndex.get(0), true); 206 250 } 207 251 } 208 252 253 /** 254 * Determines if the image is selected 255 * @param image the {@link ImageEntry} image 256 * @return {@code true} is the image is selected, {@code false} otherwise 257 */ 258 public boolean isImageSelected(ImageEntry image) { 259 int index = data.indexOf(image); 260 return selectedImagesIndex.contains(index); 261 } 262 209 263 /** 210 264 * Remove the image from the list and trigger update listener 211 265 * @param img the {@link ImageEntry} to remove -
src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java
diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java b/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java index e8ab7fbb9..e9f4710a7 100644
a b public class GeoImageLayer extends AbstractModifiableLayer implements 98 98 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 /** 103 105 * Image cycle mode flag. … … public class GeoImageLayer extends AbstractModifiableLayer implements 154 156 this.data.addImageDataUpdateListener(this); 155 157 } 156 158 159 private final class MouseListener 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 } 220 } 221 157 222 /** 158 223 * Loads a set of images, while displaying a dialog that indicates what the plugin is currently doing. 159 224 * In facts, this object is instantiated with a list of files. These files may be JPEG files or … … public class GeoImageLayer extends AbstractModifiableLayer implements 496 561 for (ImageEntry e : data.getImages()) { 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; 504 569 } … … public class GeoImageLayer extends AbstractModifiableLayer implements 515 580 } 516 581 } 517 582 518 ImageEntry e = data.getSelectedImage();519 if (e != null && e.getPos() != null) {520 Point p = mv.getPoint(e.getPos());583 for (ImageEntry e: data.getSelectedImages()) { 584 if (e != null && e.getPos() != null) { 585 Point p = mv.getPoint(e.getPos()); 521 586 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; 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;599 imgWidth = selectedIcon.getIconWidth(); 600 imgHeight = selectedIcon.getIconHeight(); 532 601 } 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 CCW545 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 602 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 } 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 } 567 632 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); 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 } 577 643 } … … public class GeoImageLayer extends AbstractModifiableLayer implements 587 653 * Show current photo on map and in image viewer. 588 654 */ 589 655 public void showCurrentPhoto() { 590 if ( data.getSelectedImage() != null) {656 if (!data.getSelectedImages().isEmpty()) { 591 657 clearOtherCurrentPhotos(); 592 658 } 593 659 updateBufferAndRepaint(); … … public class GeoImageLayer extends AbstractModifiableLayer implements 635 701 * or {@code -1} if there is no image at the mouse position 636 702 */ 637 703 private int getPhotoIdxUnderMouse(MouseEvent evt, boolean cycle) { 638 ImageEntry selectedImage = data.getSelectedImage();639 int selectedIndex = data.getImages().indexOf(selectedImage);704 ImageEntry selectedImage = this.data.getSelectedImages().isEmpty() ? null : this.data.getSelectedImages().get(0); 705 int selectedIndex = this.data.getImages().indexOf(selectedImage); 640 706 641 707 if (cycle && selectedImage != null) { 642 708 // Cycle loop is forward as that is the natural order. … … public class GeoImageLayer extends AbstractModifiableLayer implements 701 767 for (GeoImageLayer layer: 702 768 MainApplication.getLayerManager().getLayersOfType(GeoImageLayer.class)) { 703 769 if (layer != this) { 704 layer.getImageData().clearSelectedImage ();770 layer.getImageData().clearSelectedImages(); 705 771 } 706 772 } 707 773 } … … public class GeoImageLayer extends AbstractModifiableLayer implements 742 808 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 MouseListener(); 778 812 779 813 mouseMotionAdapter = new MouseMotionAdapter() { 780 814 @Override … … public class GeoImageLayer extends AbstractModifiableLayer implements 968 1002 } 969 1003 970 1004 @Override 971 public void selectedImage Changed(ImageData data) {1005 public void selectedImagesChanged(ImageData data) { 972 1006 showCurrentPhoto(); 973 1007 } 974 1008 -
src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java
diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java index cba56207b..80982233f 100644
a b public class ImageDisplay extends JComponent implements Destroyable, PreferenceC 66 66 67 67 private final ImgDisplayMouseListener imgMouseListener = new ImgDisplayMouseListener(); 68 68 69 private String emptyText; 70 69 71 private String osdText; 70 72 71 73 private static final BooleanProperty AGPIFO_STYLE = … … public class ImageDisplay extends JComponent implements Destroyable, PreferenceC 697 699 } 698 700 } 699 701 702 /** 703 * Set the message displayed when there is no image to display 704 * By default it display a simple No image 705 * @param emptyText the string to display 706 * @since XXX 707 */ 708 public void setEmptyText(String emptyText) { 709 this.emptyText = emptyText; 710 } 711 700 712 /** 701 713 * Sets the On-Screen-Display text. 702 714 * @param text text to display on top of the image … … public class ImageDisplay extends JComponent implements Destroyable, PreferenceC 729 741 Dimension size = getSize(); 730 742 if (entry == null) { 731 743 g.setColor(Color.black); 732 String noImageStr = tr("No image"); 744 if (this.emptyText == null) { 745 this.emptyText = tr("No image"); 746 } 747 String noImageStr = this.emptyText; 733 748 Rectangle2D noImageSize = g.getFontMetrics(g.getFont()).getStringBounds(noImageStr, g); 734 749 g.drawString(noImageStr, 735 750 (int) ((size.width - noImageSize.getWidth()) / 2), -
src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java
diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java index aa3c74fe2..837036aac 100644
a b import java.awt.event.KeyEvent; 13 13 import java.awt.event.WindowEvent; 14 14 import java.text.DateFormat; 15 15 import java.text.SimpleDateFormat; 16 import java.util.List; 16 17 17 18 import javax.swing.Box; 18 19 import javax.swing.JButton; … … public final class ImageViewerDialog extends ToggleDialog implements LayerChange 308 309 309 310 @Override 310 311 public void actionPerformed(ActionEvent e) { 311 if (currentData != null && currentData.getSelectedImage() != null) {312 ImageEntry toDelete = currentData.getSelectedImage ();312 if (currentData != null && !currentData.getSelectedImages().isEmpty()) { 313 ImageEntry toDelete = currentData.getSelectedImages().get(0); 313 314 314 315 int result = new ExtendedDialog( 315 316 MainApplication.getMainFrame(), … … public final class ImageViewerDialog extends ToggleDialog implements LayerChange 353 354 @Override 354 355 public void actionPerformed(ActionEvent e) { 355 356 if (currentData != null) { 356 ClipboardUtils.copyString(currentData.getSelectedImage ().getFile().toString());357 ClipboardUtils.copyString(currentData.getSelectedImages().get(0).getFile().toString()); 357 358 } 358 359 } 359 360 } … … public final class ImageViewerDialog extends ToggleDialog implements LayerChange 371 372 } 372 373 } 373 374 374 /**375 * Displays image for the given data.376 * @param data geo image data377 * @param entry image entry378 */379 public static void showImage(ImageData data, ImageEntry entry) {380 getInstance().displayImage(data, entry);381 }382 383 375 /** 384 376 * Enables (or disables) the "Previous" button. 385 377 * @param value {@code true} to enable the button, {@code false} otherwise … … public final class ImageViewerDialog extends ToggleDialog implements LayerChange 417 409 /** 418 410 * Displays image for the given layer. 419 411 * @param data the image data 420 * @param entr y image entry412 * @param entries the list of {@link ImageEntry} 421 413 */ 422 public void displayImage(ImageData data, ImageEntry entry) {414 public void displayImage(ImageData data, List<ImageEntry> entries) { 423 415 boolean imageChanged; 416 ImageEntry entry = null; 417 418 if (entries != null && entries.size() == 1) { 419 entry = entries.get(0); 420 } 424 421 425 422 synchronized (this) { 426 423 // TODO: pop up image dialog but don't load image again … … public final class ImageViewerDialog extends ToggleDialog implements LayerChange 478 475 // if this method is called to reinitialize dialog content with a blank image, 479 476 // do not actually show the dialog again with a blank image if currently hidden (fix #10672) 480 477 setTitle(tr("Geotagged Images")); 481 imgDisplay.setImage(null); 482 imgDisplay.setOsdText(""); 478 imgDisplay.setEmptyText(null); 483 479 setNextEnabled(false); 484 480 setPreviousEnabled(false); 485 481 btnDelete.setEnabled(false); 486 482 btnDeleteFromDisk.setEnabled(false); 487 483 btnCopyPath.setEnabled(false); 484 if (entries != null && entries.size() > 1) { 485 imgDisplay.setEmptyText(tr("Multiple images selected")); 486 btnFirst.setEnabled(!isFirstImageSelected(data)); 487 btnLast.setEnabled(!isLastImageSelected(data)); 488 } 489 imgDisplay.setImage(null); 490 imgDisplay.setOsdText(""); 488 491 return; 489 492 } 490 493 if (!isDialogShowing()) { … … public final class ImageViewerDialog extends ToggleDialog implements LayerChange 498 501 } 499 502 } 500 503 504 private boolean isLastImageSelected(ImageData data) { 505 return data.isImageSelected(data.getImages().get(data.getImages().size() - 1)); 506 } 507 508 private boolean isFirstImageSelected(ImageData data) { 509 return data.isImageSelected(data.getImages().get(0)); 510 } 511 501 512 /** 502 513 * When an image is closed, really close it and do not pop 503 514 * up the side dialog. … … public final class ImageViewerDialog extends ToggleDialog implements LayerChange 585 596 } 586 597 587 598 @Override 588 public void selectedImage Changed(ImageData data) {589 showImage(data, data.getSelectedImage());599 public void selectedImagesChanged(ImageData data) { 600 displayImage(data, data.getSelectedImages()); 590 601 } 591 602 592 603 @Override 593 604 public void imageDataUpdated(ImageData data) { 594 showImage(data, data.getSelectedImage());605 displayImage(data, data.getSelectedImages()); 595 606 } 596 607 } -
test/unit/org/openstreetmap/josm/data/ImageDataTest.java
diff --git a/test/unit/org/openstreetmap/josm/data/ImageDataTest.java b/test/unit/org/openstreetmap/josm/data/ImageDataTest.java index 9fcc7c5e9..2f1a6f90c 100644
a b package org.openstreetmap.josm.data; 3 3 4 4 import static org.junit.Assert.assertEquals; 5 5 import static org.junit.Assert.assertFalse; 6 import static org.junit.Assert.assertNull;7 6 import static org.junit.Assert.assertTrue; 8 7 9 8 import java.io.File; … … public class ImageDataTest { 32 31 } 33 32 34 33 @Test 35 public void testWith ullData() {34 public void testWithNullData() { 36 35 ImageData data = new ImageData(); 37 36 assertEquals(0, data.getImages().size()); 38 assert Null(data.getSelectedImage());37 assertEquals(0, data.getSelectedImages().size()); 39 38 data.selectFirstImage(); 40 assert Null(data.getSelectedImage());39 assertEquals(0, data.getSelectedImages().size()); 41 40 data.selectLastImage(); 42 assert Null(data.getSelectedImage());41 assertEquals(0, data.getSelectedImages().size()); 43 42 data.selectFirstImage(); 44 assert Null(data.getSelectedImage());43 assertEquals(0, data.getSelectedImages().size()); 45 44 data.selectPreviousImage(); 46 assert Null(data.getSelectedImage());45 assertEquals(0, data.getSelectedImages().size()); 47 46 assertFalse(data.hasNextImage()); 48 47 assertFalse(data.hasPreviousImage()); 49 48 data.removeSelectedImage(); … … public class ImageDataTest { 87 86 88 87 ImageData data = new ImageData(list); 89 88 data.selectFirstImage(); 90 assertEquals(list.get(0), data.getSelectedImage()); 89 assertEquals(1, data.getSelectedImages().size()); 90 assertEquals(list.get(0), data.getSelectedImages().get(0)); 91 91 } 92 92 93 93 @Test … … public class ImageDataTest { 97 97 98 98 ImageData data = new ImageData(list); 99 99 data.selectLastImage(); 100 assertEquals(list.get(1), data.getSelectedImage()); 100 assertEquals(1, data.getSelectedImages().size()); 101 assertEquals(list.get(1), data.getSelectedImages().get(0)); 101 102 } 102 103 103 104 @Test … … public class ImageDataTest { 107 108 ImageData data = new ImageData(list); 108 109 assertTrue(data.hasNextImage()); 109 110 data.selectNextImage(); 110 assertEquals(list.get(0), data.getSelectedImage()); 111 assertEquals(1, data.getSelectedImages().size()); 112 assertEquals(list.get(0), data.getSelectedImages().get(0)); 111 113 assertFalse(data.hasNextImage()); 112 114 data.selectNextImage(); 113 assertEquals(list.get(0), data.getSelectedImage ());115 assertEquals(list.get(0), data.getSelectedImages().get(0)); 114 116 } 115 117 116 118 @Test … … public class ImageDataTest { 123 125 data.selectLastImage(); 124 126 assertTrue(data.hasPreviousImage()); 125 127 data.selectPreviousImage(); 126 assertEquals(list.get(0), data.getSelectedImage()); 128 assertEquals(1, data.getSelectedImages().size()); 129 assertEquals(list.get(0), data.getSelectedImages().get(0)); 127 130 data.selectPreviousImage(); 128 assertEquals(list.get(0), data.getSelectedImage ());131 assertEquals(list.get(0), data.getSelectedImages().get(0)); 129 132 } 130 133 131 134 @Test … … public class ImageDataTest { 134 137 135 138 ImageData data = new ImageData(list); 136 139 data.setSelectedImage(list.get(0)); 137 assertEquals(list.get(0), data.getSelectedImage()); 140 assertEquals(1, data.getSelectedImages().size()); 141 assertEquals(list.get(0), data.getSelectedImages().get(0)); 138 142 } 139 143 140 144 @Test 141 public void testClearSelectedImage () {145 public void testClearSelectedImages() { 142 146 List<ImageEntry> list = getOneImage(); 143 147 144 148 ImageData data = new ImageData(list); 145 149 data.setSelectedImage(list.get(0)); 146 data.clearSelectedImage ();147 assert Null(data.getSelectedImage());150 data.clearSelectedImages(); 151 assertTrue(data.getSelectedImages().isEmpty()); 148 152 } 149 153 150 154 @Test … … public class ImageDataTest { 153 157 ImageData data = new ImageData(list); 154 158 ImageDataUpdateListener listener = new ImageDataUpdateListener() { 155 159 @Override 156 public void selectedImage Changed(ImageData data) {}160 public void selectedImagesChanged(ImageData data) {} 157 161 158 162 @Override 159 163 public void imageDataUpdated(ImageData data) {} 160 164 }; 161 165 new Expectations(listener) {{ 162 listener.selectedImage Changed(data); times = 1;166 listener.selectedImagesChanged(data); times = 1; 163 167 }}; 164 168 data.addImageDataUpdateListener(listener); 165 169 data.selectFirstImage(); … … public class ImageDataTest { 173 177 data.selectFirstImage(); 174 178 data.removeSelectedImage(); 175 179 assertEquals(0, data.getImages().size()); 176 assert Null(data.getSelectedImage());180 assertEquals(0, data.getSelectedImages().size()); 177 181 } 178 182 179 183 @Test … … public class ImageDataTest { 183 187 ImageData data = new ImageData(list); 184 188 ImageDataUpdateListener listener = new ImageDataUpdateListener() { 185 189 @Override 186 public void selectedImage Changed(ImageData data) {}190 public void selectedImagesChanged(ImageData data) {} 187 191 188 192 @Override 189 193 public void imageDataUpdated(ImageData data) {} 190 194 }; 191 195 new Expectations(listener) {{ 192 listener.selectedImage Changed(data); times = 2;196 listener.selectedImagesChanged(data); times = 2; 193 197 }}; 194 198 data.addImageDataUpdateListener(listener); 195 199 data.selectFirstImage(); … … public class ImageDataTest { 202 206 ImageData data = new ImageData(list); 203 207 ImageDataUpdateListener listener = new ImageDataUpdateListener() { 204 208 @Override 205 public void selectedImage Changed(ImageData data) {}209 public void selectedImagesChanged(ImageData data) {} 206 210 207 211 @Override 208 212 public void imageDataUpdated(ImageData data) {} … … public class ImageDataTest { 237 241 238 242 data.mergeFrom(data2); 239 243 assertEquals(3, data.getImages().size()); 240 assertEquals(list1.get(0), data.getSelectedImage()); 244 assertEquals(1, data.getSelectedImages().size()); 245 assertEquals(list1.get(0), data.getSelectedImages().get(0)); 241 246 } 242 247 243 248 @Test … … public class ImageDataTest { 253 258 254 259 data.mergeFrom(data2); 255 260 assertEquals(3, data.getImages().size()); 256 assertEquals(list2.get(0), data.getSelectedImage()); 261 assertEquals(1, data.getSelectedImages().size()); 262 assertEquals(list2.get(0), data.getSelectedImages().get(0)); 263 } 264 265 @Test 266 public void testAddImageToSelection() { 267 List<ImageEntry> list = getOneImage(); 268 list.add(new ImageEntry(new File("test2"))); 269 270 ImageData data = new ImageData(list); 271 data.addImageToSelection(list.get(0)); 272 data.addImageToSelection(list.get(0)); 273 assertEquals(1, data.getSelectedImages().size()); 274 data.addImageToSelection(list.get(1)); 275 assertEquals(2, data.getSelectedImages().size()); 276 } 277 278 @Test 279 public void testRemoveImageToSelection() { 280 List<ImageEntry> list = getOneImage(); 281 list.add(new ImageEntry()); 282 283 ImageData data = new ImageData(list); 284 data.selectLastImage(); 285 data.removeImageToSelection(list.get(1)); 286 assertEquals(0, data.getSelectedImages().size()); 287 data.selectFirstImage(); 288 assertEquals(1, data.getSelectedImages().size()); 289 290 } 291 292 @Test 293 public void testIsSelected() { 294 List<ImageEntry> list = getOneImage(); 295 list.add(new ImageEntry(new File("test2"))); 296 297 ImageData data = new ImageData(list); 298 assertFalse(data.isImageSelected(list.get(0))); 299 data.selectFirstImage(); 300 assertTrue(data.isImageSelected(list.get(0))); 301 data.addImageToSelection(list.get(1)); 302 assertTrue(data.isImageSelected(list.get(0))); 303 assertTrue(data.isImageSelected(list.get(1))); 304 assertFalse(data.isImageSelected(new ImageEntry())); 305 } 306 307 @Test 308 public void testActionsWithMultipleImagesSelected() { 309 List<ImageEntry> list = this.getOneImage(); 310 list.add(new ImageEntry(new File("test2"))); 311 list.add(new ImageEntry(new File("test3"))); 312 list.add(new ImageEntry(new File("test3"))); 313 314 ImageData data = new ImageData(list); 315 data.addImageToSelection(list.get(1)); 316 data.addImageToSelection(list.get(2)); 317 318 assertFalse(data.hasNextImage()); 319 assertFalse(data.hasPreviousImage()); 320 321 data.clearSelectedImages(); 322 assertEquals(0, data.getSelectedImages().size()); 323 data.addImageToSelection(list.get(1)); 324 data.selectFirstImage(); 325 assertEquals(1, data.getSelectedImages().size()); 326 } 327 328 @Test 329 public void testTriggerListenerWhenNewImageIsSelectedAndRemoved() { 330 List<ImageEntry> list = this.getOneImage(); 331 list.add(new ImageEntry()); 332 ImageData data = new ImageData(list); 333 ImageDataUpdateListener listener = new ImageDataUpdateListener() { 334 @Override 335 public void selectedImagesChanged(ImageData data) {} 336 337 @Override 338 public void imageDataUpdated(ImageData data) {} 339 }; 340 new Expectations(listener) {{ 341 listener.selectedImagesChanged(data); times = 3; 342 }}; 343 data.addImageDataUpdateListener(listener); 344 data.selectFirstImage(); 345 data.addImageToSelection(list.get(1)); 346 data.removeImageToSelection(list.get(0)); 257 347 } 258 348 259 349 @Test … … public class ImageDataTest { 287 377 288 378 ImageDataUpdateListener listener = new ImageDataUpdateListener() { 289 379 @Override 290 public void selectedImage Changed(ImageData data) {}380 public void selectedImagesChanged(ImageData data) {} 291 381 292 382 @Override 293 383 public void imageDataUpdated(ImageData data) {} … … public class ImageDataTest { 307 397 308 398 ImageDataUpdateListener listener = new ImageDataUpdateListener() { 309 399 @Override 310 public void selectedImage Changed(ImageData data) {}400 public void selectedImagesChanged(ImageData data) {} 311 401 312 402 @Override 313 403 public void imageDataUpdated(ImageData data) {}