Changeset 17740 in josm
- Timestamp:
- 2021-04-11T11:29:10+02:00 (4 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/gui
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/dialogs/layer/LayerVisibilityAction.java
r16438 r17740 70 70 private static final double DEFAULT_COLORFUL_FACTOR = 1; 71 71 private static final double MAX_COLORFUL_FACTOR = 2; 72 private final LayerListModel model; 72 private final Supplier<Collection<Layer>> layerSupplier; 73 private final Supplier<Collection<ImageryFilterSettings>> filterSettingsSupplier; 73 74 private final JPopupMenu popup; 74 75 private SideButton sideButton; … … 85 86 */ 86 87 public LayerVisibilityAction(LayerListModel model) { 87 this.model = model; 88 this(model::getSelectedLayers, () -> 89 Utils.transform(Utils.filteredCollection(model.getSelectedLayers(), ImageryLayer.class), ImageryLayer::getFilterSettings)); 90 } 91 92 /** 93 * Creates a new {@link LayerVisibilityAction} 94 * @param layerSupplier supplies the layers which should be affected 95 * @param filterSettingsSupplier supplies the filter settings which should be affecgted 96 */ 97 public LayerVisibilityAction(Supplier<Collection<Layer>> layerSupplier, Supplier<Collection<ImageryFilterSettings>> filterSettingsSupplier) { 98 this.layerSupplier = layerSupplier; 99 this.filterSettingsSupplier = filterSettingsSupplier; 88 100 popup = new JPopupMenu(); 89 101 // prevent popup close on mouse wheel move … … 103 115 addContentEntry(new GammaFilterSlider()); 104 116 addContentEntry(new SharpnessSlider()); 105 addContentEntry(new ColorSelector( model::getSelectedLayers));117 addContentEntry(new ColorSelector()); 106 118 } 107 119 … … 112 124 113 125 void setVisibleFlag(boolean visible) { 114 for (Layer l : model.getSelectedLayers()) {126 for (Layer l : layerSupplier.get()) { 115 127 l.setVisible(visible); 116 128 } … … 136 148 137 149 void updateValues() { 138 List<Layer> layers = model.getSelectedLayers();139 140 boolean allVisible = true;141 boolean allHidden = true;142 for (Layer l : layers) {143 allVisible &= l.isVisible();144 allHidden &= !l.isVisible();145 }146 147 150 for (LayerVisibilityMenuEntry slider : sliders) { 148 slider.updateLayers( layers, allVisible, allHidden);151 slider.updateLayers(); 149 152 } 150 153 } … … 162 165 @Override 163 166 public void updateEnabledState() { 164 setEnabled(! model.getSelectedLayers().isEmpty());167 setEnabled(!layerSupplier.get().isEmpty() || !filterSettingsSupplier.get().isEmpty()); 165 168 } 166 169 … … 181 184 /** 182 185 * Update the displayed value depending on the current layers 183 * @param layers The layers 184 * @param allVisible <code>true</code> if all layers are visible 185 * @param allHidden <code>true</code> if all layers are hidden 186 */ 187 void updateLayers(List<Layer> layers, boolean allVisible, boolean allHidden); 186 */ 187 void updateLayers(); 188 188 189 189 /** … … 207 207 208 208 @Override 209 public void updateLayers(List<Layer> layers, boolean allVisible, boolean allHidden) { 209 public void updateLayers() { 210 Collection<Layer> layers = layerSupplier.get(); 211 boolean allVisible = layers.stream().allMatch(Layer::isVisible); 212 boolean allHidden = layers.stream().noneMatch(Layer::isVisible); 213 210 214 setEnabled(!layers.isEmpty()); 211 215 // TODO: Indicate tristate. … … 222 226 * This is a slider for a filter value. 223 227 * @author Michael Zangl 224 * 225 * @param <T> The layer type. 226 */ 227 private abstract class AbstractFilterSlider<T extends Layer> extends JPanel implements LayerVisibilityMenuEntry { 228 */ 229 private abstract class AbstractFilterSlider extends JPanel implements LayerVisibilityMenuEntry { 228 230 private final double minValue; 229 231 private final double maxValue; 230 private final Class<T> layerClassFilter;231 232 232 233 protected final JSlider slider = new JSlider(JSlider.HORIZONTAL); … … 237 238 * @param maxValue The maximum value to map to the right side. 238 239 * @param defaultValue The default value for resetting. 239 * @param layerClassFilter The type of layer influenced by this filter. 240 */ 241 AbstractFilterSlider(double minValue, double maxValue, double defaultValue, Class<T> layerClassFilter) { 240 */ 241 AbstractFilterSlider(double minValue, double maxValue, double defaultValue) { 242 242 super(new GridBagLayout()); 243 243 this.minValue = minValue; 244 244 this.maxValue = maxValue; 245 this.layerClassFilter = layerClassFilter;246 245 247 246 add(new JLabel(getIcon()), GBC.std().span(1, 2).insets(0, 0, 5, 0)); … … 284 283 * @see #getRealValue() 285 284 */ 286 protected void onStateChanged() { 287 Collection<T> layers = filterLayers(model.getSelectedLayers()); 288 for (T layer : layers) { 289 applyValueToLayer(layer); 290 } 291 } 285 protected abstract void onStateChanged(); 292 286 293 287 protected void mouseWheelMoved(MouseWheelEvent e) { … … 307 301 } 308 302 309 abstract void applyValueToLayer(T layer);310 311 303 protected double getRealValue() { 312 304 return convertToRealValue(slider.getValue()); … … 330 322 331 323 public abstract String getLabel(); 332 333 @Override334 public void updateLayers(List<Layer> layers, boolean allVisible, boolean allHidden) {335 Collection<? extends Layer> usedLayers = filterLayers(layers);336 setVisible(!usedLayers.isEmpty());337 if (usedLayers.stream().noneMatch(Layer::isVisible)) {338 slider.setEnabled(false);339 } else {340 slider.setEnabled(true);341 updateSliderWhileEnabled(usedLayers, allHidden);342 }343 }344 345 protected Collection<T> filterLayers(List<Layer> layers) {346 return Utils.filteredCollection(layers, layerClassFilter);347 }348 349 protected abstract void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden);350 324 351 325 @Override … … 361 335 * @see Layer#setOpacity(double) 362 336 */ 363 class OpacitySlider extends AbstractFilterSlider <Layer>{337 class OpacitySlider extends AbstractFilterSlider { 364 338 /** 365 339 * Create a new {@link OpacitySlider}. 366 340 */ 367 341 OpacitySlider() { 368 super(0, 1, DEFAULT_OPACITY , Layer.class);342 super(0, 1, DEFAULT_OPACITY); 369 343 setLabels("0%", "50%", "100%"); 370 344 slider.setToolTipText(tr("Adjust opacity of the layer.") + " " + tr("Double click to reset.")); … … 376 350 setVisibleFlag(false); 377 351 } else { 378 super.onStateChanged(); 352 for (Layer layer : layerSupplier.get()) { 353 layer.setOpacity(getRealValue()); 354 } 379 355 } 380 356 } … … 382 358 @Override 383 359 protected void mouseWheelMoved(MouseWheelEvent e) { 384 if (!isEnabled() && ! filterLayers(model.getSelectedLayers()).isEmpty() && e.getPreciseWheelRotation() < 0) {360 if (!isEnabled() && !layerSupplier.get().isEmpty() && e.getPreciseWheelRotation() < 0) { 385 361 // make layer visible and set the value. 386 362 // this allows users to use the mouse wheel to make the layer visible if it was hidden previously. … … 393 369 394 370 @Override 395 protected void applyValueToLayer(Layer layer) { 396 layer.setOpacity(getRealValue()); 397 } 398 399 @Override 400 protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) { 371 public void updateLayers() { 372 Collection<Layer> usedLayers = layerSupplier.get(); 373 setVisible(!usedLayers.isEmpty()); 374 if (usedLayers.stream().noneMatch(Layer::isVisible)) { 375 slider.setEnabled(false); 376 return; 377 } 378 slider.setEnabled(true); 401 379 double opacity = usedLayers.stream() 402 380 .mapToDouble(Layer::getOpacity) … … 432 410 * @see ImageryFilterSettings#setGamma(double) 433 411 */ 434 private class GammaFilterSlider extends AbstractFilterSlider <ImageryLayer>{412 private class GammaFilterSlider extends AbstractFilterSlider { 435 413 436 414 /** … … 438 416 */ 439 417 GammaFilterSlider() { 440 super(-1, 1, DEFAULT_GAMMA_VALUE , ImageryLayer.class);418 super(-1, 1, DEFAULT_GAMMA_VALUE); 441 419 setLabels("0", "1", "∞"); 442 420 slider.setToolTipText(tr("Adjust gamma value of the layer.") + " " + tr("Double click to reset.")); … … 444 422 445 423 @Override 446 protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) { 447 double gamma = ((ImageryLayer) usedLayers.iterator().next()).getFilterSettings().getGamma(); 448 setRealValue(mapGammaToInterval(gamma)); 449 } 450 451 @Override 452 protected void applyValueToLayer(ImageryLayer layer) { 453 layer.getFilterSettings().setGamma(mapIntervalToGamma(getRealValue())); 424 public void updateLayers() { 425 Collection<ImageryFilterSettings> settings = filterSettingsSupplier.get(); 426 setVisible(!settings.isEmpty()); 427 if (!settings.isEmpty()) { 428 double gamma = settings.iterator().next().getGamma(); 429 setRealValue(mapGammaToInterval(gamma)); 430 } 431 } 432 433 @Override 434 protected void onStateChanged() { 435 for (ImageryFilterSettings settings : filterSettingsSupplier.get()) { 436 settings.setGamma(mapIntervalToGamma(getRealValue())); 437 } 454 438 } 455 439 … … 492 476 * @see ImageryFilterSettings#setSharpenLevel(double) 493 477 */ 494 private class SharpnessSlider extends AbstractFilterSlider <ImageryLayer>{478 private class SharpnessSlider extends AbstractFilterSlider { 495 479 496 480 /** … … 498 482 */ 499 483 SharpnessSlider() { 500 super(0, MAX_SHARPNESS_FACTOR, DEFAULT_SHARPNESS_FACTOR , ImageryLayer.class);484 super(0, MAX_SHARPNESS_FACTOR, DEFAULT_SHARPNESS_FACTOR); 501 485 setLabels(trc("image sharpness", "blurred"), trc("image sharpness", "normal"), trc("image sharpness", "sharp")); 502 486 slider.setToolTipText(tr("Adjust sharpness/blur value of the layer.") + " " + tr("Double click to reset.")); … … 504 488 505 489 @Override 506 protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) { 507 setRealValue(((ImageryLayer) usedLayers.iterator().next()).getFilterSettings().getSharpenLevel()); 508 } 509 510 @Override 511 protected void applyValueToLayer(ImageryLayer layer) { 512 layer.getFilterSettings().setSharpenLevel(getRealValue()); 490 public void updateLayers() { 491 Collection<ImageryFilterSettings> settings = filterSettingsSupplier.get(); 492 setVisible(!settings.isEmpty()); 493 if (!settings.isEmpty()) { 494 setRealValue(settings.iterator().next().getSharpenLevel()); 495 } 496 } 497 498 @Override 499 protected void onStateChanged() { 500 for (ImageryFilterSettings settings : filterSettingsSupplier.get()) { 501 settings.setSharpenLevel(getRealValue()); 502 } 513 503 } 514 504 … … 530 520 * @see ImageryFilterSettings#setColorfulness(double) 531 521 */ 532 private class ColorfulnessSlider extends AbstractFilterSlider <ImageryLayer>{522 private class ColorfulnessSlider extends AbstractFilterSlider { 533 523 534 524 /** … … 536 526 */ 537 527 ColorfulnessSlider() { 538 super(0, MAX_COLORFUL_FACTOR, DEFAULT_COLORFUL_FACTOR , ImageryLayer.class);528 super(0, MAX_COLORFUL_FACTOR, DEFAULT_COLORFUL_FACTOR); 539 529 setLabels(trc("image colorfulness", "less"), trc("image colorfulness", "normal"), trc("image colorfulness", "more")); 540 530 slider.setToolTipText(tr("Adjust colorfulness of the layer.") + " " + tr("Double click to reset.")); … … 542 532 543 533 @Override 544 protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) { 545 setRealValue(((ImageryLayer) usedLayers.iterator().next()).getFilterSettings().getColorfulness()); 546 } 547 548 @Override 549 protected void applyValueToLayer(ImageryLayer layer) { 550 layer.getFilterSettings().setColorfulness(getRealValue()); 534 public void updateLayers() { 535 Collection<ImageryFilterSettings> settings = filterSettingsSupplier.get(); 536 setVisible(!settings.isEmpty()); 537 if (!settings.isEmpty()) { 538 setRealValue(settings.iterator().next().getColorfulness()); 539 } 540 } 541 542 @Override 543 protected void onStateChanged() { 544 for (ImageryFilterSettings settings : filterSettingsSupplier.get()) { 545 settings.setColorfulness(getRealValue()); 546 } 551 547 } 552 548 … … 566 562 * @author Michael Zangl 567 563 */ 568 private staticclass ColorSelector extends JPanel implements LayerVisibilityMenuEntry {569 570 private staticfinal Border NORMAL_BORDER = BorderFactory.createEmptyBorder(2, 2, 2, 2);571 private staticfinal Border SELECTED_BORDER = BorderFactory.createLineBorder(Color.BLACK, 2);564 private class ColorSelector extends JPanel implements LayerVisibilityMenuEntry { 565 566 private final Border NORMAL_BORDER = BorderFactory.createEmptyBorder(2, 2, 2, 2); 567 private final Border SELECTED_BORDER = BorderFactory.createLineBorder(Color.BLACK, 2); 572 568 573 569 // TODO: Nicer color palette 574 private staticfinal Color[] COLORS = {570 private final Color[] COLORS = { 575 571 Color.RED, 576 572 Color.ORANGE, … … 581 577 Color.GRAY, 582 578 }; 583 private final Supplier<List<Layer>> layerSupplier;584 579 private final HashMap<Color, JPanel> panels = new HashMap<>(); 585 580 586 ColorSelector( Supplier<List<Layer>> layerSupplier) {581 ColorSelector() { 587 582 super(new GridBagLayout()); 588 this.layerSupplier = layerSupplier;589 583 add(new JLabel(tr("Color")), GBC.eol().insets(24 + 10, 0, 0, 0)); 590 584 for (Color color : COLORS) { … … 604 598 @Override 605 599 public void mouseClicked(MouseEvent e) { 606 List<Layer> layers = layerSupplier.get();600 Collection<Layer> layers = layerSupplier.get(); 607 601 for (Layer l : layers) { 608 602 if (l instanceof GpxLayer) { … … 623 617 624 618 @Override 625 public void updateLayers(List<Layer> layers, boolean allVisible, boolean allHidden) { 619 public void updateLayers() { 620 Collection<Layer> layers = layerSupplier.get(); 626 621 List<Color> colors = layers.stream().filter(l -> l instanceof GpxLayer) 627 622 .map(l -> ((GpxLayer) l).getColor()) -
trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java
r17553 r17740 32 32 import org.openstreetmap.josm.data.preferences.BooleanProperty; 33 33 import org.openstreetmap.josm.data.preferences.DoubleProperty; 34 import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings; 35 import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings.FilterChangeListener; 34 36 import org.openstreetmap.josm.spi.preferences.Config; 35 37 import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent; … … 37 39 import org.openstreetmap.josm.tools.Destroyable; 38 40 import org.openstreetmap.josm.tools.ExifReader; 41 import org.openstreetmap.josm.tools.ImageProcessor; 39 42 import org.openstreetmap.josm.tools.ImageProvider; 40 43 import org.openstreetmap.josm.tools.Logging; … … 45 48 * Offers basic mouse interaction (zoom, drag) and on-screen text. 46 49 */ 47 public class ImageDisplay extends JComponent implements Destroyable, PreferenceChangedListener {50 public class ImageDisplay extends JComponent implements Destroyable, PreferenceChangedListener, FilterChangeListener { 48 51 49 52 /** The file that is currently displayed */ … … 51 54 52 55 /** The image currently displayed */ 53 private transient Image image; 56 private transient BufferedImage image; 57 58 /** 59 * Process the image before it is being displayed 60 */ 61 private final ImageProcessor imageProcessor; 54 62 55 63 /** The image currently displayed */ … … 295 303 @Override 296 304 public void run() { 297 Image img;305 BufferedImage img; 298 306 try { 299 307 img = ImageIO.read(file); … … 690 698 */ 691 699 public ImageDisplay() { 700 this(image -> image); 701 } 702 703 public ImageDisplay(ImageProcessor imageProcessor) { 692 704 addMouseListener(imgMouseListener); 693 705 addMouseWheelListener(imgMouseListener); … … 695 707 Config.getPref().addPreferenceChangeListener(this); 696 708 preferenceChanged(null); 709 this.imageProcessor = imageProcessor; 710 if (imageProcessor instanceof ImageryFilterSettings) { 711 ((ImageryFilterSettings) imageProcessor).addFilterChangeListener(this); 712 } 697 713 } 698 714 … … 703 719 removeMouseMotionListener(imgMouseListener); 704 720 Config.getPref().removePreferenceChangeListener(this); 721 if (imageProcessor instanceof ImageryFilterSettings) { 722 ((ImageryFilterSettings) imageProcessor).removeFilterChangeListener(this); 723 } 705 724 } 706 725 … … 744 763 745 764 @Override 765 public void filterChanged() { 766 repaint(); 767 } 768 769 @Override 746 770 public void paintComponent(Graphics g) { 747 771 ImageEntry entry; 748 Image image;772 BufferedImage image; 749 773 VisRect visibleRect; 750 774 boolean errorLoading; … … 818 842 r.x = r.y = 0; 819 843 } 844 } 845 846 if (image != null) { 847 image = imageProcessor.process(image); 820 848 } 821 849 -
trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java
r17733 r17740 36 36 import org.openstreetmap.josm.gui.dialogs.DialogsPanel.Action; 37 37 import org.openstreetmap.josm.gui.dialogs.ToggleDialog; 38 import org.openstreetmap.josm.gui.dialogs.layer.LayerVisibilityAction; 38 39 import org.openstreetmap.josm.gui.layer.Layer; 39 40 import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent; … … 43 44 import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent; 44 45 import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener; 46 import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings; 45 47 import org.openstreetmap.josm.tools.ImageProvider; 46 48 import org.openstreetmap.josm.tools.Logging; … … 53 55 */ 54 56 public final class ImageViewerDialog extends ToggleDialog implements LayerChangeListener, ActiveLayerChangeListener, ImageDataUpdateListener { 57 58 private final ImageryFilterSettings imageryFilterSettings = new ImageryFilterSettings(); 55 59 56 60 private final ImageZoomAction imageZoomAction = new ImageZoomAction(); … … 64 68 private final ImageLastAction imageLastAction = new ImageLastAction(); 65 69 private final ImageCopyPathAction imageCopyPathAction = new ImageCopyPathAction(); 66 67 private final ImageDisplay imgDisplay = new ImageDisplay(); 70 private final LayerVisibilityAction visibilityAction = new LayerVisibilityAction(Collections::emptyList, 71 () -> Collections.singleton(imageryFilterSettings)); 72 73 private final ImageDisplay imgDisplay = new ImageDisplay(imageryFilterSettings); 68 74 private boolean centerView; 69 75 … … 162 168 buttons.add(Box.createRigidArea(new Dimension(7, 0))); 163 169 buttons.add(btnCopyPath); 170 buttons.add(Box.createRigidArea(new Dimension(7, 0))); 171 buttons.add(new JButton(visibilityAction)); 164 172 165 173 JPanel bottomPane = new JPanel(new GridBagLayout()); -
trunk/src/org/openstreetmap/josm/gui/layer/imagery/ImageryFilterSettings.java
r15659 r17740 2 2 package org.openstreetmap.josm.gui.layer.imagery; 3 3 4 import java.awt.image.BufferedImage; 4 5 import java.util.Arrays; 5 6 import java.util.List; … … 13 14 * @since 10547 14 15 */ 15 public class ImageryFilterSettings {16 public class ImageryFilterSettings implements ImageProcessor { 16 17 17 18 protected GammaImageProcessor gammaImageProcessor = new GammaImageProcessor(); … … 85 86 } 86 87 88 @Override 89 public BufferedImage process(BufferedImage image) { 90 for (ImageProcessor processor : getProcessors()) { 91 image = processor.process(image); 92 } 93 return image; 94 } 95 87 96 /** 88 97 * Adds a filter change listener
Note:
See TracChangeset
for help on using the changeset viewer.