View Javadoc
1   package siouxsie.desktop.option.impl;
2   
3   import java.awt.BorderLayout;
4   import java.awt.CardLayout;
5   import java.awt.Component;
6   import java.awt.event.MouseAdapter;
7   import java.awt.event.MouseEvent;
8   import java.util.ArrayList;
9   import java.util.Collection;
10  import java.util.HashMap;
11  import java.util.List;
12  import java.util.Map;
13  
14  import javax.swing.JComponent;
15  import javax.swing.JLabel;
16  import javax.swing.JPanel;
17  import javax.swing.JScrollPane;
18  import javax.swing.JTree;
19  import javax.swing.tree.DefaultMutableTreeNode;
20  import javax.swing.tree.DefaultTreeCellRenderer;
21  import javax.swing.tree.TreePath;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  
26  import siouxsie.desktop.option.CategoryDescription;
27  import siouxsie.desktop.option.IOptionPane;
28  import siouxsie.desktop.option.IOptionPaneInitializer;
29  import siouxsie.desktop.option.IPreferencesRenderer;
30  import siouxsie.desktop.option.OptionPaneDescription;
31  
32  /**
33   * JTree menu based preferences renderer.
34   * @author Arnaud Cogoluegnes
35   * @version $Id$
36   */
37  public class PreferencesRenderer implements IPreferencesRenderer {
38  
39  	private List<OptionPaneDescription> optionPaneDescriptions;
40  	
41  	private List<CategoryDescription> categoryDescriptions; 
42  	
43  	private IOptionPaneInitializer initializerService;
44  	
45  	private Collection<IOptionPane> optionPanes = new ArrayList<IOptionPane>();
46  	
47  	private static final Log LOG = LogFactory.getLog(PreferencesRenderer.class);
48  	
49  	private JPanel mainPanel;
50  	
51  	private JTree tree;
52  	
53  	/*
54  	 * (non-Javadoc)
55  	 * @see siouxsie.desktop.option.IPreferencesRenderer#getComponent()
56  	 */
57  	public JComponent getComponent() {
58  		return mainPanel;
59  	}
60  	
61  	/*
62  	 * (non-Javadoc)
63  	 * @see siouxsie.desktop.option.IPreferencesRenderer#save()
64  	 */
65  	public void save() throws Exception {
66  		// TODO would need a pre-commit step?
67  		for(IOptionPane pane : optionPanes) {
68  			pane.save();
69  		}		
70  	}
71  	
72  	/*
73  	 * (non-Javadoc)
74  	 * @see siouxsie.desktop.option.IPreferencesRenderer#cancel()
75  	 */
76  	public void cancel() throws Exception {
77  		// nothing special, could check modifications and warn
78  		
79  	}
80  	
81  	public void init() {		
82  		DefaultMutableTreeNode root = new DefaultMutableTreeNode();
83  		Map<String, DefaultMutableTreeNode> catIdToCat = new HashMap<String, DefaultMutableTreeNode>();
84  		for(CategoryDescription cat : categoryDescriptions) {
85  			DefaultMutableTreeNode node = new DefaultMutableTreeNode(cat);
86  			catIdToCat.put(cat.getId(), node);
87  			root.add(node);
88  		}		
89  		
90  		// default category node, just in case
91  		CategoryDescription defaultCategory = new CategoryDescription();
92  		defaultCategory.setId("siouxsie_default_option_category");
93  		defaultCategory.setName("Default");
94  		DefaultMutableTreeNode defaultCategoryNode = new DefaultMutableTreeNode(defaultCategory);
95  
96  		// the option panes panel
97  		final JPanel panel = new JPanel();
98  		final CardLayout cardLayout = new CardLayout();
99  		panel.setLayout(cardLayout);
100 		
101 		// empty at the beginning
102 		panel.add(new JPanel(),"");
103 		
104 		for(OptionPaneDescription desc : optionPaneDescriptions) {	
105 			
106 			IOptionPane optionPane;
107 			try {
108 				optionPane = desc.getOptionPane() != null ? desc.getOptionPane() : (IOptionPane) desc.getClass().newInstance();
109 				initializerService.initialize(optionPane);
110 			} catch (InstantiationException e) {
111 				LOG.error("could not create option pane",e);
112 				continue;
113 			} catch (IllegalAccessException e) {
114 				LOG.error("could not create option pane",e);
115 				continue;
116 			}			
117 			
118 			optionPane.init();
119 			
120 			DefaultMutableTreeNode node = new DefaultMutableTreeNode();
121 			node.setUserObject(optionPane);
122 			DefaultMutableTreeNode cat = catIdToCat.get(desc.getCategoryId());
123 			if(cat == null) {
124 				LOG.warn("could not find preferences category "+desc.getCategoryId()+" for option pane "+optionPane.getName());
125 				cat = defaultCategoryNode;
126 				if(root.getIndex(cat) == -1) {
127 					root.add(cat);
128 				}
129 				desc.setCategoryId(defaultCategory.getId());
130 			}
131 			cat.add(node);
132 			
133 			panel.add(optionPane.getComponent(),desc.getCategoryId()+"."+optionPane.getName());
134 			optionPanes.add(optionPane);
135 			
136 		}
137 		
138 		tree = new JTree(root);
139 		tree.setRootVisible(false);
140 		tree.setShowsRootHandles(true);
141 		
142 		tree.setCellRenderer(new DefaultTreeCellRenderer() {			
143 			@Override
144 			public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
145 				JLabel label = (JLabel) super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
146 				DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;				
147 				if(node.getUserObject() instanceof IOptionPane) {
148 					label.setText(((IOptionPane) node.getUserObject()).getName());
149 				}
150 				return label;
151 			}			
152 		});
153 		
154 		mainPanel = new JPanel(new BorderLayout());
155 		mainPanel.add(new JScrollPane(tree),BorderLayout.WEST);
156 		mainPanel.add(panel,BorderLayout.CENTER);
157 		
158 		tree.addMouseListener(new MouseAdapter() {
159 		     public void mousePressed(MouseEvent e) {
160 		         int selRow = tree.getRowForLocation(e.getX(), e.getY());
161 		         TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
162 		         if(selRow != -1) {
163 		        	 DefaultMutableTreeNode node = (DefaultMutableTreeNode) selPath.getLastPathComponent();
164 		        	 if(node.getUserObject() instanceof IOptionPane) {
165 		        		 CategoryDescription cat = (CategoryDescription)((DefaultMutableTreeNode)node.getParent()).getUserObject();
166 		        		 IOptionPane pane = (IOptionPane) node.getUserObject();
167 		        		 
168 		        		 cardLayout.show(panel, cat.getId()+"."+pane.getName());
169 		        		 
170 		        	 }
171 		         }
172 		     }
173 		 });
174 		
175 	}
176 
177 	public List<CategoryDescription> getCategoryDescriptions() {
178 		return categoryDescriptions;
179 	}
180 
181 	public void setCategoryDescriptions(
182 			List<CategoryDescription> categoryDescriptions) {
183 		this.categoryDescriptions = categoryDescriptions;
184 	}
185 
186 	public IOptionPaneInitializer getInitializerService() {
187 		return initializerService;
188 	}
189 
190 	public void setInitializerService(IOptionPaneInitializer initializerService) {
191 		this.initializerService = initializerService;
192 	}
193 
194 	public List<OptionPaneDescription> getOptionPaneDescriptions() {
195 		return optionPaneDescriptions;
196 	}
197 
198 	public void setOptionPaneDescriptions(
199 			List<OptionPaneDescription> optionPaneDescriptions) {
200 		this.optionPaneDescriptions = optionPaneDescriptions;
201 	}
202 	
203 	/**
204 	 * For test purpose only.
205 	 * @return
206 	 */
207 	protected JTree getTree() {
208 		return tree;
209 	}
210 	
211 }