diff --git a/.gitignore b/.gitignore
index 3d47f986c41db29ec6dc0d5036bf760b3a1cf366..57f16fb67c1b1589981416b323d7a9debc728665 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,41 @@
-.idea/
+/build*
+/workspace
+setting.xml
+release/
 target/
-.settings/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+icy.log
+
+### IntelliJ IDEA ###
+.idea/
+*.iws
 *.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
 .project
-.classpath
\ No newline at end of file
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+**/.DS_Store
+Icon?
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 9f729a539c2071fd29d4be2bf1f1ea546d892a39..ffe553994c9de001098b366417aa47e9fe159138 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,21 +6,19 @@
 	<parent>
 		<groupId>org.bioimageanalysis.icy</groupId>
 		<artifactId>pom-icy</artifactId>
-		<version>2.1.2</version>
+		<version>3.0.0-a.1</version>
 	</parent>
 
 	<!-- Project Information -->
 	<artifactId>scale-bar</artifactId>
-	<version>3.3.1</version>
-
-	<packaging>jar</packaging>
+	<version>4.0.0-a.1</version>
 
 	<name>Scale Bar</name>
 	<description>
         Displays a scale bar overlay on the sequence.
         Warning: this plugin needs correct sequence metadata to be effective. Otherwise it will display wrong values.
     </description>
-	<url>http://icy.bioimageanalysis.org/plugin/scale-bar/</url>
+	<url>https://icy.bioimageanalysis.org/plugin/scale-bar/</url>
 	<inceptionYear>2020</inceptionYear>
 
 	<organization>
@@ -54,20 +52,8 @@
 		</developer>
 	</developers>
 
-	<!-- Project properties -->
-	<properties></properties>
-
-	<!-- Project build configuration -->
-	<build></build>
-
 	<!-- List of project's dependencies -->
 	<dependencies>
-		<!-- The core of Icy -->
-		<dependency>
-			<groupId>org.bioimageanalysis.icy</groupId>
-			<artifactId>icy-kernel</artifactId>
-		</dependency>
-
 		<!-- The EzPlug library, simplifies writing UI for Icy plugins. -->
 		<dependency>
 			<groupId>org.bioimageanalysis.icy</groupId>
@@ -79,8 +65,7 @@
 	<repositories>
 		<repository>
 			<id>icy</id>
-			<name>Icy's Nexus</name>
-			<url>https://icy-nexus.pasteur.fr/repository/Icy/</url>
+			<url>https://nexus-icy.pasteur.cloud/repository/icy/</url>
 		</repository>
 	</repositories>
 </project>
\ No newline at end of file
diff --git a/src/main/java/plugins/tprovoost/scale/Scale.java b/src/main/java/plugins/tprovoost/scale/Scale.java
index db03aab9cd913f63ce8907eefbe2a2f96b07c0ec..51e54dcaa364de49313ba10458fbfe0ba80a3e79 100644
--- a/src/main/java/plugins/tprovoost/scale/Scale.java
+++ b/src/main/java/plugins/tprovoost/scale/Scale.java
@@ -1,14 +1,36 @@
+/*
+ * Copyright (c) 2010-2024. Institut Pasteur.
+ *
+ * This file is part of Icy.
+ * Icy is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Icy is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Icy. If not, see <https://www.gnu.org/licenses/>.
+ */
+
 package plugins.tprovoost.scale;
 
-import icy.gui.main.GlobalSequenceListener;
-import icy.gui.viewer.Viewer;
-import icy.main.Icy;
-import icy.painter.Overlay;
-import icy.plugin.abstract_.Plugin;
-import icy.plugin.interface_.PluginDaemon;
-import icy.preferences.XMLPreferences;
-import icy.sequence.Sequence;
-import icy.system.IcyHandledException;
+import org.bioimageanalysis.icy.Icy;
+import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin;
+import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginDescription;
+import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon;
+import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName;
+import org.bioimageanalysis.icy.extension.plugin.interface_.PluginDaemon;
+import org.bioimageanalysis.icy.gui.listener.GlobalSequenceListener;
+import org.bioimageanalysis.icy.gui.viewer.Viewer;
+import org.bioimageanalysis.icy.model.overlay.Overlay;
+import org.bioimageanalysis.icy.model.sequence.Sequence;
+import org.bioimageanalysis.icy.system.IcyHandledException;
+import org.bioimageanalysis.icy.system.preferences.XMLPreferences;
+import org.jetbrains.annotations.Contract;
 
 /**
  * Scale bar plug-in for Icy. Displays a scale bar on 2D viewers, with various display adjustment
@@ -22,16 +44,20 @@ import icy.system.IcyHandledException;
  * These options can be managed from the graphical interface (in the "Layers" section of the
  * inspector), or within scripts (see {@link #addScaleBarTo(Sequence)} and
  * {@link #removeScaleBarFrom(Sequence)}
- * 
- * @author Thomas Provoost, Stephane Dallongeville, Alexandre Dufour
+ *
+ * @author Thomas Provoost
+ * @author Stephane Dallongeville
+ * @author Alexandre Dufour
+ * @author Thomas Musset
  */
-public class Scale extends Plugin implements PluginDaemon, GlobalSequenceListener
-{
+@IcyPluginName("Scale Bar")
+@IcyPluginDescription(shortDesc = "Displays a scale bar on 2D viewers, with various display adjustment options.")
+@IcyPluginIcon(path = "/plugins/tprovoost/scale/icon/Scale_icon.png")
+public class Scale extends Plugin implements PluginDaemon, GlobalSequenceListener {
     private static XMLPreferences preferences = null;
 
     @Override
-    public void init()
-    {
+    public void init() {
         if (preferences == null)
             preferences = getPreferencesRoot();
 
@@ -39,63 +65,58 @@ public class Scale extends Plugin implements PluginDaemon, GlobalSequenceListene
     }
 
     @Override
-    public void run()
-    {
-        for (Sequence s : getSequences())
+    public void run() {
+        for (final Sequence s : getSequences())
             addScaleBarTo(s);
     }
 
     @Override
-    public void stop()
-    {
-        for (Sequence s : getSequences())
+    public void stop() {
+        for (final Sequence s : getSequences())
             removeScaleBarFrom(s);
 
         Icy.getMainInterface().removeGlobalSequenceListener(this);
     }
 
     @Override
-    public void sequenceOpened(Sequence sequence)
-    {
+    public void sequenceOpened(final Sequence sequence) {
         addScaleBarTo(sequence);
     }
 
     @Override
-    public void sequenceClosed(Sequence sequence)
-    {
+    public void sequenceClosed(final Sequence sequence) {
         removeScaleBarFrom(sequence);
     }
 
-    public static ScaleBarOverlay addScaleBarTo(Sequence sequence)
-    {
+    @Contract("null -> fail")
+    public static ScaleBarOverlay addScaleBarTo(final Sequence sequence) {
         if (sequence == null)
             throw new IcyHandledException("Cannot add the scale bar: no sequence specified");
 
         if (sequence.hasOverlay(ScaleBarOverlay.class))
-            return sequence.getOverlays(ScaleBarOverlay.class).get(0);
+            return sequence.getOverlays(ScaleBarOverlay.class).getFirst();
 
-        ScaleBarOverlay overlay = new ScaleBarOverlay(preferences);
+        final ScaleBarOverlay overlay = new ScaleBarOverlay(preferences);
 
         sequence.addOverlay(overlay);
 
         // Try to detect if the sequence is a screenshot (via its name)
         // => hide the overlay by default (but don't remove it)
-        String name = sequence.getName().toLowerCase();
-        if (name.startsWith("rendering") || name.startsWith("screen shot"))
-        {
-            for (Viewer viewer : sequence.getViewers())
+        final String name = sequence.getName().toLowerCase();
+        if (name.startsWith("rendering") || name.startsWith("screen shot")) {
+            for (final Viewer viewer : sequence.getViewers())
                 viewer.getCanvas().getLayer(overlay).setVisible(false);
         }
 
         return overlay;
     }
 
-    public static void removeScaleBarFrom(Sequence sequence)
-    {
+    @Contract("null -> fail")
+    public static void removeScaleBarFrom(final Sequence sequence) {
         if (sequence == null)
             throw new IcyHandledException("Cannot remove the scale bar: no sequence specified");
 
-        for (Overlay o : sequence.getOverlays(ScaleBarOverlay.class))
+        for (final Overlay o : sequence.getOverlays(ScaleBarOverlay.class))
             sequence.removeOverlay(o);
     }
 }
diff --git a/src/main/java/plugins/tprovoost/scale/ScaleBarLocation.java b/src/main/java/plugins/tprovoost/scale/ScaleBarLocation.java
index 98cf88223707df0615bdb506456dba37a2ffa3d5..b43febfb5e8ae4247e342df774d6d3dc3d3103e0 100644
--- a/src/main/java/plugins/tprovoost/scale/ScaleBarLocation.java
+++ b/src/main/java/plugins/tprovoost/scale/ScaleBarLocation.java
@@ -1,7 +1,26 @@
+/*
+ * Copyright (c) 2010-2024. Institut Pasteur.
+ *
+ * This file is part of Icy.
+ * Icy is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Icy is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Icy. If not, see <https://www.gnu.org/licenses/>.
+ */
+
 package plugins.tprovoost.scale;
 
-public enum ScaleBarLocation
-{
+import org.jetbrains.annotations.Contract;
+
+public enum ScaleBarLocation {
     IMAGE_BOTTOM_LEFT("Bottom left of image"), VIEWER_BOTTOM_LEFT("Bottom left of viewer"),
     IMAGE_BOTTOM_RIGHT("Bottom right of image"), VIEWER_BOTTOM_RIGHT("Bottom right of viewer"),
     IMAGE_TOP_LEFT("Top left of image"), VIEWER_TOP_LEFT("Top left of viewer"), IMAGE_TOP_RIGHT("Top right of image"),
@@ -9,26 +28,24 @@ public enum ScaleBarLocation
 
     public final String name;
 
-    private ScaleBarLocation(String name)
-    {
+    @Contract(pure = true)
+    ScaleBarLocation(final String name) {
         this.name = name;
     }
 
-    public String toString()
-    {
+    @Contract(pure = true)
+    @Override
+    public String toString() {
         return name;
     }
 
-    public boolean isRelativeToViewer()
-    {
-        return this == VIEWER_BOTTOM_LEFT || this == VIEWER_BOTTOM_RIGHT || this == VIEWER_TOP_LEFT
-                || this == VIEWER_TOP_RIGHT;
+    @Contract(pure = true)
+    public boolean isRelativeToViewer() {
+        return this == VIEWER_BOTTOM_LEFT || this == VIEWER_BOTTOM_RIGHT || this == VIEWER_TOP_LEFT || this == VIEWER_TOP_RIGHT;
     }
 
-    public boolean isRelativeToImage()
-    {
-        return this == IMAGE_BOTTOM_LEFT || this == IMAGE_BOTTOM_RIGHT || this == IMAGE_TOP_LEFT
-                || this == IMAGE_TOP_RIGHT;
+    @Contract(pure = true)
+    public boolean isRelativeToImage() {
+        return this == IMAGE_BOTTOM_LEFT || this == IMAGE_BOTTOM_RIGHT || this == IMAGE_TOP_LEFT || this == IMAGE_TOP_RIGHT;
     }
-
 }
diff --git a/src/main/java/plugins/tprovoost/scale/ScaleBarOverlay.java b/src/main/java/plugins/tprovoost/scale/ScaleBarOverlay.java
index 173e3f3804b048b577732e5b1268dedff271cf00..1daf9b3c1dbecdc0f85bc5787d25f64d0046e9e0 100644
--- a/src/main/java/plugins/tprovoost/scale/ScaleBarOverlay.java
+++ b/src/main/java/plugins/tprovoost/scale/ScaleBarOverlay.java
@@ -1,52 +1,57 @@
-package plugins.tprovoost.scale;
+/*
+ * Copyright (c) 2010-2024. Institut Pasteur.
+ *
+ * This file is part of Icy.
+ * Icy is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Icy is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Icy. If not, see <https://www.gnu.org/licenses/>.
+ */
 
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.Graphics2D;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.awt.RenderingHints;
-import java.awt.geom.Line2D;
-import java.awt.geom.Rectangle2D;
+package plugins.tprovoost.scale;
 
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-
-import icy.canvas.IcyCanvas;
-import icy.canvas.IcyCanvas2D;
-import icy.math.MathUtil;
-import icy.math.UnitUtil;
-import icy.math.UnitUtil.UnitPrefix;
-import icy.painter.Overlay;
-import icy.preferences.GeneralPreferences;
-import icy.preferences.XMLPreferences;
-import icy.sequence.Sequence;
-import icy.system.thread.ThreadUtil;
-import icy.util.ColorUtil;
-import icy.util.GraphicsUtil;
-import icy.util.ShapeUtil;
+import org.bioimageanalysis.icy.common.color.ColorUtil;
+import org.bioimageanalysis.icy.common.geom.shape.ShapeUtil;
+import org.bioimageanalysis.icy.common.math.MathUtil;
+import org.bioimageanalysis.icy.common.math.UnitUtil;
+import org.bioimageanalysis.icy.gui.GraphicsUtil;
+import org.bioimageanalysis.icy.gui.canvas.IcyCanvas;
+import org.bioimageanalysis.icy.gui.canvas.IcyCanvas2D;
+import org.bioimageanalysis.icy.gui.canvas.VtkCanvas;
+import org.bioimageanalysis.icy.model.overlay.Overlay;
+import org.bioimageanalysis.icy.model.sequence.Sequence;
+import org.bioimageanalysis.icy.system.preferences.GeneralPreferences;
+import org.bioimageanalysis.icy.system.preferences.XMLPreferences;
+import org.bioimageanalysis.icy.system.thread.ThreadUtil;
+import org.jetbrains.annotations.NotNull;
 import plugins.adufour.vars.gui.model.IntegerRangeModel;
 import plugins.adufour.vars.gui.swing.SwingVarEditor;
-import plugins.adufour.vars.lang.Var;
-import plugins.adufour.vars.lang.VarBoolean;
-import plugins.adufour.vars.lang.VarColor;
-import plugins.adufour.vars.lang.VarEnum;
-import plugins.adufour.vars.lang.VarInteger;
-import plugins.kernel.canvas.VtkCanvas;
+import plugins.adufour.vars.lang.*;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.geom.Line2D;
+import java.awt.geom.Rectangle2D;
 
 /**
- * Scale Bar Overay class
- * 
- * @author Stephane
+ * Scale Bar Overlay class
+ *
+ * @author Stephane Dallongeville
+ * @author Thomas Musset
  */
-public class ScaleBarOverlay extends Overlay
-{
+public class ScaleBarOverlay extends Overlay {
     private static final double[] scaleRoundedFactors = {1.0D, 2.0D, 3.0D, 4.0D, 5.0D, 6.0D, 7.0D, 8.0D, 9.0D, 10.0D, 20.0D, 30.0D, 40.0D, 50.0D, 60.0D, 70.0D,
-        80.0D, 90.0D, 100.0D, 200.0D, 300.0D, 400.0D, 500.0D, 600.0D, 700.0D, 800.0D, 900.0D};
+            80.0D, 90.0D, 100.0D, 200.0D, 300.0D, 400.0D, 500.0D, 600.0D, 700.0D, 800.0D, 900.0D};
 
-    private final XMLPreferences preferences;
+    //private final XMLPreferences preferences;
     private final Line2D.Double line;
     private JPanel optionPanel;
     private boolean init = false;
@@ -61,19 +66,16 @@ public class ScaleBarOverlay extends Overlay
     private final VarEnum<ScaleBarUnit> unit;
     private final VarBoolean autoSize;
 
-    public ScaleBarOverlay(XMLPreferences preferences)
-    {
+    public ScaleBarOverlay(final @NotNull XMLPreferences preferences) {
         super("Scale bar", OverlayPriority.TOPMOST);
 
-        this.preferences = preferences;
+        //this.preferences = preferences;
         line = new Line2D.Double();
 
         // scale bar location
-        location = new VarEnum<ScaleBarLocation>("Location", ScaleBarLocation.valueOf(preferences.get("location", ScaleBarLocation.VIEWER_BOTTOM_LEFT.name())))
-        {
+        location = new VarEnum<>("Location", ScaleBarLocation.valueOf(preferences.get("location", ScaleBarLocation.VIEWER_BOTTOM_LEFT.name()))) {
             @Override
-            public void setValue(ScaleBarLocation newValue)
-            {
+            public void setValue(final ScaleBarLocation newValue) {
                 if (getValue().equals(newValue))
                     return;
 
@@ -86,11 +88,9 @@ public class ScaleBarOverlay extends Overlay
         };
 
         // scale bar color
-        color = new VarColor("Color", new Color(preferences.getInt("color", new Color(255, 255, 255, 255).getRGB())))
-        {
+        color = new VarColor("Color", new Color(preferences.getInt("color", new Color(255, 255, 255, 255).getRGB()))) {
             @Override
-            public void setValue(Color newValue)
-            {
+            public void setValue(final Color newValue) {
                 if (getValue().equals(newValue))
                     return;
 
@@ -103,11 +103,9 @@ public class ScaleBarOverlay extends Overlay
         };
 
         // Opaque background
-        opaque = new VarBoolean("Opaque", preferences.getBoolean("opaque", false))
-        {
+        opaque = new VarBoolean("Opaque", preferences.getBoolean("opaque", false)) {
             @Override
-            public void setValue(Boolean newValue)
-            {
+            public void setValue(final Boolean newValue) {
                 if (getValue().equals(newValue))
                     return;
 
@@ -120,11 +118,9 @@ public class ScaleBarOverlay extends Overlay
         };
 
         // Display text over the scale bar
-        showText = new VarBoolean("Display size", preferences.getBoolean("showText", true))
-        {
+        showText = new VarBoolean("Display size", preferences.getBoolean("showText", true)) {
             @Override
-            public void setValue(Boolean newValue)
-            {
+            public void setValue(final Boolean newValue) {
                 if (getValue().equals(newValue))
                     return;
 
@@ -137,11 +133,9 @@ public class ScaleBarOverlay extends Overlay
         };
 
         // Scale bar size (default: 10 units)
-        size = new VarInteger("Size", preferences.getInt("size", 10))
-        {
+        size = new VarInteger("Size", preferences.getInt("size", 10)) {
             @Override
-            public void setValue(Integer newValue)
-            {
+            public void setValue(final Integer newValue) {
                 if (getValue().equals(newValue))
                     return;
 
@@ -154,11 +148,9 @@ public class ScaleBarOverlay extends Overlay
         };
 
         // Scale bar thickness (default: 5)
-        thickness = new VarInteger("Thickness", preferences.getInt("thickness", 5))
-        {
+        thickness = new VarInteger("Thickness", preferences.getInt("thickness", 5)) {
             @Override
-            public void setValue(Integer newValue)
-            {
+            public void setValue(final Integer newValue) {
                 if (getValue().equals(newValue))
                     return;
 
@@ -171,11 +163,9 @@ public class ScaleBarOverlay extends Overlay
         };
 
         // Scale bar unit (default: microns)
-        unit = new VarEnum<ScaleBarUnit>("Unit", ScaleBarUnit.valueOf(preferences.get("unit", ScaleBarUnit.MICRO.name())))
-        {
+        unit = new VarEnum<>("Unit", ScaleBarUnit.valueOf(preferences.get("unit", ScaleBarUnit.MICRO.name()))) {
             @Override
-            public void setValue(ScaleBarUnit newValue)
-            {
+            public void setValue(final ScaleBarUnit newValue) {
                 if (getValue().equals(newValue))
                     return;
 
@@ -188,11 +178,9 @@ public class ScaleBarOverlay extends Overlay
         };
 
         // auto-adjust the size and unit of the scale bar
-        autoSize = new VarBoolean("Auto-adjust size", preferences.getBoolean("autoSize", false))
-        {
+        autoSize = new VarBoolean("Auto-adjust size", preferences.getBoolean("autoSize", false)) {
             @Override
-            public void setValue(Boolean newValue)
-            {
+            public void setValue(final Boolean newValue) {
                 if (getValue().equals(newValue))
                     return;
 
@@ -205,69 +193,56 @@ public class ScaleBarOverlay extends Overlay
             }
         };
 
-        Integer currentSize = size.getValue();
+        final Integer currentSize = size.getValue();
         size.setDefaultEditorModel(new IntegerRangeModel(10, 1, 999, 1));
         size.setValue(currentSize);
 
-        Integer currentThickness = thickness.getValue();
+        final Integer currentThickness = thickness.getValue();
         thickness.setDefaultEditorModel(new IntegerRangeModel(5, 1, 20, 1));
         thickness.setValue(currentThickness);
 
         // do graphical stuff to the graphical thread
-        ThreadUtil.invokeLater(new Runnable()
-        {
-            @Override
-            public void run()
-            {
-                initOptionPanel();
-            }
-        });
+        ThreadUtil.invokeLater(this::initOptionPanel);
     }
 
     /**
      * Scale bar color (default: white)
      */
 
-    private void initOptionPanel()
-    {
+    private void initOptionPanel() {
         optionPanel = new JPanel(new GridBagLayout());
 
-        for (Var<?> variable : new Var<?>[] {location, color, opaque, autoSize, size, thickness, showText})
-        {
-            GridBagConstraints gbc = new GridBagConstraints();
+        for (final Var<?> variable : new Var<?>[]{location, color, opaque, autoSize, size, thickness, showText}) {
+            final GridBagConstraints gbc = new GridBagConstraints();
 
             gbc.insets = new Insets(2, 10, 2, 5);
             gbc.fill = GridBagConstraints.BOTH;
             optionPanel.add(new JLabel(variable.getName()), gbc);
 
             // special case: show unit next to size
-            if (variable == size)
-            {
+            if (variable == size) {
                 gbc.weightx = 0.5;
 
-                SwingVarEditor<?> editor = (SwingVarEditor<?>) variable.createVarEditor(true);
+                final SwingVarEditor<?> editor = (SwingVarEditor<?>) variable.createVarEditor(true);
                 optionPanel.add(editor.getEditorComponent(), gbc);
 
                 gbc.gridwidth = GridBagConstraints.REMAINDER;
 
-                SwingVarEditor<?> unitEditor = (SwingVarEditor<?>) unit.createVarEditor(true);
+                final SwingVarEditor<?> unitEditor = (SwingVarEditor<?>) unit.createVarEditor(true);
                 optionPanel.add(unitEditor.getEditorComponent(), gbc);
             }
-            else
-            {
+            else {
                 gbc.weightx = 1;
                 gbc.gridwidth = GridBagConstraints.REMAINDER;
-                SwingVarEditor<?> editor = (SwingVarEditor<?>) variable.createVarEditor(true);
+                final SwingVarEditor<?> editor = (SwingVarEditor<?>) variable.createVarEditor(true);
                 optionPanel.add(editor.getEditorComponent(), gbc);
             }
         }
     }
 
     @Override
-    public void paint(Graphics2D g, Sequence sequence, IcyCanvas canvas)
-    {
-        if (canvas instanceof VtkCanvas && !init)
-        {
+    public void paint(final Graphics2D g, final Sequence sequence, final IcyCanvas canvas) {
+        if (canvas instanceof VtkCanvas && !init) {
             init = true;
             return;
         }
@@ -277,8 +252,7 @@ public class ScaleBarOverlay extends Overlay
         final Graphics2D g2 = (Graphics2D) g.create();
         final IcyCanvas2D canvas2d = (IcyCanvas2D) canvas;
 
-        if (autoSize.getValue())
-        {
+        if (autoSize.getValue()) {
             int sizeW = Math.min(canvas.getCanvasSizeX() / 4, Math.max(canvas.getCanvasSizeX() / 7, 120));
             // sequence.getSizeX() / 7;
 
@@ -287,30 +261,28 @@ public class ScaleBarOverlay extends Overlay
                 // sizeW = Math.min(c2.getCanvasSizeX() / 4, Math.max(c2.getCanvasSizeX() / 7, 120));
                 sizeW = (int) Math.min(sizeW, sequence.getSizeX() * canvas.getScaleX() * 0.5);
 
-            double valueReal = (sizeW * sequence.getPixelSizeX() / canvas.getScaleX());
-            UnitPrefix bestUnit = UnitUtil.getBestUnit(valueReal * 0.1, UnitUtil.UnitPrefix.MICRO, 1);
-            double valueRealBestUnit = UnitUtil.getValueInUnit(valueReal, UnitPrefix.MICRO, bestUnit);
+            final double valueReal = (sizeW * sequence.getPixelSizeX() / canvas.getScaleX());
+            final UnitUtil.UnitPrefix bestUnit = UnitUtil.getBestUnit(valueReal * 0.1, UnitUtil.UnitPrefix.MICRO, 1);
+            final double valueRealBestUnit = UnitUtil.getValueInUnit(valueReal, UnitUtil.UnitPrefix.MICRO, bestUnit);
 
-            double closestScale = MathUtil.closest(valueRealBestUnit, scaleRoundedFactors);
+            final double closestScale = MathUtil.closest(valueRealBestUnit, scaleRoundedFactors);
             size.setValue((int) closestScale);
             unit.setValue(ScaleBarUnit.getUnitFrom(bestUnit));
         }
 
-        String text = size.getValue() + " " + unit.getValue();
-        double length = UnitUtil.getValueInUnit(size.getValue(), unit.getValue().asUnitPrefix(), UnitPrefix.MICRO) / sequence.getPixelSizeX();
+        final String text = size.getValue() + " " + unit.getValue();
+        double length = UnitUtil.getValueInUnit(size.getValue(), unit.getValue().asUnitPrefix(), UnitUtil.UnitPrefix.MICRO) / sequence.getPixelSizeX();
         final double unit;
         final double sizeX, sizeY;
 
         // image relative
-        if (location.getValue().isRelativeToImage())
-        {
+        if (location.getValue().isRelativeToImage()) {
             unit = canvas.canvasToImageDeltaX(1);
             sizeX = canvas.getImageSizeX();
             sizeY = canvas.getImageSizeY();
         }
         // viewer relative
-        else
-        {
+        else {
             unit = 1d;
             sizeX = canvas.getCanvasSizeX();
             sizeY = canvas.getCanvasSizeY();
@@ -331,16 +303,14 @@ public class ScaleBarOverlay extends Overlay
         Rectangle2D textBnds = new Rectangle2D.Double();
 
         // draw text ? prepare font and compute text bounds
-        if (showText.getValue())
-        {
+        if (showText.getValue()) {
             // set graphics font
             g2.setFont(g2.getFont().deriveFont(Font.BOLD, fontSize));
             // get text bounds
             textBnds = GraphicsUtil.getStringBounds(g2, text);
         }
 
-        switch (location.getValue())
-        {
+        switch (location.getValue()) {
             case VIEWER_BOTTOM_LEFT:
             case IMAGE_BOTTOM_LEFT:
                 line.x1 = borderDist;
@@ -373,8 +343,7 @@ public class ScaleBarOverlay extends Overlay
         line.y2 = line.y1;
 
         // opaque background ?
-        if (opaque.getValue().booleanValue())
-        {
+        if (opaque.getValue()) {
             if (ColorUtil.getLuminance(color.getValue()) > 128)
                 g2.setColor(Color.black);
             else
@@ -385,13 +354,12 @@ public class ScaleBarOverlay extends Overlay
             // give margins
             ShapeUtil.enlarge(rect, 8d * unit, 8d * unit, true);
             // draw text ? enlarge using text bounds
-            if (showText.getValue().booleanValue())
+            if (showText.getValue())
                 rect.setRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight() + textBnds.getHeight());
 
             g2.fill(rect);
         }
-        else
-        {
+        else {
             // transparent background --> just draw a light shadow
             if (ColorUtil.getLuminance(color.getValue()) > 128)
                 g2.setColor(Color.darkGray);
@@ -414,16 +382,14 @@ public class ScaleBarOverlay extends Overlay
         g2.draw(line);
 
         // draw text
-        if (showText.getValue().booleanValue())
-        {
-            float baseX = (float) line.getBounds().getCenterX();
-            float baseY = (float) (line.getBounds().getCenterY() + (unit * 4d));
+        if (showText.getValue()) {
+            final float baseX = (float) line.getBounds().getCenterX();
+            final float baseY = (float) (line.getBounds().getCenterY() + (unit * 4d));
             final float x = (float) (baseX - (textBnds.getWidth() / 2d));
             final float y = (float) (baseY - textBnds.getY());
 
             // need to draw text shadow first
-            if (!opaque.getValue().booleanValue())
-            {
+            if (!opaque.getValue()) {
                 if (ColorUtil.getLuminance(color.getValue()) > 128)
                     g2.setColor(Color.darkGray);
                 else
@@ -443,130 +409,106 @@ public class ScaleBarOverlay extends Overlay
     }
 
     @Override
-    public JPanel getOptionsPanel()
-    {
+    public JPanel getOptionsPanel() {
         return optionPanel;
     }
 
     /**
      * @return <code>true</code> if the scale bar automatically adjusts its size and unit
      */
-    public boolean getAutoSize()
-    {
+    public boolean getAutoSize() {
         return autoSize.getValue();
     }
 
     /**
      * @return the color of the scale bar
      */
-    public Color getColor()
-    {
+    public Color getColor() {
         return color.getValue();
     }
 
     /**
      * @return the opaque property of the scale bar
      */
-    public boolean getOpaque()
-    {
-        return opaque.getValue().booleanValue();
+    public boolean getOpaque() {
+        return opaque.getValue();
     }
 
     /**
      * @return the location of the scale bar on the image
      */
-    public ScaleBarLocation getLocation()
-    {
+    public ScaleBarLocation getLocation() {
         return location.getValue();
     }
 
     /**
      * @return the scale bar size (in metric units as defined by the pixel size)
      */
-    public double getSize()
-    {
+    public double getSize() {
         return size.getValue();
     }
 
     /**
      * @return whether the scale bar's size is currently displayed next to it
      */
-    public boolean getTextDisplay()
-    {
+    public boolean getTextDisplay() {
         return showText.getValue();
     }
 
     /**
      * Sets whether the scale should automatically guess its optimal size and unit
-     * 
-     * @param autoSize
      */
-    public void setAutoSize(boolean autoSize)
-    {
+    public void setAutoSize(final boolean autoSize) {
         this.autoSize.setValue(autoSize);
     }
 
     /**
      * Sets the color of the scale bar
-     * 
-     * @param color
-     *        the new color of the scale bar
+     *
+     * @param color the new color of the scale bar
      */
-    public void setColor(Color color)
-    {
+    public void setColor(final Color color) {
         this.color.setValue(color);
     }
 
     /**
      * Sets whether the scale bar should have an opaque background or not
-     * 
-     * @param opaque
      */
-    public void setOpaque(boolean opaque)
-    {
+    public void setOpaque(final boolean opaque) {
         this.opaque.setValue(opaque);
     }
 
     /**
      * Sets the location of the scale bar
-     * 
-     * @param location
-     *        the new location of the scale bar
+     *
+     * @param location the new location of the scale bar
      */
-    public void setLocation(ScaleBarLocation location)
-    {
+    public void setLocation(final ScaleBarLocation location) {
         this.location.setValue(location);
     }
 
     /**
      * Sets whether the scale bar's size should appear next to it
-     * 
-     * @param displayText
      */
-    public void setTextDisplay(boolean displayText)
-    {
+    public void setTextDisplay(final boolean displayText) {
         this.showText.setValue(displayText);
     }
 
     /**
      * Sets the size of the scale bar in metric units, as defined by the pixel size
-     * 
-     * @param size
-     *        the new size of the scale bar
+     *
+     * @param size the new size of the scale bar
      */
-    public void setSize(int size)
-    {
+    public void setSize(final int size) {
         this.size.setValue(size);
     }
 
     /**
      * Sets the scale bar unit
-     * 
-     * @param unit
-     *        the new unit
+     *
+     * @param unit the new unit
      */
-    public void setUnit(UnitPrefix unit)
-    {
+    public void setUnit(final UnitUtil.UnitPrefix unit) {
         this.unit.setValue(ScaleBarUnit.getUnitFrom(unit));
     }
 }
\ No newline at end of file
diff --git a/src/main/java/plugins/tprovoost/scale/ScaleBarUnit.java b/src/main/java/plugins/tprovoost/scale/ScaleBarUnit.java
index 7d5522fd60a9c72952b4cf10956f6a8c63145289..091d4254883608cf2d20ada077c83e4f9561d021 100644
--- a/src/main/java/plugins/tprovoost/scale/ScaleBarUnit.java
+++ b/src/main/java/plugins/tprovoost/scale/ScaleBarUnit.java
@@ -1,67 +1,62 @@
+/*
+ * Copyright (c) 2010-2024. Institut Pasteur.
+ *
+ * This file is part of Icy.
+ * Icy is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Icy is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Icy. If not, see <https://www.gnu.org/licenses/>.
+ */
+
 package plugins.tprovoost.scale;
 
-import icy.math.UnitUtil;
-import icy.math.UnitUtil.UnitPrefix;
+import org.bioimageanalysis.icy.common.math.UnitUtil;
+import org.bioimageanalysis.icy.common.math.UnitUtil.UnitPrefix;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
 
-public enum ScaleBarUnit
-{
+public enum ScaleBarUnit {
     KILO, NONE, MILLI, MICRO, NANO;
 
+    @Contract(pure = true)
     @Override
-    public String toString()
-    {
-        switch (this)
-        {
-            case KILO:
-                return "km";
-            case NONE:
-                return "m";
-            case MILLI:
-                return "mm";
-            default:
-            case MICRO:
-                return UnitUtil.MICRO_STRING + "m";
-            case NANO:
-                return "nm";
-        }
+    public @NotNull String toString() {
+        return switch (this) {
+            case KILO -> "km";
+            case NONE -> "m";
+            case MILLI -> "mm";
+            default -> UnitUtil.MICRO_STRING + "m";
+            case NANO -> "nm";
+        };
     }
 
-    public UnitPrefix asUnitPrefix()
-    {
-        switch (this)
-        {
-            case KILO:
-                return UnitPrefix.KILO;
-            case NONE:
-                return UnitPrefix.NONE;
-            case MILLI:
-                return UnitPrefix.MILLI;
-            default:
-            case MICRO:
-                return UnitPrefix.MICRO;
-            case NANO:
-                return UnitPrefix.NANO;
-        }
+    @Contract(pure = true)
+    public UnitUtil.UnitPrefix asUnitPrefix() {
+        return switch (this) {
+            case KILO -> UnitUtil.UnitPrefix.KILO;
+            case NONE -> UnitUtil.UnitPrefix.NONE;
+            case MILLI -> UnitUtil.UnitPrefix.MILLI;
+            default -> UnitUtil.UnitPrefix.MICRO;
+            case NANO -> UnitUtil.UnitPrefix.NANO;
+        };
     }
 
-    public static ScaleBarUnit getUnitFrom(UnitPrefix up)
-    {
-        switch (up)
-        {
-            case GIGA:
-            case MEGA:
-            case KILO:
-                return KILO;
-            case NONE:
-                return NONE;
-            case MILLI:
-                return MILLI;
-            case MICRO:
-            default:
-                return MICRO;
-            case NANO:
-            case PICO:
-                return NANO;
-        }
+    @Contract(pure = true)
+    public static ScaleBarUnit getUnitFrom(final @NotNull UnitPrefix up) {
+        return switch (up) {
+            case GIGA, MEGA, KILO -> KILO;
+            case NONE -> NONE;
+            case MILLI -> MILLI;
+            default -> MICRO;
+            case NANO, PICO -> NANO;
+        };
     }
 }
diff --git a/src/main/resources/Scale.png b/src/main/resources/plugins/tprovoost/scale/Scale.png
similarity index 100%
rename from src/main/resources/Scale.png
rename to src/main/resources/plugins/tprovoost/scale/Scale.png
diff --git a/src/main/resources/Scale.xml b/src/main/resources/plugins/tprovoost/scale/Scale.xml
similarity index 100%
rename from src/main/resources/Scale.xml
rename to src/main/resources/plugins/tprovoost/scale/Scale.xml
diff --git a/src/main/resources/Scale_icon.png b/src/main/resources/plugins/tprovoost/scale/icon/Scale_icon.png
similarity index 100%
rename from src/main/resources/Scale_icon.png
rename to src/main/resources/plugins/tprovoost/scale/icon/Scale_icon.png