View Javadoc

1   /*
2    *  XNap - A P2P framework and client.
3    *
4    *  See the file AUTHORS for copyright information.
5    *
6    *  This program is free software; you can redistribute it and/or modify
7    *  it under the terms of the GNU General Public License as published by
8    *  the Free Software Foundation.
9    *
10   *  This program is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   *  GNU General Public License for more details.
14   *
15   *  You should have received a copy of the GNU General Public License
16   *  along with this program; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  
20  package org.xnap.gui.prefs;
21  
22  import java.awt.BorderLayout;
23  import java.awt.Dimension;
24  import java.awt.FlowLayout;
25  import java.awt.GridBagLayout;
26  import java.awt.GridLayout;
27  import java.awt.event.ActionEvent;
28  import java.awt.event.KeyEvent;
29  
30  import javax.swing.AbstractAction;
31  import javax.swing.Action;
32  import javax.swing.Box;
33  import javax.swing.BoxLayout;
34  import javax.swing.DefaultListModel;
35  import javax.swing.Icon;
36  import javax.swing.JButton;
37  import javax.swing.JCheckBox;
38  import javax.swing.JLabel;
39  import javax.swing.JList;
40  import javax.swing.JOptionPane;
41  import javax.swing.JPanel;
42  import javax.swing.JRadioButton;
43  import javax.swing.JScrollBar;
44  import javax.swing.JScrollPane;
45  import javax.swing.JSlider;
46  import javax.swing.JTabbedPane;
47  import javax.swing.JTable;
48  import javax.swing.JTree;
49  import javax.swing.SwingUtilities;
50  import javax.swing.UIManager;
51  import javax.swing.event.ListSelectionEvent;
52  import javax.swing.event.ListSelectionListener;
53  
54  import org.xnap.XNap;
55  import org.xnap.gui.AbstractSettingsPanel;
56  import org.xnap.gui.table.AbstractColumnTableModel;
57  import org.xnap.gui.table.Column;
58  import org.xnap.gui.table.TableHeaderHandler;
59  import org.xnap.gui.theme.Theme;
60  import org.xnap.gui.theme.ThemeManager;
61  import org.xnap.gui.util.*;
62  import org.xnap.gui.util.GridBagHelper;
63  
64  /***
65   * Provides controls for look and feel settings.
66   */
67  public class LookAndFeelPrefsPanel extends AbstractSettingsPanel 
68      implements ListSelectionListener {
69      
70      //--- Data field(s) ---
71  
72      private DefaultListModel dlmLafs;
73      private JList jlLafs;
74      private DefaultListModel dlmThemes;
75      private JList jlThemes;
76      private JPanel jpPreview;
77      private JList iconThemesList;
78      private int lastIndex = 0;
79      private ConfigureThemeAction acConfigureTheme = new ConfigureThemeAction();
80  
81      //--- Constructor(s) ---
82  
83      public LookAndFeelPrefsPanel()
84      {
85  		setLayout(new GridBagLayout());
86  
87  		// look and feel list
88  		JPanel jpLafs = new JPanel(new BorderLayout());
89  		jpLafs.add(new JLabel(XNap.tr("Look and Feel")), BorderLayout.NORTH);
90  		dlmLafs = new DefaultListModel();
91  		jlLafs = new JList(dlmLafs);
92  		jlLafs.setVisibleRowCount(4);
93  		JScrollPane jspLafs = new JScrollPane(jlLafs);
94  		jpLafs.add(jspLafs, BorderLayout.CENTER);
95  
96  		// theme list
97  		JPanel jpThemes = new JPanel(new BorderLayout());
98  		jpThemes.add(new JLabel(XNap.tr("Theme")), BorderLayout.NORTH);
99  		dlmThemes = new DefaultListModel();
100 		jlThemes = new JList(dlmThemes);
101 		jlThemes.setVisibleRowCount(4);
102 		JScrollPane jspThemes = new JScrollPane(jlThemes);
103 		jpThemes.add(jspThemes, BorderLayout.CENTER);
104 
105 		// icon theme list
106 		JPanel iconThemesPanel = new JPanel(new BorderLayout());
107 		iconThemesPanel.add
108 			(new JLabel(XNap.tr("Icon Theme")), BorderLayout.NORTH);
109 		iconThemesList = new JList(new DefaultListModel());
110 		iconThemesList.setVisibleRowCount(4);
111 		JScrollPane iconThemesScrollPane = new JScrollPane(iconThemesList);
112 		iconThemesPanel.add(iconThemesScrollPane, BorderLayout.CENTER);
113 
114 		// look and feel panel
115 		JPanel jpLists = new JPanel();
116 		jpLists.setLayout(new BoxLayout(jpLists, BoxLayout.X_AXIS));
117 		jpLists.add(jpLafs);
118 		jpLists.add(Box.createHorizontalStrut(5));
119 		jpLists.add(jpThemes);
120 		jpLists.add(Box.createHorizontalStrut(5));
121 		jpLists.add(iconThemesPanel);
122 		GridBagHelper.add(this, jpLists);
123 	
124 		// configure button
125 		JPanel jpConfigure = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0));
126 		JButton jbConfigure = new JButton(acConfigureTheme);
127 		jpConfigure.add(jbConfigure);
128 		GridBagHelper.add(this, jpConfigure);
129 
130 		// preview
131 		JPanel jpControls = new JPanel();
132 		jpControls.setLayout(new BoxLayout(jpControls, BoxLayout.Y_AXIS));
133 		jpControls.add(new JLabel("I am a Label"));
134 		jpControls.add(new JButton("I am a button"));
135 		jpControls.add(new JCheckBox("I am a check box"));
136 		jpControls.add(new JRadioButton("I am a radio"));
137 
138 		JPanel jpSlider = new JPanel();
139 		jpSlider.setLayout(new BoxLayout(jpSlider, BoxLayout.Y_AXIS));
140 		JSlider js = new JSlider(JSlider.HORIZONTAL, 0, 10, 3);
141 		js.setSnapToTicks(true);
142 		js.setPreferredSize(new Dimension(50, 50));
143 		jpSlider.add(js);
144 		JScrollBar jsb = new JScrollBar(JScrollBar.HORIZONTAL, 5, 2, 0, 10);
145 		jpSlider.add(jsb);
146 
147 		JTabbedPane jtp = new JTabbedPane();
148 		jtp.addTab("Controls", jpControls);
149 		jtp.addTab("Slider", jpSlider);
150 
151 		MyTableModel tm = new MyTableModel();
152 		JTable jtTable = new JTable(tm);
153 		TableHeaderHandler.install(jtTable);
154 		jtTable.setPreferredScrollableViewportSize(new Dimension(50, 50));
155 		JScrollPane jspTable = new JScrollPane(jtTable);
156 
157 		JTree jtTree = new JTree();
158 		jtTree.setVisibleRowCount(4);
159 		JScrollPane jspTree = new JScrollPane(jtTree);
160 
161 		jpPreview = new JPanel(new GridLayout(1, 3, 10, 10));
162 		jpPreview.add(jtp);
163 		jpPreview.add(jspTable);
164 		jpPreview.add(jspTree);
165 
166 		GridBagHelper.add(this, GUIHelper.createSeparator(XNap.tr("Preview")));
167 
168 		JPanel jpWrap = new JPanel(new BorderLayout());
169 		jpWrap.add(jpPreview, BorderLayout.CENTER);
170 		GridBagHelper.add(this, jpWrap);
171 
172 		GridBagHelper.addVerticalSpacer(this);
173 
174 		initializeLists();
175     }
176 
177     public void initializeLists()
178     {
179 		UIManager.LookAndFeelInfo[] info 
180 			= ThemeManager.getInstalledLookAndFeels();
181 		String currentLaf = UIManager.getLookAndFeel().getClass().getName();
182 		for (int i = 0; i < info.length; i++) {
183 			dlmLafs.addElement(new MyLookAndFeelInfo(info[i]));
184 			if (currentLaf.equals(info[i].getClassName())) {
185 				jlLafs.setSelectedIndex(i);
186 				jlLafs.ensureIndexIsVisible(i);
187 				lastIndex = i;
188 			}
189 		}
190 		jlLafs.addListSelectionListener(this);
191 
192 
193 		DefaultListModel iconThemeModel 
194 			= ((DefaultListModel)iconThemesList.getModel());
195 
196 		Theme[] themes = ThemeManager.getThemes();
197 		String currentTheme = prefs.getTheme();
198 		String currentIconTheme = prefs.getIconTheme();
199 		for (int i = 0; i < themes.length; i++) {
200 			if (themes[i].isIconTheme()) {
201 				iconThemeModel.addElement(themes[i]);
202 				if (currentIconTheme.equals(themes[i].getClassName())) {
203 					iconThemesList.setSelectedIndex
204 						(iconThemeModel.getSize() - 1);
205 					iconThemesList.ensureIndexIsVisible
206 						(iconThemeModel.getSize() - 1);
207 				}
208 			}
209 			else {
210 				dlmThemes.addElement(themes[i]);
211 				if (currentTheme.equals(themes[i].getClassName())) {
212 					jlThemes.setSelectedIndex(dlmThemes.getSize() - 1);
213 					jlThemes.ensureIndexIsVisible(dlmThemes.getSize() - 1);
214 				}
215 			}
216 		}
217 
218 		jlThemes.addListSelectionListener(this);
219 		acConfigureTheme.setEnabled
220 			(getSelectedTheme() != null && getSelectedTheme().isConfigurable());
221     }
222 
223     public void apply() 
224     {
225 		if (getSelectedLaf() != null) {
226 			prefs.setLookAndFeel(getSelectedLaf().getClassName());
227 		}
228 		if (getSelectedTheme() != null) {
229 			prefs.setTheme(getSelectedTheme().getClassName());
230 		}
231 		if (getSelectedIconTheme() != null) {
232 			prefs.setIconTheme(getSelectedIconTheme().getClassName());
233 		}
234     }
235 
236     public Icon getIcon()
237     {
238 		return null;
239     }
240 
241     public UIManager.LookAndFeelInfo getSelectedLaf()
242     {
243 		return ((MyLookAndFeelInfo)jlLafs.getSelectedValue()).info;
244     }
245 
246     public Theme getSelectedIconTheme()
247     {
248 		return (Theme)iconThemesList.getSelectedValue();
249     }
250 
251     public Theme getSelectedTheme()
252     {
253 		return (Theme)jlThemes.getSelectedValue();
254     }
255 
256     public String getTitle()
257     {
258 		return XNap.tr("Look & Feel");
259     }
260 
261     public void updateTheme()
262     {
263 		// save current theme
264 		Object[] savedDefaults = ThemeManager.getDefaults();
265 	
266 		if (getSelectedTheme() != null) {
267 			// set theme
268 			ThemeManager.setTheme(getSelectedTheme());
269 			SwingUtilities.updateComponentTreeUI(jpPreview);
270 			
271 			// reset theme
272 			ThemeManager.setDefaults(savedDefaults);
273 			
274 			// enable configuration dialog
275 			acConfigureTheme.setEnabled(getSelectedTheme().isConfigurable());
276 		}
277     }
278 
279     /***
280      * Sets the selected look and feel for the preview panel.
281      */
282     public void valueChanged(ListSelectionEvent event) 
283     {
284 		if (event.getSource() == jlLafs) {
285 			String currentLaf = UIManager.getLookAndFeel().getClass().getName();
286 
287 			// set laf
288 			try {
289 				UIManager.setLookAndFeel(getSelectedLaf().getClassName());
290 			}
291 			catch (Exception e) {
292 				JOptionPane.showMessageDialog
293 					(this, XNap.tr("Sorry, not supported or not installed"),
294 					 "Look and Feel", JOptionPane.ERROR_MESSAGE);
295 				int i = jlLafs.getSelectedIndex();
296 				jlLafs.setSelectedIndex((i == dlmLafs.size() - 1) ? 0 : i + 1);
297 				return;
298 			}
299 
300 			// redraw component
301 			SwingUtilities.updateComponentTreeUI(jpPreview);
302 
303 			// reset laf
304 			lastIndex = jlLafs.getSelectedIndex();
305 			try {
306 				UIManager.setLookAndFeel(currentLaf);
307 			}
308 			catch (Exception e) {
309 			}
310 		}
311 		else if (event.getSource() == jlThemes) {
312 			updateTheme();
313 		}
314     }
315 
316     /***
317      * Wraps toString() for UIManager.LookAndFeelInfo class.
318      */
319     class MyLookAndFeelInfo  {
320 
321 		public UIManager.LookAndFeelInfo info;
322 	
323 		public MyLookAndFeelInfo(UIManager.LookAndFeelInfo info)
324 		{
325 			this.info = info;
326 		}
327 
328 		public String getClassName()
329 		{
330 			return info.getClassName();
331 		}
332 
333 		public String toString()
334 		{
335 			return info.getName();
336 		}
337 
338     }
339 
340     private class MyTableModel extends AbstractColumnTableModel {
341 
342 		//--- Data field(s) ---
343 
344 		private Object[][] data = {
345 			{ "Linux"  , "GPL"         },
346 			{ "FreeBSD", "BSD License" },
347 		};
348 
349 		//--- Constructor(s) ---
350 
351 		public MyTableModel() 
352 		{
353 			Column columns[] = new Column[] {
354 				new Column("Operating System", String.class),
355 				new Column("License", String.class),
356 			};
357 			addColumns(columns);
358 
359 			fireTableDataChanged();
360 		}
361 
362 		//--- Method(s) ---
363 
364 		public Object get(int i, int j) 
365 		{
366 			return data[i][j];
367         }
368 
369 		public int getRowCount() 
370 		{
371 			return data.length;
372 		}
373 
374     }
375 
376     private class ConfigureThemeAction extends AbstractAction
377     {
378 		public ConfigureThemeAction()
379 		{
380 			putValue(Action.NAME, XNap.tr("Configure Theme") + "...");
381             putValue(Action.SHORT_DESCRIPTION,
382 					 XNap.tr("Opens the theme configuration dialog."));
383             putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_C));
384         }
385 
386         public void actionPerformed(ActionEvent event) 
387 		{
388 			if (getSelectedTheme() != null
389 				&& getSelectedTheme().showConfigurationDialog
390 				(LookAndFeelPrefsPanel.this)) {
391 
392 				updateTheme();
393 			}
394         }
395 
396     }
397  
398 }