diff --git a/src/org/openstreetmap/josm/actions/ToggleEditLockLayerAction.java b/src/org/openstreetmap/josm/actions/ToggleEditLockLayerAction.java new file mode 100644 index 00000000000..cfeeab16be4 --- /dev/null +++ b/src/org/openstreetmap/josm/actions/ToggleEditLockLayerAction.java @@ -0,0 +1,68 @@ +// License: GPL. For details, see LICENSE file. +package org.openstreetmap.josm.actions; + +import static org.openstreetmap.josm.tools.I18n.tr; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.util.List; + +import javax.swing.AbstractAction; +import javax.swing.JCheckBoxMenuItem; + +import org.openstreetmap.josm.data.osm.Lockable; +import org.openstreetmap.josm.gui.dialogs.LayerListDialog; +import org.openstreetmap.josm.gui.layer.Layer; +import org.openstreetmap.josm.gui.layer.Layer.LayerAction; +import org.openstreetmap.josm.tools.CheckParameterUtil; +import org.openstreetmap.josm.tools.ImageProvider; + +/** + * An action enabling/disabling the {@linkplain Lockable#lock() read-only flag} + * of the layer specified in the constructor. + * @param Type of layer the action should be instantiated for + * + * @since xxx + */ +public class ToggleEditLockLayerAction extends AbstractAction implements LayerAction { + + private final L layer; + + /** + * Construct a new {@code ToggleEditLockLayerAction} + * @param layer the layer for which to toggle the {@linkplain Lockable#lock() read-only flag} + * + * @since xxx + */ + public ToggleEditLockLayerAction(L layer) { + super(tr("Prevent modification")); + CheckParameterUtil.ensureParameterNotNull(layer, "layer"); + putValue(SHORT_DESCRIPTION, tr("Prevent/allow changes being made in this layer")); + new ImageProvider("lock").getResource().attachImageIcon(this, true); + this.layer = layer; + } + + @Override + public void actionPerformed(ActionEvent e) { + if (layer.isLocked()) { + layer.unlock(); + } else { + layer.lock(); + } + + layer.invalidate(); + LayerListDialog.getInstance().repaint(); + } + + @Override + public Component createMenuComponent() { + JCheckBoxMenuItem item = new JCheckBoxMenuItem(this); + item.setSelected(layer.isLocked()); + return item; + } + + @Override + public boolean supportLayers(List layers) { + return layers.size() == 1 && layers.get(0) instanceof Lockable; + } +} diff --git a/src/org/openstreetmap/josm/actions/ToggleUploadDiscouragedLayerAction.java b/src/org/openstreetmap/josm/actions/ToggleUploadDiscouragedLayerAction.java index a15a58e7160..1a16f9897f3 100644 --- a/src/org/openstreetmap/josm/actions/ToggleUploadDiscouragedLayerAction.java +++ b/src/org/openstreetmap/josm/actions/ToggleUploadDiscouragedLayerAction.java @@ -31,6 +31,7 @@ public class ToggleUploadDiscouragedLayerAction extends AbstractAction implement */ public ToggleUploadDiscouragedLayerAction(OsmDataLayer layer) { super(tr("Discourage upload")); + putValue(SHORT_DESCRIPTION, tr("Allow/disallow upload of changes made in this layer")); new ImageProvider("no_upload").getResource().attachImageIcon(this, true); this.layer = layer; setEnabled(layer.isUploadable()); diff --git a/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java b/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java index 3acb837bee1..8c6daaf9c6e 100644 --- a/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java +++ b/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java @@ -52,6 +52,7 @@ import org.openstreetmap.josm.actions.AutoScaleAction; import org.openstreetmap.josm.actions.ExpertToggleAction; import org.openstreetmap.josm.actions.RenameLayerAction; +import org.openstreetmap.josm.actions.ToggleEditLockLayerAction; import org.openstreetmap.josm.actions.ToggleUploadDiscouragedLayerAction; import org.openstreetmap.josm.data.APIDataSet; import org.openstreetmap.josm.data.Bounds; @@ -743,6 +744,7 @@ public Action[] getMenuEntries() { new RenameLayerAction(getAssociatedFile(), this))); if (ExpertToggleAction.isExpert()) { actions.add(new ToggleUploadDiscouragedLayerAction(this)); + actions.add(new ToggleEditLockLayerAction<>(this)); } actions.addAll(Arrays.asList( new ConsistencyTestAction(), diff --git a/test/unit/org/openstreetmap/josm/actions/ToggleEditLockLayerActionTest.java b/test/unit/org/openstreetmap/josm/actions/ToggleEditLockLayerActionTest.java new file mode 100644 index 00000000000..06f38deac70 --- /dev/null +++ b/test/unit/org/openstreetmap/josm/actions/ToggleEditLockLayerActionTest.java @@ -0,0 +1,59 @@ +// License: GPL. For details, see LICENSE file. +package org.openstreetmap.josm.actions; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.openstreetmap.josm.data.osm.DataSet; +import org.openstreetmap.josm.gui.MainApplication; +import org.openstreetmap.josm.gui.layer.OsmDataLayer; +import org.openstreetmap.josm.testutils.JOSMTestRules; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +/** + * Unit tests for class {@link ToggleEditLockLayerAction}. + */ +final class ToggleEditLockLayerActionTest { + + /** + * Setup test. + */ + @RegisterExtension + @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") + public static JOSMTestRules test = new JOSMTestRules().main().projection(); + + /** + * Test null parameter + */ + @Test + void testNullLayer() { + assertThrows(IllegalArgumentException.class, () -> new ToggleEditLockLayerAction(null)); + } + + /** + * Test edit lock toggle functionality + * @param locked Initial layer lock status + */ + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void testLayerLockToggle(boolean locked) { + OsmDataLayer testLayer = new OsmDataLayer(new DataSet(), "testLayerLock", null); + MainApplication.getLayerManager().addLayer(testLayer); + if (locked) { + testLayer.lock(); + } + // Sanity check + assertEquals(locked, testLayer.isLocked()); + ToggleEditLockLayerAction action = new ToggleEditLockLayerAction<>(testLayer); + action.actionPerformed(null); + assertNotEquals(locked, testLayer.isLocked()); + action.actionPerformed(null); + assertEquals(locked, testLayer.isLocked()); + } +}