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..69b85321233 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,6 +25,7 @@ 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; @@ -475,7 +476,18 @@ 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 { + ILaunchConfigurationWorkingCopy launchCopy = getLaunchConfiguration().getWorkingCopy(); + launchCopy.setAttribute(DebugPlugin.ATTR_TERMINATE_TIMESTAMP, timeStamp); + launchCopy.doSave(); + } catch (CoreException 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..813f8c096f6 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,7 +371,10 @@ 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); } + addRecentLaunchTimeTooltip(launch, action); addToMenu(menu, action, accelerator); accelerator++; } @@ -627,4 +633,65 @@ 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 mytime = Long.parseLong(timeStamp); + String g = getRelativeTime(mytime); + launchAction.setToolTipText(g); + } + } catch (CoreException 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 = 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); + } + }