Changeset 10144 in josm


Ignore:
Timestamp:
2016-04-13T22:58:11+02:00 (8 years ago)
Author:
Don-vip
Message:

code refactoring - strip actions from LayerListDialog to new package gui.dialogs.layer

Location:
trunk
Files:
12 added
2 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/validation/tests/PublicTransportRouteTest.java

    r10141 r10144  
    7676                    && OsmPrimitiveType.NODE.equals(member.getType())
    7777                    && !routeNodes.contains(member.getNode())) {
    78                 errors.add(new TestError(this, Severity.WARNING, tr("Stop position not part of route"), 3603, Arrays.asList(member.getMember(), r)));
     78                errors.add(new TestError(this, Severity.WARNING,
     79                        tr("Stop position not part of route"), 3603, Arrays.asList(member.getMember(), r)));
    7980            }
    8081        }
    81 
    8282    }
    8383}
  • trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java

    r10142 r10144  
    88import java.awt.Dimension;
    99import java.awt.Font;
    10 import java.awt.GridBagLayout;
    1110import java.awt.Point;
    1211import java.awt.Rectangle;
     
    1716import java.beans.PropertyChangeEvent;
    1817import java.beans.PropertyChangeListener;
    19 import java.lang.ref.WeakReference;
    2018import java.util.ArrayList;
    2119import java.util.Arrays;
    22 import java.util.Collection;
    2320import java.util.Collections;
    2421import java.util.List;
     
    2623
    2724import javax.swing.AbstractAction;
    28 import javax.swing.BorderFactory;
    2925import javax.swing.DefaultCellEditor;
    3026import javax.swing.DefaultListSelectionModel;
     
    3329import javax.swing.JComponent;
    3430import javax.swing.JLabel;
    35 import javax.swing.JMenuItem;
    36 import javax.swing.JPanel;
    37 import javax.swing.JPopupMenu;
    38 import javax.swing.JSlider;
    3931import javax.swing.JTable;
    4032import javax.swing.JViewport;
     
    4234import javax.swing.ListSelectionModel;
    4335import javax.swing.UIManager;
    44 import javax.swing.event.ChangeEvent;
    45 import javax.swing.event.ChangeListener;
    4636import javax.swing.event.ListDataEvent;
    4737import javax.swing.event.ListSelectionEvent;
     
    5949import org.openstreetmap.josm.gui.MapView;
    6050import org.openstreetmap.josm.gui.SideButton;
    61 import org.openstreetmap.josm.gui.help.HelpUtil;
    62 import org.openstreetmap.josm.gui.layer.ImageryLayer;
     51import org.openstreetmap.josm.gui.dialogs.layer.ActivateLayerAction;
     52import org.openstreetmap.josm.gui.dialogs.layer.DeleteLayerAction;
     53import org.openstreetmap.josm.gui.dialogs.layer.DuplicateAction;
     54import org.openstreetmap.josm.gui.dialogs.layer.IEnabledStateUpdating;
     55import org.openstreetmap.josm.gui.dialogs.layer.LayerVisibilityAction;
     56import org.openstreetmap.josm.gui.dialogs.layer.MergeAction;
     57import org.openstreetmap.josm.gui.dialogs.layer.MoveDownAction;
     58import org.openstreetmap.josm.gui.dialogs.layer.MoveUpAction;
     59import org.openstreetmap.josm.gui.dialogs.layer.ShowHideLayerAction;
    6360import org.openstreetmap.josm.gui.layer.JumpToMarkerActions;
    6461import org.openstreetmap.josm.gui.layer.Layer;
    65 import org.openstreetmap.josm.gui.layer.Layer.LayerAction;
    6662import org.openstreetmap.josm.gui.layer.NativeScaleLayer;
    67 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    6863import org.openstreetmap.josm.gui.util.GuiHelper;
    6964import org.openstreetmap.josm.gui.widgets.DisableShortcutsOnFocusGainedTextField;
    7065import org.openstreetmap.josm.gui.widgets.JosmTextField;
    7166import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
    72 import org.openstreetmap.josm.tools.CheckParameterUtil;
    73 import org.openstreetmap.josm.tools.GBC;
    7467import org.openstreetmap.josm.tools.ImageProvider;
    7568import org.openstreetmap.josm.tools.InputMapUtils;
    7669import org.openstreetmap.josm.tools.MultikeyActionsHandler;
    77 import org.openstreetmap.josm.tools.MultikeyShortcutAction;
    7870import org.openstreetmap.josm.tools.MultikeyShortcutAction.MultikeyInfo;
    7971import org.openstreetmap.josm.tools.Shortcut;
    80 import org.openstreetmap.josm.tools.Utils;
    8172
    8273/**
     
    247238
    248239        // -- move up action
    249         MoveUpAction moveUpAction = new MoveUpAction();
     240        MoveUpAction moveUpAction = new MoveUpAction(model);
    250241        adaptTo(moveUpAction, model);
    251242        adaptTo(moveUpAction, selectionModel);
    252243
    253244        // -- move down action
    254         MoveDownAction moveDownAction = new MoveDownAction();
     245        MoveDownAction moveDownAction = new MoveDownAction(model);
    255246        adaptTo(moveDownAction, model);
    256247        adaptTo(moveDownAction, selectionModel);
    257248
    258249        // -- activate action
    259         activateLayerAction = new ActivateLayerAction();
     250        activateLayerAction = new ActivateLayerAction(model);
    260251        activateLayerAction.updateEnabledState();
    261252        MultikeyActionsHandler.getInstance().addAction(activateLayerAction);
     
    265256
    266257        // -- show hide action
    267         showHideLayerAction = new ShowHideLayerAction();
     258        showHideLayerAction = new ShowHideLayerAction(model);
    268259        MultikeyActionsHandler.getInstance().addAction(showHideLayerAction);
    269260        adaptTo(showHideLayerAction, selectionModel);
     
    275266
    276267        // -- delete layer action
    277         DeleteLayerAction deleteLayerAction = new DeleteLayerAction();
     268        DeleteLayerAction deleteLayerAction = new DeleteLayerAction(model);
    278269        layerList.getActionMap().put("deleteLayer", deleteLayerAction);
    279270        adaptTo(deleteLayerAction, selectionModel);
     
    325316    public LayerListModel getModel() {
    326317        return model;
    327     }
    328 
    329     protected interface IEnabledStateUpdating {
    330         void updateEnabledState();
    331318    }
    332319
     
    361348        listModel.addTableModelListener(
    362349                new TableModelListener() {
    363 
    364350                    @Override
    365351                    public void tableChanged(TableModelEvent e) {
     
    380366        super.destroy();
    381367        instance = null;
    382     }
    383 
    384     /**
    385      * The action to delete the currently selected layer
    386      */
    387     public final class DeleteLayerAction extends AbstractAction implements IEnabledStateUpdating, LayerAction {
    388 
    389         /**
    390          * Creates a {@link DeleteLayerAction} which will delete the currently
    391          * selected layers in the layer dialog.
    392          */
    393         public DeleteLayerAction() {
    394             putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
    395             putValue(SHORT_DESCRIPTION, tr("Delete the selected layers."));
    396             putValue(NAME, tr("Delete"));
    397             putValue("help", HelpUtil.ht("/Dialog/LayerList#DeleteLayer"));
    398             updateEnabledState();
    399         }
    400 
    401         @Override
    402         public void actionPerformed(ActionEvent e) {
    403             List<Layer> selectedLayers = getModel().getSelectedLayers();
    404             if (selectedLayers.isEmpty())
    405                 return;
    406             if (!Main.saveUnsavedModifications(selectedLayers, false))
    407                 return;
    408             for (Layer l: selectedLayers) {
    409                 Main.main.removeLayer(l);
    410             }
    411         }
    412 
    413         @Override
    414         public void updateEnabledState() {
    415             setEnabled(!getModel().getSelectedLayers().isEmpty());
    416         }
    417 
    418         @Override
    419         public Component createMenuComponent() {
    420             return new JMenuItem(this);
    421         }
    422 
    423         @Override
    424         public boolean supportLayers(List<Layer> layers) {
    425             return true;
    426         }
    427 
    428         @Override
    429         public boolean equals(Object obj) {
    430             return obj instanceof DeleteLayerAction;
    431         }
    432 
    433         @Override
    434         public int hashCode() {
    435             return getClass().hashCode();
    436         }
    437     }
    438 
    439     /**
    440      * Action which will toggle the visibility of the currently selected layers.
    441      */
    442     public final class ShowHideLayerAction extends AbstractAction implements IEnabledStateUpdating, LayerAction, MultikeyShortcutAction {
    443 
    444         private transient WeakReference<Layer> lastLayer;
    445         private final transient Shortcut multikeyShortcut;
    446 
    447         /**
    448          * Creates a {@link ShowHideLayerAction} which will toggle the visibility of
    449          * the currently selected layers
    450          */
    451         public ShowHideLayerAction() {
    452             putValue(NAME, tr("Show/hide"));
    453             putValue(SMALL_ICON, ImageProvider.get("dialogs", "showhide"));
    454             putValue(SHORT_DESCRIPTION, tr("Toggle visible state of the selected layer."));
    455             putValue("help", HelpUtil.ht("/Dialog/LayerList#ShowHideLayer"));
    456             multikeyShortcut = Shortcut.registerShortcut("core_multikey:showHideLayer", tr("Multikey: {0}",
    457                     tr("Show/hide layer")), KeyEvent.VK_S, Shortcut.SHIFT);
    458             multikeyShortcut.setAccelerator(this);
    459             updateEnabledState();
    460         }
    461 
    462         @Override
    463         public Shortcut getMultikeyShortcut() {
    464             return multikeyShortcut;
    465         }
    466 
    467         @Override
    468         public void actionPerformed(ActionEvent e) {
    469             for (Layer l : model.getSelectedLayers()) {
    470                 l.toggleVisible();
    471             }
    472         }
    473 
    474         @Override
    475         public void executeMultikeyAction(int index, boolean repeat) {
    476             Layer l = LayerListDialog.getLayerForIndex(index);
    477             if (l != null) {
    478                 l.toggleVisible();
    479                 lastLayer = new WeakReference<>(l);
    480             } else if (repeat && lastLayer != null) {
    481                 l = lastLayer.get();
    482                 if (LayerListDialog.isLayerValid(l)) {
    483                     l.toggleVisible();
    484                 }
    485             }
    486         }
    487 
    488         @Override
    489         public void updateEnabledState() {
    490             setEnabled(!model.getSelectedLayers().isEmpty());
    491         }
    492 
    493         @Override
    494         public Component createMenuComponent() {
    495             return new JMenuItem(this);
    496         }
    497 
    498         @Override
    499         public boolean supportLayers(List<Layer> layers) {
    500             return true;
    501         }
    502 
    503         @Override
    504         public boolean equals(Object obj) {
    505             return obj instanceof ShowHideLayerAction;
    506         }
    507 
    508         @Override
    509         public int hashCode() {
    510             return getClass().hashCode();
    511         }
    512 
    513         @Override
    514         public List<MultikeyInfo> getMultikeyCombinations() {
    515             return LayerListDialog.getLayerInfoByClass(Layer.class);
    516         }
    517 
    518         @Override
    519         public MultikeyInfo getLastMultikeyAction() {
    520             if (lastLayer != null)
    521                 return LayerListDialog.getLayerInfo(lastLayer.get());
    522             return null;
    523         }
    524     }
    525 
    526     /**
    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 static final double MAX_SHARPNESS_FACTOR = 2;
    535         private static final double MAX_COLORFUL_FACTOR = 2;
    536         private final LayerListModel model;
    537         private final JPopupMenu popup;
    538         private SideButton sideButton;
    539         private JCheckBox visibilityCheckbox;
    540         final OpacitySlider opacitySlider = new OpacitySlider();
    541         private final ArrayList<FilterSlider<?>> sliders = new ArrayList<>();
    542 
    543         /**
    544          * Creates a new {@link LayerVisibilityAction}
    545          * @param model The list to get the selection from.
    546          */
    547         public LayerVisibilityAction(LayerListModel model) {
    548             this.model = model;
    549             popup = new JPopupMenu();
    550 
    551             // just to add a border
    552             JPanel content = new JPanel();
    553             popup.add(content);
    554             content.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
    555             content.setLayout(new GridBagLayout());
    556 
    557             putValue(SMALL_ICON, ImageProvider.get("dialogs/layerlist", "visibility"));
    558             putValue(SHORT_DESCRIPTION, tr("Change visibility of the selected layer."));
    559 
    560             visibilityCheckbox = new JCheckBox(tr("Show layer"));
    561             visibilityCheckbox.addChangeListener(new ChangeListener() {
    562                 @Override
    563                 public void stateChanged(ChangeEvent e) {
    564                     setVisibleFlag(visibilityCheckbox.isSelected());
    565                 }
    566             });
    567             content.add(visibilityCheckbox, GBC.eop());
    568 
    569             addSlider(content, opacitySlider);
    570             addSlider(content, new ColorfulnessSlider());
    571             addSlider(content, new GammaFilterSlider());
    572             addSlider(content, new SharpnessSlider());
    573         }
    574 
    575         private void addSlider(JPanel content, FilterSlider<?> slider) {
    576             content.add(new JLabel(slider.getIcon()), GBC.std().span(1, 2).insets(0, 0, 5, 0));
    577             content.add(new JLabel(slider.getLabel()), GBC.eol());
    578             content.add(slider, GBC.eop());
    579             sliders.add(slider);
    580         }
    581 
    582         protected void setVisibleFlag(boolean visible) {
    583             for (Layer l : model.getSelectedLayers()) {
    584                 l.setVisible(visible);
    585             }
    586             updateValues();
    587         }
    588 
    589         @Override
    590         public void actionPerformed(ActionEvent e) {
    591             updateValues();
    592             if (e.getSource() == sideButton) {
    593                 popup.show(sideButton, 0, sideButton.getHeight());
    594             } else {
    595                 // Action can be trigger either by opacity button or by popup menu (in case toggle buttons are hidden).
    596                 // In that case, show it in the middle of screen (because opacityButton is not visible)
    597                 popup.show(Main.parent, Main.parent.getWidth() / 2, (Main.parent.getHeight() - popup.getHeight()) / 2);
    598             }
    599         }
    600 
    601         protected void updateValues() {
    602             List<Layer> layers = model.getSelectedLayers();
    603 
    604             visibilityCheckbox.setEnabled(!layers.isEmpty());
    605             boolean allVisible = true;
    606             boolean allHidden = true;
    607             for (Layer l : layers) {
    608                 allVisible &= l.isVisible();
    609                 allHidden &= !l.isVisible();
    610             }
    611             // TODO: Indicate tristate.
    612             visibilityCheckbox.setSelected(allVisible && !allHidden);
    613 
    614             for (FilterSlider<?> slider : sliders) {
    615                 slider.updateSlider(layers, allHidden);
    616             }
    617         }
    618 
    619         @Override
    620         public boolean supportLayers(List<Layer> layers) {
    621             return !layers.isEmpty();
    622         }
    623 
    624         @Override
    625         public Component createMenuComponent() {
    626             return new JMenuItem(this);
    627         }
    628 
    629         @Override
    630         public void updateEnabledState() {
    631             setEnabled(!model.getSelectedLayers().isEmpty());
    632         }
    633 
    634         /**
    635          * Sets the corresponding side button.
    636          * @param sideButton the corresponding side button
    637          */
    638         void setCorrespondingSideButton(SideButton sideButton) {
    639             this.sideButton = sideButton;
    640         }
    641 
    642         /**
    643          * This is a slider for a filter value.
    644          * @author Michael Zangl
    645          *
    646          * @param <T> The layer type.
    647          */
    648         private abstract class FilterSlider<T extends Layer> extends JSlider {
    649             private final double minValue;
    650             private final double maxValue;
    651             private final Class<T> layerClassFilter;
    652 
    653             /**
    654              * Create a new filter slider.
    655              * @param minValue The minimum value to map to the left side.
    656              * @param maxValue The maximum value to map to the right side.
    657              * @param layerClassFilter The type of layer influenced by this filter.
    658              */
    659             FilterSlider(double minValue, double maxValue, Class<T> layerClassFilter) {
    660                 super(JSlider.HORIZONTAL);
    661                 this.minValue = minValue;
    662                 this.maxValue = maxValue;
    663                 this.layerClassFilter = layerClassFilter;
    664                 setMaximum(SLIDER_STEPS);
    665                 int tick = convertFromRealValue(1);
    666                 setMinorTickSpacing(tick);
    667                 setMajorTickSpacing(tick);
    668                 setPaintTicks(true);
    669 
    670                 addChangeListener(new ChangeListener() {
    671                     @Override
    672                     public void stateChanged(ChangeEvent e) {
    673                         onStateChanged();
    674                     }
    675                 });
    676             }
    677 
    678             /**
    679              * Called whenever the state of the slider was changed.
    680              * @see #getValueIsAdjusting()
    681              * @see #getRealValue()
    682              */
    683             protected void onStateChanged() {
    684                 Collection<T> layers = filterLayers(model.getSelectedLayers());
    685                 for (T layer : layers) {
    686                     applyValueToLayer(layer);
    687                 }
    688             }
    689 
    690             protected void applyValueToLayer(T layer) {
    691             }
    692 
    693             protected double getRealValue() {
    694                 return convertToRealValue(getValue());
    695             }
    696 
    697             protected double convertToRealValue(int value) {
    698                 double s = (double) value / SLIDER_STEPS;
    699                 return s * maxValue + (1-s) * minValue;
    700             }
    701 
    702             protected void setRealValue(double value) {
    703                 setValue(convertFromRealValue(value));
    704             }
    705 
    706             protected int convertFromRealValue(double value) {
    707                 int i = (int) ((value - minValue) / (maxValue - minValue) * SLIDER_STEPS + .5);
    708                 if (i < getMinimum()) {
    709                     return getMinimum();
    710                 } else if (i > getMaximum()) {
    711                     return getMaximum();
    712                 } else {
    713                     return i;
    714                 }
    715             }
    716 
    717             public abstract ImageIcon getIcon();
    718 
    719             public abstract String getLabel();
    720 
    721             public void updateSlider(List<Layer> layers, boolean allHidden) {
    722                 Collection<? extends Layer> usedLayers = filterLayers(layers);
    723                 if (usedLayers.isEmpty() || allHidden) {
    724                     setEnabled(false);
    725                 } else {
    726                     setEnabled(true);
    727                     updateSliderWhileEnabled(usedLayers, allHidden);
    728                 }
    729             }
    730 
    731             protected Collection<T> filterLayers(List<Layer> layers) {
    732                 return Utils.filteredCollection(layers, layerClassFilter);
    733             }
    734 
    735             protected abstract void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden);
    736         }
    737 
    738         /**
    739          * This slider allows you to change the opacity of a layer.
    740          *
    741          * @author Michael Zangl
    742          * @see Layer#setOpacity(double)
    743          */
    744         class OpacitySlider extends FilterSlider<Layer> {
    745             /**
    746              * Creaate a new {@link OpacitySlider}.
    747              */
    748             OpacitySlider() {
    749                 super(0, 1, Layer.class);
    750                 setToolTipText(tr("Adjust opacity of the layer."));
    751 
    752             }
    753 
    754             @Override
    755             protected void onStateChanged() {
    756                 if (getRealValue() <= 0.001 && !getValueIsAdjusting()) {
    757                     setVisibleFlag(false);
    758                 } else {
    759                     super.onStateChanged();
    760                 }
    761             }
    762 
    763             @Override
    764             protected void applyValueToLayer(Layer layer) {
    765                 layer.setOpacity(getRealValue());
    766             }
    767 
    768             @Override
    769             protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) {
    770                 double opacity = 0;
    771                 for (Layer l : usedLayers) {
    772                     opacity += l.getOpacity();
    773                 }
    774                 opacity /= usedLayers.size();
    775                 if (opacity == 0) {
    776                     opacity = 1;
    777                     setVisibleFlag(true);
    778                 }
    779                 setRealValue(opacity);
    780             }
    781 
    782             @Override
    783             public String getLabel() {
    784                 return tr("Opacity");
    785             }
    786 
    787             @Override
    788             public ImageIcon getIcon() {
    789                 return ImageProvider.get("dialogs/layerlist", "transparency");
    790             }
    791 
    792             @Override
    793             public String toString() {
    794                 return "OpacitySlider [getRealValue()=" + getRealValue() + "]";
    795             }
    796         }
    797 
    798         /**
    799          * This slider allows you to change the gamma value of a layer.
    800          *
    801          * @author Michael Zangl
    802          * @see ImageryLayer#setGamma(double)
    803          */
    804         private class GammaFilterSlider extends FilterSlider<ImageryLayer> {
    805 
    806             /**
    807              * Create a new {@link GammaFilterSlider}
    808              */
    809             GammaFilterSlider() {
    810                 super(0, MAX_GAMMA_FACTOR, ImageryLayer.class);
    811                 setToolTipText(tr("Adjust gamma value of the layer."));
    812             }
    813 
    814             @Override
    815             protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) {
    816                 double gamma = ((ImageryLayer) usedLayers.iterator().next()).getGamma();
    817                 setRealValue(gamma);
    818             }
    819 
    820             @Override
    821             protected void applyValueToLayer(ImageryLayer layer) {
    822                 layer.setGamma(getRealValue());
    823             }
    824 
    825             @Override
    826             public ImageIcon getIcon() {
    827                return ImageProvider.get("dialogs/layerlist", "gamma");
    828             }
    829 
    830             @Override
    831             public String getLabel() {
    832                 return tr("Gamma");
    833             }
    834         }
    835 
    836         /**
    837          * This slider allows you to change the sharpness of a layer.
    838          *
    839          * @author Michael Zangl
    840          * @see ImageryLayer#setSharpenLevel(double)
    841          */
    842         private class SharpnessSlider extends FilterSlider<ImageryLayer> {
    843 
    844             /**
    845              * Creates a new {@link SharpnessSlider}
    846              */
    847             SharpnessSlider() {
    848                 super(0, MAX_SHARPNESS_FACTOR, ImageryLayer.class);
    849                 setToolTipText(tr("Adjust sharpness/blur value of the layer."));
    850             }
    851 
    852             @Override
    853             protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) {
    854                 setRealValue(((ImageryLayer) usedLayers.iterator().next()).getSharpenLevel());
    855             }
    856 
    857             @Override
    858             protected void applyValueToLayer(ImageryLayer layer) {
    859                 layer.setSharpenLevel(getRealValue());
    860             }
    861 
    862             @Override
    863             public ImageIcon getIcon() {
    864                return ImageProvider.get("dialogs/layerlist", "sharpness");
    865             }
    866 
    867             @Override
    868             public String getLabel() {
    869                 return tr("Sharpness");
    870             }
    871         }
    872 
    873         /**
    874          * This slider allows you to change the colorfulness of a layer.
    875          *
    876          * @author Michael Zangl
    877          * @see ImageryLayer#setColorfulness(double)
    878          */
    879         private class ColorfulnessSlider extends FilterSlider<ImageryLayer> {
    880 
    881             /**
    882              * Create a new {@link ColorfulnessSlider}
    883              */
    884             ColorfulnessSlider() {
    885                 super(0, MAX_COLORFUL_FACTOR, ImageryLayer.class);
    886                 setToolTipText(tr("Adjust colorfulness of the layer."));
    887             }
    888 
    889             @Override
    890             protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) {
    891                 setRealValue(((ImageryLayer) usedLayers.iterator().next()).getColorfulness());
    892             }
    893 
    894             @Override
    895             protected void applyValueToLayer(ImageryLayer layer) {
    896                 layer.setColorfulness(getRealValue());
    897             }
    898 
    899             @Override
    900             public ImageIcon getIcon() {
    901                return ImageProvider.get("dialogs/layerlist", "colorfulness");
    902             }
    903 
    904             @Override
    905             public String getLabel() {
    906                 return tr("Colorfulness");
    907             }
    908         }
    909     }
    910 
    911     /**
    912      * The action to activate the currently selected layer
    913      */
    914 
    915     public final class ActivateLayerAction extends AbstractAction
    916     implements IEnabledStateUpdating, MapView.LayerChangeListener, MultikeyShortcutAction {
    917         private transient Layer layer;
    918         private transient Shortcut multikeyShortcut;
    919 
    920         /**
    921          * Constructs a new {@code ActivateLayerAction}.
    922          * @param layer the layer
    923          */
    924         public ActivateLayerAction(Layer layer) {
    925             this();
    926             CheckParameterUtil.ensureParameterNotNull(layer, "layer");
    927             this.layer = layer;
    928             putValue(NAME, tr("Activate"));
    929             updateEnabledState();
    930         }
    931 
    932         /**
    933          * Constructs a new {@code ActivateLayerAction}.
    934          */
    935         public ActivateLayerAction() {
    936             putValue(NAME, tr("Activate"));
    937             putValue(SMALL_ICON, ImageProvider.get("dialogs", "activate"));
    938             putValue(SHORT_DESCRIPTION, tr("Activate the selected layer"));
    939             multikeyShortcut = Shortcut.registerShortcut("core_multikey:activateLayer", tr("Multikey: {0}",
    940                     tr("Activate layer")), KeyEvent.VK_A, Shortcut.SHIFT);
    941             multikeyShortcut.setAccelerator(this);
    942             putValue("help", HelpUtil.ht("/Dialog/LayerList#ActivateLayer"));
    943         }
    944 
    945         @Override
    946         public Shortcut getMultikeyShortcut() {
    947             return multikeyShortcut;
    948         }
    949 
    950         @Override
    951         public void actionPerformed(ActionEvent e) {
    952             Layer toActivate;
    953             if (layer != null) {
    954                 toActivate = layer;
    955             } else {
    956                 toActivate = model.getSelectedLayers().get(0);
    957             }
    958             execute(toActivate);
    959         }
    960 
    961         private void execute(Layer layer) {
    962             // model is  going to be updated via LayerChangeListener and PropertyChangeEvents
    963             Main.map.mapView.setActiveLayer(layer);
    964             layer.setVisible(true);
    965         }
    966 
    967         protected boolean isActiveLayer(Layer layer) {
    968             if (!Main.isDisplayingMapView()) return false;
    969             return Main.map.mapView.getActiveLayer() == layer;
    970         }
    971 
    972         @Override
    973         public void updateEnabledState() {
    974             GuiHelper.runInEDTAndWait(new Runnable() {
    975                 @Override
    976                 public void run() {
    977                     if (layer == null) {
    978                         if (getModel().getSelectedLayers().size() != 1) {
    979                             setEnabled(false);
    980                             return;
    981                         }
    982                         Layer selectedLayer = getModel().getSelectedLayers().get(0);
    983                         setEnabled(!isActiveLayer(selectedLayer));
    984                     } else {
    985                         setEnabled(!isActiveLayer(layer));
    986                     }
    987                 }
    988             });
    989         }
    990 
    991         @Override
    992         public void activeLayerChange(Layer oldLayer, Layer newLayer) {
    993             updateEnabledState();
    994         }
    995 
    996         @Override
    997         public void layerAdded(Layer newLayer) {
    998             updateEnabledState();
    999         }
    1000 
    1001         @Override
    1002         public void layerRemoved(Layer oldLayer) {
    1003             updateEnabledState();
    1004         }
    1005 
    1006         @Override
    1007         public void executeMultikeyAction(int index, boolean repeat) {
    1008             Layer l = LayerListDialog.getLayerForIndex(index);
    1009             if (l != null) {
    1010                 execute(l);
    1011             }
    1012         }
    1013 
    1014         @Override
    1015         public List<MultikeyInfo> getMultikeyCombinations() {
    1016             return LayerListDialog.getLayerInfoByClass(Layer.class);
    1017         }
    1018 
    1019         @Override
    1020         public MultikeyInfo getLastMultikeyAction() {
    1021             return null; // Repeating action doesn't make much sense for activating
    1022         }
    1023     }
    1024 
    1025     /**
    1026      * The action to merge the currently selected layer into another layer.
    1027      */
    1028     public final class MergeAction extends AbstractAction implements IEnabledStateUpdating, LayerAction, Layer.MultiLayerAction {
    1029         private transient Layer layer;
    1030         private transient List<Layer> layers;
    1031 
    1032         /**
    1033          * Constructs a new {@code MergeAction}.
    1034          * @param layer the layer
    1035          * @throws IllegalArgumentException if {@code layer} is null
    1036          */
    1037         public MergeAction(Layer layer) {
    1038             this(layer, null);
    1039             CheckParameterUtil.ensureParameterNotNull(layer, "layer");
    1040         }
    1041 
    1042         /**
    1043          * Constructs a new {@code MergeAction}.
    1044          * @param layers the layer list
    1045          * @throws IllegalArgumentException if {@code layers} is null
    1046          */
    1047         public MergeAction(List<Layer> layers) {
    1048             this(null, layers);
    1049             CheckParameterUtil.ensureParameterNotNull(layers, "layers");
    1050         }
    1051 
    1052         /**
    1053          * Constructs a new {@code MergeAction}.
    1054          * @param layer the layer (null if layer list if specified)
    1055          * @param layers the layer list (null if a single layer is specified)
    1056          */
    1057         private MergeAction(Layer layer, List<Layer> layers) {
    1058             this.layer = layer;
    1059             this.layers = layers;
    1060             putValue(NAME, tr("Merge"));
    1061             putValue(SMALL_ICON, ImageProvider.get("dialogs", "mergedown"));
    1062             putValue(SHORT_DESCRIPTION, tr("Merge this layer into another layer"));
    1063             putValue("help", HelpUtil.ht("/Dialog/LayerList#MergeLayer"));
    1064             updateEnabledState();
    1065         }
    1066 
    1067         @Override
    1068         public void actionPerformed(ActionEvent e) {
    1069             if (layer != null) {
    1070                 Main.main.menu.merge.merge(layer);
    1071             } else if (layers != null) {
    1072                 Main.main.menu.merge.merge(layers);
    1073             } else {
    1074                 if (getModel().getSelectedLayers().size() == 1) {
    1075                     Layer selectedLayer = getModel().getSelectedLayers().get(0);
    1076                     Main.main.menu.merge.merge(selectedLayer);
    1077                 } else {
    1078                     Main.main.menu.merge.merge(getModel().getSelectedLayers());
    1079                 }
    1080             }
    1081         }
    1082 
    1083         @Override
    1084         public void updateEnabledState() {
    1085             if (layer == null && layers == null) {
    1086                 if (getModel().getSelectedLayers().isEmpty()) {
    1087                     setEnabled(false);
    1088                 } else  if (getModel().getSelectedLayers().size() > 1) {
    1089                     setEnabled(supportLayers(getModel().getSelectedLayers()));
    1090                 } else {
    1091                     Layer selectedLayer = getModel().getSelectedLayers().get(0);
    1092                     List<Layer> targets = getModel().getPossibleMergeTargets(selectedLayer);
    1093                     setEnabled(!targets.isEmpty());
    1094                 }
    1095             } else if (layer != null) {
    1096                 List<Layer> targets = getModel().getPossibleMergeTargets(layer);
    1097                 setEnabled(!targets.isEmpty());
    1098             } else {
    1099                 setEnabled(supportLayers(layers));
    1100             }
    1101         }
    1102 
    1103         @Override
    1104         public boolean supportLayers(List<Layer> layers) {
    1105             if (layers.isEmpty()) {
    1106                 return false;
    1107             } else {
    1108                 final Layer firstLayer = layers.get(0);
    1109                 final List<Layer> remainingLayers = layers.subList(1, layers.size());
    1110                 return getModel().getPossibleMergeTargets(firstLayer).containsAll(remainingLayers);
    1111             }
    1112         }
    1113 
    1114         @Override
    1115         public Component createMenuComponent() {
    1116             return new JMenuItem(this);
    1117         }
    1118 
    1119         @Override
    1120         public MergeAction getMultiLayerAction(List<Layer> layers) {
    1121             return new MergeAction(layers);
    1122         }
    1123     }
    1124 
    1125     /**
    1126      * The action to merge the currently selected layer into another layer.
    1127      */
    1128     public final class DuplicateAction extends AbstractAction implements IEnabledStateUpdating {
    1129         private transient Layer layer;
    1130 
    1131         /**
    1132          * Constructs a new {@code DuplicateAction}.
    1133          * @param layer the layer
    1134          * @throws IllegalArgumentException if {@code layer} is null
    1135          */
    1136         public DuplicateAction(Layer layer) {
    1137             this();
    1138             CheckParameterUtil.ensureParameterNotNull(layer, "layer");
    1139             this.layer = layer;
    1140             updateEnabledState();
    1141         }
    1142 
    1143         /**
    1144          * Constructs a new {@code DuplicateAction}.
    1145          */
    1146         public DuplicateAction() {
    1147             putValue(NAME, tr("Duplicate"));
    1148             putValue(SMALL_ICON, ImageProvider.get("dialogs", "duplicatelayer"));
    1149             putValue(SHORT_DESCRIPTION, tr("Duplicate this layer"));
    1150             putValue("help", HelpUtil.ht("/Dialog/LayerList#DuplicateLayer"));
    1151             updateEnabledState();
    1152         }
    1153 
    1154         private void duplicate(Layer layer) {
    1155             if (!Main.isDisplayingMapView())
    1156                 return;
    1157 
    1158             List<String> layerNames = new ArrayList<>();
    1159             for (Layer l: Main.map.mapView.getAllLayers()) {
    1160                 layerNames.add(l.getName());
    1161             }
    1162             if (layer instanceof OsmDataLayer) {
    1163                 OsmDataLayer oldLayer = (OsmDataLayer) layer;
    1164                 // Translators: "Copy of {layer name}"
    1165                 String newName = tr("Copy of {0}", oldLayer.getName());
    1166                 int i = 2;
    1167                 while (layerNames.contains(newName)) {
    1168                     // Translators: "Copy {number} of {layer name}"
    1169                     newName = tr("Copy {1} of {0}", oldLayer.getName(), i);
    1170                     i++;
    1171                 }
    1172                 Main.main.addLayer(new OsmDataLayer(oldLayer.data.clone(), newName, null));
    1173             }
    1174         }
    1175 
    1176         @Override
    1177         public void actionPerformed(ActionEvent e) {
    1178             if (layer != null) {
    1179                 duplicate(layer);
    1180             } else {
    1181                 duplicate(getModel().getSelectedLayers().get(0));
    1182             }
    1183         }
    1184 
    1185         @Override
    1186         public void updateEnabledState() {
    1187             if (layer == null) {
    1188                 if (getModel().getSelectedLayers().size() == 1) {
    1189                     setEnabled(getModel().getSelectedLayers().get(0) instanceof OsmDataLayer);
    1190                 } else {
    1191                     setEnabled(false);
    1192                 }
    1193             } else {
    1194                 setEnabled(layer instanceof OsmDataLayer);
    1195             }
    1196         }
    1197368    }
    1198369
     
    1342513
    1343514        protected boolean isActiveLayer(Layer layer) {
    1344             if (!Main.isDisplayingMapView()) return false;
     515            if (!Main.isDisplayingMapView())
     516                return false;
    1345517            return Main.map.mapView.getActiveLayer() == layer;
    1346518        }
     
    1408580
    1409581    /**
    1410      * The action to move up the currently selected entries in the list.
    1411      */
    1412     class MoveUpAction extends AbstractAction implements  IEnabledStateUpdating {
    1413         MoveUpAction() {
    1414             putValue(NAME, tr("Move up"));
    1415             putValue(SMALL_ICON, ImageProvider.get("dialogs", "up"));
    1416             putValue(SHORT_DESCRIPTION, tr("Move the selected layer one row up."));
    1417             updateEnabledState();
    1418         }
    1419 
    1420         @Override
    1421         public void updateEnabledState() {
    1422             setEnabled(model.canMoveUp());
    1423         }
    1424 
    1425         @Override
    1426         public void actionPerformed(ActionEvent e) {
    1427             model.moveUp();
    1428         }
    1429     }
    1430 
    1431     /**
    1432      * The action to move down the currently selected entries in the list.
    1433      */
    1434     class MoveDownAction extends AbstractAction implements IEnabledStateUpdating {
    1435         MoveDownAction() {
    1436             putValue(NAME, tr("Move down"));
    1437             putValue(SMALL_ICON, ImageProvider.get("dialogs", "down"));
    1438             putValue(SHORT_DESCRIPTION, tr("Move the selected layer one row down."));
    1439             updateEnabledState();
    1440         }
    1441 
    1442         @Override
    1443         public void updateEnabledState() {
    1444             setEnabled(model.canMoveDown());
    1445         }
    1446 
    1447         @Override
    1448         public void actionPerformed(ActionEvent e) {
    1449             model.moveDown();
    1450         }
    1451     }
    1452 
    1453     /**
    1454582     * Observer interface to be implemented by views using {@link LayerListModel}.
    1455583     */
     
    1518646         * removes a listener from  this model
    1519647         * @param listener the listener
    1520          *
    1521648         */
    1522649        public void removeLayerListModelListener(LayerListModelListener listener) {
     
    1636763         */
    1637764        protected void onAddLayer(Layer layer) {
    1638             if (layer == null) return;
     765            if (layer == null)
     766                return;
    1639767            layer.addPropertyChangeListener(this);
    1640768            fireTableDataChanged();
     
    1651779         */
    1652780        public Layer getFirstLayer() {
    1653             if (getRowCount() == 0) return null;
     781            if (getRowCount() == 0)
     782                return null;
    1654783            return getLayers().get(0);
    1655784        }
     
    1683812         */
    1684813        public void moveUp() {
    1685             if (!canMoveUp()) return;
     814            if (!canMoveUp())
     815                return;
    1686816            List<Integer> sel = getSelectedRows();
    1687817            List<Layer> layers = getLayers();
     
    1712842        /**
    1713843         * Move down the currently selected layers by one position
    1714          *
    1715844         */
    1716845        public void moveDown() {
    1717             if (!canMoveDown()) return;
     846            if (!canMoveDown())
     847                return;
    1718848            List<Integer> sel = getSelectedRows();
    1719849            Collections.reverse(sel);
     
    1734864
    1735865        /**
    1736          * Make sure the first of the selected layers is visible in the
    1737          * views of this model.
    1738          *
     866         * Make sure the first of the selected layers is visible in the views of this model.
    1739867         */
    1740868        protected void ensureSelectedIsVisible() {
    1741869            int index = selectionModel.getMinSelectionIndex();
    1742             if (index < 0) return;
     870            if (index < 0)
     871                return;
    1743872            List<Layer> layers = getLayers();
    1744             if (index >= layers.size()) return;
     873            if (index >= layers.size())
     874                return;
    1745875            Layer layer = layers.get(index);
    1746876            fireMakeVisible(index, layer);
     
    1748878
    1749879        /**
    1750          * Replies a list of layers which are possible merge targets
    1751          * for <code>source</code>
     880         * Replies a list of layers which are possible merge targets for <code>source</code>
    1752881         *
    1753882         * @param source the source layer
     
    1811940         */
    1812941        protected Layer getActiveLayer() {
    1813             if (!Main.isDisplayingMapView()) return null;
    1814             return Main.map.mapView.getActiveLayer();
     942            return Main.isDisplayingMapView() ? Main.map.mapView.getActiveLayer() : null;
    1815943        }
    1816944
     
    1821949         */
    1822950        protected NativeScaleLayer getNativeScaleLayer() {
    1823             if (!Main.isDisplayingMapView()) return null;
    1824             return Main.map.mapView.getNativeScaleLayer();
     951            return Main.isDisplayingMapView() ? Main.map.mapView.getNativeScaleLayer() : null;
    1825952        }
    1826953
     
    1832959        public int getRowCount() {
    1833960            List<Layer> layers = getLayers();
    1834             if (layers == null) return 0;
    1835             return layers.size();
     961            return layers == null ? 0 : layers.size();
    1836962        }
    1837963
     
    19431069                Layer layer = (Layer) evt.getSource();
    19441070                final int idx = getLayers().indexOf(layer);
    1945                 if (idx < 0) return;
     1071                if (idx < 0)
     1072                    return;
    19461073                fireRefresh();
    19471074            }
     
    19671094
    19681095    /**
    1969      * Creates a {@link ShowHideLayerAction} in the
    1970      * context of this {@link LayerListDialog}.
     1096     * Creates a {@link ShowHideLayerAction} in the context of this {@link LayerListDialog}.
    19711097     *
    19721098     * @return the action
    19731099     */
    19741100    public ShowHideLayerAction createShowHideLayerAction() {
    1975         return new ShowHideLayerAction();
    1976     }
    1977 
    1978     /**
    1979      * Creates a {@link DeleteLayerAction} in the
    1980      * context of this {@link LayerListDialog}.
     1101        return new ShowHideLayerAction(model);
     1102    }
     1103
     1104    /**
     1105     * Creates a {@link DeleteLayerAction} in the context of this {@link LayerListDialog}.
    19811106     *
    19821107     * @return the action
    19831108     */
    19841109    public DeleteLayerAction createDeleteLayerAction() {
    1985         return new DeleteLayerAction();
    1986     }
    1987 
    1988     /**
    1989      * Creates a {@link ActivateLayerAction} for <code>layer</code> in the
    1990      * context of this {@link LayerListDialog}.
     1110        return new DeleteLayerAction(model);
     1111    }
     1112
     1113    /**
     1114     * Creates a {@link ActivateLayerAction} for <code>layer</code> in the context of this {@link LayerListDialog}.
    19911115     *
    19921116     * @param layer the layer
     
    19941118     */
    19951119    public ActivateLayerAction createActivateLayerAction(Layer layer) {
    1996         return new ActivateLayerAction(layer);
    1997     }
    1998 
    1999     /**
    2000      * Creates a {@link MergeLayerAction} for <code>layer</code> in the
    2001      * context of this {@link LayerListDialog}.
     1120        return new ActivateLayerAction(layer, model);
     1121    }
     1122
     1123    /**
     1124     * Creates a {@link MergeLayerAction} for <code>layer</code> in the context of this {@link LayerListDialog}.
    20021125     *
    20031126     * @param layer the layer
     
    20051128     */
    20061129    public MergeAction createMergeLayerAction(Layer layer) {
    2007         return new MergeAction(layer);
    2008     }
    2009 
    2010     /**
    2011      * Creates a {@link DuplicateAction} for <code>layer</code> in the
    2012      * context of this {@link LayerListDialog}.
     1130        return new MergeAction(layer, model);
     1131    }
     1132
     1133    /**
     1134     * Creates a {@link DuplicateAction} for <code>layer</code> in the context of this {@link LayerListDialog}.
    20131135     *
    20141136     * @param layer the layer
     
    20161138     */
    20171139    public DuplicateAction createDuplicateLayerAction(Layer layer) {
    2018         return new DuplicateAction(layer);
     1140        return new DuplicateAction(layer, model);
    20191141    }
    20201142
     
    20251147     */
    20261148    public static Layer getLayerForIndex(int index) {
    2027 
    20281149        if (!Main.isDisplayingMapView())
    20291150            return null;
     
    20441165     */
    20451166    public static List<MultikeyInfo> getLayerInfoByClass(Class<?> layerClass) {
    2046 
    20471167        List<MultikeyInfo> result = new ArrayList<>();
    20481168
     
    20691189     */
    20701190    public static boolean isLayerValid(Layer l) {
    2071 
    20721191        if (l == null || !Main.isDisplayingMapView())
    20731192            return false;
     
    20821201     */
    20831202    public static MultikeyInfo getLayerInfo(Layer l) {
    2084 
    20851203        if (l == null || !Main.isDisplayingMapView())
    20861204            return null;
  • trunk/test/unit/org/openstreetmap/josm/gui/dialogs/layer/LayerVisibilityActionTest.java

    r10143 r10144  
    11// License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.dialogs;
     2package org.openstreetmap.josm.gui.dialogs.layer;
    33
    44import static org.junit.Assert.assertEquals;
     
    1010import org.openstreetmap.josm.JOSMFixture;
    1111import org.openstreetmap.josm.Main;
     12import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
    1213import org.openstreetmap.josm.gui.dialogs.LayerListDialog.LayerListModel;
    13 import org.openstreetmap.josm.gui.dialogs.LayerListDialog.LayerVisibilityAction;
    1414import org.openstreetmap.josm.gui.layer.TMSLayer;
    1515import org.openstreetmap.josm.gui.layer.TMSLayerTest;
    1616
    1717/**
    18  * Unit tests of {@link LayerListDialog} class.
     18 * Unit tests of {@link LayerVisibilityAction} class.
    1919 */
    20 public class LayerListDialogTest {
     20public class LayerVisibilityActionTest {
    2121
    2222    /**
Note: See TracChangeset for help on using the changeset viewer.