1 package com.melloware.jukes.gui.view.preferences;
2
3 import java.awt.Component;
4 import java.beans.PropertyChangeEvent;
5 import java.beans.PropertyChangeListener;
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.Comparator;
9 import java.util.logging.Logger;
10 import java.util.prefs.Preferences;
11
12 import javax.swing.DefaultListCellRenderer;
13 import javax.swing.JList;
14 import javax.swing.JPanel;
15 import javax.swing.JScrollPane;
16 import javax.swing.ListModel;
17 import javax.swing.ListSelectionModel;
18 import javax.swing.LookAndFeel;
19 import javax.swing.UIManager;
20 import javax.swing.UnsupportedLookAndFeelException;
21 import javax.swing.event.ListSelectionEvent;
22 import javax.swing.event.ListSelectionListener;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26
27 import com.jgoodies.binding.list.ArrayListModel;
28 import com.jgoodies.binding.value.ValueModel;
29 import com.jgoodies.forms.builder.PanelBuilder;
30 import com.jgoodies.forms.layout.CellConstraints;
31 import com.jgoodies.forms.layout.FormLayout;
32 import com.jgoodies.looks.plastic.PlasticLookAndFeel;
33 import com.jgoodies.looks.plastic.PlasticTheme;
34 import com.jgoodies.uif.application.Application;
35 import com.jgoodies.uif.laf.ExtUIManager;
36 import com.jgoodies.uif.laf.LookConfiguration;
37 import com.jgoodies.uif.laf.LookConfigurations;
38 import com.jgoodies.uif.lazy.Preparable;
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public final class LookAndFeelPanel extends JPanel {
53
54
55
56 private static final Log LOG = LogFactory.getLog(LookAndFeelPanel.class);
57
58 private static final ListModel PLASTIC_THEMES_MODEL =
59 new ArrayListModel(PlasticLookAndFeel.getInstalledThemes());
60
61 private static final ListModel NO_THEMES_MODEL =
62 new ArrayListModel();
63
64
65 private static ListModel supportedLookAndFeelInstances;
66
67 private final LookConfigurations configurations;
68
69 private JList lafList;
70 private JList themesList;
71 private transient ListSelectionListener themeListener;
72 private LookAndFeelPreviewPanel previewPanel;
73 private boolean isLookChanged = false;
74
75
76
77
78
79
80
81
82
83
84
85 public LookAndFeelPanel(ValueModel triggerChannel) {
86 this.configurations = getClonedLookConfigurations();
87 initComponents();
88 build();
89 registerListeners();
90 triggerChannel.addValueChangeListener(new CommitHandler());
91 }
92
93 private static LookConfigurations getClonedLookConfigurations() {
94 Object storedValue =
95 ExtUIManager.getLookConfigurations();
96 LookConfigurations storedConfigs = (LookConfigurations) storedValue;
97 return (LookConfigurations) storedConfigs.clone();
98 }
99
100
101
102
103
104
105
106 public void ensureSelectionsAreVisible() {
107 lafList.ensureIndexIsVisible(lafList.getSelectedIndex());
108 themesList.ensureIndexIsVisible(themesList.getSelectedIndex());
109 }
110
111
112
113 private void initComponents() {
114 lafList = new JList();
115 lafList.setModel(getSupportedLookAndFeelInstances());
116 lafList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
117 lafList.setCellRenderer(new LooksListCellRenderer());
118 selectLook(configurations.getDefaultConfiguration().getLookAndFeel());
119
120 themesList = new JList();
121 updateThemesModel();
122 selectTheme(getSelectedConfiguration().getTheme());
123 themesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
124 themesList.setCellRenderer(new ThemesListCellRenderer());
125
126 previewPanel = new LookAndFeelPreviewPanel();
127 }
128
129
130
131
132 private void build() {
133 FormLayout fl = new FormLayout(
134 "fill:default:grow, 4dlu, fill:default:grow",
135 "pref, 1dlu, fill:100dlu, 9dlu, pref, 1dlu, pref");
136 fl.setColumnGroups(new int[][]{{1, 3}});
137 fl.setRowGroups(new int[][]{{3, 7}});
138
139 PanelBuilder builder = new PanelBuilder(fl, this);
140 builder.setDefaultDialogBorder();
141 CellConstraints cc = new CellConstraints();
142
143 builder.addTitle("Look && Feel", cc.xy (1, 1));
144 builder.addTitle("Theme", cc.xy (3, 1));
145 builder.add(new JScrollPane(lafList), cc.xy (1, 3));
146 builder.add(new JScrollPane(themesList), cc.xy (3, 3));
147 builder.addTitle("Preview", cc.xyw(1, 5, 3));
148 builder.add(previewPanel, cc.xyw(1, 7, 3));
149 }
150
151
152
153
154
155 private void registerListeners() {
156
157 lafList.addListSelectionListener(new ListSelectionListener() {
158 public void valueChanged(ListSelectionEvent e) {
159 if (!e.getValueIsAdjusting())
160 changedLookAndFeel();
161 }
162 });
163 themeListener = new ListSelectionListener() {
164 public void valueChanged(ListSelectionEvent e) {
165 if (!e.getValueIsAdjusting())
166 changedTheme();
167 }
168 };
169
170 themesList.addListSelectionListener(themeListener);
171 }
172
173
174
175
176
177
178 private void changedLookAndFeel() {
179 isLookChanged = true;
180
181
182
183
184
185
186 themesList.removeListSelectionListener(themeListener);
187 updateThemesModel();
188 selectTheme(getSelectedConfiguration().getTheme());
189 themesList.addListSelectionListener(themeListener);
190
191 updatePreviewPanel();
192 }
193
194
195
196
197 private void changedTheme() {
198 LookAndFeel laf = getSelectedLookAndFeel();
199 if (!(laf instanceof PlasticLookAndFeel))
200 return;
201 putConfiguration(createLookConfiguration());
202 updatePreviewPanel();
203 }
204
205
206
207
208 private void selectLook(LookAndFeel selectedLook) {
209 String lafClassName = selectedLook.getClass().getName();
210 ListModel model = lafList.getModel();
211 for (int i = 0; i < model.getSize(); i++) {
212 LookAndFeel laf = (LookAndFeel) model.getElementAt(i);
213 if (lafClassName.equals(laf.getClass().getName())) {
214 lafList.setSelectedIndex(i);
215 lafList.ensureIndexIsVisible(i);
216 break;
217 }
218 }
219 }
220
221
222
223
224 private void selectTheme(Object selectedTheme) {
225 if (selectedTheme == null)
226 return;
227 String themeClassName = selectedTheme.getClass().getName();
228 ListModel model = themesList.getModel();
229 for (int i = 0; i < model.getSize(); i++) {
230 PlasticTheme theme = (PlasticTheme) model.getElementAt(i);
231 if (themeClassName.equals(theme.getClass().getName())) {
232 themesList.setSelectedIndex(i);
233 themesList.ensureIndexIsVisible(i);
234 break;
235 }
236 }
237 }
238
239
240
241
242 private void updatePreviewPanel() {
243 try {
244
245 LookAndFeel oldLaf = UIManager.getLookAndFeel();
246 LookAndFeel selectedLaF = getSelectedLookAndFeel();
247 PlasticTheme oldTheme = null;
248
249 if (selectedLaF instanceof PlasticLookAndFeel) {
250 oldTheme = (PlasticTheme) PlasticLookAndFeel.getPlasticTheme();
251 PlasticTheme theme = getSelectedTheme();
252 if (theme != null)
253 PlasticLookAndFeel.setPlasticTheme(theme);
254 }
255
256 UIManager.setLookAndFeel(selectedLaF);
257 previewPanel.updateAndValidate();
258
259 if (selectedLaF instanceof PlasticLookAndFeel)
260 PlasticLookAndFeel.setPlasticTheme(oldTheme);
261
262
263 UIManager.setLookAndFeel(oldLaf);
264 previewPanel.updateComponentTree();
265
266 } catch (UnsupportedLookAndFeelException e) {
267
268 }
269 }
270
271
272
273
274 private void updateThemesModel() {
275 boolean supportsThemes =
276 getSelectedLookAndFeel() instanceof PlasticLookAndFeel;
277
278 ListModel newModel = supportsThemes
279 ? PLASTIC_THEMES_MODEL
280 : NO_THEMES_MODEL;
281 if (themesList.getModel() != newModel)
282 themesList.setModel(newModel);
283
284 themesList.setEnabled(supportsThemes);
285 }
286
287
288
289 private LookConfiguration getSelectedConfiguration() {
290 return configurations.getDefaultConfiguration();
291 }
292
293 @SuppressWarnings("unchecked")
294 private void putConfiguration(LookConfiguration config) {
295 configurations.getConfigurations().add(config);
296 configurations.setDefaultConfiguration(config);
297 }
298
299 private LookConfiguration createLookConfiguration() {
300 LookAndFeel laf = getSelectedLookAndFeel();
301 Object theme =
302 laf instanceof PlasticLookAndFeel ? getSelectedTheme() : null;
303 return new LookConfiguration(laf, theme);
304 }
305
306 private LookAndFeel getSelectedLookAndFeel() {
307 return (LookAndFeel) lafList.getSelectedValue();
308 }
309
310 private PlasticTheme getSelectedTheme() {
311 return (PlasticTheme) themesList.getSelectedValue();
312 }
313
314
315
316
317
318
319 private synchronized static ListModel getSupportedLookAndFeelInstances() {
320 if (supportedLookAndFeelInstances == null) {
321 supportedLookAndFeelInstances =
322 new ArrayListModel(computeSupportedLookAndFeelInstances());
323 }
324 return supportedLookAndFeelInstances;
325 }
326
327
328
329
330 @SuppressWarnings("unchecked")
331 private static java.util.List computeSupportedLookAndFeelInstances() {
332 UIManager.LookAndFeelInfo[] lafInfos =
333 UIManager.getInstalledLookAndFeels();
334 java.util.List result = new ArrayList(lafInfos.length);
335 for (int i = 0; i < lafInfos.length; i++) {
336 String className = lafInfos[i].getClassName();
337 LookAndFeel laf =
338 ExtUIManager.createLookAndFeelInstance(className);
339 if ((laf != null) && (laf.isSupportedLookAndFeel()))
340 result.add(laf);
341 }
342 Collections.sort(result, new Comparator() {
343 public int compare(Object o1, Object o2) {
344 LookAndFeel laf1 = (LookAndFeel) o1;
345 LookAndFeel laf2 = (LookAndFeel) o2;
346 return laf1.getName().toUpperCase().compareTo(
347 laf2.getName().toUpperCase());
348 }
349 });
350 return result;
351 }
352
353
354
355 private class CommitHandler implements PropertyChangeListener {
356
357 public void propertyChange(PropertyChangeEvent evt) {
358 if (Boolean.TRUE.equals(evt.getNewValue())) {
359 if (isLookChanged) {
360 LOG.warn("You may have to restart Jukes to see the Look and Feel changes");
361 }
362 ExtUIManager.setLookConfigurations(configurations);
363 final LookConfiguration config = createLookConfiguration();
364 ExtUIManager.setDefaultLookConfiguration(config);
365 final Preferences prefs = Application.getUserPreferences();
366 if (config.getTheme() != null) {
367 prefs.put("laf.themeName."+ config.getLookAndFeel().getName(), config.getTheme().getClass().getName());
368 }
369
370 }
371 }
372 }
373
374
375 private static class LooksListCellRenderer extends DefaultListCellRenderer {
376
377 public Component getListCellRendererComponent(
378 JList list, Object value, int index,
379 boolean isSelected,
380 boolean cellHasFocus) {
381 return super.getListCellRendererComponent(
382 list,
383 ((LookAndFeel) value).getName(),
384 index, isSelected, cellHasFocus);
385 }
386 }
387
388
389 private static class ThemesListCellRenderer extends DefaultListCellRenderer {
390
391 public Component getListCellRendererComponent(
392 JList list, Object value, int index,
393 boolean isSelected,
394 boolean cellHasFocus) {
395 return super.getListCellRendererComponent(
396 list,
397 (value instanceof PlasticTheme
398 ? ((PlasticTheme) value).getName()
399 : value),
400 index, isSelected, cellHasFocus);
401 }
402 }
403
404
405
406
407
408 public static class EagerInitializer implements Preparable {
409
410
411
412
413
414 public void prepare() {
415 Logger.getLogger("LookAndFeelPanel").info(
416 "Computing supported look and feels...");
417 getSupportedLookAndFeelInstances();
418 Logger.getLogger("LookAndFeelPanel").info(
419 "Preloading preview panel classes...");
420 new LookAndFeelPreviewPanel();
421 }
422 }
423
424 }