Index: /applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/AdvancedSettingsDialog.java
===================================================================
--- /applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/AdvancedSettingsDialog.java	(revision 36080)
+++ /applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/AdvancedSettingsDialog.java	(revision 36081)
@@ -14,4 +14,7 @@
 import org.openstreetmap.josm.tools.GBC;
 
+/**
+ * A dialog for users to set "advanced" settings for the tool
+ */
 public class AdvancedSettingsDialog extends MyDialog {
     private final TagEditorModel tagsModel = new TagEditorModel();
@@ -20,5 +23,9 @@
     private final JCheckBox cSoftCur = new JCheckBox(tr("Rotate crosshair"));
     private final JCheckBox cNoClickDrag = new JCheckBox(tr("Disable click+drag"));
+    private final JCheckBox cToggleMapMode = new JCheckBox(tr("Switch between circle and rectangle modes"));
 
+    /**
+     * Create a new advanced settings dialog
+     */
     public AdvancedSettingsDialog() {
         super(tr("Advanced settings"));
@@ -34,8 +41,12 @@
         panel.add(cSoftCur, GBC.eol().fill(GBC.HORIZONTAL));
         panel.add(cNoClickDrag, GBC.eol().fill(GBC.HORIZONTAL));
+        panel.add(cToggleMapMode, GBC.eol().fill(GBC.HORIZONTAL));
 
         cBigMode.setSelected(ToolSettings.isBBMode());
         cSoftCur.setSelected(ToolSettings.isSoftCursor());
         cNoClickDrag.setSelected(ToolSettings.isNoClickAndDrag());
+        cToggleMapMode.setSelected(ToolSettings.isTogglingBuildingTypeOnRepeatedKeyPress());
+
+        cToggleMapMode.setToolTipText(tr("This is similar to the select action toggling between lasso and rectangle select modes"));
 
         setupDialog();
@@ -43,4 +54,7 @@
     }
 
+    /**
+     * Save the settings
+     */
     public final void saveSettings() {
         ToolSettings.saveTags(tagsModel.getTags());
@@ -48,4 +62,5 @@
         ToolSettings.setSoftCursor(cSoftCur.isSelected());
         ToolSettings.setNoClickAndDrag(cNoClickDrag.isSelected());
+        ToolSettings.setTogglingBuildingTypeOnRepeatedKeyPress(cToggleMapMode.isSelected());
     }
 }
Index: /applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/BuildingsToolsPlugin.java
===================================================================
--- /applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/BuildingsToolsPlugin.java	(revision 36080)
+++ /applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/BuildingsToolsPlugin.java	(revision 36081)
@@ -1,4 +1,6 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.plugins.buildings_tools;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import javax.swing.JMenu;
@@ -15,12 +17,26 @@
 import org.openstreetmap.josm.plugins.Plugin;
 import org.openstreetmap.josm.plugins.PluginInformation;
+import org.openstreetmap.josm.tools.ImageProvider;
 
+/**
+ * The entry point for the buildings tools plugin
+ */
 public class BuildingsToolsPlugin extends Plugin {
     public static final Projection MERCATOR = Projections.getProjectionByCode("EPSG:3857"); // Mercator
 
+    /**
+     * Convert a latlon to east north
+     * @param p The latlon to convert
+     * @return The east-north ({@link #MERCATOR})
+     */
     public static EastNorth latlon2eastNorth(ILatLon p) {
         return MERCATOR.latlon2eastNorth(p);
     }
 
+    /**
+     * Convert an east-north to a latlon
+     * @param p The east north to convert (from {@link #MERCATOR})
+     * @return The latlon
+     */
     public static LatLon eastNorth2latlon(EastNorth p) {
         return MERCATOR.eastNorth2latlon(p);
@@ -29,9 +45,16 @@
     public BuildingsToolsPlugin(PluginInformation info) {
         super(info);
-        JMenu dataMenu = MainApplication.getMenu().dataMenu;
-        MainMenu.add(dataMenu, new BuildingSizeAction());
-        MainMenu.add(dataMenu, new BuildingCircleAction());
-        MainMenu.add(dataMenu, new BuildingRectangleAction());
-        MainMenu.add(dataMenu, new MergeAddrPointsAction());
+        JMenu moreToolsMenu = MainApplication.getMenu().moreToolsMenu;
+        if (moreToolsMenu.getMenuComponentCount() > 0) {
+            moreToolsMenu.addSeparator();
+        }
+        MainMenu.add(moreToolsMenu, new DrawBuildingAction());
+        JMenu optionMenu = new JMenu(tr("Draw buildings modes"));
+        optionMenu.setIcon(ImageProvider.get("preference_small", ImageProvider.ImageSizes.MENU));
+        moreToolsMenu.add(optionMenu);
+        MainMenu.add(optionMenu, new BuildingSizeAction());
+        MainMenu.add(optionMenu, new BuildingCircleAction());
+        MainMenu.add(optionMenu, new BuildingRectangleAction());
+        MainMenu.add(optionMenu, new MergeAddrPointsAction());
     }
 
@@ -39,5 +62,5 @@
     public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
         if (oldFrame == null && newFrame != null) {
-            MainApplication.getMap().addMapMode(new IconToggleButton(new DrawBuildingAction()));
+            newFrame.addMapMode(new IconToggleButton(new DrawBuildingAction()));
         }
     }
Index: /applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/DrawBuildingAction.java
===================================================================
--- /applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/DrawBuildingAction.java	(revision 36080)
+++ /applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/DrawBuildingAction.java	(revision 36081)
@@ -23,5 +23,4 @@
 import org.openstreetmap.josm.tools.Geometry;
 import org.openstreetmap.josm.tools.ImageProvider;
-import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -45,6 +44,10 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
+/**
+ * The action for drawing the building
+ */
 public class DrawBuildingAction extends MapMode implements MapViewPaintable, DataSelectionListener,
         KeyPressReleaseListener, ModifierExListener {
+    private static final long serialVersionUID = -3515263157730927711L;
     // We need to avoid opening many file descriptors on Linux under Wayland -- see JOSM #21929. This will probably also
     // improve performance, since we aren't creating cursors all the time.
@@ -73,4 +76,7 @@
     private final PreferenceChangedListener shapeChangeListener = event -> updCursor();
 
+    /**
+     * Create a new {@link DrawBuildingAction} object
+     */
     public DrawBuildingAction() {
         super(tr("Draw buildings"), "building", tr("Draw buildings"),
@@ -88,14 +94,12 @@
 
     private static Cursor getCursor() {
-        try {
-            if (ToolSettings.Shape.CIRCLE == ToolSettings.getShape()) {
+        switch (ToolSettings.getShape()) {
+            case RECTANGLE:
+                return CURSOR_BUILDING;
+            case CIRCLE:
                 return CURSOR_SILO;
-            } else {
-                return CURSOR_BUILDING;
-            }
-        } catch (Exception e) {
-            Logging.error(e);
-        }
-        return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
+            default:
+                return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
+        }
     }
 
@@ -161,4 +165,7 @@
     }
 
+    /**
+     * Cancel the drawing of a building
+     */
     public final void cancelDrawing() {
         mode = Mode.None;
@@ -194,8 +201,21 @@
             cancelDrawing();
         }
+        if (!ToolSettings.isTogglingBuildingTypeOnRepeatedKeyPress()
+                || !MainApplication.isDisplayingMapView() || !getShortcut().isEvent(e)) {
+            return;
+        }
+        e.consume();
+        switch (ToolSettings.getShape()) {
+            case CIRCLE:
+                ToolSettings.saveShape(ToolSettings.Shape.RECTANGLE);
+                break;
+            case RECTANGLE:
+                ToolSettings.saveShape(ToolSettings.Shape.CIRCLE);
+        }
     }
 
     @Override
     public void doKeyReleased(KeyEvent e) {
+        // Do nothing
     }
 
@@ -437,4 +457,8 @@
     }
 
+    /**
+     * Update the snap for drawing
+     * @param newSelection The selection to use
+     */
     public final void updateSnap(Collection<? extends OsmPrimitive> newSelection) {
         building.clearAngleSnap();
Index: /applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/ToolSettings.java
===================================================================
--- /applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/ToolSettings.java	(revision 36080)
+++ /applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/ToolSettings.java	(revision 36081)
@@ -5,4 +5,5 @@
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -14,4 +15,7 @@
 import org.openstreetmap.josm.tools.Logging;
 
+/**
+ * A holder for plugin settings
+ */
 public final class ToolSettings {
 
@@ -22,4 +26,7 @@
     public static final BooleanProperty PROP_USE_ADDR_NODE = new BooleanProperty("buildings_tools.addrNode", false);
 
+    /**
+     * The shapes that users can create
+     */
     public enum Shape {
             CIRCLE, RECTANGLE
@@ -32,4 +39,8 @@
     private static final Map<String, String> TAGS = new HashMap<>();
 
+    /**
+     * Get the current shape that will be created
+     * @return The shape
+     */
     public static Shape getShape() {
         loadShape();
@@ -37,8 +48,17 @@
     }
 
+    /**
+     * Set whether to use the address dialog
+     * @param useAddr {@code true} if the address dialog should be used
+     */
     public static void setAddrDialog(boolean useAddr) {
         ToolSettings.useAddr = useAddr;
     }
 
+    /**
+     * Set some constraints for new buildings
+     * @param newwidth The max width ({@link Shape#RECTANGLE}) or max diameter ({@link Shape#CIRCLE})
+     * @param newlenstep The step sizes to use when setting the length of a {@link Shape#RECTANGLE}
+     */
     public static void setSizes(double newwidth, double newlenstep) {
         width = newwidth;
@@ -46,21 +66,41 @@
     }
 
+    /**
+     * Get the width/diameter
+     * @return The max width ({@link Shape#RECTANGLE}) or max diameter ({@link Shape#CIRCLE})
+     */
     public static double getWidth() {
         return width;
     }
 
+    /**
+     * Get the step length for {@link Shape#RECTANGLE}
+     * @return The amount to increase the length of a {@link Shape#RECTANGLE}.
+     */
     public static double getLenStep() {
         return lenstep;
     }
 
+    /**
+     * Check if we want to show the user an address dialog
+     * @return {@code true} if the user should be shown the address dialog
+     */
     public static boolean isUsingAddr() {
         return useAddr;
     }
 
+    /**
+     * Get the tags that the user wants to set on all new objects
+     * @return The tag map
+     */
     public static Map<String, String> getTags() {
         loadTags();
-        return TAGS;
-    }
-
+        return Collections.unmodifiableMap(TAGS);
+    }
+
+    /**
+     * Set the tags to put on all new objects
+     * @param tags The tags to set
+     */
     public static void saveTags(Map<String, String> tags) {
         TAGS.clear();
@@ -74,4 +114,7 @@
     }
 
+    /**
+     * Load tags from preferences
+     */
     private static void loadTags() {
         TAGS.clear();
@@ -87,8 +130,16 @@
     }
 
+    /**
+     * Set the shape to use
+     * @param shape The shape
+     */
     public static void saveShape(Shape shape) {
         Config.getPref().put("buildings_tool.shape", shape.name());
     }
 
+    /**
+     * Load the shape to use from preferences
+     * @return The shape to use
+     */
     private static Shape loadShape() {
         String shape = Config.getPref().get("buildings_tool.shape");
@@ -102,8 +153,16 @@
     }
 
+    /**
+     * Set the Big buildings mode
+     * @param bbmode {@code true} if big building mode should be used
+     */
     public static void setBBMode(boolean bbmode) {
         Config.getPref().putBoolean("buildings_tools.bbmode", bbmode);
     }
 
+    /**
+     * Get the Big buildings mode
+     * @return {@code true} if big building mode should be used
+     */
     public static boolean isBBMode() {
         return Config.getPref().getBoolean("buildings_tools.bbmode", false);
@@ -134,4 +193,20 @@
     }
 
+    /**
+     * Check if we are toggling between {@link Shape} types if the user toggles the mapmode with a keypress
+     * @return {@code true} if we want to change the shape type
+     */
+    public static boolean isTogglingBuildingTypeOnRepeatedKeyPress() {
+        return Config.getPref().getBoolean("buildings_tools.toggle_building_type", false);
+    }
+
+    /**
+     * Set whether or not we are toggling between {@link Shape} types if the user toggles the mapmode with a keypress
+     * @param toggle {@code true} if we want to change the shape type
+     */
+    public static void setTogglingBuildingTypeOnRepeatedKeyPress(boolean toggle) {
+        Config.getPref().putBoolean("buildings_tools.toggle_building_type", toggle);
+    }
+
     public static boolean isNoClickAndDrag() {
         return Config.getPref().getBoolean("buildings_tools.noclickdrag", false);
Index: /applications/editors/josm/plugins/buildings_tools/test/unit/org/openstreetmap/josm/plugins/buildings_tools/BuildingsToolsPluginTest.java
===================================================================
--- /applications/editors/josm/plugins/buildings_tools/test/unit/org/openstreetmap/josm/plugins/buildings_tools/BuildingsToolsPluginTest.java	(revision 36081)
+++ /applications/editors/josm/plugins/buildings_tools/test/unit/org/openstreetmap/josm/plugins/buildings_tools/BuildingsToolsPluginTest.java	(revision 36081)
@@ -0,0 +1,47 @@
+package org.openstreetmap.josm.plugins.buildings_tools;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+import java.util.jar.Attributes;
+
+import org.junit.jupiter.api.Test;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.LayerManager;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.plugins.PluginException;
+import org.openstreetmap.josm.plugins.PluginInformation;
+import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
+import org.openstreetmap.josm.testutils.annotations.Main;
+import org.openstreetmap.josm.testutils.annotations.Projection;
+
+/**
+ * Test class for {@link BuildingsToolsPlugin}
+ */
+@BasicPreferences
+@Main
+@Projection
+class BuildingsToolsPluginTest {
+    /**
+     * This makes certain we don't have an IAE after removing last layer and adding a new one
+     * @throws PluginException If something occurs during {@link PluginInformation} construction
+     */
+    @Test
+    void testMapReinitialization() throws PluginException {
+        final BuildingsToolsPlugin plugin =
+                new BuildingsToolsPlugin(new PluginInformation(new Attributes(), "buildings_tools", "https://example.com"));
+        MainApplication.getMainPanel().addMapFrameListener(plugin);
+        try {
+            final LayerManager layerManager = MainApplication.getLayerManager();
+            for (int i = 0; i < 20; i++) {
+                final Layer layer = new OsmDataLayer(new DataSet(), "testMapReinitialization", null);
+                assertDoesNotThrow(() -> layerManager.addLayer(layer));
+                assertDoesNotThrow(() -> layerManager.removeLayer(layer));
+            }
+        } finally {
+            MainApplication.getMainPanel().removeMapFrameListener(plugin);
+        }
+    }
+
+}
Index: /applications/editors/josm/plugins/buildings_tools/test/unit/org/openstreetmap/josm/plugins/buildings_tools/DrawBuildingActionTest.java
===================================================================
--- /applications/editors/josm/plugins/buildings_tools/test/unit/org/openstreetmap/josm/plugins/buildings_tools/DrawBuildingActionTest.java	(revision 36081)
+++ /applications/editors/josm/plugins/buildings_tools/test/unit/org/openstreetmap/josm/plugins/buildings_tools/DrawBuildingActionTest.java	(revision 36081)
@@ -0,0 +1,75 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.buildings_tools;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.awt.event.KeyEvent;
+import java.time.Instant;
+
+import javax.swing.JLabel;
+import javax.swing.KeyStroke;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+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.annotations.BasicPreferences;
+import org.openstreetmap.josm.testutils.annotations.Main;
+import org.openstreetmap.josm.testutils.annotations.Projection;
+
+/**
+ * Test class for {@link DrawBuildingAction}
+ */
+@BasicPreferences
+@Main
+@Projection
+class DrawBuildingActionTest {
+    private static DrawBuildingAction action;
+
+    @BeforeEach
+    void setup() {
+        action = new DrawBuildingAction();
+    }
+
+    @AfterEach
+    void tearDown() {
+        action.destroy();
+        action = null;
+    }
+
+
+    /**
+     * Ensure that we are toggling the map mode properly
+     */
+    @ParameterizedTest
+    @ValueSource(booleans = {false, true})
+    void testToggle(boolean setToggle) {
+        // Ensure we are showing the main map
+        MainApplication.getLayerManager().addLayer(new OsmDataLayer(new DataSet(), "testToggle", null));
+        ToolSettings.setTogglingBuildingTypeOnRepeatedKeyPress(setToggle);
+        assertEquals(setToggle, ToolSettings.isTogglingBuildingTypeOnRepeatedKeyPress());
+        final ToolSettings.Shape shape = ToolSettings.getShape();
+        final KeyStroke keyStroke = action.getShortcut().getKeyStroke();
+        MainApplication.getMap().selectMapMode(action);
+        action.doKeyPressed(getKeyEvent(keyStroke));
+        assertNotEquals(setToggle, shape == ToolSettings.getShape());
+        action.doKeyPressed(getKeyEvent(keyStroke));
+        assertEquals(shape, ToolSettings.getShape());
+    }
+
+    /**
+     * Get a key event to send the action
+     * @param keyStroke The keystroke to use
+     * @return The event
+     */
+    private KeyEvent getKeyEvent(KeyStroke keyStroke) {
+        assertNotNull(keyStroke);
+        return new KeyEvent(new JLabel(), KeyEvent.KEY_PRESSED, Instant.now().toEpochMilli(),
+                keyStroke.getModifiers(), keyStroke.getKeyCode(), keyStroke.getKeyChar());
+    }
+}
