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__ */