3030
3131package org .scijava .ui .swing .options ;
3232
33+ import java .awt .Component ;
3334import java .awt .EventQueue ;
35+ import java .awt .Window ;
3436import java .util .ArrayList ;
37+ import java .util .HashSet ;
38+ import java .util .Set ;
3539
3640import javax .swing .SwingUtilities ;
3741import javax .swing .UIManager ;
3842import javax .swing .UIManager .LookAndFeelInfo ;
3943import javax .swing .UnsupportedLookAndFeelException ;
4044
45+ import org .scijava .display .Display ;
46+ import org .scijava .display .DisplayService ;
4147import org .scijava .log .LogService ;
4248import org .scijava .menu .MenuConstants ;
4349import org .scijava .module .MutableModuleItem ;
4450import org .scijava .options .OptionsPlugin ;
4551import org .scijava .plugin .Menu ;
4652import org .scijava .plugin .Parameter ;
4753import org .scijava .plugin .Plugin ;
54+ import org .scijava .ui .UIService ;
4855import org .scijava .ui .UserInterface ;
49- import org .scijava .ui .swing .SwingApplicationFrame ;
56+ import org .scijava .ui .viewer .DisplayViewer ;
57+ import org .scijava .widget .UIComponent ;
5058
5159/**
5260 * Runs the Edit::Options::Look and Feel dialog.
@@ -67,7 +75,10 @@ public class OptionsLookAndFeel extends OptionsPlugin {
6775 // -- Parameters --
6876
6977 @ Parameter
70- private UserInterface ui ;
78+ private UIService uiService ;
79+
80+ @ Parameter
81+ private DisplayService displayService ;
7182
7283 @ Parameter
7384 private LogService log ;
@@ -78,18 +89,10 @@ public class OptionsLookAndFeel extends OptionsPlugin {
7889
7990 // -- OptionsLookAndFeel methods --
8091
81- public UserInterface getUI () {
82- return ui ;
83- }
84-
8592 public String getLookAndFeel () {
8693 return lookAndFeel ;
8794 }
8895
89- public void setUI (final UserInterface ui ) {
90- this .ui = ui ;
91- }
92-
9396 public void setLookAndFeel (final String lookAndFeel ) {
9497 this .lookAndFeel = lookAndFeel ;
9598 }
@@ -108,11 +111,7 @@ public void run() {
108111
109112 @ Override
110113 public void run () {
111- // FIXME: Get all windows from UIService rather than just app.
112- final SwingApplicationFrame swingAppFrame =
113- (SwingApplicationFrame ) ui .getApplicationFrame ();
114- SwingUtilities .updateComponentTreeUI (swingAppFrame );
115- swingAppFrame .pack ();
114+ refreshSwingComponents ();
116115 }
117116 });
118117 }
@@ -141,7 +140,7 @@ protected void initLookAndFeel() {
141140 final String lafClass = UIManager .getLookAndFeel ().getClass ().getName ();
142141
143142 final LookAndFeelInfo [] lookAndFeels = UIManager .getInstalledLookAndFeels ();
144- final ArrayList <String > lookAndFeelChoices = new ArrayList <String >();
143+ final ArrayList <String > lookAndFeelChoices = new ArrayList <>();
145144 for (final LookAndFeelInfo lafInfo : lookAndFeels ) {
146145 final String lafName = lafInfo .getName ();
147146 lookAndFeelChoices .add (lafInfo .getName ());
@@ -155,4 +154,62 @@ protected void initLookAndFeel() {
155154 lookAndFeelItem .setChoices (lookAndFeelChoices );
156155 }
157156
157+ // -- Helper methods --
158+
159+ /** Tells all known Swing components to change to the new Look & Feel. */
160+ private void refreshSwingComponents () {
161+ // TODO: Change this hacky logic to call a clean UIService API
162+ // for window retrieval. But does not exist as of this writing.
163+
164+ final Set <Component > components = new HashSet <>();
165+
166+ // add Swing UI components from visible UIs
167+ for (final UserInterface ui : uiService .getVisibleUIs ()) {
168+ findComponents (components , ui .getApplicationFrame ());
169+ findComponents (components , ui .getConsolePane ());
170+ }
171+
172+ // add Swing UI components from visible displays
173+ for (final Display <?> d : displayService .getDisplays ()) {
174+ final DisplayViewer <?> viewer = uiService .getDisplayViewer (d );
175+ if (viewer == null ) continue ;
176+ findComponents (components , viewer .getWindow ());
177+ }
178+
179+ // refresh all discovered components
180+ for (final Component c : components ) {
181+ SwingUtilities .updateComponentTreeUI (c );
182+ if (c instanceof Window ) ((Window ) c ).pack ();
183+ }
184+ }
185+
186+ /**
187+ * Extracts Swing components from the given object, adding them to
188+ * the specified set.
189+ */
190+ private void findComponents (final Set <Component > set , final Object o ) {
191+ if (o == null ) return ;
192+ if (o instanceof UIComponent ) {
193+ final UIComponent <?> c = (UIComponent <?>) o ;
194+ findComponents (set , c .getComponent ());
195+ }
196+ if (o instanceof Window ) set .add ((Window ) o );
197+ else if (o instanceof Component ) {
198+ final Component c = (Component ) o ;
199+ final Window w = SwingUtilities .getWindowAncestor (c );
200+ set .add (w == null ? c : w );
201+ }
202+ }
203+
204+ // -- Deprecated methods --
205+
206+ @ Deprecated
207+ public UserInterface getUI () {
208+ return uiService .getDefaultUI ();
209+ }
210+
211+ @ Deprecated
212+ public void setUI (@ SuppressWarnings ("unused" ) final UserInterface ui ) {
213+ throw new UnsupportedOperationException ();
214+ }
158215}
0 commit comments