From 9b13f34e6fe3e763fd50f8b3af32f85085e9b08a Mon Sep 17 00:00:00 2001 From: Thomas <thomas.musset@pasteur.fr> Date: Thu, 27 Jun 2024 17:16:51 +0200 Subject: [PATCH] updated pom to v2.0.0-a.1, fix classes accordingly to new architecture, added icon, updated .gitignore --- .gitignore | 44 ++++++++++--- pom.xml | 12 ++-- .../java/plugins/fab/trackmanager/Link.java | 1 - .../PluginTrackManagerProcessor.java | 11 ++-- .../fab/trackmanager/TrackDetection.java | 2 +- .../plugins/fab/trackmanager/TrackGroup.java | 4 +- .../fab/trackmanager/TrackLengthDialog.java | 7 +-- .../fab/trackmanager/TrackManager.java | 58 +++++++++--------- .../fab/trackmanager/TrackManagerPainter.java | 20 +++--- .../TrackManagerProcessorListener.java | 2 +- .../trackmanager/TrackPainterChangeEvent.java | 2 +- .../trackmanager/TrackPainterListener.java | 2 +- .../plugins/fab/trackmanager/TrackPanel.java | 25 ++++---- .../plugins/fab/trackmanager/TrackPool.java | 12 ++-- .../fab/trackmanager/TrackSegment.java | 10 +-- .../blocks/LoadTracksFromXML.java | 12 ++-- .../trackmanager/blocks/SaveTracksToXML.java | 14 +++-- src/main/resources/track-manager.png | Bin 0 -> 7776 bytes 18 files changed, 138 insertions(+), 100 deletions(-) create mode 100644 src/main/resources/track-manager.png diff --git a/.gitignore b/.gitignore index 7f5de73..57f16fb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,41 @@ -.idea/ -.settings/ -bin/ -build/ +/build* +/workspace +setting.xml +release/ target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +icy.log + +### IntelliJ IDEA ### +.idea/ +*.iws *.iml -*.jar +*.ipr + +### Eclipse ### +.apt_generated .classpath +.factorypath .project -export.jardesc -**/.DS_Store \ No newline at end of file +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +**/.DS_Store +Icon? \ No newline at end of file diff --git a/pom.xml b/pom.xml index 9dad1af..582587f 100644 --- a/pom.xml +++ b/pom.xml @@ -8,13 +8,11 @@ <parent> <groupId>org.bioimageanalysis.icy</groupId> <artifactId>pom-icy</artifactId> - <version>2.2.0</version> + <version>3.0.0-a.1</version> </parent> <artifactId>track-manager</artifactId> - <version>2.0.0</version> - - <packaging>jar</packaging> + <version>2.0.0-a.1</version> <name>Track Manager</name> <description> @@ -23,6 +21,10 @@ </description> <dependencies> + <dependency> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>ezplug</artifactId> + </dependency> <dependency> <groupId>org.bioimageanalysis.icy</groupId> <artifactId>protocols</artifactId> @@ -36,7 +38,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/fab/trackmanager/Link.java b/src/main/java/plugins/fab/trackmanager/Link.java index 72db57c..8145eb3 100644 --- a/src/main/java/plugins/fab/trackmanager/Link.java +++ b/src/main/java/plugins/fab/trackmanager/Link.java @@ -21,7 +21,6 @@ package plugins.fab.trackmanager; import plugins.nchenouard.spot.Detection; public class Link { - TrackSegment start; TrackSegment end; diff --git a/src/main/java/plugins/fab/trackmanager/PluginTrackManagerProcessor.java b/src/main/java/plugins/fab/trackmanager/PluginTrackManagerProcessor.java index 3dc4307..1276a8b 100644 --- a/src/main/java/plugins/fab/trackmanager/PluginTrackManagerProcessor.java +++ b/src/main/java/plugins/fab/trackmanager/PluginTrackManagerProcessor.java @@ -18,16 +18,15 @@ package plugins.fab.trackmanager; -import icy.gui.component.PopupPanel; -import icy.gui.util.GuiUtil; -import icy.plugin.abstract_.Plugin; +import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin; +import org.bioimageanalysis.icy.gui.GuiUtil; +import org.bioimageanalysis.icy.gui.component.panel.PopupPanel; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public abstract class PluginTrackManagerProcessor extends Plugin { - /** * Panel used by inherited class to display data */ @@ -123,11 +122,11 @@ public abstract class PluginTrackManagerProcessor extends Plugin { return mainPanel; } - @Override + /*@Override protected void finalize() throws Throwable { trackPool = null; super.finalize(); - } + }*/ public final void setTrackPool(final TrackPool trackPool) { this.trackPool = trackPool; diff --git a/src/main/java/plugins/fab/trackmanager/TrackDetection.java b/src/main/java/plugins/fab/trackmanager/TrackDetection.java index 53694ff..0876f46 100644 --- a/src/main/java/plugins/fab/trackmanager/TrackDetection.java +++ b/src/main/java/plugins/fab/trackmanager/TrackDetection.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/fab/trackmanager/TrackGroup.java b/src/main/java/plugins/fab/trackmanager/TrackGroup.java index 1288b76..e600bab 100644 --- a/src/main/java/plugins/fab/trackmanager/TrackGroup.java +++ b/src/main/java/plugins/fab/trackmanager/TrackGroup.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.fab.trackmanager; -import icy.sequence.Sequence; +import org.bioimageanalysis.icy.model.sequence.Sequence; import plugins.nchenouard.spot.Detection; import java.util.ArrayList; diff --git a/src/main/java/plugins/fab/trackmanager/TrackLengthDialog.java b/src/main/java/plugins/fab/trackmanager/TrackLengthDialog.java index 93c690a..aeb940e 100644 --- a/src/main/java/plugins/fab/trackmanager/TrackLengthDialog.java +++ b/src/main/java/plugins/fab/trackmanager/TrackLengthDialog.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.fab.trackmanager; -import icy.gui.dialog.ActionDialog; -import icy.gui.util.GuiUtil; +import org.bioimageanalysis.icy.gui.GuiUtil; +import org.bioimageanalysis.icy.gui.dialog.ActionDialog; import javax.swing.*; import java.awt.event.ActionEvent; @@ -31,7 +31,6 @@ public class TrackLengthDialog implements ActionListener { TrackPool trackPool; public TrackLengthDialog(final TrackPool trackPool) { - this.trackPool = trackPool; final ActionDialog actionDialog = new ActionDialog("Select by length"); actionDialog.getContentPane().setLayout( diff --git a/src/main/java/plugins/fab/trackmanager/TrackManager.java b/src/main/java/plugins/fab/trackmanager/TrackManager.java index 3c36163..29e10d7 100644 --- a/src/main/java/plugins/fab/trackmanager/TrackManager.java +++ b/src/main/java/plugins/fab/trackmanager/TrackManager.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,31 @@ package plugins.fab.trackmanager; -import icy.file.FileUtil; -import icy.gui.component.PopupPanel; -import icy.gui.component.sequence.SequenceChooser; -import icy.gui.dialog.MessageDialog; -import icy.gui.frame.IcyFrame; -import icy.gui.frame.IcyFrameEvent; -import icy.gui.frame.IcyFrameListener; -import icy.gui.frame.progress.AnnounceFrame; -import icy.gui.util.ComponentUtil; -import icy.gui.util.GuiUtil; -import icy.gui.viewer.Viewer; -import icy.main.Icy; -import icy.network.NetworkUtil; -import icy.plugin.PluginDescriptor; -import icy.plugin.PluginLoader; -import icy.plugin.abstract_.PluginActionable; -import icy.resource.ResourceUtil; -import icy.sequence.Sequence; -import icy.swimmingPool.SwimmingObject; -import icy.swimmingPool.SwimmingPoolEvent; -import icy.swimmingPool.SwimmingPoolEventType; -import icy.swimmingPool.SwimmingPoolListener; -import icy.system.IcyExceptionHandler; -import icy.util.XMLUtil; +import org.bioimageanalysis.icy.Icy; +import org.bioimageanalysis.icy.extension.plugin.PluginDescriptor; +import org.bioimageanalysis.icy.extension.plugin.PluginLoader; +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.gui.GuiUtil; +import org.bioimageanalysis.icy.gui.component.ComponentUtil; +import org.bioimageanalysis.icy.gui.component.panel.PopupPanel; +import org.bioimageanalysis.icy.gui.dialog.MessageDialog; +import org.bioimageanalysis.icy.gui.frame.IcyFrame; +import org.bioimageanalysis.icy.gui.frame.IcyFrameEvent; +import org.bioimageanalysis.icy.gui.frame.IcyFrameListener; +import org.bioimageanalysis.icy.gui.frame.progress.AnnounceFrame; +import org.bioimageanalysis.icy.gui.sequence.SequenceChooser; +import org.bioimageanalysis.icy.gui.viewer.Viewer; +import org.bioimageanalysis.icy.io.FileUtil; +import org.bioimageanalysis.icy.io.xml.XMLUtil; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.bioimageanalysis.icy.model.swimmingPool.SwimmingObject; +import org.bioimageanalysis.icy.model.swimmingPool.SwimmingPoolEvent; +import org.bioimageanalysis.icy.model.swimmingPool.SwimmingPoolEventType; +import org.bioimageanalysis.icy.model.swimmingPool.SwimmingPoolListener; +import org.bioimageanalysis.icy.network.NetworkUtil; +import org.bioimageanalysis.icy.system.IcyExceptionHandler; import org.w3c.dom.Document; import org.w3c.dom.Element; import plugins.nchenouard.spot.Detection; @@ -62,8 +63,9 @@ import java.util.prefs.Preferences; /** * @author Fabrice de Chaumont */ +@IcyPluginName("Track Manager") +@IcyPluginIcon(path = "/track-manager.png") public class TrackManager extends PluginActionable implements AdjustmentListener, ActionListener, SwimmingPoolListener, IcyFrameListener { - /* * List of active trackEditor shared between trackeditors (not used anymore) */ @@ -97,7 +99,7 @@ public class TrackManager extends PluginActionable implements AdjustmentListener void loadTrackProcessor(final PluginDescriptor pluginDescriptor) { - if (pluginDescriptor== null || pluginDescriptor.getPluginClass() == null) { + if (pluginDescriptor == null || pluginDescriptor.getPluginClass() == null) { System.err.println("Can't load processor (plugin not found)"); return; } @@ -1174,7 +1176,7 @@ public class TrackManager extends PluginActionable implements AdjustmentListener for (final PluginDescriptor plugin : PluginLoader.getPlugins()) { if (plugin.isInstanceOf(PluginTrackManagerProcessor.class)) if (!plugin.isAbstract()) { - final JMenuItem menuItem = new JMenuItem(plugin.getName(), ResourceUtil.scaleIcon(plugin.getIcon(), 24)); + final JMenuItem menuItem = new JMenuItem(plugin.getName(), new ImageIcon(plugin.getIcon().getImage().getScaledInstance(24, 24, Image.SCALE_SMOOTH))); pluginPopupMenu.add(menuItem); diff --git a/src/main/java/plugins/fab/trackmanager/TrackManagerPainter.java b/src/main/java/plugins/fab/trackmanager/TrackManagerPainter.java index 003cd26..16e38f3 100644 --- a/src/main/java/plugins/fab/trackmanager/TrackManagerPainter.java +++ b/src/main/java/plugins/fab/trackmanager/TrackManagerPainter.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,14 +18,14 @@ package plugins.fab.trackmanager; -import icy.canvas.Canvas2D; -import icy.canvas.IcyCanvas; -import icy.painter.Overlay; -import icy.sequence.Sequence; -import icy.swimmingPool.SwimmingObject; -import icy.type.point.Point5D; -import icy.util.GraphicsUtil; -import icy.util.ShapeUtil; +import org.bioimageanalysis.icy.common.geom.point.Point5D; +import org.bioimageanalysis.icy.common.geom.shape.ShapeUtil; +import org.bioimageanalysis.icy.gui.GraphicsUtil; +import org.bioimageanalysis.icy.gui.canvas.Canvas2D; +import org.bioimageanalysis.icy.gui.canvas.IcyCanvas; +import org.bioimageanalysis.icy.model.overlay.Overlay; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.bioimageanalysis.icy.model.swimmingPool.SwimmingObject; import plugins.nchenouard.spot.Detection; import java.awt.*; @@ -371,7 +371,7 @@ public class TrackManagerPainter extends Overlay { // line sections if (detectionList.size() > 1) { - Detection startDetection = detectionList.get(0); + Detection startDetection = detectionList.getFirst(); for (int i = 1; i < ts.getDetectionList().size(); i++) { final Detection endDetection = detectionList.get(i); diff --git a/src/main/java/plugins/fab/trackmanager/TrackManagerProcessorListener.java b/src/main/java/plugins/fab/trackmanager/TrackManagerProcessorListener.java index 508939b..7e771b2 100644 --- a/src/main/java/plugins/fab/trackmanager/TrackManagerProcessorListener.java +++ b/src/main/java/plugins/fab/trackmanager/TrackManagerProcessorListener.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/fab/trackmanager/TrackPainterChangeEvent.java b/src/main/java/plugins/fab/trackmanager/TrackPainterChangeEvent.java index 444eb07..f9e65c1 100644 --- a/src/main/java/plugins/fab/trackmanager/TrackPainterChangeEvent.java +++ b/src/main/java/plugins/fab/trackmanager/TrackPainterChangeEvent.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/fab/trackmanager/TrackPainterListener.java b/src/main/java/plugins/fab/trackmanager/TrackPainterListener.java index a80c277..12a62db 100644 --- a/src/main/java/plugins/fab/trackmanager/TrackPainterListener.java +++ b/src/main/java/plugins/fab/trackmanager/TrackPainterListener.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/fab/trackmanager/TrackPanel.java b/src/main/java/plugins/fab/trackmanager/TrackPanel.java index 5d85da9..40c0702 100644 --- a/src/main/java/plugins/fab/trackmanager/TrackPanel.java +++ b/src/main/java/plugins/fab/trackmanager/TrackPanel.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,16 @@ package plugins.fab.trackmanager; -import icy.gui.main.GlobalSequenceListener; -import icy.gui.main.GlobalViewerListener; -import icy.gui.viewer.Viewer; -import icy.gui.viewer.ViewerEvent; -import icy.gui.viewer.ViewerListener; -import icy.main.Icy; -import icy.painter.Overlay; -import icy.sequence.DimensionId; -import icy.sequence.Sequence; -import icy.system.thread.ThreadUtil; +import org.bioimageanalysis.icy.Icy; +import org.bioimageanalysis.icy.gui.listener.GlobalSequenceListener; +import org.bioimageanalysis.icy.gui.listener.GlobalViewerListener; +import org.bioimageanalysis.icy.gui.viewer.Viewer; +import org.bioimageanalysis.icy.gui.viewer.ViewerEvent; +import org.bioimageanalysis.icy.gui.viewer.ViewerListener; +import org.bioimageanalysis.icy.model.overlay.Overlay; +import org.bioimageanalysis.icy.model.sequence.DimensionId; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.bioimageanalysis.icy.system.thread.ThreadUtil; import plugins.nchenouard.spot.Detection; import javax.swing.*; @@ -47,8 +47,7 @@ import java.util.HashMap; * * @author Fabrice de Chaumont */ -public class TrackPanel extends JPanel implements MouseListener, MouseMotionListener, TrackPainterListener, - TrackManagerProcessorListener, ViewerListener, GlobalSequenceListener, GlobalViewerListener, Runnable { +public class TrackPanel extends JPanel implements MouseListener, MouseMotionListener, TrackPainterListener, TrackManagerProcessorListener, ViewerListener, GlobalSequenceListener, GlobalViewerListener, Runnable { TimeCursor timeCursor = new TimeCursor(); diff --git a/src/main/java/plugins/fab/trackmanager/TrackPool.java b/src/main/java/plugins/fab/trackmanager/TrackPool.java index 1daaf5e..879d3fd 100644 --- a/src/main/java/plugins/fab/trackmanager/TrackPool.java +++ b/src/main/java/plugins/fab/trackmanager/TrackPool.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,11 @@ package plugins.fab.trackmanager; -import icy.gui.dialog.MessageDialog; -import icy.gui.frame.progress.AnnounceFrame; -import icy.main.Icy; -import icy.sequence.Sequence; -import icy.swimmingPool.SwimmingObject; +import org.bioimageanalysis.icy.Icy; +import org.bioimageanalysis.icy.gui.dialog.MessageDialog; +import org.bioimageanalysis.icy.gui.frame.progress.AnnounceFrame; +import org.bioimageanalysis.icy.model.sequence.Sequence; +import org.bioimageanalysis.icy.model.swimmingPool.SwimmingObject; import plugins.nchenouard.spot.Detection; import javax.swing.event.ChangeEvent; diff --git a/src/main/java/plugins/fab/trackmanager/TrackSegment.java b/src/main/java/plugins/fab/trackmanager/TrackSegment.java index 17e6d2e..4afa588 100644 --- a/src/main/java/plugins/fab/trackmanager/TrackSegment.java +++ b/src/main/java/plugins/fab/trackmanager/TrackSegment.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.fab.trackmanager; -import icy.util.Random; +import org.bioimageanalysis.icy.common.math.Random; import plugins.nchenouard.spot.Detection; import java.lang.ref.Reference; @@ -206,7 +206,7 @@ public class TrackSegment implements Cloneable { * Add a detection in the segmentTrack */ public void addDetection(final Detection detection) { - if (detectionList.size() > 0) { + if (!detectionList.isEmpty()) { final Detection detectionPrevious = getLastDetection(); if (detection.getT() != detectionPrevious.getT() + 1) { System.err.println( @@ -316,10 +316,10 @@ public class TrackSegment implements Cloneable { * return last detection ( should be last in time too ) */ public Detection getLastDetection() { - if (detectionList.size() == 0) + if (detectionList.isEmpty()) return null; - return detectionList.get(detectionList.size() - 1); + return detectionList.getLast(); } /** diff --git a/src/main/java/plugins/fab/trackmanager/blocks/LoadTracksFromXML.java b/src/main/java/plugins/fab/trackmanager/blocks/LoadTracksFromXML.java index 2a3d239..9487a08 100644 --- a/src/main/java/plugins/fab/trackmanager/blocks/LoadTracksFromXML.java +++ b/src/main/java/plugins/fab/trackmanager/blocks/LoadTracksFromXML.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,11 @@ package plugins.fab.trackmanager.blocks; -import icy.plugin.abstract_.Plugin; -import icy.plugin.interface_.PluginBundled; -import icy.plugin.interface_.PluginLibrary; +import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName; +import org.bioimageanalysis.icy.extension.plugin.interface_.PluginBundled; +import org.bioimageanalysis.icy.extension.plugin.interface_.PluginLibrary; import plugins.adufour.blocks.tools.roi.ROIBlock; import plugins.adufour.blocks.util.VarList; import plugins.adufour.vars.lang.Var; @@ -37,6 +39,8 @@ import java.util.List; * * @author Stephane */ +@IcyPluginName("Load Tracks From XML") +@IcyPluginIcon(path = "/track-manager.png") public class LoadTracksFromXML extends Plugin implements ROIBlock, PluginLibrary, PluginBundled { final VarMutable file = new VarMutable("XML file", null) { @Override diff --git a/src/main/java/plugins/fab/trackmanager/blocks/SaveTracksToXML.java b/src/main/java/plugins/fab/trackmanager/blocks/SaveTracksToXML.java index cc3d4ce..72cffb4 100644 --- a/src/main/java/plugins/fab/trackmanager/blocks/SaveTracksToXML.java +++ b/src/main/java/plugins/fab/trackmanager/blocks/SaveTracksToXML.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.fab.trackmanager.blocks; -import icy.plugin.abstract_.Plugin; -import icy.plugin.interface_.PluginBundled; -import icy.plugin.interface_.PluginLibrary; -import icy.type.collection.CollectionUtil; +import org.bioimageanalysis.icy.common.collection.CollectionUtil; +import org.bioimageanalysis.icy.extension.plugin.abstract_.Plugin; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginIcon; +import org.bioimageanalysis.icy.extension.plugin.annotation_.IcyPluginName; +import org.bioimageanalysis.icy.extension.plugin.interface_.PluginBundled; +import org.bioimageanalysis.icy.extension.plugin.interface_.PluginLibrary; import plugins.adufour.blocks.tools.roi.ROIBlock; import plugins.adufour.blocks.util.VarList; import plugins.adufour.vars.lang.Var; @@ -36,6 +38,8 @@ import java.io.File; * * @author Stephane */ +@IcyPluginName("Save Tracks To XML") +@IcyPluginIcon(path = "/track-manager.png") public class SaveTracksToXML extends Plugin implements ROIBlock, PluginLibrary, PluginBundled { final Var<TrackGroup> tracks = new Var<>("Track group", new TrackGroup(null)); final VarMutable file = new VarMutable("XML file", null) { diff --git a/src/main/resources/track-manager.png b/src/main/resources/track-manager.png new file mode 100644 index 0000000000000000000000000000000000000000..ae9f4633300b549dee3b34c50b3573d2d5aeeea8 GIT binary patch literal 7776 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 literal 0 HcmV?d00001 -- GitLab