Skip to content

Commit e978aed

Browse files
authored
Show notification after running macro (#3269)
This PR adds a notification that will show up after a macro is done. Depending on the settings it will always / when the KeY window is not focused / never show up. |OS (Desktop Environment) | | | - | - | | Windows | ![screenshot-notification-windows](https://github.com/KeYProject/key/assets/94171076/9fe5febc-5d32-4808-bb93-b3573f760fd4) | | MacOS | ![screenshot-notification-macos](https://github.com/KeYProject/key/assets/8257939/38707e48-2a84-4217-bf19-3079aac5e21d") (claims it comes from the app "Script Editor") | | Linux (KDE) | ![image](https://github.com/KeYProject/key/assets/12560461/6071fada-6bbb-4485-8b49-83311f5b73e2) | | Linux (Gnome) | ![screenshot-notification-gnome](https://github.com/KeYProject/key/assets/94171076/8ccc3bda-93d6-40b3-a448-0b841aa989b4) | | Linux (XFCE) | ![screenshot-notification-xfce](https://github.com/KeYProject/key/assets/94171076/2ffa6eff-9390-42ec-8299-4fa80be73dbc) | | Linux (Cinnamon) | ![screenshot-notification-cinnamon](https://github.com/KeYProject/key/assets/94171076/edb96e32-b8f9-4151-ac92-179d112711bd) | The view settings panel has also been restructured. ![Screenshot_20230922_090859](https://github.com/KeYProject/key/assets/12560461/865c2a72-9ac0-48a6-8f68-a58a7025beb4)
2 parents ae6efac + b7c549d commit e978aed

File tree

11 files changed

+242
-55
lines changed

11 files changed

+242
-55
lines changed

key.core/src/main/java/de/uka/ilkd/key/macros/ProofMacroFinishedInfo.java

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,36 +27,33 @@
2727
public class ProofMacroFinishedInfo extends DefaultTaskFinishedInfo {
2828

2929
private final Map<String, Object> proofMacroSpecificData = new HashMap<>();
30-
private final boolean cancelled;
3130

3231

3332
ProofMacroFinishedInfo(ProofMacro macro, ImmutableList<Goal> goals, Proof proof, long time,
34-
int appliedRules, int closedGoals, boolean cancelled) {
33+
int appliedRules, int closedGoals) {
3534
super(macro, goals, proof, time, appliedRules, closedGoals);
36-
this.cancelled = cancelled;
3735
}
3836

3937
ProofMacroFinishedInfo(ProofMacro macro, Goal goal, Proof proof, long time, int appliedRules,
4038
int closedGoals) {
4139
this(macro, ImmutableSLList.<Goal>nil().prepend(goal), proof, time, appliedRules,
42-
closedGoals, false);
40+
closedGoals);
4341
}
4442

4543
ProofMacroFinishedInfo(ProofMacro macro, ImmutableList<Goal> goals, Proof proof,
4644
Statistics statistics) {
4745
this(macro, goals, proof, statistics == null ? 0 : statistics.timeInMillis,
48-
statistics == null ? 0 : statistics.totalRuleApps,
49-
proof == null ? 0 : (proof.countBranches() - proof.openGoals().size()), false);
46+
statistics == null ? 0 : statistics.nodes - statistics.branches,
47+
proof == null ? 0 : (proof.countBranches() - proof.openGoals().size()));
5048
}
5149

5250
ProofMacroFinishedInfo(ProofMacro macro, Goal goal, Proof proof, Statistics statistics) {
5351
this(macro, goal, proof, statistics == null ? 0 : statistics.timeInMillis,
54-
statistics == null ? 0 : statistics.totalRuleApps,
52+
statistics == null ? 0 : statistics.nodes - statistics.branches,
5553
proof == null ? 0 : (proof.countBranches() - proof.openGoals().size()));
5654
}
5755

58-
ProofMacroFinishedInfo(ProofMacro macro, ImmutableList<Goal> goals, Proof proof,
59-
boolean cancelled) {
56+
ProofMacroFinishedInfo(ProofMacro macro, ImmutableList<Goal> goals, Proof proof) {
6057
this(macro, goals, proof, proof == null ? null : proof.getStatistics());
6158
}
6259

@@ -69,7 +66,7 @@ public ProofMacroFinishedInfo(ProofMacro macro, Goal goal) {
6966
}
7067

7168
public ProofMacroFinishedInfo(ProofMacro macro, ImmutableList<Goal> goals) {
72-
this(macro, goals, goals.isEmpty() ? null : goals.head().proof(), false);
69+
this(macro, goals, goals.isEmpty() ? null : goals.head().proof());
7370
}
7471

7572
public ProofMacroFinishedInfo(ProofMacro macro, ImmutableList<Goal> goals,
@@ -79,36 +76,31 @@ public ProofMacroFinishedInfo(ProofMacro macro, ImmutableList<Goal> goals,
7976
}
8077

8178
public ProofMacroFinishedInfo(ProofMacro macro, Proof proof) {
82-
this(macro, proof.openEnabledGoals(), proof, false);
83-
}
84-
85-
public ProofMacroFinishedInfo(ProofMacro macro, Proof proof, boolean cancelled) {
86-
this(macro, proof.openEnabledGoals(), proof, cancelled);
79+
this(macro, proof.openEnabledGoals(), proof);
8780
}
8881

8982
public ProofMacroFinishedInfo(ProofMacro macro, ProofMacroFinishedInfo info) {
90-
this(macro, info.getGoals(), info.getProof(), info.cancelled);
83+
this(macro, info.getGoals(), info.getProof());
9184
}
9285

9386
ProofMacroFinishedInfo(ProofMacro macro, ProofMacroFinishedInfo info,
9487
ImmutableList<Goal> goals) {
9588
this(macro, goals, info.getProof(), info.getTime(), info.getAppliedRules(),
96-
info.getClosedGoals(), info.cancelled);
89+
info.getClosedGoals());
9790
}
9891

9992
ProofMacroFinishedInfo(ProofMacroFinishedInfo info, ApplyStrategyInfo stratInfo) {
10093
this(info.getMacro(), info.getGoals(), info.getProof(),
10194
info.getTime() + stratInfo.getTime(),
10295
info.getAppliedRules() + stratInfo.getAppliedRuleApps(),
103-
info.getClosedGoals() + stratInfo.getClosedGoals(), info.cancelled);
96+
info.getClosedGoals() + stratInfo.getClosedGoals());
10497
}
10598

10699
ProofMacroFinishedInfo(ProofMacroFinishedInfo info, ApplyStrategyInfo stratInfo,
107100
ImmutableList<Goal> goals) {
108101
this(info.getMacro(), goals, stratInfo.getProof(), info.getTime() + stratInfo.getTime(),
109102
info.getAppliedRules() + stratInfo.getAppliedRuleApps(),
110-
goals.size() <= info.getGoals().size() ? (info.getGoals().size() - goals.size()) : 0,
111-
false);
103+
goals.size() <= info.getGoals().size() ? (info.getGoals().size() - goals.size()) : 0);
112104
}
113105

114106
public void addInfo(String key, Object value) {
@@ -123,10 +115,6 @@ public ProofMacro getMacro() {
123115
return (ProofMacro) getSource();
124116
}
125117

126-
public boolean isCancelled() {
127-
return cancelled;
128-
}
129-
130118
@SuppressWarnings("unchecked")
131119
public ImmutableList<Goal> getGoals() {
132120
final Object result = getResult();
@@ -138,6 +126,6 @@ public ImmutableList<Goal> getGoals() {
138126
}
139127

140128
public static ProofMacroFinishedInfo getDefaultInfo(ProofMacro macro, Proof proof) {
141-
return new ProofMacroFinishedInfo(macro, ImmutableSLList.nil(), proof, false);
129+
return new ProofMacroFinishedInfo(macro, ImmutableSLList.nil(), proof);
142130
}
143131
}

key.core/src/main/java/de/uka/ilkd/key/macros/SequentialProofMacro.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public ProofMacroFinishedInfo applyTo(UserInterfaceControl uic, Proof proof,
8484
}
8585
final ImmutableList<Goal> gs = initNodes.isEmpty() ? proof.openEnabledGoals()
8686
: proof.getSubtreeEnabledGoals(initNodes.get(0));
87-
ProofMacroFinishedInfo info = new ProofMacroFinishedInfo(this, gs, proof, false);
87+
ProofMacroFinishedInfo info = new ProofMacroFinishedInfo(this, gs, proof);
8888
for (final ProofMacro macro : getProofMacros()) {
8989
// reverse to original nodes
9090
for (Node initNode : initNodes) {

key.core/src/main/java/de/uka/ilkd/key/macros/TryCloseMacro.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ public ProofMacroFinishedInfo applyTo(UserInterfaceControl uic, Proof proof,
162162
//
163163
// inform the listener
164164
ProofMacroFinishedInfo info =
165-
new ProofMacroFinishedInfo(this, goals, proof, 0, 0, 0, false);
165+
new ProofMacroFinishedInfo(this, goals, proof, 0, 0, 0);
166166

167167
//
168168
// start actual autoprove

key.core/src/main/java/de/uka/ilkd/key/prover/impl/DefaultTaskFinishedInfo.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
public class DefaultTaskFinishedInfo implements TaskFinishedInfo {
1010

11+
/**
12+
* See {@link TaskFinishedInfo#getSource()} for possible values.
13+
*/
1114
private final Object source;
1215

1316
// TODO
@@ -27,7 +30,7 @@ public class DefaultTaskFinishedInfo implements TaskFinishedInfo {
2730
* @param result task result
2831
* @param proof the proof the task worked on
2932
* @param time time the task took (milliseconds)
30-
* @param appliedRules how many rules were applied
33+
* @param appliedRules how many nodes were created
3134
* @param closedGoals how many goals were closed
3235
*/
3336
public DefaultTaskFinishedInfo(Object source, Object result, Proof proof, long time,

key.core/src/main/java/de/uka/ilkd/key/settings/ViewSettings.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* number is exceeded no SchemaVariables get instantiated in the displayed tooltip. 3) whether
1414
* intermediate proofsteps should be hidden in the proof tree view
1515
*
16+
* @see de.uka.ilkd.key.gui.settings.StandardUISettings
1617
* @author unknown
1718
* @author weigl
1819
*/
@@ -99,11 +100,6 @@ public class ViewSettings extends AbstractPropertiesSettings {
99100
*/
100101
private static final String CONFIRM_EXIT = "[View]ConfirmExit";
101102

102-
/**
103-
* Heatmap options property
104-
*/
105-
private static final String HEATMAP_OPTIONS = "[View]HeatmapOptions";
106-
107103
private static final String FONT_SIZE_FACTOR = "[View]uiFontSizeFactor";
108104

109105
private static final String SEQUENT_VIEW_TOOLTIP = "[View]SequentViewTooltips";
@@ -145,9 +141,15 @@ public class ViewSettings extends AbstractPropertiesSettings {
145141
*/
146142
private static final String USER_FOLDER_BOOKMARKS = "[View]folderBookmarks";
147143

144+
private static final String NOTIFICATION_AFTER_MACRO = "[View]notificationAfterMacro";
145+
148146
private static final String LOOK_AND_FEEL_DEFAULT =
149147
UIManager.getCrossPlatformLookAndFeelClassName();
150148

149+
public static final String NOTIFICATION_ALWAYS = "Always";
150+
public static final String NOTIFICATION_UNFOCUSED = "When not focused";
151+
public static final String NOTIFICATION_NEVER = "Never";
152+
151153
/**
152154
* Show Taclet uninstantiated in tooltip -- for learning
153155
*/
@@ -215,6 +217,9 @@ public class ViewSettings extends AbstractPropertiesSettings {
215217
private final PropertyEntry<List<String>> folderBookmarks =
216218
createStringListProperty(USER_FOLDER_BOOKMARKS, System.getProperty("user.home"));
217219

220+
private final PropertyEntry<String> notificationAfterMacro =
221+
createStringProperty(NOTIFICATION_AFTER_MACRO, NOTIFICATION_UNFOCUSED);
222+
218223
/**
219224
* Clutter rules are rules with less priority in the taclet menu
220225
*/
@@ -555,4 +560,17 @@ public List<String> getFolderBookmarks() {
555560
public void setFolderBookmarks(List<String> bm) {
556561
folderBookmarks.set(bm);
557562
}
563+
564+
public String notificationAfterMacro() {
565+
return notificationAfterMacro.get();
566+
}
567+
568+
public void setNotificationAfterMacro(String value) {
569+
if (value.equals(NOTIFICATION_ALWAYS) || value.equals(NOTIFICATION_UNFOCUSED)
570+
|| value.equals(NOTIFICATION_NEVER)) {
571+
notificationAfterMacro.set(value);
572+
} else {
573+
throw new IllegalStateException("tried to set wrong value for notification setting");
574+
}
575+
}
558576
}

key.ui/src/main/java/de/uka/ilkd/key/gui/MainWindow.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,7 @@ public void scrollTo(int y) {
12371237
}
12381238

12391239
void displayResults(String message) {
1240+
LOGGER.debug("displaying results: {}", message);
12401241
setStatusLine(message);
12411242
}
12421243

key.ui/src/main/java/de/uka/ilkd/key/gui/ProofMacroWorker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ protected ProofMacroFinishedInfo doInBackground() {
100100
}
101101
} catch (final InterruptedException exception) {
102102
LOGGER.debug("Proof macro has been interrupted:", exception);
103-
info = new ProofMacroFinishedInfo(macro, selectedProof, true);
103+
info = new ProofMacroFinishedInfo(macro, selectedProof);
104104
this.exception = exception;
105105
} catch (final Exception exception) {
106106
// This should actually never happen.

key.ui/src/main/java/de/uka/ilkd/key/gui/WindowUserInterfaceControl.java

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
import de.uka.ilkd.key.prover.TaskStartedInfo;
3939
import de.uka.ilkd.key.prover.impl.ApplyStrategyInfo;
4040
import de.uka.ilkd.key.rule.IBuiltInRuleApp;
41+
import de.uka.ilkd.key.settings.ProofIndependentSettings;
42+
import de.uka.ilkd.key.settings.ViewSettings;
4143
import de.uka.ilkd.key.speclang.PositionedString;
4244
import de.uka.ilkd.key.strategy.StrategyProperties;
4345
import de.uka.ilkd.key.ui.AbstractMediatorUserInterfaceControl;
@@ -48,6 +50,7 @@
4850
import de.uka.ilkd.key.util.ThreadUtilities;
4951

5052
import org.key_project.util.collection.ImmutableSet;
53+
import org.key_project.util.java.SwingUtil;
5154

5255
import org.slf4j.Logger;
5356
import org.slf4j.LoggerFactory;
@@ -192,9 +195,12 @@ private void taskFinishedInternal(TaskFinishedInfo info) {
192195
"Couldn't close Goal Nr. " + g.node().serialNr() + " automatically");
193196
dialog.show();
194197
}
198+
if (!isAtLeastOneMacroRunning()) {
199+
showNotification("Automated proof search", info.toString());
200+
}
195201
}
196202
mainWindow.displayResults(info.toString());
197-
} else if (info != null && info.getSource() instanceof ProofMacro) {
203+
} else if (info != null && info.getSource() instanceof ProofMacro macro) {
198204
if (!isAtLeastOneMacroRunning()) {
199205
mainWindow.hideStatusProgress();
200206
assert info instanceof ProofMacroFinishedInfo;
@@ -210,9 +216,12 @@ private void taskFinishedInternal(TaskFinishedInfo info) {
210216
"Couldn't close Goal Nr. " + g.node().serialNr() + " automatically");
211217
dialog.show();
212218
}
219+
if (!isAtLeastOneMacroRunning()) {
220+
showNotification(macro.getName(), info.toString());
221+
}
213222
}
214223
}
215-
} else if (info != null && info.getSource() instanceof ProblemLoader) {
224+
} else if (info != null && info.getSource() instanceof ProblemLoader problemLoader) {
216225
resetStatus(this);
217226
Throwable result = (Throwable) info.getResult();
218227
if (info.getResult() != null) {
@@ -223,7 +232,6 @@ private void taskFinishedInternal(TaskFinishedInfo info) {
223232
} else {
224233
KeYMediator mediator = mainWindow.getMediator();
225234
mediator.getNotationInfo().refresh(mediator.getServices());
226-
ProblemLoader problemLoader = (ProblemLoader) info.getSource();
227235
if (problemLoader.hasProofScript()) {
228236
Pair<String, Location> scriptAndLoc;
229237
try {
@@ -249,6 +257,24 @@ private void taskFinishedInternal(TaskFinishedInfo info) {
249257
Runtime.getRuntime().gc();
250258
}
251259

260+
/**
261+
* Show a notification, if enabled by the settings.
262+
*
263+
* @param title header
264+
* @param text body
265+
*/
266+
private void showNotification(String title, String text) {
267+
var mode =
268+
ProofIndependentSettings.DEFAULT_INSTANCE.getViewSettings().notificationAfterMacro();
269+
if (mode.equals(ViewSettings.NOTIFICATION_ALWAYS)) {
270+
SwingUtil.showNotification(title, text);
271+
} else if (mode.equals(ViewSettings.NOTIFICATION_UNFOCUSED)) {
272+
if (!MainWindow.getInstance().isActive()) {
273+
SwingUtil.showNotification(title, text);
274+
}
275+
}
276+
}
277+
252278
protected boolean inStopAtFirstUncloseableGoalMode(Proof proof) {
253279
return proof.getSettings().getStrategySettings().getActiveStrategyProperties()
254280
.getProperty(StrategyProperties.STOPMODE_OPTIONS_KEY)

0 commit comments

Comments
 (0)