diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..3d47f986c41db29ec6dc0d5036bf760b3a1cf366 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.idea/ +target/ +.settings/ +*.iml +.project +.classpath \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..4a6defa5df18c9f1b2a8567fb66b9ed390adf038 --- /dev/null +++ b/pom.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <!-- Inherited Icy Parent POM --> + <parent> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>parent-pom-plugin</artifactId> + <version>1.0.3</version> + </parent> + + <!-- Project Information --> + <artifactId>timestamp-overlay</artifactId> + <version>1.0.6</version> + + <packaging>jar</packaging> + + <name>Timestamp Overlay</name> + <description>Displays a customizable time stamp over a 2D sequence.</description> + <url>http://icy.bioimageanalysis.org/plugin/timestamp-overlay/</url> + <inceptionYear>2020</inceptionYear> + + <organization> + <name>Institut Pasteur</name> + <url>https://pasteur.fr</url> + </organization> + + <licenses> + <license> + <name>GNU GPLv3</name> + <url>https://www.gnu.org/licenses/gpl-3.0.en.html</url> + <distribution>repo</distribution> + </license> + </licenses> + + <developers> + <developer> + <id>sdallongeville</id> + <name>Stéphane Dallongeville</name> + <url>https://research.pasteur.fr/fr/member/stephane-dallongeville/</url> + <roles> + <role>founder</role> + <role>lead</role> + <role>architect</role> + <role>developer</role> + <role>debugger</role> + <role>tester</role> + <role>maintainer</role> + <role>support</role> + </roles> + </developer> + </developers> + + <!-- Project properties --> + <properties> + + </properties> + + <!-- Project build configuration --> + <build> + + </build> + + <!-- List of project's dependencies --> + <dependencies> + <!-- The core of Icy --> + <dependency> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>icy-kernel</artifactId> + </dependency> + </dependencies> + + <!-- Icy Maven repository (to find parent POM) --> + <repositories> + <repository> + <id>icy</id> + <name>Icy's Nexus</name> + <url>https://icy-nexus.pasteur.fr/repository/Icy/</url> + </repository> + </repositories> +</project> diff --git a/src/main/java/plugins/fab/timestamp/TimeStampOverlay$DisplayStyle.class b/src/main/java/plugins/fab/timestamp/TimeStampOverlay$DisplayStyle.class new file mode 100644 index 0000000000000000000000000000000000000000..dfca7e9ba05cd8567731af1d9f74b4c160bbee1b Binary files /dev/null and b/src/main/java/plugins/fab/timestamp/TimeStampOverlay$DisplayStyle.class differ diff --git a/src/main/java/plugins/fab/timestamp/TimeStampOverlay.class b/src/main/java/plugins/fab/timestamp/TimeStampOverlay.class new file mode 100644 index 0000000000000000000000000000000000000000..a3e9ba1400212327f34cf891c077f373e2dac685 Binary files /dev/null and b/src/main/java/plugins/fab/timestamp/TimeStampOverlay.class differ diff --git a/src/main/java/plugins/fab/timestamp/TimeStampOverlay.java b/src/main/java/plugins/fab/timestamp/TimeStampOverlay.java new file mode 100644 index 0000000000000000000000000000000000000000..0d3ea623a4e026ed7a6accd0b8fc08d8fe6ab32b --- /dev/null +++ b/src/main/java/plugins/fab/timestamp/TimeStampOverlay.java @@ -0,0 +1,178 @@ +package plugins.fab.timestamp; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.event.KeyEvent; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.concurrent.TimeUnit; + +import icy.canvas.IcyCanvas; +import icy.gui.frame.progress.AnnounceFrame; +import icy.math.MathUtil; +import icy.math.UnitUtil; +import icy.painter.Overlay; +import icy.sequence.Sequence; +import icy.util.GraphicsUtil; +import icy.util.StringUtil; + +public class TimeStampOverlay extends Overlay +{ + enum DisplayStyle + { + FRAME, TIME + }; + + String timeStampText; + int x; + int y; + Font font; + DisplayStyle displayStyle = DisplayStyle.FRAME; + Rectangle2D textBound = new Rectangle2D.Double(0, 0, 0, 0); + int fontSize = 20; + int displaySelectionIndex = 0; + + public TimeStampOverlay(Sequence sequence) + { + super("Timestamp"); + + x = 20; + y = sequence.getHeight() - 20; + font = new Font("Arial", Font.BOLD, fontSize); + } + + /** + * Display the time with all the units. + * + * @param valueInMs + * : value in milliseconds + * @param displayMs : Even if a unit is not relevant (equals to zero), it will be displayed. + * @return <b>Example:</b> "2h 3min 40sec 350ms". + */ + public static String getTimeAsString(double valueInMs, boolean displayMs) + { + double v = Math.abs(valueInMs); + + final int day = (int) (v / (24d * 60d * 60d * 1000d)); + v %= 24d * 60d * 60d * 1000d; + final int hour = (int) (v / (60d * 60d * 1000d)); + v %= 60d * 60d * 1000d; + final int minute = (int) (v / (60d * 1000d)); + v %= 60d * 1000d; + final int second = (int) (v / 1000d); + v %= 1000d; + final double ms = MathUtil.round(v, 1); + + String result = ""; + + if (day > 0) + result += day + "d "; + if (hour > 0) + result += String.format("%2dh ", Integer.valueOf(hour)); + else if (!StringUtil.isEmpty(result)) + result += "00h "; + if (minute > 0) + result += String.format("%2dmin ", Integer.valueOf(minute)); + else if (!StringUtil.isEmpty(result)) + result += "00min "; + if (second > 0) + result += String.format("%2dsec ", Integer.valueOf(second)); + else if (!StringUtil.isEmpty(result)) + result += "00sec "; + if (ms > 0d) + result += String.format("%05.1fms", Double.valueOf(ms)); + else if (displayMs && !StringUtil.isEmpty(result)) + result += String.format("%05.1fms", Double.valueOf(0)); + + return result; + } + + @Override + public void paint(Graphics2D g, Sequence sequence, IcyCanvas canvas) + { + + if (g == null) + return; + + g.setColor(Color.white); + g.setFont(font); + + switch (displayStyle) + { + case FRAME: + timeStampText = "Current frame: " + canvas.getPositionT(); + break; + + case TIME: + final double timeIntervalMs = sequence.getTimeInterval() * 1000d; + final TimeUnit unit = UnitUtil.getBestTimeUnit(timeIntervalMs * 10); + double ms = canvas.getPositionT() * timeIntervalMs; + + // minute or "higher" time unit ? + if (unit.ordinal() >= TimeUnit.MINUTES.ordinal()) + timeStampText = getTimeAsString(ms, (timeIntervalMs % 1000d) != 0d); + else + timeStampText = UnitUtil.displayTimeAsStringWithComma(ms, 3, unit); + break; + } + + g.drawString(timeStampText, x, y); + + Rectangle2D r = GraphicsUtil.getStringBounds(g, font, timeStampText); + r.setRect(r.getX() + x, r.getY() + y, r.getWidth(), r.getHeight()); + textBound = r; + } + + @Override + public void keyPressed(KeyEvent e, Point2D imagePoint, IcyCanvas canvas) + { + if (e.isConsumed()) + return; + + if (e.getKeyChar() == 'm') + { + x = (int) imagePoint.getX(); + y = (int) imagePoint.getY(); + canvas.getSequence().painterChanged(this); + return; + } + + // if ( !isPointInTextArea( imagePoint ) ) return; + + if (e.getKeyChar() == 't') + { + displaySelectionIndex++; + if (displaySelectionIndex >= DisplayStyle.values().length) + { + displaySelectionIndex = 0; + } + + displayStyle = DisplayStyle.values()[displaySelectionIndex]; + + } + + if (e.getKeyChar() == '+') + { + fontSize++; + } + + if (e.getKeyChar() == '-') + { + fontSize--; + if (fontSize < 2) + fontSize = 2; + } + + if (e.getKeyChar() == 'k') + { + canvas.getSequence().removePainter(this); + new AnnounceFrame("Time Stamp removed", 2); + } + + font = new Font("Arial", Font.BOLD, fontSize); + canvas.getSequence().painterChanged(this); + + e.consume(); + } +} diff --git a/src/main/java/plugins/fab/timestamp/Timestamp.class b/src/main/java/plugins/fab/timestamp/Timestamp.class new file mode 100644 index 0000000000000000000000000000000000000000..09638ce64d13ceab40237f6f438d4c8e12bb17ef Binary files /dev/null and b/src/main/java/plugins/fab/timestamp/Timestamp.class differ diff --git a/src/main/java/plugins/fab/timestamp/Timestamp.java b/src/main/java/plugins/fab/timestamp/Timestamp.java new file mode 100644 index 0000000000000000000000000000000000000000..e6d10a77ff8c91e2985b668cb319f938e7e3289a --- /dev/null +++ b/src/main/java/plugins/fab/timestamp/Timestamp.java @@ -0,0 +1,26 @@ +package plugins.fab.timestamp; + +import icy.gui.frame.progress.ToolTipFrame; +import icy.plugin.abstract_.PluginActionable; +import icy.sequence.Sequence; + +public class Timestamp extends PluginActionable +{ + + // IcyFrame mainFrame ; + + @Override + public void run() + { + new ToolTipFrame("<html>" + "<b>TimeStamp added.</b>" + "<br>" + + "<br>Place your cursor over the TimeStamp's text and type one of the following letters to change the display:" + + "<br>" + "<li> t : switch from frame to time (using time scale) display" + + "<li> +/- : increase / decrease font size" + "<li> m : move time stamp to cursor location" + + "<li> k : remove time stamp" + "</html>"); + + final Sequence sequence = getActiveSequence(); + + if (sequence != null) + sequence.addOverlay(new TimeStampOverlay(sequence)); + } +}