Changeset 10011 in josm
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java
r9975 r10011 8 8 import java.awt.Dimension; 9 9 import java.awt.Font; 10 import java.awt.GridBagLayout; 10 11 import java.awt.Point; 11 12 import java.awt.Rectangle; … … 19 20 import java.util.ArrayList; 20 21 import java.util.Arrays; 22 import java.util.Collection; 21 23 import java.util.Collections; 22 24 import java.util.List; … … 24 26 25 27 import javax.swing.AbstractAction; 28 import javax.swing.BorderFactory; 26 29 import javax.swing.DefaultCellEditor; 27 30 import javax.swing.DefaultListSelectionModel; … … 31 34 import javax.swing.JLabel; 32 35 import javax.swing.JMenuItem; 36 import javax.swing.JPanel; 33 37 import javax.swing.JPopupMenu; 34 38 import javax.swing.JSlider; … … 67 71 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher; 68 72 import org.openstreetmap.josm.tools.CheckParameterUtil; 73 import org.openstreetmap.josm.tools.GBC; 69 74 import org.openstreetmap.josm.tools.ImageProvider; 70 75 import org.openstreetmap.josm.tools.InputMapUtils; … … 264 269 adaptTo(showHideLayerAction, selectionModel); 265 270 266 // -- layer opacity action 267 LayerOpacityAction layerOpacityAction = new LayerOpacityAction(model); 268 adaptTo(layerOpacityAction, selectionModel); 269 SideButton opacityButton = new SideButton(layerOpacityAction, false); 270 layerOpacityAction.setCorrespondingSideButton(opacityButton); 271 272 // -- layer gamma action 273 LayerGammaAction layerGammaAction = new LayerGammaAction(model); 274 adaptTo(layerGammaAction, selectionModel); 275 SideButton gammaButton = new SideButton(layerGammaAction, false); 276 layerGammaAction.setCorrespondingSideButton(gammaButton); 271 LayerVisibilityAction visibilityAction = new LayerVisibilityAction(model); 272 adaptTo(visibilityAction, selectionModel); 273 SideButton visibilityButton = new SideButton(visibilityAction, false); 274 visibilityAction.setCorrespondingSideButton(visibilityButton); 277 275 278 276 // -- delete layer action … … 301 299 new SideButton(moveDownAction, false), 302 300 new SideButton(activateLayerAction, false), 303 new SideButton(showHideLayerAction, false), 304 opacityButton, 305 gammaButton, 301 visibilityButton, 306 302 new SideButton(deleteLayerAction, false) 307 303 )); … … 529 525 530 526 /** 531 * Abstract action which allows to adjust a double value using a slider 532 */ 533 public abstract static class AbstractLayerPropertySliderAction extends AbstractAction implements IEnabledStateUpdating, LayerAction { 534 protected final LayerListModel model; 535 protected final JPopupMenu popup; 536 protected final JSlider slider; 537 private final double factor; 527 * This is a menu that includes all settings for the layer visibility. It combines gamma/opacity sliders and the visible-checkbox. 528 * 529 * @author Michael Zangl 530 */ 531 public static final class LayerVisibilityAction extends AbstractAction implements IEnabledStateUpdating, LayerAction { 532 protected static final int SLIDER_STEPS = 100; 533 private static final double MAX_GAMMA_FACTOR = 2; 534 private final LayerListModel model; 535 private final JPopupMenu popup; 536 private JSlider opacitySlider; 537 private JSlider gammaSlider; 538 538 private SideButton sideButton; 539 540 protected AbstractLayerPropertySliderAction(LayerListModel model, String name, final double factor) { 541 super(name); 539 private JCheckBox visibilityCheckbox; 540 541 /** 542 * Creates a new {@link LayerVisibilityAction} 543 * @param model The list to get the selection from. 544 */ 545 public LayerVisibilityAction(LayerListModel model) { 542 546 this.model = model; 543 this.factor = factor;544 updateEnabledState();545 546 547 popup = new JPopupMenu(); 547 slider = new JSlider(JSlider.VERTICAL); 548 slider.addChangeListener(new ChangeListener() { 548 549 // just to add a border 550 JPanel content = new JPanel(); 551 popup.add(content); 552 content.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 553 content.setLayout(new GridBagLayout()); 554 555 putValue(SMALL_ICON, ImageProvider.get("dialogs/layerlist", "visibility")); 556 putValue(SHORT_DESCRIPTION, tr("Change visibility of the selected layer.")); 557 558 visibilityCheckbox = new JCheckBox(tr("Show layer")); 559 visibilityCheckbox.addChangeListener(new ChangeListener() { 549 560 @Override 550 561 public void stateChanged(ChangeEvent e) { 551 setV alue(slider.getValue() / factor);562 setVisible(visibilityCheckbox.isSelected()); 552 563 } 553 564 }); 554 popup.add(slider); 555 } 556 557 protected abstract void setValue(double value); 558 559 protected abstract double getValue(); 560 561 /** 562 * Sets the corresponding side button. 563 * @param sideButton the corresponding side button 564 */ 565 final void setCorrespondingSideButton(SideButton sideButton) { 566 this.sideButton = sideButton; 565 content.add(visibilityCheckbox, GBC.eop()); 566 567 content.add(new JLabel(ImageProvider.get("dialogs/layerlist", "transparency")), GBC.std().span(1, 2).insets(0, 0, 5, 0)); 568 content.add(new JLabel(tr("Opacity")), GBC.eol()); 569 opacitySlider = new JSlider(JSlider.HORIZONTAL); 570 opacitySlider.setMaximum(SLIDER_STEPS); 571 opacitySlider.addChangeListener(new ChangeListener() { 572 @Override 573 public void stateChanged(ChangeEvent e) { 574 setOpacityValue(readOpacityValue(), opacitySlider.getValueIsAdjusting()); 575 } 576 }); 577 opacitySlider.setToolTipText(tr("Adjust opacity of the layer.")); 578 content.add(opacitySlider, GBC.eop()); 579 580 content.add(new JLabel(ImageProvider.get("dialogs/layerlist", "gamma")), GBC.std().span(1, 2).insets(0, 0, 5, 0)); 581 content.add(new JLabel(tr("Gamma")), GBC.eol()); 582 gammaSlider = new JSlider(JSlider.HORIZONTAL); 583 gammaSlider.setMaximum(SLIDER_STEPS); 584 gammaSlider.addChangeListener(new ChangeListener() { 585 @Override 586 public void stateChanged(ChangeEvent e) { 587 setGammaValue(readGammaValue()); 588 } 589 }); 590 gammaSlider.setToolTipText(tr("Adjust gamma value of the layer.")); 591 content.add(gammaSlider, GBC.eol()); 592 } 593 594 protected double readOpacityValue() { 595 return (double) opacitySlider.getValue() / SLIDER_STEPS; 596 } 597 598 protected double readGammaValue() { 599 return (double) gammaSlider.getValue() / SLIDER_STEPS * MAX_GAMMA_FACTOR; 600 } 601 602 protected void setVisible(boolean visible) { 603 for (Layer l : model.getSelectedLayers()) { 604 l.setVisible(visible); 605 } 606 updateValues(); 607 } 608 609 protected void setOpacityValue(double value, boolean adjusting) { 610 if (value <= 0 && !adjusting) { 611 setVisible(false); 612 } else { 613 for (Layer l : model.getSelectedLayers()) { 614 l.setOpacity(value); 615 } 616 } 617 } 618 619 protected void setGammaValue(double value) { 620 for (ImageryLayer imageryLayer : Utils.filteredCollection(model.getSelectedLayers(), ImageryLayer.class)) { 621 imageryLayer.setGamma(value); 622 } 567 623 } 568 624 569 625 @Override 570 626 public void actionPerformed(ActionEvent e) { 571 slider.setValue((int) (getValue() * factor));627 updateValues(); 572 628 if (e.getSource() == sideButton) { 573 629 popup.show(sideButton, 0, sideButton.getHeight()); … … 579 635 } 580 636 637 protected void updateValues() { 638 List<Layer> layers = model.getSelectedLayers(); 639 640 visibilityCheckbox.setEnabled(!layers.isEmpty()); 641 boolean allVisible = true; 642 boolean allHidden = true; 643 for (Layer l : layers) { 644 allVisible &= l.isVisible(); 645 allHidden &= !l.isVisible(); 646 } 647 // TODO: Indicate tristate. 648 visibilityCheckbox.setSelected(allVisible && !allHidden); 649 650 updateOpacitySlider(layers, allHidden); 651 652 updateGammaSlider(layers, allHidden); 653 } 654 655 private void updateGammaSlider(List<Layer> layers, boolean allHidden) { 656 Collection<ImageryLayer> gammaLayers = Utils.filteredCollection(layers, ImageryLayer.class); 657 if (gammaLayers.isEmpty() || allHidden) { 658 gammaSlider.setEnabled(false); 659 } else { 660 gammaSlider.setEnabled(true); 661 double gamma = gammaLayers.iterator().next().getGamma(); 662 gammaSlider.setValue((int) (gamma * SLIDER_STEPS / MAX_GAMMA_FACTOR)); 663 } 664 } 665 666 private void updateOpacitySlider(List<Layer> layers, boolean allHidden) { 667 if (layers.isEmpty() || allHidden) { 668 opacitySlider.setEnabled(false); 669 } else { 670 opacitySlider.setEnabled(true); 671 double opacity = 0; 672 for (Layer l : layers) { 673 opacity += l.getOpacity(); 674 } 675 opacity /= layers.size(); 676 if (opacity == 0) { 677 opacity = 1; 678 setOpacityValue(opacity, false); 679 } 680 opacitySlider.setValue((int) (opacity * SLIDER_STEPS)); 681 } 682 } 683 684 @Override 685 public boolean supportLayers(List<Layer> layers) { 686 return !layers.isEmpty(); 687 } 688 581 689 @Override 582 690 public Component createMenuComponent() { 583 691 return new JMenuItem(this); 584 692 } 585 }586 587 /**588 * Action which allows to change the opacity of one or more layers.589 */590 public static final class LayerOpacityAction extends AbstractLayerPropertySliderAction {591 private transient Layer layer;592 593 /**594 * Creates a {@link LayerOpacityAction} which allows to change the opacity of one or more layers.595 *596 * @param model layer list model597 * @param layer the layer. Must not be null.598 * @throws IllegalArgumentException if layer is null599 */600 public LayerOpacityAction(LayerListModel model, Layer layer) {601 this(model);602 CheckParameterUtil.ensureParameterNotNull(layer, "layer");603 this.layer = layer;604 updateEnabledState();605 }606 607 /**608 * Creates a {@link ShowHideLayerAction} which will toggle the visibility of the currently selected layers609 * @param model layer list model610 */611 public LayerOpacityAction(LayerListModel model) {612 super(model, tr("Opacity"), 100);613 putValue(SHORT_DESCRIPTION, tr("Adjust opacity of the layer."));614 putValue(SMALL_ICON, ImageProvider.get("dialogs/layerlist", "transparency"));615 }616 617 @Override618 protected void setValue(double value) {619 if (!isEnabled()) return;620 if (layer != null) {621 layer.setOpacity(value);622 } else {623 for (Layer l : model.getSelectedLayers()) {624 l.setOpacity(value);625 }626 }627 }628 629 @Override630 protected double getValue() {631 if (layer != null)632 return layer.getOpacity();633 else {634 double opacity = 0;635 List<Layer> layers = model.getSelectedLayers();636 for (Layer l : layers) {637 opacity += l.getOpacity();638 }639 return opacity / layers.size();640 }641 }642 693 643 694 @Override 644 695 public void updateEnabledState() { 645 if (layer == null) { 646 setEnabled(!model.getSelectedLayers().isEmpty()); 647 } else { 648 setEnabled(true); 649 } 650 } 651 652 @Override 653 public boolean supportLayers(List<Layer> layers) { 654 return true; 655 } 656 } 657 658 /** 659 * Action which allows to change the gamma of one imagery layer. 660 */ 661 public static final class LayerGammaAction extends AbstractLayerPropertySliderAction { 662 663 /** 664 * Constructs a new {@code LayerGammaAction}. 665 * @param model layer list model 666 */ 667 public LayerGammaAction(LayerListModel model) { 668 super(model, tr("Gamma"), 50); 669 putValue(SHORT_DESCRIPTION, tr("Adjust gamma value of the layer.")); 670 putValue(SMALL_ICON, ImageProvider.get("dialogs/layerlist", "gamma")); 671 } 672 673 @Override 674 protected void setValue(double value) { 675 for (ImageryLayer imageryLayer : Utils.filteredCollection(model.getSelectedLayers(), ImageryLayer.class)) { 676 imageryLayer.setGamma(value); 677 } 678 } 679 680 @Override 681 protected double getValue() { 682 return Utils.filteredCollection(model.getSelectedLayers(), ImageryLayer.class).iterator().next().getGamma(); 683 } 684 685 @Override 686 public void updateEnabledState() { 687 setEnabled(!Utils.filteredCollection(model.getSelectedLayers(), ImageryLayer.class).isEmpty()); 688 } 689 690 @Override 691 public boolean supportLayers(List<Layer> layers) { 692 return !Utils.filteredCollection(layers, ImageryLayer.class).isEmpty(); 696 setEnabled(!model.getSelectedLayers().isEmpty()); 697 } 698 699 /** 700 * Sets the corresponding side button. 701 * @param sideButton the corresponding side button 702 */ 703 void setCorrespondingSideButton(SideButton sideButton) { 704 this.sideButton = sideButton; 693 705 } 694 706 } -
trunk/src/org/openstreetmap/josm/gui/layer/Layer.java
r10008 r10011 361 361 } 362 362 363 /** 364 * Gets the opacity of the layer, in range 0...1 365 * @return The opacity 366 */ 363 367 public double getOpacity() { 364 368 return opacity; 365 369 } 366 370 371 /** 372 * Sets the opacity of the layer, in range 0...1 373 * @param opacity The opacity 374 * @throws IllegalArgumentException if the opacity is out of range 375 */ 367 376 public void setOpacity(double opacity) { 368 377 if (!(opacity >= 0 && opacity <= 1)) -
trunk/test/unit/org/openstreetmap/josm/gui/dialogs/LayerListDialogTest.java
r9926 r10011 3 3 4 4 import static org.junit.Assert.assertEquals; 5 import static org.junit.Assert.assertFalse; 5 6 import static org.junit.Assert.assertTrue; 6 7 … … 9 10 import org.openstreetmap.josm.JOSMFixture; 10 11 import org.openstreetmap.josm.Main; 11 import org.openstreetmap.josm.gui.dialogs.LayerListDialog.LayerGammaAction;12 12 import org.openstreetmap.josm.gui.dialogs.LayerListDialog.LayerListModel; 13 import org.openstreetmap.josm.gui.dialogs.LayerListDialog.Layer OpacityAction;13 import org.openstreetmap.josm.gui.dialogs.LayerListDialog.LayerVisibilityAction; 14 14 import org.openstreetmap.josm.gui.layer.TMSLayer; 15 15 import org.openstreetmap.josm.gui.layer.TMSLayerTest; … … 29 29 30 30 /** 31 * Unit test of {@link Layer GammaAction} class.31 * Unit test of {@link LayerVisibilityAction} class. 32 32 */ 33 33 @Test 34 public void testLayer GammaAction() {34 public void testLayerVisibilityAction() { 35 35 TMSLayer layer = TMSLayerTest.createTmsLayer(); 36 36 try { 37 LayerListModel model = LayerListDialog.getInstance().getModel(); 38 LayerVisibilityAction action = new LayerVisibilityAction(model); 39 action.updateEnabledState(); 40 assertFalse(action.isEnabled()); 41 37 42 Main.map.mapView.addLayer(layer); 38 LayerListModel model = LayerListDialog.getInstance().getModel();39 LayerGammaAction action = new LayerGammaAction(model);40 43 action.updateEnabledState(); 41 44 assertTrue(action.isEnabled()); 42 45 assertTrue(action.supportLayers(model.getSelectedLayers())); 43 assertEquals(1.0, action.getValue(), 1e-15);44 action.setValue(0.5);45 assertEquals(0.5, action.getValue(), 1e-15);46 } finally {47 Main.map.mapView.removeLayer(layer);48 }49 }50 46 51 /** 52 * Unit test of {@link LayerOpacityAction} class. 53 */ 54 @Test 55 public void testLayerOpacityAction() { 56 TMSLayer layer = TMSLayerTest.createTmsLayer(); 57 try { 58 Main.map.mapView.addLayer(layer); 59 LayerListModel model = LayerListDialog.getInstance().getModel(); 60 LayerOpacityAction action = new LayerOpacityAction(model); 61 action.updateEnabledState(); 62 assertTrue(action.isEnabled()); 63 assertTrue(action.supportLayers(model.getSelectedLayers())); 64 assertEquals(1.0, action.getValue(), 1e-15); 65 action.setValue(0.5); 66 assertEquals(0.5, action.getValue(), 1e-15); 47 // now check values 48 action.updateValues(); 49 assertEquals(1.0, action.readOpacityValue(), 1e-15); 50 assertEquals(1.0, action.readGammaValue(), 1e-15); 51 52 action.setOpacityValue(.5, false); 53 action.setGammaValue(1.5); 54 action.updateValues(); 55 56 assertEquals(0.5, action.readOpacityValue(), 1e-15); 57 assertEquals(1.5, action.readGammaValue(), 1e-15); 58 59 action.setVisible(false); 60 action.updateValues(); 61 assertFalse(layer.isVisible()); 62 63 action.setVisible(true); 64 action.updateValues(); 65 assertTrue(layer.isVisible()); 66 67 // layer stays visible during adjust 68 action.setOpacityValue(0, true); 69 assertEquals(0, layer.getOpacity(), 1e-15); 70 layer.setOpacity(.1); // to make layer.isVisible work 71 assertTrue(layer.isVisible()); 72 layer.setOpacity(0); 73 74 action.setOpacityValue(0, false); 75 assertEquals(0, layer.getOpacity(), 1e-15); 76 layer.setOpacity(.1); // to make layer.isVisible work 77 assertFalse(layer.isVisible()); 78 layer.setOpacity(0); 79 action.updateValues(); 80 81 // Opacity reset when it was 0 and user set layer to visible. 82 action.setVisible(true); 83 action.updateValues(); 84 assertEquals(1.0, action.readOpacityValue(), 1e-15); 85 assertEquals(1.0, layer.getOpacity(), 1e-15); 86 67 87 } finally { 68 88 Main.map.mapView.removeLayer(layer);
Note:
See TracChangeset
for help on using the changeset viewer.