From 98914fd44b9f04d0438544ca7c7219c93448b99c Mon Sep 17 00:00:00 2001 From: Sougandh S Date: Mon, 8 Jun 2026 09:56:33 +0530 Subject: [PATCH] Show relative termination time in Launch History tooltip Display the relative termination time (for example, "a moment ago", "5 mins ago", or "1 hour ago") in launch history tooltips using the stored termination timestamp. This provides a quick indication of when a launch was last terminated --- .../core/org/eclipse/debug/core/Launch.java | 25 ++++++- .../internal/ui/actions/ActionMessages.java | 7 ++ .../ui/actions/ActionMessages.properties | 13 +++- .../actions/AbstractLaunchHistoryAction.java | 67 ++++++++++++++++++- 4 files changed, 108 insertions(+), 4 deletions(-) diff --git a/debug/org.eclipse.debug.core/core/org/eclipse/debug/core/Launch.java b/debug/org.eclipse.debug.core/core/org/eclipse/debug/core/Launch.java index ad366baf37a..5525d9acc0f 100644 --- a/debug/org.eclipse.debug.core/core/org/eclipse/debug/core/Launch.java +++ b/debug/org.eclipse.debug.core/core/org/eclipse/debug/core/Launch.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2026 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -25,15 +25,19 @@ import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IDisconnect; import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.ISourceLocator; import org.eclipse.debug.internal.core.DebugCoreMessages; import org.eclipse.debug.internal.core.LaunchManager; +import org.osgi.service.prefs.BackingStoreException; /** * A launch is the result of launching a debug session @@ -475,7 +479,24 @@ protected void fireChanged() { * properly created/initialized. */ protected void fireTerminate() { - setAttribute(DebugPlugin.ATTR_TERMINATE_TIMESTAMP, Long.toString(System.currentTimeMillis())); + String timeStamp = Long.toString(System.currentTimeMillis()); + setAttribute(DebugPlugin.ATTR_TERMINATE_TIMESTAMP, timeStamp); + ILaunchConfiguration launchConfig = getLaunchConfiguration(); + if (launchConfig != null) { + try { + if (launchConfig.isLocal()) { + ILaunchConfigurationWorkingCopy launchCopy = launchConfig.getWorkingCopy(); + launchCopy.setAttribute(DebugPlugin.ATTR_TERMINATE_TIMESTAMP, timeStamp); + launchCopy.doSave(); + } else { + IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(DebugPlugin.getUniqueIdentifier()); + prefs.put(launchConfig.getMemento(), timeStamp); + prefs.flush(); + } + } catch (CoreException | BackingStoreException e) { + DebugPlugin.log(e); + } + } if (!fSuppressChange) { ((LaunchManager)getLaunchManager()).fireUpdate(this, LaunchManager.TERMINATE); ((LaunchManager)getLaunchManager()).fireUpdate(new ILaunch[] {this}, LaunchManager.TERMINATE); diff --git a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.java b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.java index 606467dee19..8942b51694a 100644 --- a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.java +++ b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.java @@ -261,5 +261,12 @@ public class ActionMessages extends NLS { public static String ExpressionPasteDialog; public static String ExpressionPasteRemember; public static String ExpressionPastePromptButton; + public static String LaunchActionToolTip_Seconds; + public static String LaunchActionToolTip_Minutes; + public static String LaunchActionToolTip_OneMinute; + public static String LaunchActionToolTip_OneHour; + public static String LaunchActionToolTip_Hours; + public static String LaunchActionToolTip_OneDay; + public static String LaunchActionToolTip_Days; } \ No newline at end of file diff --git a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.properties b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.properties index 24c158b608b..e16e1bb711c 100644 --- a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.properties +++ b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.properties @@ -245,4 +245,15 @@ ExpressionPasteSingleButton=Single Expression ExpressionPastePromptButton=Prompt ExpressionPasteTitle=Paste Multiline Expression ExpressionPasteDialog=You are pasting a multiline expression. Choose whether to paste it as a single combined expression or as separate multiple expressions. -ExpressionPasteRemember=Remember my preference next time \ No newline at end of file +ExpressionPasteRemember=Remember my preference next time + +LaunchActionToolTip_Seconds = a moment ago +LaunchActionToolTip_OneMinute = 1 min ago +LaunchActionToolTip_Minutes = {0} mins ago +LaunchActionToolTip_OneHour = 1 hour ago +LaunchActionToolTip_Hours = {0} hours ago +LaunchActionToolTip_OneDay = 1 day ago +LaunchActionToolTip_Days = {0} days ago + + + diff --git a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/actions/AbstractLaunchHistoryAction.java b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/actions/AbstractLaunchHistoryAction.java index 0a5d52c57b8..5f6495bd4cd 100644 --- a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/actions/AbstractLaunchHistoryAction.java +++ b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/actions/AbstractLaunchHistoryAction.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2026 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -50,6 +50,7 @@ import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MenuAdapter; import org.eclipse.swt.events.MenuEvent; @@ -353,6 +354,8 @@ protected void fillMenu(Menu menu) { LaunchAction action= new LaunchAction(launch, getMode()); if (checkIfLaunchActive(launch, launches)) { action.setText(action.getText() + " \u2699"); //$NON-NLS-1$ + } else { + addRecentLaunchTimeTooltip(launch, action); } addToMenu(menu, action, accelerator); accelerator++; @@ -368,6 +371,8 @@ protected void fillMenu(Menu menu) { LaunchAction action= new LaunchAction(launch, getMode()); if (checkIfLaunchActive(launch, launches)) { action.setText(action.getText() + " \u2699"); //$NON-NLS-1$ + } else { + addRecentLaunchTimeTooltip(launch, action); } addToMenu(menu, action, accelerator); accelerator++; @@ -627,4 +632,64 @@ private LaunchConfigurationManager getLaunchConfigurationManager() { protected String getLaunchGroupIdentifier() { return fLaunchGroup.getIdentifier(); } + + /** + * Adds a tooltip showing how long ago the given launch was terminated if + * there's a valid terminate timestamp attribute. + * + * @param launch launch configuration + * @param launchAction launch action to update + */ + private void addRecentLaunchTimeTooltip(ILaunchConfiguration launch, LaunchAction launchAction) { + try { + String timeStamp = launch.getAttribute(DebugPlugin.ATTR_TERMINATE_TIMESTAMP, ""); //$NON-NLS-1$ + if (!timeStamp.isEmpty()) { + long timestamp = Long.parseLong(timeStamp); + launchAction.setToolTipText(getRelativeTime(timestamp)); + } + } catch (CoreException | NumberFormatException e) { + DebugUIPlugin.log(e); + } + } + + /** + * Returns a human-readable relative time string for the given timestamp. + * + * @param timestamp timestamp in milliseconds since the epoch + * @return relative time string + */ + private String getRelativeTime(long timestamp) { + long diffMillis = Math.max(0L, System.currentTimeMillis() - timestamp); + long seconds = diffMillis / 1000; + + if (seconds < 60) { + return ActionMessages.LaunchActionToolTip_Seconds; + } + + long minutes = seconds / 60; + + if (minutes == 1) { + return ActionMessages.LaunchActionToolTip_OneMinute; + } + if (minutes < 60) { + return NLS.bind(ActionMessages.LaunchActionToolTip_Minutes, minutes); + } + + long hours = minutes / 60; + + if (hours == 1) { + return ActionMessages.LaunchActionToolTip_OneHour; + } + if (hours < 24) { + return NLS.bind(ActionMessages.LaunchActionToolTip_Hours, hours); + } + + long days = hours / 24; + + if (days == 1) { + return ActionMessages.LaunchActionToolTip_OneDay; + } + return NLS.bind(ActionMessages.LaunchActionToolTip_Days, days); + } + }