001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.dialogs.layer;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.event.ActionEvent;
007import java.awt.event.KeyEvent;
008import java.util.List;
009
010import javax.swing.AbstractAction;
011
012import org.openstreetmap.josm.gui.dialogs.IEnabledStateUpdating;
013import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
014import org.openstreetmap.josm.gui.dialogs.LayerListDialog.LayerListModel;
015import org.openstreetmap.josm.gui.help.HelpUtil;
016import org.openstreetmap.josm.gui.layer.Layer;
017import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
018import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
019import org.openstreetmap.josm.gui.util.GuiHelper;
020import org.openstreetmap.josm.gui.util.MultikeyShortcutAction;
021import org.openstreetmap.josm.tools.CheckParameterUtil;
022import org.openstreetmap.josm.tools.Destroyable;
023import org.openstreetmap.josm.tools.ImageProvider;
024import org.openstreetmap.josm.tools.Shortcut;
025
026/**
027 * The action to activate the currently selected layer
028 */
029public final class ActivateLayerAction extends AbstractAction
030implements IEnabledStateUpdating, ActiveLayerChangeListener, MultikeyShortcutAction, Destroyable {
031    private transient Layer layer;
032    private final transient Shortcut multikeyShortcut;
033    private final LayerListModel model;
034
035    /**
036     * Constructs a new {@code ActivateLayerAction}.
037     * @param layer the layer
038     * @param model layer list model
039     */
040    public ActivateLayerAction(Layer layer, LayerListModel model) {
041        this(model);
042        CheckParameterUtil.ensureParameterNotNull(layer, "layer");
043        this.layer = layer;
044        putValue(NAME, tr("Activate"));
045        updateEnabledState();
046    }
047
048    /**
049     * Constructs a new {@code ActivateLayerAction}.
050     * @param model layer list model
051     */
052    public ActivateLayerAction(LayerListModel model) {
053        this.model = model;
054        putValue(NAME, tr("Activate"));
055        new ImageProvider("dialogs", "activate").getResource().attachImageIcon(this, true);
056        putValue(SHORT_DESCRIPTION, tr("Activate the selected layer"));
057        multikeyShortcut = Shortcut.registerShortcut("core_multikey:activateLayer", tr("Multikey: {0}",
058                tr("Activate layer")), KeyEvent.VK_A, Shortcut.SHIFT);
059        multikeyShortcut.setAccelerator(this);
060        putValue("help", HelpUtil.ht("/Dialog/LayerList#ActivateLayer"));
061    }
062
063    @Override
064    public Shortcut getMultikeyShortcut() {
065        return multikeyShortcut;
066    }
067
068    @Override
069    public void actionPerformed(ActionEvent e) {
070        Layer toActivate;
071        if (layer != null) {
072            toActivate = layer;
073        } else {
074            List<Layer> layers = model.getSelectedLayers();
075            if (layers.isEmpty()) {
076                // see #19476 for a possible cause
077                return;
078            }
079            toActivate = layers.get(0);
080        }
081        execute(toActivate);
082    }
083
084    private void execute(Layer layer) {
085        // model is going to be updated via LayerChangeListener and PropertyChangeEvents
086        model.getLayerManager().setActiveLayer(layer);
087        layer.setVisible(true);
088    }
089
090    boolean isActiveLayer(Layer layer) {
091        return model.getLayerManager().getActiveLayer() == layer;
092    }
093
094    @Override
095    public void updateEnabledState() {
096        GuiHelper.runInEDTAndWait(() -> {
097            if (layer == null) {
098                if (model.getSelectedLayers().size() != 1) {
099                    setEnabled(false);
100                    return;
101                }
102                setEnabled(!isActiveLayer(model.getSelectedLayers().get(0)));
103            } else {
104                setEnabled(!isActiveLayer(layer));
105            }
106        });
107    }
108
109    @Override
110    public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
111        updateEnabledState();
112    }
113
114    @Override
115    public void executeMultikeyAction(int index, boolean repeat) {
116        Layer l = LayerListDialog.getLayerForIndex(index);
117        if (l != null) {
118            execute(l);
119        }
120    }
121
122    @Override
123    public List<MultikeyInfo> getMultikeyCombinations() {
124        return LayerListDialog.getLayerInfoByClass(Layer.class);
125    }
126
127    @Override
128    public MultikeyInfo getLastMultikeyAction() {
129        return null; // Repeating action doesn't make much sense for activating
130    }
131
132    @Override
133    public void destroy() {
134        layer = null;
135    }
136
137}