001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.preferences.remotecontrol;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.Color;
007import java.awt.Font;
008import java.awt.GridBagLayout;
009import java.awt.event.ActionListener;
010import java.util.LinkedHashMap;
011import java.util.Map;
012import java.util.Map.Entry;
013
014import javax.swing.BorderFactory;
015import javax.swing.Box;
016import javax.swing.JCheckBox;
017import javax.swing.JLabel;
018import javax.swing.JPanel;
019import javax.swing.JSeparator;
020
021import org.openstreetmap.josm.gui.help.HelpUtil;
022import org.openstreetmap.josm.gui.preferences.DefaultTabPreferenceSetting;
023import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
024import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
025import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
026import org.openstreetmap.josm.gui.util.GuiHelper;
027import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
028import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
029import org.openstreetmap.josm.io.remotecontrol.RemoteControl;
030import org.openstreetmap.josm.io.remotecontrol.handler.RequestHandler;
031import org.openstreetmap.josm.spi.preferences.Config;
032import org.openstreetmap.josm.tools.GBC;
033
034/**
035 * Preference settings for Remote Control.
036 *
037 * @author Frederik Ramm
038 */
039public final class RemoteControlPreference extends DefaultTabPreferenceSetting {
040
041    /**
042     * Factory used to build a new instance of this preference setting
043     */
044    public static class Factory implements PreferenceSettingFactory {
045
046        @Override
047        public PreferenceSetting createPreferenceSetting() {
048            return new RemoteControlPreference();
049        }
050    }
051
052    private RemoteControlPreference() {
053        super(/* ICON(preferences/) */ "remotecontrol", tr("Remote Control"), tr("Settings for the remote control feature."));
054        for (PermissionPrefWithDefault p : PermissionPrefWithDefault.getPermissionPrefs()) {
055            JCheckBox cb = new JCheckBox(p.preferenceText);
056            cb.setSelected(p.isAllowed());
057            prefs.put(p, cb);
058        }
059    }
060
061    private final Map<PermissionPrefWithDefault, JCheckBox> prefs = new LinkedHashMap<>();
062    private JCheckBox enableRemoteControl;
063
064    private final JCheckBox loadInNewLayer = new JCheckBox(tr("Download as new layer"));
065    private final JCheckBox alwaysAskUserConfirm = new JCheckBox(tr("Confirm all Remote Control actions manually"));
066
067    @Override
068    public void addGui(final PreferenceTabbedPane gui) {
069
070        JPanel remote = new VerticallyScrollablePanel(new GridBagLayout());
071
072        final JLabel descLabel = new JLabel("<html>"
073                + tr("Allows JOSM to be controlled from other applications, e.g. from a web browser.")
074                + "</html>");
075        descLabel.setFont(descLabel.getFont().deriveFont(Font.PLAIN));
076        remote.add(descLabel, GBC.eol().insets(5, 5, 0, 10).fill(GBC.HORIZONTAL));
077
078        final JLabel portLabel = new JLabel("<html>"
079                + tr("JOSM will always listen at <b>port {0}</b> (http) on localhost."
080                + "<br>This port is not configurable because it is referenced by external applications talking to JOSM.",
081                Config.getPref().get("remote.control.port", "8111")) + "</html>");
082        portLabel.setFont(portLabel.getFont().deriveFont(Font.PLAIN));
083        remote.add(portLabel, GBC.eol().insets(5, 5, 0, 10).fill(GBC.HORIZONTAL));
084
085        enableRemoteControl = new JCheckBox(tr("Enable remote control"), RemoteControl.PROP_REMOTECONTROL_ENABLED.get());
086        remote.add(enableRemoteControl, GBC.eol());
087
088        final JPanel wrapper = new JPanel(new GridBagLayout());
089        wrapper.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.gray)));
090
091        remote.add(wrapper, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 5, 5));
092
093        wrapper.add(new JSeparator(), GBC.eop().fill(GBC.HORIZONTAL).insets(15, 5, 15, 5));
094
095        wrapper.add(new JLabel(tr("Permitted actions:")), GBC.eol().insets(5, 0, 0, 0));
096        for (JCheckBox p : prefs.values()) {
097            wrapper.add(p, GBC.eol().insets(15, 5, 0, 0).fill(GBC.HORIZONTAL));
098        }
099
100        wrapper.add(new JSeparator(), GBC.eop().fill(GBC.HORIZONTAL).insets(15, 5, 15, 5));
101        wrapper.add(loadInNewLayer, GBC.eol().fill(GBC.HORIZONTAL));
102        wrapper.add(alwaysAskUserConfirm, GBC.eol().fill(GBC.HORIZONTAL));
103
104        remote.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
105
106        loadInNewLayer.setSelected(Config.getPref().getBoolean(
107                RequestHandler.loadInNewLayerKey, RequestHandler.loadInNewLayerDefault));
108        alwaysAskUserConfirm.setSelected(Config.getPref().getBoolean(
109                RequestHandler.globalConfirmationKey, RequestHandler.globalConfirmationDefault));
110
111        ActionListener remoteControlEnabled = e -> GuiHelper.setEnabledRec(wrapper, enableRemoteControl.isSelected());
112        enableRemoteControl.addActionListener(remoteControlEnabled);
113        remoteControlEnabled.actionPerformed(null);
114        createPreferenceTabWithScrollPane(gui, remote);
115    }
116
117    @Override
118    public boolean ok() {
119        boolean enabled = enableRemoteControl.isSelected();
120        boolean changed = RemoteControl.PROP_REMOTECONTROL_ENABLED.put(enabled);
121        if (enabled) {
122            for (Entry<PermissionPrefWithDefault, JCheckBox> p : prefs.entrySet()) {
123                Config.getPref().putBoolean(p.getKey().pref, p.getValue().isSelected());
124            }
125            Config.getPref().putBoolean(RequestHandler.loadInNewLayerKey, loadInNewLayer.isSelected());
126            Config.getPref().putBoolean(RequestHandler.globalConfirmationKey, alwaysAskUserConfirm.isSelected());
127        }
128        if (changed) {
129            if (enabled) {
130                RemoteControl.start();
131            } else {
132                RemoteControl.stop();
133            }
134        }
135        return false;
136    }
137
138    @Override
139    public String getHelpContext() {
140        return HelpUtil.ht("/Preferences/RemoteControl");
141    }
142}