From 4dc52f9c5798fa0c01ffecc1421633d258a77df1 Mon Sep 17 00:00:00 2001
From: Thomas <thomas.musset@pasteur.fr>
Date: Mon, 1 Jul 2024 17:45:31 +0200
Subject: [PATCH] updated pom to v2.0.0-a.1, fix classes accordingly to new
 architecture, added icon, updated .gitignore

---
 .gitignore                                    |  46 ++++--
 pom.xml                                       |  10 +-
 .../Microscopy/MicroManager/MicroManager.java | 153 ++++++++----------
 .../MicroManager/core/AcquisitionHandler.java |  31 ++--
 .../MicroManager/core/AcquisitionResult.java  |  13 +-
 .../event/AcquisitionListener.java            |   4 +-
 .../MicroManager/event/CoreListener.java      |   2 +-
 .../MicroManager/event/LiveListener.java      |   4 +-
 .../MicroManager/gui/AboutPanel.java          |   4 +-
 .../gui/AcquisitionInfoPanel.java             |  10 +-
 .../MicroManager/gui/ActionsPanel.java        |  46 +++---
 .../MicroManager/gui/CameraSettingsPanel.java |  56 +++----
 .../MicroManager/gui/ChannelTable.java        |  14 +-
 .../MicroManager/gui/ConfigurationPanel.java  |  35 ++--
 .../MicroManager/gui/LiveSettingsPanel.java   |   6 +-
 .../MicroManager/gui/LoadFrame.java           |  35 ++--
 .../MicroManager/gui/LoadingFrame.java        |   8 +-
 .../MicroManager/gui/MMMainFrame.java         |  82 ++++------
 .../MicroManager/gui/MainPanel.java           |   2 +-
 .../MicroManager/gui/OptionsPanel.java        |   4 +-
 .../MicroManager/gui/PluginsToolbar.java      |  40 ++---
 .../MicroManager/patch/ClassPatcher.java      |  45 +++---
 .../MicroManager/patch/MMPatcher.java         |   4 +-
 .../MicroManager/patch/MMStudioMethods.java   |   7 +-
 .../MicroManager/tools/FrameUtils.java        |  56 +------
 .../MicroManager/tools/MMUtils.java           | 110 ++++++-------
 .../MicroManager/tools/StageMover.java        |  28 ++--
 .../MicromanagerPlugin.java                   |  10 +-
 .../MicroManagerForIcy/MicroscopePlugin.java  |   4 +-
 src/main/resources/mmj.png                    | Bin 0 -> 15076 bytes
 30 files changed, 403 insertions(+), 466 deletions(-)
 create mode 100644 src/main/resources/mmj.png

diff --git a/.gitignore b/.gitignore
index 4d4593d..57f16fb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,13 +1,41 @@
-.idea/
-.settings/
-workspace/
-build/
+/build*
+/workspace
+setting.xml
+release/
 target/
-bin/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+icy.log
+
+### IntelliJ IDEA ###
+.idea/
+*.iws
 *.iml
-*.eml
-*.jar
-.project
+*.ipr
+
+### Eclipse ###
+.apt_generated
 .classpath
-export.jardesc
+.factorypath
+.project
+.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 e8a2787..3c35a3a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,11 +7,11 @@
     <parent>
         <artifactId>pom-icy</artifactId>
         <groupId>org.bioimageanalysis.icy</groupId>
-        <version>2.2.0</version>
+        <version>3.0.0-a.1</version>
     </parent>
 
     <artifactId>micromanager</artifactId>
-    <version>2.0.0</version>
+    <version>2.0.0-a.1</version>
 
     <name>MicroManager for Icy</name>
     <description>
@@ -20,10 +20,6 @@
         Compatible with Micro-Manager 1.4.19 or above but we recommend to use the current last (1.4.23 / nightly build)
     </description>
 
-    <properties>
-        <artifact-to-extract>MMCoreJ,MMJ_</artifact-to-extract>
-    </properties>
-
     <dependencies>
         <dependency>
             <groupId>org.micromanager</groupId>
@@ -40,7 +36,7 @@
     <repositories>
         <repository>
             <id>icy</id>
-            <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/Microscopy/MicroManager/MicroManager.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/MicroManager.java
index 91a6305..f695b7a 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/MicroManager.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/MicroManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,21 +18,24 @@
 
 package plugins.tprovoost.Microscopy.MicroManager;
 
-import icy.common.Version;
-import icy.file.FileUtil;
-import icy.gui.dialog.MessageDialog;
-import icy.gui.frame.progress.FailedAnnounceFrame;
-import icy.image.IcyBufferedImage;
-import icy.main.Icy;
-import icy.sequence.Sequence;
-import icy.system.IcyExceptionHandler;
-import icy.system.thread.ThreadUtil;
-import icy.util.ClassUtil;
-import icy.util.StringUtil;
 import mmcorej.CMMCore;
 import mmcorej.MMCoreJ;
 import mmcorej.StrVector;
 import mmcorej.TaggedImage;
+import org.bioimageanalysis.icy.Icy;
+import org.bioimageanalysis.icy.common.Version;
+import org.bioimageanalysis.icy.common.reflect.ClassUtil;
+import org.bioimageanalysis.icy.common.string.StringUtil;
+import org.bioimageanalysis.icy.gui.dialog.MessageDialog;
+import org.bioimageanalysis.icy.gui.frame.progress.FailedAnnounceFrame;
+import org.bioimageanalysis.icy.io.FileUtil;
+import org.bioimageanalysis.icy.model.image.IcyBufferedImage;
+import org.bioimageanalysis.icy.model.sequence.Sequence;
+import org.bioimageanalysis.icy.system.logging.IcyLogger;
+import org.bioimageanalysis.icy.system.thread.ThreadUtil;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.json.JSONObject;
 import org.micromanager.MMStudio;
 import org.micromanager.MMVersion;
@@ -85,6 +88,7 @@ public class MicroManager {
     /**
      * @return the MicroManager main frame instance.
      */
+    @Contract(pure = true)
     public static MMMainFrame getInstance() {
         // initialize micro manager if needed --> NO ! we need to init ourself
         // if (instance == null)
@@ -96,14 +100,16 @@ public class MicroManager {
     /**
      * @return the MicroManager version
      */
-    public static Version getMMVersion() {
+    @Contract(value = " -> new", pure = true)
+    public static @NotNull Version getMMVersion() {
         // is this method really safe ??
-        return new Version(MMVersion.VERSION_STRING);
+        return Version.fromString(MMVersion.VERSION_STRING);
     }
 
     /**
      * @return the core listener list.
      */
+    @Contract(pure = true)
     public static List<CoreListener> getCoreListeners() {
         final List<CoreListener> result;
 
@@ -136,6 +142,7 @@ public class MicroManager {
     /**
      * @return the acquisition listener list.
      */
+    @Contract(pure = true)
     public static List<AcquisitionListener> getAcquisitionListeners() {
         final List<AcquisitionListener> result;
 
@@ -170,6 +177,7 @@ public class MicroManager {
     /**
      * @return the live listener list.
      */
+    @Contract(pure = true)
     public static List<LiveListener> getLiveListeners() {
         final List<LiveListener> result;
 
@@ -210,49 +218,13 @@ public class MicroManager {
         }
     }
 
-    /**
-     * @param listener the <i>acquisition</i> listener to register
-     * @deprecated Use {@link #addAcquisitionListener(AcquisitionListener)} instead.
-     */
-    @Deprecated
-    public static void registerListener(final AcquisitionListener listener) {
-        addAcquisitionListener(listener);
-    }
-
-    /**
-     * @param listener the <i>acquisition</i> listener to remove
-     * @deprecated Use {@link #removeAcquisitionListener(AcquisitionListener)} instead.
-     */
-    @Deprecated
-    public static void removeListener(final AcquisitionListener listener) {
-        removeAcquisitionListener(listener);
-    }
-
-    /**
-     * @param listener the <i>live</i> listener to register
-     * @deprecated Use {@link #addLiveListener(LiveListener)} instead.
-     */
-    @Deprecated
-    public static void registerListener(final LiveListener listener) {
-        addLiveListener(listener);
-    }
-
-    /**
-     * @param listener the <i>live</i> listener to remove
-     * @deprecated Use {@link #removeLiveListener(LiveListener)} instead.
-     */
-    @Deprecated
-    public static void removeListener(final LiveListener listener) {
-        removeLiveListener(listener);
-    }
-
     /**
      * Use this to access micro-manager main object to access low level function that
      * are not been implemented in Icy's micro-Manager.
      *
      * @return The micro-manager main studio object.
      */
-    public static MMStudio getMMStudio() {
+    public static @Nullable MMStudio getMMStudio() {
         final MMMainFrame inst = getInstance();
         if (inst == null)
             return null;
@@ -271,7 +243,7 @@ public class MicroManager {
      *
      * @return The micro-manager core object
      */
-    public static CMMCore getCore() {
+    public static @Nullable CMMCore getCore() {
         final MMStudio mmstudio = getMMStudio();
         if (mmstudio == null)
             return null;
@@ -389,7 +361,7 @@ public class MicroManager {
     /**
      * @return The acquisition engine wrapper from MicroManager.
      */
-    public static AcquisitionWrapperEngine getAcquisitionEngine() {
+    public static @Nullable AcquisitionWrapperEngine getAcquisitionEngine() {
         final MMStudio mmstudio = getMMStudio();
         if (mmstudio == null)
             return null;
@@ -400,7 +372,7 @@ public class MicroManager {
     /**
      * @return The internal new acquisition engine from MicroManager.
      */
-    public static IAcquisitionEngine2010 getAcquisitionEngine2010() {
+    public static @Nullable IAcquisitionEngine2010 getAcquisitionEngine2010() {
         final MMStudio mmstudio = getMMStudio();
         if (mmstudio == null)
             return null;
@@ -412,7 +384,7 @@ public class MicroManager {
      * @return The engine settings for the most recently started acquisition sequence, or return
      * null if you never started an acquisition.
      */
-    public static SequenceSettings getAcquisitionSettings() {
+    public static @Nullable SequenceSettings getAcquisitionSettings() {
         final AcquisitionWrapperEngine acqEngine = getAcquisitionEngine();
         if (acqEngine == null)
             return null;
@@ -424,7 +396,7 @@ public class MicroManager {
      * @return The summaryMetadata for the most recently started acquisition sequence, or return
      * null if you never started an acquisition.
      */
-    public static JSONObject getAcquisitionMetaData() {
+    public static @Nullable JSONObject getAcquisitionMetaData() {
         final AcquisitionWrapperEngine acqEngine = getAcquisitionEngine();
         if (acqEngine == null)
             return null;
@@ -499,7 +471,7 @@ public class MicroManager {
      * {@link #addAcquisitionListener(AcquisitionListener)}<br>
      * @throws Exception if an error occurred while retrieved last tagged images
      */
-    public static List<TaggedImage> getLastTaggedImage() throws Exception {
+    public static @NotNull List<TaggedImage> getLastTaggedImage() throws Exception {
         final CMMCore core = MicroManager.getCore();
 
         if (core == null || !core.isSequenceRunning())
@@ -567,7 +539,7 @@ public class MicroManager {
      * @return next captured image as List of {@link TaggedImage} or an empty list if the continuous acquisition is not running
      * @throws Exception if an error occurred
      */
-    public static List<TaggedImage> getNextTaggedImage() throws Exception {
+    public static @NotNull List<TaggedImage> getNextTaggedImage() throws Exception {
         final CMMCore core = MicroManager.getCore();
 
         if (core == null || !core.isSequenceRunning())
@@ -575,16 +547,19 @@ public class MicroManager {
 
         final boolean[] done = new boolean[]{false};
         final LiveListener listener = new LiveListener() {
+            @Contract(pure = true)
             @Override
             public void liveStopped() {
                 done[0] = true;
             }
 
+            @Contract(pure = true)
             @Override
             public void liveStarted() {
                 // nothing here
             }
 
+            @Contract(pure = true)
             @Override
             public void liveImgReceived(final List<TaggedImage> images) {
                 done[0] = true;
@@ -642,7 +617,7 @@ public class MicroManager {
      * @return the captured image as List of {@link TaggedImage}
      * @throws Exception if an error occurred
      */
-    public static List<TaggedImage> snapTaggedImage() throws Exception {
+    public static @NotNull List<TaggedImage> snapTaggedImage() throws Exception {
         final CMMCore core = MicroManager.getCore();
         if (core == null)
             return new ArrayList<>();
@@ -846,7 +821,7 @@ public class MicroManager {
      * @return the list of sequence corresponding to the last sequence acquisition or * <code>null</code> if no acquisition was done.
      * @see #startAcquisition(int, double)
      */
-    public static List<Sequence> getAcquisitionResult() {
+    public static @Nullable List<Sequence> getAcquisitionResult() {
         if ((acquisitionManager == null) || acquisitionManager.getSequences().isEmpty())
             return null;
 
@@ -923,7 +898,7 @@ public class MicroManager {
      * @return the current camera binning mode (String format)
      * @throws Exception if an error occurred
      */
-    private static String getBinningAsString(final CMMCore core, final String camera) throws Exception {
+    private static String getBinningAsString(final @NotNull CMMCore core, final String camera) throws Exception {
         return core.getProperty(camera, MMCoreJ.getG_Keyword_Binning());
     }
 
@@ -1175,7 +1150,7 @@ public class MicroManager {
     /**
      * @return all available config group
      */
-    public static List<String> getConfigGroups() {
+    public static @NotNull List<String> getConfigGroups() {
         final CMMCore core = getCore();
         if (core == null)
             return new ArrayList<>();
@@ -1193,7 +1168,7 @@ public class MicroManager {
      * @param group group name
      * @return all available config preset for the specified group
      */
-    public static List<String> getConfigs(final String group) {
+    public static @NotNull List<String> getConfigs(final String group) {
         final CMMCore core = getCore();
         if (core == null)
             return new ArrayList<>();
@@ -1278,6 +1253,7 @@ public class MicroManager {
     /**
      * @return internal preset name set on last call to {@link #setConfigForGroup(String, String, boolean)} method (workaround for MM empty preset name bug)
      */
+    @Contract(pure = true)
     public static String getInternalSetPreset() {
         if (inConfigSet)
             return lastPresetSet;
@@ -1336,7 +1312,7 @@ public class MicroManager {
      * @see #getChannelGroup()
      * @see #getConfigs(String)
      */
-    public static List<String> getChannelConfigs() {
+    public static @NotNull List<String> getChannelConfigs() {
         return getConfigs(MicroManager.getChannelGroup());
     }
 
@@ -1408,6 +1384,7 @@ public class MicroManager {
      * @return <code>true</code> if Micro-Manager is initialized / loaded.<br>
      * @see MicromanagerPlugin#init()
      */
+    @Contract(pure = true)
     public static boolean isInitialized() {
         return instance != null;
     }
@@ -1450,17 +1427,19 @@ public class MicroManager {
             }
             catch (final Throwable t) {
                 // an fatal error occurred, force error on version checking then...
-                version = new Version("1");
+                version = new Version(1);
             }
 
             // cannot get version or wrong version ?
-            if ((version == null) || version.isLower(new Version("1.4.19")))
+            if ((version == null) || version.isLower(new Version(1, 4, 19)))
             // || version.isGreater(new Version("1.4.22")))
             {
                 MessageDialog.showDialog("Error while loading Micro-Manager",
-                        "Your version of Micro-Manager seems to not be compatible !\n" + "This plugin is only compatible with version 1.4.19 or above.\n"
-                                + "Also check that you are using the same architecture for Icy and Micro-Manager (32/64 bits)\n"
-                                + "You need to restart Icy to redefine the Micro-Manager folder.",
+                        """
+                                Your version of Micro-Manager seems to not be compatible !
+                                This plugin is only compatible with version 1.4.19 or above.
+                                Also check that you are using the same architecture for Icy and Micro-Manager (32/64 bits)
+                                You need to restart Icy to redefine the Micro-Manager folder.""",
                         MessageDialog.ERROR_MESSAGE);
                 // so user can change the defined MM folder
                 MMUtils.resetLibrayPath();
@@ -1480,9 +1459,7 @@ public class MicroManager {
                     instance = new MMMainFrame();
                 }
                 catch (final Throwable e) {
-                    IcyExceptionHandler.showErrorMessage(e, true, true);
-                    MessageDialog.showDialog("Error while loading Micro-Manager", e.getMessage() + "\nYou may try to restart Icy to fix the issue.",
-                            MessageDialog.ERROR_MESSAGE);
+                    IcyLogger.error(MicroManager.class, e, "Error while loading Micro-Manager.", "You may try to restart Icy to fix the issue.");
                     return;
                 }
 
@@ -1529,8 +1506,7 @@ public class MicroManager {
                 cleanOldMM();
             }
             catch (final Throwable e) {
-                IcyExceptionHandler.showErrorMessage(e, true, true);
-                new FailedAnnounceFrame("An error occurred while initializing Micro-Manager (see console output for more details).");
+                IcyLogger.error(MicroManager.class, e, "Error while initializing Micro-Manager.");
 
                 // shutdown everything
                 shutdown();
@@ -1543,8 +1519,10 @@ public class MicroManager {
             // cannot load class --> version mismatch probably
             MessageDialog
                     .showDialog("Cannot load Micro-Manager",
-                            "Your version of Micro-Manager seems to not be compatible !\n" + "This plugin is only compatible with version 1.4.19 or above.\n"
-                                    + "Also check that you are using the same architecture for Icy and Micro-Manager (32/64 bits).",
+                            """
+                                    Your version of Micro-Manager seems to not be compatible !
+                                    This plugin is only compatible with version 1.4.19 or above.
+                                    Also check that you are using the same architecture for Icy and Micro-Manager (32/64 bits).""",
                             MessageDialog.ERROR_MESSAGE);
         }
     }
@@ -1609,17 +1587,17 @@ public class MicroManager {
                 stopLiveMode();
             }
             catch (final Throwable t) {
-                IcyExceptionHandler.showErrorMessage(t, true);
+                IcyLogger.error(MicroManager.class, t);
             }
         }
 
-        if (liveListeners != null)
-            liveListeners.clear();
-        if (acqListeners != null)
-            acqListeners.clear();
+        //if (liveListeners != null)
+        liveListeners.clear();
+        //if (acqListeners != null)
+        acqListeners.clear();
         StageMover.clearListener();
-        if (metadatas != null)
-            metadatas.clear();
+        //if (metadatas != null)
+        metadatas.clear();
 
         // stop live listener
         if (liveManager != null) {
@@ -1674,8 +1652,7 @@ public class MicroManager {
 
                 final JSONObject tags = image.tags;
 
-                final boolean firstImage = (MDUtils.getPositionIndex(tags) == 0) && (MDUtils.getFrameIndex(tags) == 0) && (MDUtils.getChannelIndex(tags) == 0)
-                        && (MDUtils.getSliceIndex(tags) == 0);
+                final boolean firstImage = (MDUtils.getPositionIndex(tags) == 0) && (MDUtils.getFrameIndex(tags) == 0) && (MDUtils.getChannelIndex(tags) == 0) && (MDUtils.getSliceIndex(tags) == 0);
                 final boolean newAcquisition = (acquisitionManager == null) || acquisitionManager.isDone();
 
                 // first acquisition image or new acquisition --> create the new acquisition
@@ -1717,7 +1694,7 @@ public class MicroManager {
                     l.acqImgReveived(image);
             }
             catch (final Exception e) {
-                IcyExceptionHandler.showErrorMessage(e, true);
+                IcyLogger.error(MicroManager.class, e);
             }
         }
     }
@@ -1753,7 +1730,7 @@ public class MicroManager {
                                 catch (final Exception e) {
                                     // can happen with advanced acquisition set with a lower time
                                     // interval than current exposure time
-                                    IcyExceptionHandler.showErrorMessage(e, true);
+                                    IcyLogger.error(MicroManager.class, e);
                                 }
                             }
                         }
@@ -1769,7 +1746,7 @@ public class MicroManager {
                     }
                     catch (final Exception e) {
                         // should not happen
-                        IcyExceptionHandler.showErrorMessage(e, true);
+                        IcyLogger.error(MicroManager.class, e);
                     }
                 }
 
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/core/AcquisitionHandler.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/core/AcquisitionHandler.java
index fe236a8..f5c973d 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/core/AcquisitionHandler.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/core/AcquisitionHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,15 +18,16 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.core;
 
-import icy.gui.frame.IcyFrame;
-import icy.gui.frame.IcyFrameAdapter;
-import icy.gui.frame.IcyFrameEvent;
-import icy.gui.util.GuiUtil;
-import icy.sequence.Sequence;
-import icy.system.IcyExceptionHandler;
-import icy.system.thread.ThreadUtil;
-import icy.util.ReflectionUtil;
 import mmcorej.TaggedImage;
+import org.bioimageanalysis.icy.common.reflect.ReflectionUtil;
+import org.bioimageanalysis.icy.gui.GuiUtil;
+import org.bioimageanalysis.icy.gui.frame.IcyFrame;
+import org.bioimageanalysis.icy.gui.frame.IcyFrameAdapter;
+import org.bioimageanalysis.icy.gui.frame.IcyFrameEvent;
+import org.bioimageanalysis.icy.model.sequence.Sequence;
+import org.bioimageanalysis.icy.system.logging.IcyLogger;
+import org.bioimageanalysis.icy.system.thread.ThreadUtil;
+import org.jetbrains.annotations.NotNull;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.micromanager.MMStudio;
@@ -65,7 +66,7 @@ public class AcquisitionHandler implements AcquisitionListener {
         MicroManager.addAcquisitionListener(this);
     }
 
-    private void initDialog(final MMMainFrame mainFrame) {
+    private void initDialog(final @NotNull MMMainFrame mainFrame) {
         final MMStudio mmstudio = mainFrame.getMMStudio();
 
         try {
@@ -73,7 +74,7 @@ public class AcquisitionHandler implements AcquisitionListener {
             advAcqDialog = (AcqControlDlg) ReflectionUtil.getFieldObject(mmstudio, "acqControlWin_");
         }
         catch (final Exception ex) {
-            System.err.println("Warning: cannot retrieve AcqControlDlg from Micro-Manager.");
+            IcyLogger.warn(this.getClass(), ex, "Cannot retrieve AcqControlDlg from Micro-Manager.");
         }
 
         // not existing yet ? --> create it now
@@ -85,7 +86,7 @@ public class AcquisitionHandler implements AcquisitionListener {
                 ReflectionUtil.getField(mmstudio.getClass(), "acqControlWin_").set(mmstudio, advAcqDialog);
             }
             catch (final Exception ex) {
-                System.err.println("Warning: cannot set AcqControlDlg from Micro-Manager.");
+                IcyLogger.warn(this.getClass(), ex, "Cannot set AcqControlDlg from Micro-Manager.");
             }
         }
 
@@ -199,7 +200,7 @@ public class AcquisitionHandler implements AcquisitionListener {
                 MicroManager.stopLiveMode();
         }
         catch (final Exception e) {
-            IcyExceptionHandler.showErrorMessage(e, false);
+            IcyLogger.error(this.getClass(), e);
         }
     }
 
@@ -229,7 +230,7 @@ public class AcquisitionHandler implements AcquisitionListener {
             });
         }
         catch (final JSONException e) {
-            IcyExceptionHandler.showErrorMessage(e, true);
+            IcyLogger.error(this.getClass(), e);
         }
     }
 
@@ -246,7 +247,7 @@ public class AcquisitionHandler implements AcquisitionListener {
                 MicroManager.startLiveMode();
             }
             catch (final Exception e) {
-                IcyExceptionHandler.showErrorMessage(e, true);
+                IcyLogger.error(this.getClass(), e);
             }
 
             liveModeWasRunning = false;
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/core/AcquisitionResult.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/core/AcquisitionResult.java
index 23cfb5a..5c75c65 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/core/AcquisitionResult.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/core/AcquisitionResult.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,11 +18,12 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.core;
 
-import icy.gui.viewer.Viewer;
-import icy.main.Icy;
-import icy.sequence.Sequence;
-import icy.util.StringUtil;
 import mmcorej.TaggedImage;
+import org.bioimageanalysis.icy.Icy;
+import org.bioimageanalysis.icy.common.string.StringUtil;
+import org.bioimageanalysis.icy.gui.viewer.Viewer;
+import org.bioimageanalysis.icy.model.sequence.Sequence;
+import org.jetbrains.annotations.NotNull;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.micromanager.api.SequenceSettings;
@@ -61,7 +62,7 @@ public class AcquisitionResult {
         return new ArrayList<>(sequences.values());
     }
 
-    public void imageReceived(final TaggedImage taggedImage) throws JSONException, MMScriptException {
+    public void imageReceived(final @NotNull TaggedImage taggedImage) throws JSONException, MMScriptException {
         final JSONObject tags = taggedImage.tags;
         final Integer position = MDUtils.getPositionIndex(tags);
 
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/event/AcquisitionListener.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/event/AcquisitionListener.java
index f1c04f5..083ea0f 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/event/AcquisitionListener.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/event/AcquisitionListener.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,8 +18,8 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.event;
 
-import icy.sequence.Sequence;
 import mmcorej.TaggedImage;
+import org.bioimageanalysis.icy.model.sequence.Sequence;
 import org.json.JSONObject;
 import org.micromanager.api.SequenceSettings;
 import plugins.tprovoost.Microscopy.MicroManager.MicroManager;
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/event/CoreListener.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/event/CoreListener.java
index f466c01..53936b0 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/event/CoreListener.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/event/CoreListener.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/event/LiveListener.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/event/LiveListener.java
index 8d2b2d8..585c6ad 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/event/LiveListener.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/event/LiveListener.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,8 +18,8 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.event;
 
-import icy.sequence.Sequence;
 import mmcorej.TaggedImage;
+import org.bioimageanalysis.icy.model.sequence.Sequence;
 import plugins.tprovoost.Microscopy.MicroManager.MicroManager;
 import plugins.tprovoost.Microscopy.MicroManager.tools.MMUtils;
 
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/AboutPanel.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/AboutPanel.java
index 1067b46..12f9fc6 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/AboutPanel.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/AboutPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,7 +18,7 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.gui;
 
-import icy.network.NetworkUtil;
+import org.bioimageanalysis.icy.network.NetworkUtil;
 import org.micromanager.MMVersion;
 
 import javax.swing.*;
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/AcquisitionInfoPanel.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/AcquisitionInfoPanel.java
index c46f9ff..b36d1e7 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/AcquisitionInfoPanel.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/AcquisitionInfoPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,9 +18,10 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.gui;
 
-import icy.math.MathUtil;
-import icy.system.thread.ThreadUtil;
 import mmcorej.CMMCore;
+import org.bioimageanalysis.icy.common.math.MathUtil;
+import org.bioimageanalysis.icy.system.logging.IcyLogger;
+import org.bioimageanalysis.icy.system.thread.ThreadUtil;
 import plugins.tprovoost.Microscopy.MicroManager.MicroManager;
 import plugins.tprovoost.Microscopy.MicroManager.tools.StageMover;
 
@@ -251,8 +252,7 @@ public class AcquisitionInfoPanel extends JPanel implements Runnable {
                 setPixelSize(core.getPixelSizeUm());
             }
             catch (final Throwable t) {
-                System.err.println("Warning: can't read camera informations from Micro-Manager");
-                System.err.println("Cause: " + t);
+                IcyLogger.warn(this.getClass(), t, "Cannot read camera information from Micro-Manager.");
             }
         }
     }
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/ActionsPanel.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/ActionsPanel.java
index f28a4e1..f41c073 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/ActionsPanel.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/ActionsPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,20 +18,20 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.gui;
 
-import icy.gui.component.button.IcyButton;
-import icy.gui.component.button.IcyToggleButton;
-import icy.gui.dialog.MessageDialog;
-import icy.main.Icy;
-import icy.math.FPSMeter;
-import icy.resource.ResourceUtil;
-import icy.resource.icon.IcyIcon;
-import icy.sequence.Sequence;
-import icy.sequence.SequenceEvent;
-import icy.sequence.SequenceListener;
-import icy.system.IcyExceptionHandler;
-import icy.util.StringUtil;
 import mmcorej.CMMCore;
 import mmcorej.TaggedImage;
+import org.bioimageanalysis.icy.Icy;
+import org.bioimageanalysis.icy.common.math.FPSMeter;
+import org.bioimageanalysis.icy.common.string.StringUtil;
+import org.bioimageanalysis.icy.gui.component.button.IcyButton;
+import org.bioimageanalysis.icy.gui.component.button.IcyToggleButton;
+import org.bioimageanalysis.icy.gui.component.icon.SVGIcon;
+import org.bioimageanalysis.icy.gui.dialog.MessageDialog;
+import org.bioimageanalysis.icy.model.sequence.Sequence;
+import org.bioimageanalysis.icy.model.sequence.SequenceEvent;
+import org.bioimageanalysis.icy.model.sequence.SequenceListener;
+import org.bioimageanalysis.icy.system.IcyExceptionHandler;
+import org.bioimageanalysis.icy.system.logging.IcyLogger;
 import org.json.JSONObject;
 import org.micromanager.MMStudio;
 import plugins.tprovoost.Microscopy.MicroManager.MicroManager;
@@ -116,7 +116,7 @@ public class ActionsPanel extends JPanel implements LiveListener, SequenceListen
         gridBagLayout.rowWeights = new double[]{1.0, 1.0, 1.0, 1.0, 1.0, Double.MIN_VALUE};
         setLayout(gridBagLayout);
 
-        snapBtn = new IcyButton("Snap", new IcyIcon(ResourceUtil.ICON_PHOTO));
+        snapBtn = new IcyButton("Snap", SVGIcon.PHOTO_CAMERA);
         snapBtn.setToolTipText("Snap an image");
         snapBtn.setIconTextGap(12);
         final GridBagConstraints gbc_snapBtn = new GridBagConstraints();
@@ -126,7 +126,7 @@ public class ActionsPanel extends JPanel implements LiveListener, SequenceListen
         gbc_snapBtn.gridy = 0;
         add(snapBtn, gbc_snapBtn);
 
-        liveBtn = new IcyToggleButton("Live", new IcyIcon("camera"));
+        liveBtn = new IcyToggleButton("Live", SVGIcon.VIDEOCAM);
         liveBtn.setToolTipText("Enable / Disable the live display");
         liveBtn.setIconTextGap(12);
         final GridBagConstraints gbc_liveBtn = new GridBagConstraints();
@@ -136,7 +136,7 @@ public class ActionsPanel extends JPanel implements LiveListener, SequenceListen
         gbc_liveBtn.gridy = 1;
         add(liveBtn, gbc_liveBtn);
 
-        albumBtn = new IcyButton("Album", new IcyIcon("movie"));
+        albumBtn = new IcyButton("Album", SVGIcon.CAMERA_ROLL);
         albumBtn.setToolTipText("Snap an image and store it in the album");
         albumBtn.setIconTextGap(12);
         final GridBagConstraints gbc_albumBtn = new GridBagConstraints();
@@ -146,7 +146,7 @@ public class ActionsPanel extends JPanel implements LiveListener, SequenceListen
         gbc_albumBtn.gridy = 2;
         add(albumBtn, gbc_albumBtn);
 
-        advAcqBtn = new IcyButton("Multi-D Acq.", new IcyIcon(ResourceUtil.ICON_LAYER_V1));
+        advAcqBtn = new IcyButton("Multi-D Acq.", SVGIcon.LAYERS);
         advAcqBtn.setToolTipText("Multi dimension acquisition");
         advAcqBtn.setIconTextGap(8);
         final GridBagConstraints gbc_advAcqBtn = new GridBagConstraints();
@@ -156,7 +156,7 @@ public class ActionsPanel extends JPanel implements LiveListener, SequenceListen
         gbc_advAcqBtn.gridy = 3;
         add(advAcqBtn, gbc_advAcqBtn);
 
-        refreshBtn = new IcyButton("Refresh", new IcyIcon(ResourceUtil.ICON_RELOAD));
+        refreshBtn = new IcyButton("Refresh", SVGIcon.REPLAY);
         refreshBtn.setToolTipText("Force GUI refresh");
         refreshBtn.setIconTextGap(12);
         final GridBagConstraints gbc_refreshBtn = new GridBagConstraints();
@@ -403,7 +403,7 @@ public class ActionsPanel extends JPanel implements LiveListener, SequenceListen
         liveSequence.beginUpdate();
         try {
             // format not anymore compatible --> need to clear sequence first
-            if (!MMUtils.isCompatible(liveSequence, images.get(0).tags))
+            if (!MMUtils.isCompatible(liveSequence, images.getFirst().tags))
                 liveSequence.removeAllImages();
 
             final LiveSettingsPanel livePanel = mainFrame.livePanel;
@@ -474,8 +474,7 @@ public class ActionsPanel extends JPanel implements LiveListener, SequenceListen
             }
         }
         catch (final Exception e) {
-            System.err.println("MicroManager: cannot update live image.");
-            IcyExceptionHandler.showErrorMessage(e, false, true);
+            IcyLogger.error(this.getClass(), e, "Cannot update live image.");
         }
         finally {
             liveSequence.endUpdate();
@@ -499,7 +498,6 @@ public class ActionsPanel extends JPanel implements LiveListener, SequenceListen
     @Override
     public void sequenceChanged(final SequenceEvent sequenceEvent) {
         // ignore this event
-
     }
 
     @Override
@@ -511,7 +509,7 @@ public class ActionsPanel extends JPanel implements LiveListener, SequenceListen
         if (sequence == albumSequence) {
             // album not saved ?
             //if (StringUtil.isEmpty(sequence.getFilename())) {
-            // ask user if he want to save it
+            // ask user if he wants to save it
             //}
 
             // clear it
@@ -561,7 +559,7 @@ public class ActionsPanel extends JPanel implements LiveListener, SequenceListen
                 }
             }
             catch (final Exception e) {
-                System.err.println("MicroManager: cannot process stack acquisition.");
+                //IcyLogger.error(this.getClass(), e, "Stack acquisition failed.");
                 IcyExceptionHandler.handleException(e, true);
             }
         }
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/CameraSettingsPanel.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/CameraSettingsPanel.java
index 48a128a..48183ad 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/CameraSettingsPanel.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/CameraSettingsPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,18 +18,17 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.gui;
 
-import icy.gui.component.NumberTextField;
-import icy.gui.component.button.IcyButton;
-import icy.gui.component.button.IcyToggleButton;
-import icy.gui.dialog.MessageDialog;
-import icy.resource.icon.IcyIcon;
-import icy.system.IcyExceptionHandler;
-import icy.system.thread.ThreadUtil;
-import icy.util.StringUtil;
 import mmcorej.CMMCore;
 import mmcorej.DeviceType;
 import mmcorej.MMCoreJ;
 import mmcorej.StrVector;
+import org.bioimageanalysis.icy.common.string.StringUtil;
+import org.bioimageanalysis.icy.gui.component.button.IcyButton;
+import org.bioimageanalysis.icy.gui.component.button.IcyToggleButton;
+import org.bioimageanalysis.icy.gui.component.field.NumberTextField;
+import org.bioimageanalysis.icy.gui.component.icon.SVGIcon;
+import org.bioimageanalysis.icy.system.logging.IcyLogger;
+import org.bioimageanalysis.icy.system.thread.ThreadUtil;
 import org.micromanager.MMStudio;
 import plugins.tprovoost.Microscopy.MicroManager.MicroManager;
 
@@ -116,8 +115,7 @@ public class CameraSettingsPanel extends JPanel implements Runnable {
                 refreshOpenShutterButton(open);
             }
             catch (final Throwable t) {
-                MessageDialog.showDialog("Cannot change shutter state: " + t, MessageDialog.ERROR_MESSAGE);
-                System.err.println("Cannot change shutter state: " + t);
+                IcyLogger.error(this.getClass(), t, "Cannot change shutter state.");
             }
         });
         lblAutoShutter.addMouseListener(new MouseAdapter() {
@@ -145,8 +143,7 @@ public class CameraSettingsPanel extends JPanel implements Runnable {
                     shutterOpenBtn.setEnabled(!autoshutter);
             }
             catch (final Throwable t) {
-                MessageDialog.showDialog("Cannot set auto shutter: " + t, MessageDialog.ERROR_MESSAGE);
-                System.err.println("Cannot set auto shutter: " + t);
+                IcyLogger.error(this.getClass(), t, "Cannot set auto shutter.");
             }
         });
         autofocusBtn.addActionListener(e -> {
@@ -154,14 +151,14 @@ public class CameraSettingsPanel extends JPanel implements Runnable {
             if (studio != null)
                 studio.autofocusNow();
             else
-                System.err.println("MMStudio is null, cannot autofocus");
+                IcyLogger.error(this.getClass(), "Cannot autofocus now (MMStudio is null).");
         });
         autofocusSettingBtn.addActionListener(e -> {
             final MMStudio studio = MicroManager.getMMStudio();
             if (studio != null)
                 studio.showAutofocusDialog();
             else
-                System.err.println("MMStudio is null, cannot open autofocus setting panel");
+                IcyLogger.error(this.getClass(), "Cannot show autofocus dialog (MMStudio is null).");
         });
     }
 
@@ -226,7 +223,7 @@ public class CameraSettingsPanel extends JPanel implements Runnable {
         gbc_shuttersCombo.gridy = 2;
         add(shuttersCombo, gbc_shuttersCombo);
 
-        shutterOpenBtn = new IcyToggleButton("Open", new IcyIcon("shutter"));
+        shutterOpenBtn = new IcyToggleButton("Open", SVGIcon.CAMERA);
         shutterOpenBtn.setIconTextGap(10);
         shutterOpenBtn.setToolTipText("Open / close the shutter");
 
@@ -265,7 +262,7 @@ public class CameraSettingsPanel extends JPanel implements Runnable {
         gbc_lblAutofocus.gridy = 4;
         add(lblAutofocus, gbc_lblAutofocus);
 
-        autofocusBtn = new IcyButton(new IcyIcon("autofocus"));
+        autofocusBtn = new IcyButton(SVGIcon.CENTER_FOCUS_STRONG);
         autofocusBtn.setToolTipText("Perform autofocus now");
         final GridBagConstraints gbc_autofocusBtn = new GridBagConstraints();
         gbc_autofocusBtn.fill = GridBagConstraints.BOTH;
@@ -274,7 +271,7 @@ public class CameraSettingsPanel extends JPanel implements Runnable {
         gbc_autofocusBtn.gridy = 4;
         add(autofocusBtn, gbc_autofocusBtn);
 
-        autofocusSettingBtn = new IcyButton(new IcyIcon("af_setting"));
+        autofocusSettingBtn = new IcyButton(SVGIcon.SETTINGS_PHOTO_CAMERA);
         autofocusSettingBtn.setToolTipText("Autofocus settings");
         final GridBagConstraints gbc_autoFocusSettingBtn = new GridBagConstraints();
         gbc_autoFocusSettingBtn.fill = GridBagConstraints.BOTH;
@@ -299,13 +296,15 @@ public class CameraSettingsPanel extends JPanel implements Runnable {
         mainFrame.unlock();
     }
 
+    /*@Deprecated(forRemoval = true)
     public void logError(final Exception e) {
         getMMStudio().logError(e);
-    }
+    }*/
 
+    /*@Deprecated(forRemoval = true)
     public void logError(final Exception e, final String msg) {
         getMMStudio().logError(e, msg);
-    }
+    }*/
 
     public String getCameraName() {
         return cameraName;
@@ -343,8 +342,8 @@ public class CameraSettingsPanel extends JPanel implements Runnable {
             MicroManager.setExposure(exposure);
         }
         catch (final Exception e) {
-            logError(e, "Couldn't set exposure time.");
-            IcyExceptionHandler.showErrorMessage(e, true);
+            IcyLogger.error(this.getClass(), e, "Cannot set exposure time.");
+            //logError(e, "Couldn't set exposure time.");
         }
     }
 
@@ -360,8 +359,8 @@ public class CameraSettingsPanel extends JPanel implements Runnable {
             MicroManager.setBinning(binning);
         }
         catch (final Exception e) {
-            logError(e, "Couldn't set camera binning.");
-            IcyExceptionHandler.showErrorMessage(e, true);
+            IcyLogger.error(this.getClass(), e, "Cannot set camera binning.");
+            //logError(e, "Couldn't set camera binning.");
         }
     }
 
@@ -420,7 +419,8 @@ public class CameraSettingsPanel extends JPanel implements Runnable {
             }
         }
         catch (final Exception e) {
-            logError(e);
+            IcyLogger.error(this.getClass(), e);
+            //logError(e);
         }
     }
 
@@ -463,7 +463,8 @@ public class CameraSettingsPanel extends JPanel implements Runnable {
             }
         }
         catch (final Exception e) {
-            logError(e);
+            IcyLogger.error(this.getClass(), e);
+            //logError(e);
         }
     }
 
@@ -512,7 +513,8 @@ public class CameraSettingsPanel extends JPanel implements Runnable {
             autoShutterCheckbox.setSelected(autoShutter);
         }
         catch (final Exception e) {
-            logError(e);
+            IcyLogger.error(this.getClass(), e);
+            //logError(e);
         }
     }
 
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/ChannelTable.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/ChannelTable.java
index bb67d21..62c1426 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/ChannelTable.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/ChannelTable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,10 +18,10 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.gui;
 
-import icy.system.IcyExceptionHandler;
 import mmcorej.CMMCore;
 import mmcorej.Configuration;
 import mmcorej.PropertySetting;
+import org.bioimageanalysis.icy.system.logging.IcyLogger;
 import org.micromanager.acquisition.AcquisitionWrapperEngine;
 import org.micromanager.dialogs.ChannelCellEditor;
 import org.micromanager.dialogs.ChannelCellRenderer;
@@ -42,7 +42,7 @@ import java.util.List;
 /**
  * Custom table representing channel definition for Micro-Manager advanced acquisition
  *
- * @author Stephane
+ * @author Stephane Dallongeville
  */
 public class ChannelTable extends JTable {
     final protected ChannelTableModel model;
@@ -118,8 +118,7 @@ public class ChannelTable extends JTable {
                 return true;
             }
             catch (final Throwable t) {
-                System.err.println("Cannot set channel group in Micro-Manager.");
-                IcyExceptionHandler.showErrorMessage(t, true);
+                IcyLogger.error(ChannelTable.class, t, "Cannot set channel group in Micro-Manager.");
             }
         }
 
@@ -135,7 +134,7 @@ public class ChannelTable extends JTable {
 
         if (!cfgs.isEmpty()) {
             try {
-                final Configuration presetData = core.getConfigData(group, cfgs.get(0));
+                final Configuration presetData = core.getConfigData(group, cfgs.getFirst());
 
                 if (presetData.size() >= 1L) {
                     final PropertySetting setting = presetData.getSetting(0L);
@@ -147,8 +146,7 @@ public class ChannelTable extends JTable {
                 }
             }
             catch (final Exception e) {
-                System.err.println("Error with Micro-Manager:");
-                IcyExceptionHandler.showErrorMessage(e, true);
+                IcyLogger.error(ChannelTable.class, e, "Error with Micro-Manager");
                 return false;
             }
         }
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/ConfigurationPanel.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/ConfigurationPanel.java
index d8b61bf..dcc7a0c 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/ConfigurationPanel.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/ConfigurationPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,15 +18,14 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.gui;
 
-import icy.gui.component.button.IcyButton;
-import icy.gui.dialog.ConfirmDialog;
-import icy.gui.dialog.MessageDialog;
-import icy.resource.ResourceUtil;
-import icy.resource.icon.IcyIcon;
-import icy.system.IcyExceptionHandler;
-import icy.system.thread.ThreadUtil;
-import icy.util.StringUtil;
 import mmcorej.CMMCore;
+import org.bioimageanalysis.icy.common.string.StringUtil;
+import org.bioimageanalysis.icy.gui.component.button.IcyButton;
+import org.bioimageanalysis.icy.gui.component.icon.SVGIcon;
+import org.bioimageanalysis.icy.gui.dialog.ConfirmDialog;
+import org.bioimageanalysis.icy.gui.dialog.MessageDialog;
+import org.bioimageanalysis.icy.system.logging.IcyLogger;
+import org.bioimageanalysis.icy.system.thread.ThreadUtil;
 import org.micromanager.ConfigGroupPad;
 import org.micromanager.MMStudio;
 import org.micromanager.dialogs.GroupEditor;
@@ -81,7 +80,7 @@ public class ConfigurationPanel extends JPanel {
                 ThreadUtil.invokeLater(() -> refreshGroupNow(groupNameRefresh, configName));
             }
             catch (final Exception e) {
-                IcyExceptionHandler.showErrorMessage(e, true);
+                IcyLogger.error(this.getClass(), e);
             }
         };
     }
@@ -104,7 +103,7 @@ public class ConfigurationPanel extends JPanel {
         gbl_configButtonPanel.rowWeights = new double[]{0.0, Double.MIN_VALUE};
         configButtonPanel.setLayout(gbl_configButtonPanel);
 
-        final IcyButton addGroupBtn = new IcyButton(new IcyIcon("sq_plus"));
+        final IcyButton addGroupBtn = new IcyButton(SVGIcon.ADD);
         addGroupBtn.addActionListener(e -> {
             final GroupEditor ge = new GroupEditor("", "", getMMStudio(), getCore(), true);
             if (ge.getWidth() < 580)
@@ -132,10 +131,10 @@ public class ConfigurationPanel extends JPanel {
         gbc_addGroupBtn.gridx = 1;
         gbc_addGroupBtn.gridy = 0;
         configButtonPanel.add(addGroupBtn, gbc_addGroupBtn);
-        final IcyButton editGroupBtn = new IcyButton(new IcyIcon("doc_edit"));
+        final IcyButton editGroupBtn = new IcyButton(SVGIcon.EDIT);
         editGroupBtn.addActionListener(e -> {
             final String groupName = MMUtils.getSelectedGroupName(groupPad);
-            final String groupName2 = groupPad.getSelectedGroup();
+            //final String groupName2 = groupPad.getSelectedGroup();
 
             if (StringUtil.isEmpty(groupName))
                 MessageDialog.showDialog("To edit a group, please select it first then press the edit group button.");
@@ -151,7 +150,7 @@ public class ConfigurationPanel extends JPanel {
                 });
             }
         });
-        final IcyButton removeGroupBtn = new IcyButton(new IcyIcon("sq_minus"));
+        final IcyButton removeGroupBtn = new IcyButton(SVGIcon.REMOVE);
         removeGroupBtn.addActionListener(e -> {
             final String groupName = MMUtils.getSelectedGroupName(groupPad);
 
@@ -192,7 +191,7 @@ public class ConfigurationPanel extends JPanel {
         gbc_presetLabel.gridy = 0;
         configButtonPanel.add(presetLabel, gbc_presetLabel);
 
-        final IcyButton addPresetBtn = new IcyButton(new IcyIcon("sq_plus"));
+        final IcyButton addPresetBtn = new IcyButton(SVGIcon.ADD);
         addPresetBtn.addActionListener(e -> {
             final String groupName = MMUtils.getSelectedGroupName(groupPad);
 
@@ -215,7 +214,7 @@ public class ConfigurationPanel extends JPanel {
         gbc_addPresetBtn.gridx = 7;
         gbc_addPresetBtn.gridy = 0;
         configButtonPanel.add(addPresetBtn, gbc_addPresetBtn);
-        final IcyButton editPresetBtn = new IcyButton(new IcyIcon("doc_edit"));
+        final IcyButton editPresetBtn = new IcyButton(SVGIcon.EDIT);
         editPresetBtn.addActionListener(e -> {
             final String groupName = MMUtils.getSelectedGroupName(groupPad);
             final String presetName = MMUtils.getSelectedPresetName(groupPad);
@@ -232,7 +231,7 @@ public class ConfigurationPanel extends JPanel {
                 });
             }
         });
-        final IcyButton removePresetBtn = new IcyButton(new IcyIcon("sq_minus"));
+        final IcyButton removePresetBtn = new IcyButton(SVGIcon.REMOVE);
         removePresetBtn.addActionListener(e -> {
             final String groupName = MMUtils.getSelectedGroupName(groupPad);
             final String presetName = MMUtils.getSelectedPresetName(groupPad);
@@ -282,7 +281,7 @@ public class ConfigurationPanel extends JPanel {
         gbc_editPresetBtn.gridy = 0;
         configButtonPanel.add(editPresetBtn, gbc_editPresetBtn);
 
-        final IcyButton saveBtn = new IcyButton(new IcyIcon(ResourceUtil.ICON_SAVE));
+        final IcyButton saveBtn = new IcyButton(SVGIcon.SAVE);
         saveBtn.setToolTipText("Save current presets to configuration file...");
         saveBtn.addActionListener(e -> mainFrame.saveConfig());
         final GridBagConstraints gbc_saveBtn = new GridBagConstraints();
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/LiveSettingsPanel.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/LiveSettingsPanel.java
index 1ece6a7..4372153 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/LiveSettingsPanel.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/LiveSettingsPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,8 +18,8 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.gui;
 
-import icy.gui.component.NumberTextField;
-import icy.util.StringUtil;
+import org.bioimageanalysis.icy.common.string.StringUtil;
+import org.bioimageanalysis.icy.gui.component.field.NumberTextField;
 
 import javax.swing.*;
 import javax.swing.border.TitledBorder;
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/LoadFrame.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/LoadFrame.java
index b6d9e3a..ca334be 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/LoadFrame.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/LoadFrame.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,16 +18,15 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.gui;
 
-import icy.action.IcyAbstractAction;
-import icy.file.FileUtil;
-import icy.gui.component.button.IcyButton;
-import icy.gui.dialog.OpenDialog;
-import icy.main.Icy;
-import icy.preferences.PluginsPreferences;
-import icy.preferences.XMLPreferences;
-import icy.resource.ResourceUtil;
-import icy.resource.icon.IcyIcon;
-import icy.system.IcyExceptionHandler;
+import org.bioimageanalysis.icy.Icy;
+import org.bioimageanalysis.icy.gui.action.IcyAbstractAction;
+import org.bioimageanalysis.icy.gui.component.button.IcyButton;
+import org.bioimageanalysis.icy.gui.component.icon.SVGIcon;
+import org.bioimageanalysis.icy.gui.dialog.OpenDialog;
+import org.bioimageanalysis.icy.io.FileUtil;
+import org.bioimageanalysis.icy.system.logging.IcyLogger;
+import org.bioimageanalysis.icy.system.preferences.PluginsPreferences;
+import org.bioimageanalysis.icy.system.preferences.XMLPreferences;
 import plugins.tprovoost.Microscopy.MicroManager.tools.MMUtils;
 import plugins.tprovoost.Microscopy.MicroManagerForIcy.MicromanagerPlugin;
 
@@ -132,7 +131,7 @@ public class LoadFrame extends JDialog {
                     openButton.setEnabled(true);
                 }
                 catch (final IOException e1) {
-                    IcyExceptionHandler.showErrorMessage(e1, true);
+                    IcyLogger.error(this.getClass(), e1);
                 }
             }
             else
@@ -232,15 +231,11 @@ public class LoadFrame extends JDialog {
         lbl_devices.setFont(lbl_files.getFont().deriveFont(Font.BOLD, 12));
         lbl_config_presets.setFont(lbl_files.getFont().deriveFont(Font.BOLD, 12));
 
-        openButton = new IcyButton(openAction);
-        openButton.setIcon(new IcyIcon(ResourceUtil.ICON_OPEN));
+        openButton = new IcyButton(openAction, SVGIcon.FOLDER_OPEN);
         openButton.setEnabled(false);
-        final IcyButton cancelButton = new IcyButton(cancelAction);
-        cancelButton.setIcon(new IcyIcon(ResourceUtil.ICON_DELETE));
-        final IcyButton addButton = new IcyButton(addAction);
-        addButton.setIcon(new IcyIcon(ResourceUtil.ICON_PLUS));
-        final IcyButton removeButton = new IcyButton(removeAction);
-        removeButton.setIcon(new IcyIcon(ResourceUtil.ICON_MINUS));
+        final IcyButton cancelButton = new IcyButton(cancelAction, SVGIcon.DELETE);
+        final IcyButton addButton = new IcyButton(addAction, SVGIcon.ADD);
+        final IcyButton removeButton = new IcyButton(removeAction, SVGIcon.REMOVE);
 
         final JPanel buttonPanel = new JPanel();
         getContentPane().add(buttonPanel, BorderLayout.SOUTH);
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/LoadingFrame.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/LoadingFrame.java
index 800aa72..7603247 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/LoadingFrame.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/LoadingFrame.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,8 +18,8 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.gui;
 
-import icy.gui.frame.IcyFrame;
-import icy.system.thread.ThreadUtil;
+import org.bioimageanalysis.icy.gui.frame.IcyFrame;
+import org.bioimageanalysis.icy.system.thread.ThreadUtil;
 
 import javax.swing.*;
 import java.awt.*;
@@ -27,7 +27,7 @@ import java.awt.*;
 /**
  * Simple static Loading Frame for Micro-Manager initialization.
  *
- * @author Stephane
+ * @author Stephane Dallongeville
  */
 public class LoadingFrame extends IcyFrame {
     JProgressBar progressBar;
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/MMMainFrame.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/MMMainFrame.java
index 4e8f9d0..9bea7ce 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/MMMainFrame.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/MMMainFrame.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,30 +18,28 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.gui;
 
-import icy.common.MenuCallback;
-import icy.file.FileUtil;
-import icy.gui.dialog.ActionDialog;
-import icy.gui.dialog.ConfirmDialog;
-import icy.gui.dialog.MessageDialog;
-import icy.gui.dialog.SaveDialog;
-import icy.gui.frame.IcyFrame;
-import icy.gui.frame.IcyFrameAdapter;
-import icy.gui.frame.IcyFrameEvent;
-import icy.gui.frame.progress.FailedAnnounceFrame;
-import icy.gui.frame.progress.ToolTipFrame;
-import icy.gui.util.ComponentUtil;
-import icy.main.Icy;
-import icy.preferences.PluginPreferences;
-import icy.preferences.XMLPreferences;
-import icy.resource.ResourceUtil;
-import icy.resource.icon.IcyIcon;
-import icy.system.IcyExceptionHandler;
-import icy.system.thread.ThreadUtil;
-import icy.util.ReflectionUtil;
-import icy.util.StringUtil;
 import mmcorej.CMMCore;
 import mmcorej.MMCoreJ;
 import mmcorej.MMEventCallback;
+import org.bioimageanalysis.icy.Icy;
+import org.bioimageanalysis.icy.common.reflect.ReflectionUtil;
+import org.bioimageanalysis.icy.common.string.StringUtil;
+import org.bioimageanalysis.icy.gui.component.ComponentUtil;
+import org.bioimageanalysis.icy.gui.component.icon.SVGIcon;
+import org.bioimageanalysis.icy.gui.component.menu.IcyMenuItem;
+import org.bioimageanalysis.icy.gui.dialog.ActionDialog;
+import org.bioimageanalysis.icy.gui.dialog.ConfirmDialog;
+import org.bioimageanalysis.icy.gui.dialog.MessageDialog;
+import org.bioimageanalysis.icy.gui.dialog.SaveDialog;
+import org.bioimageanalysis.icy.gui.frame.IcyFrame;
+import org.bioimageanalysis.icy.gui.frame.IcyFrameAdapter;
+import org.bioimageanalysis.icy.gui.frame.IcyFrameEvent;
+import org.bioimageanalysis.icy.gui.frame.progress.ToolTipFrame;
+import org.bioimageanalysis.icy.io.FileUtil;
+import org.bioimageanalysis.icy.system.logging.IcyLogger;
+import org.bioimageanalysis.icy.system.preferences.PluginPreferences;
+import org.bioimageanalysis.icy.system.preferences.XMLPreferences;
+import org.bioimageanalysis.icy.system.thread.ThreadUtil;
 import org.micromanager.MMOptions;
 import org.micromanager.MMStudio;
 import org.micromanager.MainFrame;
@@ -50,7 +48,6 @@ import org.micromanager.conf2.ConfiguratorDlg2;
 import org.micromanager.conf2.MMConfigFileException;
 import org.micromanager.conf2.MicroscopeModel;
 import org.micromanager.dialogs.CalibrationListDlg;
-import org.micromanager.utils.ReportingUtils;
 import plugins.tprovoost.Microscopy.MicroManager.MicroManager;
 import plugins.tprovoost.Microscopy.MicroManager.core.AcquisitionHandler;
 import plugins.tprovoost.Microscopy.MicroManager.event.CoreListener;
@@ -170,7 +167,7 @@ public class MMMainFrame extends IcyFrame {
                     options.closeOnExit_ = false;
                 }
                 catch (final Exception ex) {
-                    System.err.println("Warning: cannot patch options informations from Micro-Manager.");
+                    IcyLogger.warn(MMMainFrame.this.getClass(), ex, "Cannot patch options information from Micro-Manager");
                 }
 
                 try {
@@ -181,7 +178,7 @@ public class MMMainFrame extends IcyFrame {
                     contrastPrefs = (Preferences) ReflectionUtil.getFieldObject(mmstudio, "contrastPrefs_");
                 }
                 catch (final Exception ex) {
-                    System.err.println("Warning: cannot retrieve Preferences from Micro-Manager.");
+                    IcyLogger.warn(MMMainFrame.this.getClass(), ex, "Cannot retrieve Preferences from Micro-Manager");
                 }
 
                 final MainFrame frame = MMStudio.getFrame();
@@ -363,8 +360,7 @@ public class MMMainFrame extends IcyFrame {
         final JMenuBar menuBar = new JMenuBar();
         menuBar.add(toReturn);
         setJMenuBar(menuBar);
-        final JMenuItem hconfig = new JMenuItem("Configuration Wizard");
-        hconfig.setIcon(new IcyIcon("star.png"));
+        final IcyMenuItem hconfig = new IcyMenuItem("Configuration Wizard", SVGIcon.STAR);
         hconfig.addActionListener(e -> {
             // we have some plugins running ?
             if (pluginsPanel.getRunningPluginsCount() > 0) {
@@ -394,8 +390,7 @@ public class MMMainFrame extends IcyFrame {
             refreshGUI();
         });
 
-        final JMenuItem menuPxSizeConfigItem = new JMenuItem("Pixel Size Config");
-        menuPxSizeConfigItem.setIcon(new IcyIcon(ResourceUtil.ICON_PROPERTIES));
+        final IcyMenuItem menuPxSizeConfigItem = new IcyMenuItem("Pixel Size Config", SVGIcon.SETTINGS);
         menuPxSizeConfigItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G, InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK));
         menuPxSizeConfigItem.addActionListener(e -> {
             final CalibrationListDlg dlg = new CalibrationListDlg(mmstudio.getCore());
@@ -407,9 +402,8 @@ public class MMMainFrame extends IcyFrame {
             pixelSizeConfig.setResizable(true);
         });
 
-        final JMenuItem loadConfigItem = new JMenuItem("Load Configuration");
+        final IcyMenuItem loadConfigItem = new IcyMenuItem("Load Configuration", SVGIcon.FOLDER_OPEN);
         loadConfigItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK));
-        loadConfigItem.setIcon(new IcyIcon(ResourceUtil.ICON_OPEN));
         loadConfigItem.addActionListener(e -> {
             final LoadFrame f = new LoadFrame();
 
@@ -431,13 +425,11 @@ public class MMMainFrame extends IcyFrame {
             }
         });
 
-        final JMenuItem saveConfigItem = new JMenuItem("Save Configuration");
+        final IcyMenuItem saveConfigItem = new IcyMenuItem("Save Configuration", SVGIcon.SAVE);
         saveConfigItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK));
-        saveConfigItem.setIcon(new IcyIcon(ResourceUtil.ICON_SAVE));
         saveConfigItem.addActionListener(e -> saveConfig());
 
-        final JMenuItem aboutItem = new JMenuItem("About");
-        aboutItem.setIcon(new IcyIcon(ResourceUtil.ICON_INFO));
+        final IcyMenuItem aboutItem = new IcyMenuItem("About", SVGIcon.INFO);
         aboutItem.addActionListener(e -> {
             final JDialog dialog = new JDialog(Icy.getMainInterface().getMainFrame(), "About");
 
@@ -449,9 +441,8 @@ public class MMMainFrame extends IcyFrame {
             dialog.setVisible(true);
         });
 
-        final JMenuItem propertyBrowserItem = new JMenuItem("Property Browser");
+        final IcyMenuItem propertyBrowserItem = new IcyMenuItem("Property Browser", SVGIcon.DATABASE);
         propertyBrowserItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_COMMA, InputEvent.CTRL_DOWN_MASK));
-        propertyBrowserItem.setIcon(new IcyIcon(ResourceUtil.ICON_DATABASE));
         propertyBrowserItem.addActionListener(e -> {
             final PropertyEditor editor = new PropertyEditor();
             editor.setGui(mmstudio);
@@ -463,13 +454,11 @@ public class MMMainFrame extends IcyFrame {
             propertyBrowser.setResizable(true);
         });
 
-        final JMenuItem resetMMPath = new JMenuItem("Reset Micro-Manager path");
-        resetMMPath.setIcon(new IcyIcon("folder"));
+        final IcyMenuItem resetMMPath = new IcyMenuItem("Reset Micro-Manager path", SVGIcon.FOLDER);
         resetMMPath.addActionListener(e -> {
             // so user can change the defined MM folder
             MMUtils.resetLibrayPath();
-            MessageDialog.showDialog("Information", "You need to restart Icy now to change the defined Micro-Manager folder.",
-                    MessageDialog.INFORMATION_MESSAGE);
+            MessageDialog.showDialog("Information", "You need to restart Icy now to change the defined Micro-Manager folder.", MessageDialog.INFORMATION_MESSAGE);
         });
 
         // JMenuItem loadPresetConfigItem = new JMenuItem("Load Core properties from XML");
@@ -494,8 +483,7 @@ public class MMMainFrame extends IcyFrame {
         // }
         // });
         //
-        final JMenuItem mmSettingItem = new JMenuItem("Micro-Manager options");
-        mmSettingItem.setIcon(new IcyIcon(ResourceUtil.ICON_COG, true));
+        final IcyMenuItem mmSettingItem = new IcyMenuItem("Micro-Manager options", SVGIcon.SETTINGS);
         mmSettingItem.setToolTipText("Set a variety of Micro-Manager configuration options");
         mmSettingItem.addActionListener(e -> {
             if (options == null)
@@ -522,8 +510,7 @@ public class MMMainFrame extends IcyFrame {
         // }
         // });
 
-        final JMenuItem mmScriptPanel = new JMenuItem("Script panel");
-        mmScriptPanel.setIcon(new IcyIcon(ResourceUtil.getAlphaIconAsImage("text_curstor"), true));
+        final IcyMenuItem mmScriptPanel = new IcyMenuItem("Script panel", SVGIcon.EDIT);
         mmScriptPanel.setToolTipText("Open Micro-Manager script panel");
         mmScriptPanel.addActionListener(e -> mmstudio.showScriptPanel());
 
@@ -621,9 +608,8 @@ public class MMMainFrame extends IcyFrame {
                 model.saveToFile(path);
         }
         catch (final MMConfigFileException e) {
-            ReportingUtils.logError(e);
-            IcyExceptionHandler.showErrorMessage(e, false);
-            new FailedAnnounceFrame("Unable to save configuration file");
+            IcyLogger.error(this.getClass(), e, "Error while saving Micro-Manager configuration.");
+            //ReportingUtils.logError(e);
         }
     }
 
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/MainPanel.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/MainPanel.java
index a353018..1b33279 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/MainPanel.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/MainPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/OptionsPanel.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/OptionsPanel.java
index cf25b00..7f09f49 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/OptionsPanel.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/OptionsPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,8 +18,8 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.gui;
 
-import icy.gui.dialog.ConfirmDialog;
 import mmcorej.CMMCore;
+import org.bioimageanalysis.icy.gui.dialog.ConfirmDialog;
 import org.micromanager.MMOptions;
 import org.micromanager.logging.LogFileManager;
 import org.micromanager.utils.NumberUtils;
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/PluginsToolbar.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/PluginsToolbar.java
index 079fed1..7c6beac 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/PluginsToolbar.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/gui/PluginsToolbar.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,10 +18,12 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.gui;
 
-import icy.plugin.PluginDescriptor;
-import icy.plugin.PluginLauncher;
-import icy.plugin.PluginLoader;
-import plugins.tprovoost.Microscopy.MicroManager.tools.FrameUtils;
+import org.bioimageanalysis.icy.extension.plugin.PluginDescriptor;
+import org.bioimageanalysis.icy.extension.plugin.PluginLauncher;
+import org.bioimageanalysis.icy.extension.plugin.PluginLoader;
+import org.bioimageanalysis.icy.gui.component.button.IcyButton;
+import org.bioimageanalysis.icy.gui.component.icon.SVGIcon;
+import org.jetbrains.annotations.NotNull;
 import plugins.tprovoost.Microscopy.MicroManagerForIcy.MicroscopePlugin;
 
 import javax.swing.*;
@@ -53,14 +55,23 @@ public class PluginsToolbar extends JPanel {
         initialize(PluginLoader.getPlugins(MicroscopePlugin.class));
     }
 
-    private void initialize(final List<PluginDescriptor> plugins) {
+    private void initialize(final @NotNull List<PluginDescriptor> plugins) {
         pluginToolbar = new JToolBar(SwingConstants.HORIZONTAL);
         pluginToolbar.setRollover(true);
         pluginToolbar.setFloatable(false);
         pluginToolbar.setToolTipText("Micro Manager plugins for Icy");
 
         for (final PluginDescriptor plugin : plugins) {
-            pluginToolbar.add(FrameUtils.createPluginButton(plugin, e -> {
+            final JButton pluginButton;
+            final SVGIcon pluginSVGIcon = plugin.getSVGIcon();
+            if (pluginSVGIcon != null)
+                pluginButton = new IcyButton(pluginSVGIcon);
+            else
+                pluginButton = new JButton(plugin.getIcon());
+
+            pluginButton.setToolTipText(plugin.getName());
+
+            pluginButton.addActionListener(e -> {
                 // create the microscope plugin
                 final MicroscopePlugin microscopePlugin = (MicroscopePlugin) PluginLauncher.start(plugin);
 
@@ -69,19 +80,10 @@ public class PluginsToolbar extends JPanel {
                     addPlugin(microscopePlugin);
                     microscopePlugin.start();
                 }
-            }));
+            });
+            pluginToolbar.add(pluginButton);
         }
 
-        // if (plugins.size() == 0)
-        // {
-        // MessageDialog.showDialog("Information",
-        // "You don't have any Micro manager plugins installed, use the search bar to install some",
-        // MessageDialog.INFORMATION_MESSAGE);
-        //
-        // // search for micro manager plugin
-        // // Icy.getMainInterface().getSearchEngine().search("micro-manager");
-        // }
-
         setLayout(new BorderLayout());
         setBorder(new TitledBorder("Plugins"));
         add(pluginToolbar, BorderLayout.CENTER);
@@ -139,7 +141,7 @@ public class PluginsToolbar extends JPanel {
     }
 
     /**
-     * Shutdown all running plugins (should automatically call removePlugin(..))
+     * Shutdown all running plugins (should automatically call removePlugin(...))
      */
     public void shutdownPlugins() {
         for (final MicroscopePlugin plugin : getRunningPlugins())
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/patch/ClassPatcher.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/patch/ClassPatcher.java
index c6d55b5..9ccf1fa 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/patch/ClassPatcher.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/patch/ClassPatcher.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,23 +18,16 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.patch;
 
-import java.security.ProtectionDomain;
-import java.util.ArrayList;
-
-import icy.system.IcyExceptionHandler;
-import icy.system.SystemUtil;
-import icy.util.StringUtil;
-import javassist.CannotCompileException;
-import javassist.ClassClassPath;
-import javassist.ClassPool;
-import javassist.CtClass;
-import javassist.CtField;
-import javassist.CtMethod;
-import javassist.CtNewMethod;
-import javassist.LoaderClassPath;
-import javassist.NotFoundException;
+import javassist.*;
 import javassist.bytecode.AccessFlag;
 import javassist.bytecode.FieldInfo;
+import org.bioimageanalysis.icy.common.string.StringUtil;
+import org.bioimageanalysis.icy.system.SystemUtil;
+import org.bioimageanalysis.icy.system.logging.IcyLogger;
+import org.jetbrains.annotations.NotNull;
+
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
 
 /**
  * The code hacker provides a mechanism for altering the behavior of classes
@@ -239,8 +232,7 @@ public class ClassPatcher {
             return pool.toClass(classRef);
         }
         catch (final CannotCompileException e) {
-            IcyExceptionHandler.showErrorMessage(e, false);
-            System.err.println("Cannot load class: " + fullClass);
+            IcyLogger.error(this.getClass(), e, "Cannot load class: " + fullClass);
             return null;
         }
     }
@@ -265,8 +257,7 @@ public class ClassPatcher {
             return pool.toClass(classRef, neighbor, classLoader, protectionDomain);
         }
         catch (final CannotCompileException e) {
-            IcyExceptionHandler.showErrorMessage(e, false);
-            System.err.println("Cannot load class: " + fullClass);
+            IcyLogger.error(this.getClass(), e, "Cannot load class: " + fullClass);
             return null;
         }
     }
@@ -323,7 +314,7 @@ public class ClassPatcher {
      * Generates a new line of code calling the <code>imagej.legacy.patches</code> class and method
      * corresponding to the given method signature.
      */
-    private String newCode(final String fullClass, final String methodSig) {
+    private @NotNull String newCode(final @NotNull String fullClass, final String methodSig) {
         final int dotIndex = fullClass.lastIndexOf(".");
         final String className = fullClass.substring(dotIndex + 1);
 
@@ -360,13 +351,13 @@ public class ClassPatcher {
     /**
      * Extracts the method name from the given method signature.
      */
-    private String getMethodName(final String methodSig) {
+    private @NotNull String getMethodName(final @NotNull String methodSig) {
         final int parenIndex = methodSig.indexOf("(");
         final int spaceIndex = methodSig.lastIndexOf(" ", parenIndex);
         return methodSig.substring(spaceIndex + 1, parenIndex);
     }
 
-    private String[] getMethodArgs(final String methodSig, final boolean wantResult) {
+    private String @NotNull [] getMethodArgs(final @NotNull String methodSig, final boolean wantResult) {
         final ArrayList<String> result = new ArrayList<>();
 
         final int parenIndex = methodSig.indexOf("(");
@@ -381,14 +372,14 @@ public class ClassPatcher {
         return result.toArray(new String[0]);
     }
 
-    private String[] getMethodArgTypes(final String methodSig, final boolean wantResult) {
+    private String @NotNull [] getMethodArgTypes(final String methodSig, final boolean wantResult) {
         final String[] args = getMethodArgs(methodSig, wantResult);
         for (int i = 0; i < args.length; i++)
             args[i] = args[i].split(" ")[0];
         return args;
     }
 
-    private String[] getMethodArgNames(final String methodSig, final boolean wantResult) {
+    private String @NotNull [] getMethodArgNames(final String methodSig, final boolean wantResult) {
         final String[] args = getMethodArgs(methodSig, wantResult);
         for (int i = 0; i < args.length; i++)
             args[i] = args[i].split(" ")[1];
@@ -398,7 +389,7 @@ public class ClassPatcher {
     /**
      * Returns true if the given method signature is static.
      */
-    private boolean isStatic(final String methodSig) {
+    private boolean isStatic(final @NotNull String methodSig) {
         final int parenIndex = methodSig.indexOf("(");
         final String methodPrefix = methodSig.substring(0, parenIndex);
         for (final String token : methodPrefix.split(" ")) {
@@ -411,7 +402,7 @@ public class ClassPatcher {
     /**
      * Returns true if the given method signature returns void.
      */
-    private boolean isVoid(final String methodSig) {
+    private boolean isVoid(final @NotNull String methodSig) {
         final int parenIndex = methodSig.indexOf("(");
         final String methodPrefix = methodSig.substring(0, parenIndex);
         return methodPrefix.startsWith("void ") || methodPrefix.indexOf(" void ") > 0;
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/patch/MMPatcher.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/patch/MMPatcher.java
index 38cf863..73d993b 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/patch/MMPatcher.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/patch/MMPatcher.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,7 +18,7 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.patch;
 
-import icy.plugin.PluginLoader;
+import org.bioimageanalysis.icy.extension.plugin.PluginLoader;
 import org.micromanager.MMVersion;
 
 /**
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/patch/MMStudioMethods.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/patch/MMStudioMethods.java
index 2771b26..203b847 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/patch/MMStudioMethods.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/patch/MMStudioMethods.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -21,9 +21,8 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.patch;
 
+import org.bioimageanalysis.icy.system.logging.IcyLogger;
 import org.micromanager.MMStudio;
-
-import icy.system.IcyExceptionHandler;
 import plugins.tprovoost.Microscopy.MicroManager.MicroManager;
 
 /**
@@ -56,7 +55,7 @@ public class MMStudioMethods {
                 MicroManager.stopLiveMode();
         }
         catch (final Throwable t) {
-            IcyExceptionHandler.showErrorMessage(t, true);
+            IcyLogger.error(MMStudioMethods.class, t);
         }
     }
 }
\ No newline at end of file
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/tools/FrameUtils.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/tools/FrameUtils.java
index d0e519a..f014470 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/tools/FrameUtils.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/tools/FrameUtils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,15 +18,13 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.tools;
 
-import icy.gui.component.button.IcyButton;
-import icy.gui.frame.IcyFrame;
-import icy.gui.util.GuiUtil;
-import icy.plugin.PluginDescriptor;
-import icy.resource.icon.IcyIcon;
+import org.bioimageanalysis.icy.gui.GuiUtil;
+import org.bioimageanalysis.icy.gui.frame.IcyFrame;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import java.awt.*;
-import java.awt.event.ActionListener;
 
 /**
  * Utilities class used for wrapping Micro-Manager Frames and Dialogs in a IcyFrame.
@@ -42,7 +40,7 @@ public class FrameUtils {
      * @param window the window to add to the main pane
      * @return the window converted as an {@link IcyFrame}
      */
-    public static IcyFrame addMMWindowToDesktopPane(final Window window) {
+    public static @NotNull IcyFrame addMMWindowToDesktopPane(final Window window) {
         final IcyFrame frame = GuiUtil.createIcyFrameFromWindow(window);
         frame.addToDesktopPane();
         frame.setVisible(true);
@@ -56,11 +54,9 @@ public class FrameUtils {
      * @param label     button label
      * @return the button searched or <code>null</code> if was not found
      */
-    public static JButton findButtonComponents(final Container container, final String label) {
+    public static @Nullable JButton findButtonComponents(final @NotNull Container container, final String label) {
         for (final Component c : container.getComponents()) {
-            if (c instanceof JButton) {
-                final JButton button = (JButton) c;
-
+            if (c instanceof final JButton button) {
                 if (button.getText().equalsIgnoreCase(label))
                     return button;
             }
@@ -68,40 +64,4 @@ public class FrameUtils {
 
         return null;
     }
-
-    /**
-     * Create an {@link IcyButton} from given information
-     *
-     * @param buttonText button text
-     * @param iconPath   the icon path. Can be null if no icon wanted
-     * @param action     the action to execute when button is clicked
-     * @return an IcyButton with buttonText and an icon on it if iconPath not null.<br>
-     * The button returned have an actionListener wich execute the runnable.
-     */
-    public static IcyButton createUIButton(final String buttonText, final String iconPath, final Runnable action) {
-        final IcyButton theButton;
-        if (iconPath != null && !iconPath.isEmpty())
-            theButton = new IcyButton(buttonText, new IcyIcon(iconPath, IcyIcon.DEFAULT_SIZE));
-        else
-            theButton = new IcyButton(buttonText);
-        theButton.addActionListener(e -> action.run());
-        return theButton;
-    }
-
-    /**
-     * Create a button to launch the specified plugin
-     *
-     * @param plugin plugin descriptor
-     * @param action the action to execute when we click on the button
-     * @return an IcyButton with text and icon describing the specified plugin.
-     */
-    public static IcyButton createPluginButton(final PluginDescriptor plugin, final ActionListener action) {
-        final IcyButton result = new IcyButton(new IcyIcon(plugin.getIconAsImage(), 32, false));
-
-        result.setToolTipText(plugin.getName());
-        if (action != null)
-            result.addActionListener(action);
-
-        return result;
-    }
 }
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/tools/MMUtils.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/tools/MMUtils.java
index ca4af07..34ba4f2 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/tools/MMUtils.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/tools/MMUtils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,37 +18,38 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.tools;
 
-import icy.file.FileUtil;
-import icy.gui.dialog.MessageDialog;
-import icy.gui.frame.progress.FailedAnnounceFrame;
-import icy.gui.frame.progress.ProgressFrame;
-import icy.image.IcyBufferedImage;
-import icy.image.colormap.IcyColorMap;
-import icy.main.Icy;
-import icy.network.NetworkUtil;
-import icy.plugin.PluginLoader;
-import icy.plugin.PluginLoader.PluginClassLoader;
-import icy.preferences.PluginsPreferences;
-import icy.preferences.XMLPreferences;
-import icy.sequence.MetaDataUtil;
-import icy.sequence.Sequence;
-import icy.system.IcyExceptionHandler;
-import icy.system.SystemUtil;
-import icy.system.thread.ThreadUtil;
-import icy.type.DataType;
-import icy.type.collection.CollectionUtil;
-import icy.type.collection.array.Array2DUtil;
-import icy.type.collection.array.ArrayUtil;
-import icy.type.point.Point3D;
-import icy.util.DateUtil;
-import icy.util.OMEUtil;
-import icy.util.ReflectionUtil;
-import icy.util.StringUtil;
 import mmcorej.TaggedImage;
 import ome.xml.meta.OMEXMLMetadata;
 import ome.xml.model.Pixels;
 import ome.xml.model.primitives.NonNegativeInteger;
 import ome.xml.model.primitives.Timestamp;
+import org.bioimageanalysis.icy.Icy;
+import org.bioimageanalysis.icy.common.collection.CollectionUtil;
+import org.bioimageanalysis.icy.common.collection.array.Array2DUtil;
+import org.bioimageanalysis.icy.common.collection.array.ArrayUtil;
+import org.bioimageanalysis.icy.common.datetime.DateUtil;
+import org.bioimageanalysis.icy.common.geom.point.Point3D;
+import org.bioimageanalysis.icy.common.string.StringUtil;
+import org.bioimageanalysis.icy.common.type.DataType;
+import org.bioimageanalysis.icy.extension.plugin.PluginLoader;
+import org.bioimageanalysis.icy.gui.dialog.MessageDialog;
+import org.bioimageanalysis.icy.gui.frame.progress.FailedAnnounceFrame;
+import org.bioimageanalysis.icy.gui.frame.progress.ProgressFrame;
+import org.bioimageanalysis.icy.io.FileUtil;
+import org.bioimageanalysis.icy.model.OMEUtil;
+import org.bioimageanalysis.icy.model.colormap.IcyColorMap;
+import org.bioimageanalysis.icy.model.image.IcyBufferedImage;
+import org.bioimageanalysis.icy.model.sequence.MetaDataUtil;
+import org.bioimageanalysis.icy.model.sequence.Sequence;
+import org.bioimageanalysis.icy.network.NetworkUtil;
+import org.bioimageanalysis.icy.system.SystemUtil;
+import org.bioimageanalysis.icy.system.logging.IcyLogger;
+import org.bioimageanalysis.icy.system.preferences.PluginsPreferences;
+import org.bioimageanalysis.icy.system.preferences.XMLPreferences;
+import org.bioimageanalysis.icy.system.thread.ThreadUtil;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.joda.time.DateTime;
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -195,7 +196,8 @@ public class MMUtils {
      * @param images the list of {@link TaggedImage} to test
      * @return <code>true</code> if the specified list of TaggedImage contains a <code>null</code> or poison image.
      */
-    public static boolean hasNullOrPoison(final List<TaggedImage> images) {
+    @Contract(pure = true)
+    public static boolean hasNullOrPoison(final @NotNull List<TaggedImage> images) {
         for (final TaggedImage image : images)
             if ((image == null) || TaggedImageQueue.isPoison(image))
                 return true;
@@ -218,7 +220,7 @@ public class MMUtils {
      * @return the resulting {@link IcyBufferedImage} image
      * @throws JSONException if an error occurred while reading the metadata
      */
-    public static IcyBufferedImage convertToIcyImage(final List<TaggedImage> images) throws JSONException {
+    public static @Nullable IcyBufferedImage convertToIcyImage(final @NotNull List<TaggedImage> images) throws JSONException {
         final List<TaggedImage> goodImages = new ArrayList<>(images.size());
         int w, h, bpp;
 
@@ -246,7 +248,7 @@ public class MMUtils {
 
         if ((!goodImages.isEmpty()) && (w > 0) && (h > 0) && (bpp > 0)) {
             // create the data array
-            final Object[] data = Array2DUtil.createArray(ArrayUtil.getDataType(goodImages.get(0).pix),
+            final Object[] data = Array2DUtil.createArray(ArrayUtil.getDataType(goodImages.getFirst().pix),
                     goodImages.size());
 
             for (int i = 0; i < goodImages.size(); i++)
@@ -278,7 +280,7 @@ public class MMUtils {
      * @throws JSONException     if an error occurred while reading the metadata
      * @throws MMScriptException if an error occurred on MM script parsing
      */
-    public static void setMetadata(final Sequence sequence, final JSONObject tags) throws JSONException, MMScriptException {
+    public static void setMetadata(final @NotNull Sequence sequence, final JSONObject tags) throws JSONException, MMScriptException {
         final OMEXMLMetadata metadata = sequence.getOMEXMLMetadata();
         final int numComp = Math.max(1, MDUtils.getNumberOfComponents(tags));
 
@@ -420,8 +422,7 @@ public class MMUtils {
      * @param sizeC       wanted global size C (number of channel), set to <code>-1</code> to keep current value
      * @throws JSONException if an error occurred while reading the metadata
      */
-    public static void setImageMetadata(final TaggedImage taggedImage, final int t, final int z, final int c, final int sizeT, final int sizeZ, final int sizeC)
-            throws JSONException {
+    public static void setImageMetadata(final TaggedImage taggedImage, final int t, final int z, final int c, final int sizeT, final int sizeZ, final int sizeC) throws JSONException {
         if (taggedImage == null)
             return;
 
@@ -489,8 +490,8 @@ public class MMUtils {
      * @throws MMScriptException if an error occurred on MM script parsing
      * @see #setImageMetadata(TaggedImage, int, int, int, int, int, int)
      */
-    public static boolean setImage(final Sequence sequence, final TaggedImage taggedImage, final long startDate)
-            throws JSONException, MMScriptException {
+    @Contract("_, null, _ -> false")
+    public static boolean setImage(final Sequence sequence, final TaggedImage taggedImage, final long startDate) throws JSONException, MMScriptException {
         // incorrect image --> do nothing
         if ((taggedImage == null) || TaggedImageQueue.isPoison(taggedImage))
             return false;
@@ -576,7 +577,7 @@ public class MMUtils {
                 exposure = MicroManager.getExposure() / 1000d;
         }
         catch (final Throwable e) {
-            IcyExceptionHandler.showErrorMessage(e, false);
+            IcyLogger.error(MMUtils.class, e);
         }
 
         metadata.setPlanePositionX(OMEUtil.getLength(pos.getX()), 0, planeIndex);
@@ -599,6 +600,7 @@ public class MMUtils {
      * @throws JSONException     if an error occurred while reading the metadata
      * @throws MMScriptException if an error occurred on MM script parsing
      */
+    @Contract("_, null -> false")
     public static boolean setImage(final Sequence sequence, final TaggedImage taggedImage) throws JSONException, MMScriptException {
         return setImage(sequence, taggedImage, 0L);
     }
@@ -611,7 +613,7 @@ public class MMUtils {
      * @throws JSONException     if an error occurred while reading the metadata
      * @throws MMScriptException if an error occurred on MM script parsing
      */
-    public static boolean isCompatible(final Sequence sequence, final JSONObject metadata) throws JSONException, MMScriptException {
+    public static boolean isCompatible(final @NotNull Sequence sequence, final JSONObject metadata) throws JSONException, MMScriptException {
         if (sequence.isEmpty())
             return true;
 
@@ -619,7 +621,7 @@ public class MMUtils {
                 && (sequence.getSizeY() == MDUtils.getHeight(metadata))
                 && (sequence.getSizeC() == (MDUtils.getNumChannels(metadata)
                 * Math.max(1, MDUtils.getNumberOfComponents(metadata))))
-                && (sequence.getDataType_().getSize() == ((MDUtils.getBitDepth(metadata) + 7) / 8));
+                && (sequence.getDataType().getSize() == ((MDUtils.getBitDepth(metadata) + 7) / 8));
     }
 
     /**
@@ -629,35 +631,27 @@ public class MMUtils {
      * @throws JSONException     if an error occurred while reading the metadata
      * @throws MMScriptException if an error occurred on MM script parsing
      */
-    public static IcyBufferedImage createEmptyImage(final JSONObject metadata) throws JSONException, MMScriptException {
+    @Contract("_ -> new")
+    public static @NotNull IcyBufferedImage createEmptyImage(final JSONObject metadata) throws JSONException, MMScriptException {
         final int width = MDUtils.getWidth(metadata);
         final int height = MDUtils.getHeight(metadata);
         final int numChannels = MDUtils.getNumChannels(metadata) * Math.max(1, MDUtils.getNumberOfComponents(metadata));
         final int bpp = MDUtils.getBitDepth(metadata);
         final int bytespp = (bpp + 7) / 8;
 
-        switch (bytespp) {
-            default:
-            case 1:
-                return new IcyBufferedImage(width, height, numChannels, DataType.UBYTE);
-            case 2:
-                return new IcyBufferedImage(width, height, numChannels, DataType.USHORT);
-            case 3:
-            case 4:
-                return new IcyBufferedImage(width, height, numChannels, DataType.UINT);
-            case 5:
-            case 6:
-            case 7:
-            case 8:
-                return new IcyBufferedImage(width, height, numChannels, DataType.DOUBLE);
-        }
+        return switch (bytespp) {
+            default -> new IcyBufferedImage(width, height, numChannels, DataType.UBYTE);
+            case 2 -> new IcyBufferedImage(width, height, numChannels, DataType.USHORT);
+            case 3, 4 -> new IcyBufferedImage(width, height, numChannels, DataType.UINT);
+            case 5, 6, 7, 8 -> new IcyBufferedImage(width, height, numChannels, DataType.DOUBLE);
+        };
     }
 
     /**
      * @param group the {@link ConfigGroupPad} name
      * @return the selected group name from specified ConfigGroupPad
      */
-    public static String getSelectedGroupName(final ConfigGroupPad group) {
+    public static String getSelectedGroupName(final @NotNull ConfigGroupPad group) {
         /*try {
             return (String) ReflectionUtil.invokeMethod(group, "getGroup", true, new Object[]{});
         }
@@ -677,7 +671,7 @@ public class MMUtils {
      * @param group the {@link ConfigGroupPad} name
      * @return the selected preset name from specified ConfigGroupPad
      */
-    public static String getSelectedPresetName(final ConfigGroupPad group) {
+    public static String getSelectedPresetName(final @NotNull ConfigGroupPad group) {
         /*try {
             return (String) ReflectionUtil.invokeMethod(group, "getPreset", true, new Object[]{});
         }
@@ -734,7 +728,7 @@ public class MMUtils {
             return false;
 
         final ClassLoader cl = PluginLoader.getLoader();
-        if (cl instanceof PluginClassLoader) {
+        if (cl instanceof PluginLoader.PluginClassLoader) {
             for (final File f : files) {
                 final String path = f.getAbsolutePath();
                 final String ext = FileUtil.getFileExtension(path, false).toLowerCase();
@@ -757,7 +751,7 @@ public class MMUtils {
                         continue;
 
                     // we can add it
-                    ((PluginClassLoader) cl).add(path);
+                    ((PluginLoader.PluginClassLoader) cl).add(path);
                 }
             }
         }
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/tools/StageMover.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/tools/StageMover.java
index b6c45ee..17dacf0 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManager/tools/StageMover.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManager/tools/StageMover.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,13 +18,15 @@
 
 package plugins.tprovoost.Microscopy.MicroManager.tools;
 
-import icy.preferences.XMLPreferences;
-import icy.roi.ROI2D;
-import icy.sequence.Sequence;
-import icy.system.thread.ThreadUtil;
-import icy.type.point.Point3D;
-import icy.util.StringUtil;
 import mmcorej.CMMCore;
+import org.bioimageanalysis.icy.common.geom.point.Point3D;
+import org.bioimageanalysis.icy.common.string.StringUtil;
+import org.bioimageanalysis.icy.model.roi.ROI2D;
+import org.bioimageanalysis.icy.model.sequence.Sequence;
+import org.bioimageanalysis.icy.system.preferences.XMLPreferences;
+import org.bioimageanalysis.icy.system.thread.ThreadUtil;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
 import plugins.tprovoost.Microscopy.MicroManager.MicroManager;
 
 import java.awt.geom.Point2D;
@@ -143,6 +145,7 @@ public class StageMover {
     /**
      * @return state of X inverted axis.
      */
+    @Contract(pure = true)
     public static boolean isInvertX() {
         return invertX;
     }
@@ -150,6 +153,7 @@ public class StageMover {
     /**
      * @return state of Y inverted axis.
      */
+    @Contract(pure = true)
     public static boolean isInvertY() {
         return invertY;
     }
@@ -157,6 +161,7 @@ public class StageMover {
     /**
      * @return state of Y inverted axis.
      */
+    @Contract(pure = true)
     public static boolean isInvertZ() {
         return invertZ;
     }
@@ -174,6 +179,7 @@ public class StageMover {
     /**
      * @return state of X and Y axis inversion.
      */
+    @Contract(pure = true)
     public static boolean isSwitchXY() {
         return switchXY;
     }
@@ -181,7 +187,7 @@ public class StageMover {
     /**
      * Fire Z stage position change event
      *
-     * @param s stage devicce name
+     * @param s stage device name
      * @param z Z position
      */
     public static void onStagePositionChanged(final String s, final double z) {
@@ -322,7 +328,7 @@ public class StageMover {
      * @return the X, Y and Z coordinates of the current stage/focus device(s).
      * @throws Exception if an error occurs
      */
-    public static Point3D.Double getXYZ() throws Exception {
+    public static Point3D.@NotNull Double getXYZ() throws Exception {
         final Point2D.Double pt2d = getXY();
         return new Point3D.Double(pt2d.x, pt2d.y, getZ());
     }
@@ -333,7 +339,7 @@ public class StageMover {
      * @return the X, Y and Z coordinates of the current stage/focus device(s) in double[3] format
      * @throws Exception if an error occurs
      */
-    public static double[] getXYZAsDoubleArray() throws Exception {
+    public static double @NotNull [] getXYZAsDoubleArray() throws Exception {
         final Point3D.Double pt = getXYZ();
         return new double[]{pt.x, pt.y, pt.z};
     }
@@ -642,7 +648,7 @@ public class StageMover {
      * @param y y value of the point we want to go to.
      * @throws Exception if an error occurs
      */
-    public static void moveToPoint(final Sequence s, final double x, final double y) throws Exception {
+    public static void moveToPoint(final @NotNull Sequence s, final double x, final double y) throws Exception {
         final double pxsize;
         final double vectx = x - s.getBounds2D().getCenterX();
         // Y coordinates are inverted in the sequence
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManagerForIcy/MicromanagerPlugin.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManagerForIcy/MicromanagerPlugin.java
index 737b860..0d954c9 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManagerForIcy/MicromanagerPlugin.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManagerForIcy/MicromanagerPlugin.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,11 +18,15 @@
 
 package plugins.tprovoost.Microscopy.MicroManagerForIcy;
 
-import icy.plugin.abstract_.PluginActionable;
-import icy.plugin.interface_.PluginThreaded;
+import org.bioimageanalysis.icy.extension.plugin.abstract_.PluginActionable;
+import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon;
+import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName;
+import org.bioimageanalysis.icy.extension.plugin.interface_.PluginThreaded;
 import plugins.tprovoost.Microscopy.MicroManager.MicroManager;
 import plugins.tprovoost.Microscopy.MicroManager.tools.MMUtils;
 
+@IcyPluginName("Micro-Manager")
+@IcyPluginIcon(path = "/mmj.png")
 public final class MicromanagerPlugin extends PluginActionable implements PluginThreaded {
     /**
      * Initialize Micro-Manager sub system.
diff --git a/src/main/java/plugins/tprovoost/Microscopy/MicroManagerForIcy/MicroscopePlugin.java b/src/main/java/plugins/tprovoost/Microscopy/MicroManagerForIcy/MicroscopePlugin.java
index 2f7603e..291e932 100644
--- a/src/main/java/plugins/tprovoost/Microscopy/MicroManagerForIcy/MicroscopePlugin.java
+++ b/src/main/java/plugins/tprovoost/Microscopy/MicroManagerForIcy/MicroscopePlugin.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2023. Institut Pasteur.
+ * Copyright (c) 2010-2024. Institut Pasteur.
  *
  * This file is part of Icy.
  * Icy is free software: you can redistribute it and/or modify
@@ -18,7 +18,7 @@
 
 package plugins.tprovoost.Microscopy.MicroManagerForIcy;
 
-import icy.plugin.abstract_.Plugin;
+import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin;
 import plugins.tprovoost.Microscopy.MicroManager.MicroManager;
 
 /**
diff --git a/src/main/resources/mmj.png b/src/main/resources/mmj.png
new file mode 100644
index 0000000000000000000000000000000000000000..9a64c58c2537a9f82c3e99f8f8ec2bc82c754549
GIT binary patch
literal 15076
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%0AJx@DqfSTYh-4u2LG2_0jg@ItywRw9XlN+o
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
RAH2N^QFx&$TP|(t|33p96F>j}

literal 0
HcmV?d00001

-- 
GitLab