Skip to content

Commit

Permalink
Merge pull request #7904 from sdedic/lsp/reload-branding
Browse files Browse the repository at this point in the history
Support for UserQuestionException during reloads
  • Loading branch information
sdedic authored Jan 15, 2025
2 parents 4c4a8eb + 91b30af commit daa8132
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 5 deletions.
14 changes: 14 additions & 0 deletions platform/openide.text/apichanges.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,20 @@
<apidef name="text">Text API</apidef>
</apidefs>
<changes>
<change id="DocumentOpenClose.ReloadAutomaticUserAnswers">
<api name="text"/>
<summary>DocumentFilter can block a reload, UserQuestionExceptions can be branded to true or false.</summary>
<version major="6" minor="96"/>
<date day="24" month="10" year="2024"/>
<author login="sdedic"/>
<compatibility addition="yes" binary="compatible" source="compatible"
semantic="compatible" deletion="no"
modification="no"/>
<description>
The implementation handles <code>UserQuestionException</code> during reload, which means a DocumentFilter
may block document reload. Support for automatic UserQuestionException handling was added as branding API
</description>
</change>
<change id="EditorCookie.Observable.PROP_RELOADING">
<api name="text"/>
<summary>Added EditorCookie.Observable.PROP_RELOADING and associated begin/end events</summary>
Expand Down
9 changes: 9 additions & 0 deletions platform/openide.text/arch.xml
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,15 @@ in methods
<code>org/netbeans/modules/openide/text/Bundle.properties</code>
to <code>yes</code> or <code>no</code> in a branding file in your application.
</api>
<api name="org.netbeans.modules.openide.text.UserQuestionAnswer" group="branding" type="export" category="devel">
Controls handling of UserQuestionExceptions thrown during document I/O by
<a href="@TOP@/org/openide/text/CloneableEditorSupport.html">CloneableEditorSupport</a>
Specific classes can be branded to result in
"yes" (reload without asking) or "no" (cancel the re/load operation). If unspecified or set to any other value, the
user will be asked the question (this is the default behaviour).
<p/>
The support is available from version 6.96
</api>
</answer>


Expand Down
3 changes: 1 addition & 2 deletions platform/openide.text/manifest.mf
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ Manifest-Version: 1.0
OpenIDE-Module: org.openide.text
OpenIDE-Module-Localizing-Bundle: org/openide/text/Bundle.properties
AutoUpdate-Essential-Module: true
OpenIDE-Module-Specification-Version: 6.95

OpenIDE-Module-Specification-Version: 6.96
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,48 @@
*/
package org.netbeans.modules.openide.text;

import java.util.MissingResourceException;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.NbBundle;
import org.openide.util.UserQuestionException;

public final class AskEditorQuestions {
public enum QuestionResult {
/**
* The implementation should ask the user. The default, if no
* value is present in the resource bundle.
*/
ASK_USER,

/**
* Assume yes, do not ask the user, proceed immediately.
*/
YES,

/**
* Assume no, do not ask the user, proceed immediately.
*/
NO,
}
private AskEditorQuestions() {
}

public static QuestionResult askUserQuestion(UserQuestionException uqe) {
String key = "UserQuestionAnswer_" + uqe.getClass().getName();
try {
String ask = NbBundle.getMessage(AskEditorQuestions.class, key); // NOI18N
if ("yes".equals(ask)) {
return QuestionResult.YES;
}
if ("no".equals(ask)) {
return QuestionResult.NO;
}
} catch (MissingResourceException ex) {
// expected
}
return QuestionResult.ASK_USER;
}

public static boolean askReloadDocument(String localizedMessage) {
String ask = NbBundle.getMessage(AskEditorQuestions.class, "ASK_OnReload"); // NOI18N
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,9 @@ private void atomicLockedRun() {
loadDoc.remove(0, loadDoc.getLength());
}
} catch (BadLocationException ex) {
if (ex.getCause() instanceof IOException) {
throw (IOException)ex.getCause();
}
LOG.log(Level.INFO, null, ex);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.io.IOException;
import javax.swing.text.StyledDocument;
import org.netbeans.modules.openide.text.AskEditorQuestions;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.Exceptions;
Expand All @@ -45,6 +46,29 @@ class UserQuestionExceptionHandler implements Runnable {
}

void runInEDT() {
AskEditorQuestions.QuestionResult shouldAsk = AskEditorQuestions.askUserQuestion(uqe);
// attempt to handle automatic responses synchronously:
if (AskEditorQuestions.QuestionResult.NO == shouldAsk) {
openRefused();
return;
} else if (AskEditorQuestions.QuestionResult.YES == shouldAsk) {
try {
uqe.confirmed();
uqe = null;
doc = openDocument();
opened(doc);
return;
} catch (UserQuestionException ex) {
// bad luck, go for EDT access.
uqe = ex;
} catch (IOException ex1) {
handleIOException(ex1);
return;
} catch (RuntimeException ex) {
handleRuntimeException(ex);
return;
}
}
Mutex.EVENT.readAccess(this);
}

Expand All @@ -60,9 +84,18 @@ boolean handleUserQuestionException() {
handleStart();
try {
while (true) {
NotifyDescriptor nd = new NotifyDescriptor.Confirmation(uqe.getLocalizedMessage(), NotifyDescriptor.YES_NO_OPTION);
nd.setOptions(new Object[]{NotifyDescriptor.YES_OPTION, NotifyDescriptor.NO_OPTION});
Object res = DialogDisplayer.getDefault().notify(nd);
AskEditorQuestions.QuestionResult shouldAsk = AskEditorQuestions.askUserQuestion(uqe);
Object res;
if (AskEditorQuestions.QuestionResult.ASK_USER == shouldAsk) {
NotifyDescriptor nd = new NotifyDescriptor.Confirmation(uqe.getLocalizedMessage(), NotifyDescriptor.YES_NO_OPTION);
nd.setOptions(new Object[]{NotifyDescriptor.YES_OPTION, NotifyDescriptor.NO_OPTION});
res = DialogDisplayer.getDefault().notify(nd);
} else if (AskEditorQuestions.QuestionResult.YES == shouldAsk) {
res = NotifyDescriptor.OK_OPTION;
} else {
res = NotifyDescriptor.NO_OPTION;
}

if (NotifyDescriptor.OK_OPTION.equals(res)) {
try {
uqe.confirmed();
Expand Down

0 comments on commit daa8132

Please sign in to comment.