2929
3030package org .scijava .ui .swing .laf ;
3131
32- import java .awt .Component ;
33- import java .awt .EventQueue ;
34- import java .awt .Window ;
35- import java .util .ArrayList ;
36- import java .util .HashSet ;
37- import java .util .Set ;
32+ import java .util .Arrays ;
33+ import java .util .Collections ;
34+ import java .util .List ;
35+ import java .util .stream .Collectors ;
3836
39- import javax .swing .SwingUtilities ;
37+ import javax .swing .LookAndFeel ;
4038import javax .swing .UIManager ;
4139import javax .swing .UIManager .LookAndFeelInfo ;
42- import javax .swing .UnsupportedLookAndFeelException ;
4340
44- import com .formdev .flatlaf .FlatLightLaf ;
45- import com .formdev .flatlaf .FlatDarkLaf ;
46- import com .formdev .flatlaf .FlatIntelliJLaf ;
47- import com .formdev .flatlaf .FlatLaf ;
48- import com .formdev .flatlaf .FlatDarculaLaf ;
49-
50- import org .scijava .display .Display ;
51- import org .scijava .display .DisplayService ;
52- import org .scijava .log .LogService ;
5341import org .scijava .menu .MenuConstants ;
5442import org .scijava .module .MutableModuleItem ;
5543import org .scijava .options .OptionsPlugin ;
5644import org .scijava .plugin .Menu ;
5745import org .scijava .plugin .Parameter ;
5846import org .scijava .plugin .Plugin ;
59- import org .scijava .ui .UIService ;
60- import org .scijava .ui .UserInterface ;
61- import org .scijava .ui .viewer .DisplayViewer ;
62- import org .scijava .widget .UIComponent ;
6347
6448/**
6549 * Runs the Edit::Options::Look and Feel dialog.
@@ -79,9 +63,10 @@ public class OptionsLookAndFeel extends OptionsPlugin {
7963
8064 // -- Parameters --
8165
82- @ Parameter
83- private LogService log ;
66+ @ Parameter ( required = false )
67+ private SwingLookAndFeelService lafService ;
8468
69+ // NB: This setting is persisted by the SwingLookAndFeelService.
8570 @ Parameter (label = "Look & Feel" , persist = false ,
8671 initializer = "initLookAndFeel" )
8772 private String lookAndFeel ;
@@ -100,164 +85,28 @@ public void setLookAndFeel(final String lookAndFeel) {
10085
10186 @ Override
10287 public void run () {
103- // set look and feel
104- final LookAndFeelInfo [] lookAndFeels = UIManager .getInstalledLookAndFeels ();
105- for (final LookAndFeelInfo lookAndFeelInfo : lookAndFeels ) {
106- if (lookAndFeelInfo .getName ().equals (lookAndFeel )) {
107- try {
108- UIManager .setLookAndFeel (lookAndFeelInfo .getClassName ());
109- EventQueue .invokeLater (new Runnable () {
110-
111- @ Override
112- public void run () {
113- refreshSwingComponents ();
114- }
115- });
116- }
117- catch (final ClassNotFoundException e ) {
118- log .error (e );
119- }
120- catch (final InstantiationException e ) {
121- log .error (e );
122- }
123- catch (final IllegalAccessException e ) {
124- log .error (e );
125- }
126- catch (final UnsupportedLookAndFeelException e ) {
127- log .error (e );
128- }
129- break ;
130- }
131- }
132-
88+ if (lafService != null ) lafService .setLookAndFeel (lookAndFeel );
13389 super .run ();
13490 }
13591
13692 // -- Initializers --
13793
13894 protected void initLookAndFeel () {
139- final String lafClass = UIManager .getLookAndFeel ().getClass ().getName ();
140- LookAndFeelInfo [] lookAndFeels = UIManager .getInstalledLookAndFeels ();
141-
142- // Make UIManager aware of FlatLaf look and feels, as needed
143- if (!isRegistered (lookAndFeels , FlatLightLaf .NAME )) FlatLightLaf .installLafInfo ();
144- if (!isRegistered (lookAndFeels , FlatDarkLaf .NAME )) FlatDarkLaf .installLafInfo ();
145- if (!isRegistered (lookAndFeels , FlatDarculaLaf .NAME )) FlatDarculaLaf .installLafInfo ();
146- if (!isRegistered (lookAndFeels , FlatIntelliJLaf .NAME )) FlatIntelliJLaf .installLafInfo ();
147- lookAndFeels = UIManager .getInstalledLookAndFeels (); // retrieve updated list
148-
149- final ArrayList <String > lookAndFeelChoices = new ArrayList <>();
150- for (final LookAndFeelInfo lafInfo : lookAndFeels ) {
151- final String lafName = lafInfo .getName ();
152- lookAndFeelChoices .add (lafInfo .getName ());
153- if (lafClass .equals (lafInfo .getClassName ())) {
154- lookAndFeel = lafName ;
155- }
156- }
157-
158- final MutableModuleItem <String > lookAndFeelItem =
95+ final MutableModuleItem <String > lafItem = //
15996 getInfo ().getMutableInput (LOOK_AND_FEEL , String .class );
160- lookAndFeelItem .setChoices (lookAndFeelChoices );
161- }
162-
163- // -- Helper methods --
164-
165- /** Assesses whether lookAndFeels contains the laf associated with lafName*/
166- private boolean isRegistered (final LookAndFeelInfo [] lookAndFeels , final String lafName ) {
167- for (final LookAndFeelInfo lafInfo : lookAndFeels ) {
168- if (lafInfo .getName ().equals (lafName ))
169- return true ;
170- }
171- return false ;
172- }
173-
174- /** Tells all known Swing components to change to the new Look & Feel. */
175- private void refreshSwingComponents () {
176- // TODO: Change this hacky logic to call a clean UIService API
177- // for window retrieval. But does not exist as of this writing.
17897
179- final Set <Component > components = new HashSet <>();
98+ final LookAndFeel laf = UIManager .getLookAndFeel ();
99+ lookAndFeel = laf == null ? "<None>" : laf .getName ();
180100
181- // add Swing UI components from visible UIs
182- for (final UserInterface ui : uiService ().getVisibleUIs ()) {
183- findComponents (components , ui .getApplicationFrame ());
184- findComponents (components , ui .getConsolePane ());
101+ if (lafService == null ) {
102+ lafItem .setChoices (Collections .singletonList (lookAndFeel ));
185103 }
186-
187- // add Swing UI components from visible displays
188- for (final Display <?> d : displayService ().getDisplays ()) {
189- final DisplayViewer <?> viewer = uiService ().getDisplayViewer (d );
190- if (viewer == null ) continue ;
191- findComponents (components , viewer .getWindow ());
192- }
193-
194- // refresh all discovered components
195- for (final Component c : components ) {
196- SwingUtilities .updateComponentTreeUI (c );
197- if (c instanceof Window ) ((Window ) c ).pack ();
198- }
199- }
200-
201- /**
202- * Extracts Swing components from the given object, adding them to
203- * the specified set.
204- */
205- private void findComponents (final Set <Component > set , final Object o ) {
206- if (o == null ) return ;
207- if (o instanceof UIComponent ) {
208- final UIComponent <?> c = (UIComponent <?>) o ;
209- findComponents (set , c .getComponent ());
210- }
211- if (o instanceof Window ) set .add ((Window ) o );
212- else if (o instanceof Component ) {
213- final Component c = (Component ) o ;
214- final Window w = SwingUtilities .getWindowAncestor (c );
215- set .add (w == null ? c : w );
216- }
217- }
218-
219- private UIService uiService () {
220- return getContext ().service (UIService .class );
221- }
222-
223- private DisplayService displayService () {
224- return getContext ().service (DisplayService .class );
225- }
226-
227- /**
228- * Sets the application look and feel.
229- * <p>
230- * Useful for setting up the look and feel early on in application startup
231- * routine (e.g., through a macro or script)
232- * </p>
233- *
234- * @param lookAndFeel the look and feel. Supported values include "FlatLaf
235- * Light", "FlatLaf Dark", "FlatLaf Darcula", "FlatLaf
236- * IntelliJ", and JVM defaults
237- * ("javax.swing.plaf.metal.MetalLookAndFeel", etc.)
238- */
239- public static void setupLookAndFeel (final String lookAndFeel ) {
240- switch (lookAndFeel ) { // FIXME: should FlatLaf.updateUI() calls be replaced with updateUILater()?
241- case FlatLightLaf .NAME :
242- if (FlatLightLaf .setup ()) FlatLaf .updateUI ();
243- return ;
244- case FlatDarkLaf .NAME :
245- if (FlatDarkLaf .setup ()) FlatLaf .updateUI ();
246- return ;
247- case FlatDarculaLaf .NAME :
248- if (FlatDarculaLaf .setup ()) FlatLaf .updateUI ();
249- return ;
250- case FlatIntelliJLaf .NAME :
251- if (FlatIntelliJLaf .setup ()) FlatLaf .updateUI ();
252- return ;
253- default :
254- try {
255- UIManager .setLookAndFeel (lookAndFeel );
256- FlatLaf .updateUI ();
257- } catch (final Exception ex ) {
258- ex .printStackTrace ();
259- FlatLaf .revalidateAndRepaintAllFramesAndDialogs (); // Recover from possible ill-states
260- }
104+ else {
105+ final LookAndFeelInfo [] infos = lafService .getLookAndFeels ();
106+ final List <String > choices = Arrays .stream (infos )//
107+ .map (info -> info .getName ())//
108+ .collect (Collectors .toList ());
109+ lafItem .setChoices (choices );
261110 }
262111 }
263112}
0 commit comments