001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.layer;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.event.ActionEvent;
007import java.awt.event.KeyEvent;
008import java.lang.ref.WeakReference;
009import java.util.List;
010
011import javax.swing.AbstractAction;
012
013import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
014import org.openstreetmap.josm.tools.MultikeyActionsHandler;
015import org.openstreetmap.josm.tools.MultikeyShortcutAction;
016import org.openstreetmap.josm.tools.Shortcut;
017
018public final class JumpToMarkerActions {
019
020    public interface JumpToMarkerLayer {
021        void jumpToNextMarker();
022
023        void jumpToPreviousMarker();
024    }
025
026    private JumpToMarkerActions() {
027        // Hide default constructor for utils classes
028    }
029
030    private static volatile JumpToNextMarker jumpToNextMarkerAction;
031    private static volatile JumpToPreviousMarker jumpToPreviousMarkerAction;
032
033    public static void initialize() {
034        jumpToNextMarkerAction = new JumpToNextMarker(null);
035        jumpToPreviousMarkerAction = new JumpToPreviousMarker(null);
036        MultikeyActionsHandler.getInstance().addAction(jumpToNextMarkerAction);
037        MultikeyActionsHandler.getInstance().addAction(jumpToPreviousMarkerAction);
038    }
039
040    public static void unregisterActions() {
041        MultikeyActionsHandler.getInstance().removeAction(jumpToNextMarkerAction);
042        MultikeyActionsHandler.getInstance().removeAction(jumpToPreviousMarkerAction);
043    }
044
045    private abstract static class JumpToMarker extends AbstractAction implements MultikeyShortcutAction {
046
047        private final transient Layer layer;
048        private final transient Shortcut multikeyShortcut;
049        private transient WeakReference<Layer> lastLayer;
050
051        JumpToMarker(JumpToMarkerLayer layer, Shortcut shortcut) {
052            this.layer = (Layer) layer;
053            this.multikeyShortcut = shortcut;
054            this.multikeyShortcut.setAccelerator(this);
055        }
056
057        protected final void setLastLayer(Layer l) {
058            lastLayer = new WeakReference<>(l);
059        }
060
061        @Override
062        public Shortcut getMultikeyShortcut() {
063            return multikeyShortcut;
064        }
065
066        @Override
067        public void actionPerformed(ActionEvent e) {
068            execute(layer);
069        }
070
071        @Override
072        public void executeMultikeyAction(int index, boolean repeat) {
073            Layer l = LayerListDialog.getLayerForIndex(index);
074            if (l != null) {
075                if (l instanceof JumpToMarkerLayer) {
076                    execute(l);
077                }
078            } else if (repeat && lastLayer != null) {
079                l = lastLayer.get();
080                if (LayerListDialog.isLayerValid(l)) {
081                    execute(l);
082                }
083            }
084        }
085
086        protected abstract void execute(Layer l);
087
088        @Override
089        public List<MultikeyInfo> getMultikeyCombinations() {
090            return LayerListDialog.getLayerInfoByClass(JumpToMarkerLayer.class);
091        }
092
093        @Override
094        public MultikeyInfo getLastMultikeyAction() {
095            if (lastLayer != null)
096                return LayerListDialog.getLayerInfo(lastLayer.get());
097            else
098                return null;
099        }
100    }
101
102    public static final class JumpToNextMarker extends JumpToMarker {
103
104        public JumpToNextMarker(JumpToMarkerLayer layer) {
105            super(layer, Shortcut.registerShortcut("core_multikey:nextMarker", tr("Multikey: {0}", tr("Next marker")),
106                    KeyEvent.VK_J, Shortcut.ALT_CTRL));
107            putValue(SHORT_DESCRIPTION, tr("Jump to next marker"));
108            putValue(NAME, tr("Jump to next marker"));
109        }
110
111        @Override
112        protected void execute(Layer l) {
113            ((JumpToMarkerLayer) l).jumpToNextMarker();
114            setLastLayer(l);
115        }
116    }
117
118    public static final class JumpToPreviousMarker extends JumpToMarker {
119
120        public JumpToPreviousMarker(JumpToMarkerLayer layer) {
121            super(layer, Shortcut.registerShortcut("core_multikey:previousMarker", tr("Multikey: {0}", tr("Previous marker")),
122                    KeyEvent.VK_P, Shortcut.ALT_CTRL));
123            putValue(SHORT_DESCRIPTION, tr("Jump to previous marker"));
124            putValue(NAME, tr("Jump to previous marker"));
125        }
126
127        @Override
128        protected void execute(Layer l) {
129            ((JumpToMarkerLayer) l).jumpToPreviousMarker();
130            setLastLayer(l);
131        }
132    }
133}