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