Skip to content

Commit 640782f

Browse files
committed
Make the HeadlessUI a real boy
The HeadlessUI is now a SciJava UserInterface plugin, just like any other user interface. This is useful because while we want it to always be chosen when headless mode is active, it should also be used in non-headless mode when nothing else is available. This will help prevent NPEs etc. in UIService method calls. Consequently, this commit adds some defensive checks to DefaultUIService. These are needed now with the new HeadlessUI, because that UI returns null for methods like dialogPrompt -- something that no other UIs did previously. In other words: we relaxed the postconditions of some UserInterface methods to allow for null returns, and therefore the DefaultUIService needs to behave accordingly, handling those nulls.
1 parent aa8be0f commit 640782f

File tree

2 files changed

+13
-99
lines changed

2 files changed

+13
-99
lines changed

src/main/java/org/scijava/ui/DefaultUIService.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ public boolean isHeadless() {
189189

190190
@Override
191191
public UserInterface getDefaultUI() {
192-
if (isHeadless()) return HeadlessUI.getInstance();
192+
if (isHeadless()) return uiMap().get(HeadlessUI.NAME);
193193
if (defaultUI != null) return defaultUI;
194194
return uiList().isEmpty() ? null : uiList().get(0);
195195
}
@@ -302,32 +302,29 @@ public DialogPrompt.Result showDialog(final String message,
302302
if (ui == null) return null;
303303
final DialogPrompt dialogPrompt =
304304
ui.dialogPrompt(message, title, messageType, optionType);
305-
return dialogPrompt.prompt();
305+
return dialogPrompt == null ? null : dialogPrompt.prompt();
306306
}
307307

308308
@Override
309309
public File chooseFile(final File file, final String style) {
310310
final UserInterface ui = getDefaultUI();
311-
if (ui == null) return null;
312-
return ui.chooseFile(file, style);
311+
return ui == null ? null : ui.chooseFile(file, style);
313312
}
314313

315314
@Override
316315
public File
317316
chooseFile(final String title, final File file, final String style)
318317
{
319318
final UserInterface ui = getDefaultUI();
320-
if (ui == null) return null;
321-
return ui.chooseFile(title, file, style);
319+
return ui == null ? null : ui.chooseFile(title, file, style);
322320
}
323321

324322
@Override
325323
public void showContextMenu(final String menuRoot, final Display<?> display,
326324
final int x, final int y)
327325
{
328326
final UserInterface ui = getDefaultUI();
329-
if (ui == null) return;
330-
ui.showContextMenu(menuRoot, display, x, y);
327+
if (ui != null) ui.showContextMenu(menuRoot, display, x, y);
331328
}
332329

333330
@Override

src/main/java/org/scijava/ui/headlessUI/HeadlessUI.java

Lines changed: 8 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -31,42 +31,28 @@
3131

3232
package org.scijava.ui.headlessUI;
3333

34-
import static org.scijava.Priority.LAST_PRIORITY;
35-
3634
import java.io.File;
3735

38-
import org.scijava.Context;
36+
import org.scijava.Priority;
3937
import org.scijava.display.Display;
40-
import org.scijava.plugin.PluginInfo;
41-
import org.scijava.ui.ApplicationFrame;
42-
import org.scijava.ui.Desktop;
38+
import org.scijava.plugin.AbstractRichPlugin;
39+
import org.scijava.plugin.Plugin;
4340
import org.scijava.ui.DialogPrompt;
44-
import org.scijava.ui.StatusBar;
45-
import org.scijava.ui.SystemClipboard;
46-
import org.scijava.ui.ToolBar;
4741
import org.scijava.ui.UserInterface;
48-
import org.scijava.ui.console.ConsolePane;
4942
import org.scijava.ui.viewer.DisplayWindow;
5043

5144
/**
5245
* A "null object" UI implementation that can be returned when a UIService is
5346
* running headless
5447
*
5548
* @author Richard Domander (Royal Veterinary College, London)
49+
* @author Curtis Rueden
5650
*/
57-
public class HeadlessUI implements UserInterface {
58-
59-
private static HeadlessUI instance;
51+
@Plugin(type = UserInterface.class, name = HeadlessUI.NAME,
52+
priority = Priority.VERY_LOW_PRIORITY)
53+
public class HeadlessUI extends AbstractRichPlugin implements UserInterface {
6054

61-
private HeadlessUI() {}
62-
63-
public static HeadlessUI getInstance() {
64-
if (instance == null) {
65-
instance = new HeadlessUI();
66-
}
67-
68-
return instance;
69-
}
55+
public static final String NAME = "headless";
7056

7157
@Override
7258
public void show() {}
@@ -76,45 +62,12 @@ public boolean isVisible() {
7662
return false;
7763
}
7864

79-
@Override
80-
public void show(final Object o) {}
81-
8265
@Override
8366
public void show(final String name, final Object o) {}
8467

8568
@Override
8669
public void show(final Display<?> display) {}
8770

88-
@Override
89-
public Desktop getDesktop() {
90-
return null;
91-
}
92-
93-
@Override
94-
public ApplicationFrame getApplicationFrame() {
95-
return null;
96-
}
97-
98-
@Override
99-
public ToolBar getToolBar() {
100-
return null;
101-
}
102-
103-
@Override
104-
public StatusBar getStatusBar() {
105-
return null;
106-
}
107-
108-
@Override
109-
public ConsolePane<?> getConsolePane() {
110-
return null;
111-
}
112-
113-
@Override
114-
public SystemClipboard getSystemClipboard() {
115-
return null;
116-
}
117-
11871
@Override
11972
public DisplayWindow createDisplayWindow(final Display<?> display) {
12073
return null;
@@ -128,11 +81,6 @@ public DialogPrompt dialogPrompt(final String message, final String title,
12881
return null;
12982
}
13083

131-
@Override
132-
public File chooseFile(final File file, final String style) {
133-
return null;
134-
}
135-
13684
@Override
13785
public File chooseFile(final String title, final File file,
13886
final String style)
@@ -156,37 +104,6 @@ public boolean requiresEDT() {
156104
return false;
157105
}
158106

159-
/** Returns null since this is a contextless null object */
160-
@Override
161-
public Context context() {
162-
return null;
163-
}
164-
165-
/** Returns null since this is a contextless null object */
166-
@Override
167-
public Context getContext() {
168-
return null;
169-
}
170-
171-
@Override
172-
public void setContext(final Context context) {}
173-
174-
@Override
175-
public PluginInfo<?> getInfo() {
176-
return null;
177-
}
178-
179-
@Override
180-
public void setInfo(final PluginInfo<?> info) {}
181-
182107
@Override
183108
public void dispose() {}
184-
185-
@Override
186-
public double getPriority() {
187-
return LAST_PRIORITY;
188-
}
189-
190-
@Override
191-
public void setPriority(final double priority) {}
192109
}

0 commit comments

Comments
 (0)