View Javadoc

1   /*
2    * Copyright (c) 2003-2008 by Cosylab d. d.
3    *
4    * This file is part of CosyBeans-Common.
5    *
6    * CosyBeans-Common 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, either version 3 of the License, or
9    * (at your option) any later version.
10   *
11   * CosyBeans-Common is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   * You should have received a copy of the GNU General Public License
17   * along with CosyBeans-Common.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  package com.cosylab.gui.components.customizer;
21  
22  import com.cosylab.gui.components.introspection.BeanPropertiesTableModel;
23  import com.cosylab.gui.components.introspection.DefaultPropertiesTable;
24  
25  import com.cosylab.util.Debug;
26  import com.cosylab.util.ObjectList;
27  
28  import java.awt.Color;
29  
30  import java.util.ArrayList;
31  import java.util.Arrays;
32  import java.util.HashMap;
33  import java.util.Iterator;
34  
35  import javax.swing.JComponent;
36  import javax.swing.border.LineBorder;
37  import javax.swing.table.TableModel;
38  
39  
40  /**
41   * Default implementation of the <code>Editor</code> interface. Supports
42   * editing of aspects via a simple property table,  multiple aspects, and
43   * custom editors for selected aspects.
44   *
45   * @author <a href="mailto:jernej.kamenik@cosylab.com">Jernej Kamenik</a>
46   * @version $id$
47   */
48  public class DefaultEditor implements Editor
49  {
50  	private DefaultPropertiesTable defaultPropertiesTable = null;
51  	private HashMap<String, ArrayList<Editor>> customEditors = null;
52  	private HashMap<String, BeanPropertiesTableModel> defaultPropertiesTableModels = null;
53  	private Object displayer = null;
54  	private ObjectList activeEditors = null;
55  
56  	/**
57  	 * Cunstructs an empty editor.
58  	 */
59  	public DefaultEditor()
60  	{
61  		super();
62  		defaultPropertiesTableModels = new HashMap<String, BeanPropertiesTableModel>();
63  		customEditors = new HashMap<String, ArrayList<Editor>>();
64  		activeEditors = new ObjectList(Editor.class);
65  		defaultPropertiesTable = new DefaultPropertiesTable();
66  		defaultPropertiesTable.setBorder(new LineBorder(Color.BLACK));
67  	}
68  
69  	/**
70  	 * <p>
71  	 * Should return names of properties of a dispalyer to be edited within the
72  	 * sepcified aspect through generic proeprty tables. This empty
73  	 * implementation however returns null.
74  	 * </p>
75  	 * 
76  	 * <p>
77  	 * Subclasses should override this method to return arrays of
78  	 * <code>String</code> names of properties to be edited via property
79  	 * tables in the specified aspect.
80  	 * </p>
81  	 * 
82  	 * <p>
83  	 * The Strings returned should specify names of qualified <i>JavaBean</i>
84  	 * properties with conventional getter and setter methods.
85  	 * </p>
86  	 * 
87  	 * <p>
88  	 * If a custom editor has been specified for the aspect the result of theis
89  	 * method is ignored as the custom editor is used for editing the aspect
90  	 * instead of generic property table.
91  	 * </p>
92  	 *
93  	 * @param aspect the aspect of the displayer to be edited with generic
94  	 *        proeprty table
95  	 *
96  	 * @return array of names of properties to be edited with the proeprty
97  	 *         table in the specified aspect
98  	 */
99  	public String[] getDefaultProperties(String aspect)
100 	{
101 		Debug.out(aspect);
102 
103 		return null;
104 	}
105 
106 	/**
107 	 * Returns the editor component for the selected aspect and displayer. If a
108 	 * custom editor exists for the selected aspect, it is returned. Otherwise
109 	 * a property table is returned containing the selected proeprties of the
110 	 * aspect as returned by <code>#getDefaultProperties(String)</code>
111 	 * method.
112 	 *
113 	 * @param displayer the component for which the editor should be returned
114 	 * @param aspect the specific editing aspect for which the editor should be
115 	 *        returned
116 	 *
117 	 * @return the editor component for the selected aspect and displayer.
118 	 *
119 	 * @throws IllegalArgumentException if no custom editor is found for the
120 	 *         aspect and  getDefaultProperties(String) returns null for the
121 	 *         aspect.
122 	 *
123 	 * @see com.cosylab.gui.components.customizer.Editor#getEditorComponent(Object,
124 	 *      String)
125 	 */
126 	public JComponent getEditorComponent(Object displayer, String aspect)
127 		throws IllegalArgumentException
128 	{
129 		Editor ed;
130 		Iterator it = activeEditors.iterator();
131 
132 		while (it.hasNext()) {
133 			if ((ed = (Editor)it.next()).canEdit(displayer, aspect)) {
134 				return ed.getEditorComponent(displayer, aspect);
135 			}
136 		}
137 
138 		ArrayList l = customEditors.get(aspect);
139 
140 		if (l != null) {
141 			it = l.iterator();
142 
143 			while (it.hasNext()) {
144 				if ((ed = (Editor)it.next()).canEdit(displayer, aspect)) {
145 					activeEditors.add(ed);
146 
147 					return ed.getEditorComponent(displayer, aspect);
148 				}
149 			}
150 		}
151 
152 		initializeDefaultPropertiesTable(displayer, aspect);
153 
154 		return defaultPropertiesTable;
155 	}
156 
157 	/**
158 	 * Overrides the current editor for the specified aspect with the editor
159 	 * specified. This method can be used to replace generic property tables
160 	 * as editors for the  aspect specified.
161 	 *
162 	 * @param aspect for which to use the editor specified
163 	 * @param editor the editor to replace the current editor of the aspect
164 	 *        specified
165 	 */
166 	public void addCustomEditor(String aspect, Editor editor)
167 	{
168 		ArrayList<Editor> l = customEditors.get(aspect);
169 
170 		if (l == null) {
171 			l = new ArrayList<Editor>();
172 			customEditors.put(aspect, l);
173 		}
174 
175 		l.add(editor);
176 	}
177 
178 	/**
179 	 * Applies all the changes done to the custom editors as well as the
180 	 * property tables.
181 	 *
182 	 * @see com.cosylab.gui.components.customizer.Editor#applySettings()
183 	 */
184 	public void applySettings()
185 	{
186 		applyTableProperties();
187 
188 		Editor[] eds = getActiveEditors();
189 
190 		for (int i = 0; i < eds.length; i++) {
191 			eds[i].applySettings();
192 		}
193 	}
194 
195 	/**
196 	 * Inspecting the <code>ASPECTS</code> and all the custom editors, this
197 	 * method determines, wether the specified aspect of the dispalyer can be
198 	 * edited by this editor.
199 	 *
200 	 * @param displayer Object to be edited (is ignored and can be
201 	 *        <code>null</code>)
202 	 * @param aspect String name of aspect to be edited.
203 	 *
204 	 * @return <code>true</code> if the specifed aspect of the displayer can be
205 	 *         edited, <code>false</code> otherwise.
206 	 *
207 	 * @see com.cosylab.gui.components.customizer.Editor#canEdit(Object,
208 	 *      String)
209 	 */
210 	public boolean canEdit(Object displayer, String aspect)
211 	{
212 		ArrayList<Editor> l = customEditors.get(aspect);
213 
214 		if (l != null) {
215 			Iterator<Editor> it = l.iterator();
216 
217 			while (it.hasNext()) {
218 				if (it.next().canEdit(displayer, aspect)) {
219 					return true;
220 				}
221 			}
222 		}
223 
224 		return (Arrays.binarySearch(ASPECTS, aspect) >= 0
225 		&& getDefaultProperties(aspect) != null);
226 	}
227 
228 	/**
229 	 * Reverts all the changes done to the custom editors as well as the
230 	 * property tables.
231 	 *
232 	 * @see com.cosylab.gui.components.customizer.Editor#revertSettings()
233 	 */
234 	public void revertSettings()
235 	{
236 		Editor[] eds = getActiveEditors();
237 
238 		for (int i = 0; i < eds.length; i++) {
239 			eds[i].revertSettings();
240 		}
241 	}
242 
243 	/**
244 	 * Stops editing with all custom editors as well as property tables.
245 	 *
246 	 * @see com.cosylab.gui.components.customizer.Editor#stopEditing()
247 	 */
248 	public void stopEditing()
249 	{
250 		defaultPropertiesTableModels.clear();
251 
252 		Editor[] eds = getActiveEditors();
253 
254 		for (int i = 0; i < eds.length; i++) {
255 			eds[i].stopEditing();
256 		}
257 
258 		activeEditors.clear();
259 	}
260 
261 	/*
262 	 * Applies the changes done to the property tables.
263 	 */
264 	protected void applyTableProperties()
265 	{
266 		if (displayer == null) {
267 			return;
268 		}
269 
270 		Object[] modelList = defaultPropertiesTableModels.values().toArray();
271 		//Class c = displayer.getClass();
272 
273 		for (int i = 0; i < modelList.length; i++) {
274 			BeanPropertiesTableModel model = (BeanPropertiesTableModel)modelList[i];
275 
276 			try {
277 				model.applyProperties();
278 			} catch (Exception e) {
279 				e.printStackTrace();
280 			}
281 		}
282 	}
283 
284 	/*
285 	 * Initializes the proeprty table for the selected displayer and aspect.
286 	 */
287 	protected void initializeDefaultPropertiesTable(Object displayer,
288 	    String aspect) throws IllegalArgumentException
289 	{
290 		this.displayer = displayer;
291 
292 		if (defaultPropertiesTableModels.containsKey(aspect)) {
293 			defaultPropertiesTable.setModel((TableModel)defaultPropertiesTableModels
294 			    .get(aspect));
295 		} else {
296 			String[] names = getDefaultProperties(aspect);
297 
298 			if (names != null) {
299 				BeanPropertiesTableModel model = new BeanPropertiesTableModel(displayer,
300 					    names);
301 				defaultPropertiesTableModels.put(aspect, model);
302 				defaultPropertiesTable.setModel(model);
303 			}
304 		}
305 	}
306 
307 	/*
308 	 * Returns all the custom editors that have been supplied.
309 	 */
310 	private Editor[] getActiveEditors()
311 	{
312 		return (Editor[])activeEditors.toArray();
313 	}
314 }
315 
316 /* __oOo__ */