1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.mlc.swing.layout;
31
32 import com.jgoodies.forms.layout.CellConstraints;
33 import com.jgoodies.forms.layout.FormLayout;
34 import java.awt.Component;
35 import java.awt.LayoutManager2;
36 import java.beans.*;
37 import java.lang.reflect.Method;
38 import java.util.*;
39
40 /***
41 * This class acts as a surogate layout manager for the JGoodies
42 * (www.jgoodies.com) FormLayout manager. This layout manager enables us to
43 * associate names with components and then define the constraints for the
44 * component elsewhere (like xml)
45 *
46 * @author Michael Connor
47 */
48 public class ContainerLayout implements LayoutManager2
49 {
50 java.util.List<String> rowSpecs = new ArrayList<String>();
51
52 java.util.List<String> columnSpecs = new ArrayList<String>();
53
54 LinkedHashMap<String, CellConstraints> componentConstraints = new LinkedHashMap<String, CellConstraints>();
55
56 Map<Component, String> componentsToNames = new HashMap<Component, String>();
57
58 Map<String, Map<String, Object>> componentNameToCustomProps = new HashMap<String, Map<String, Object>>();
59
60 Map<String, ComponentDef> componentNameToComponentDef = new HashMap<String, ComponentDef>();
61
62 FormLayout formLayout;
63
64 String name;
65
66 public ContainerLayout(String name, String columnSpecs, String rowSpecs)
67 {
68 this.name = name;
69 StringTokenizer cols = new StringTokenizer(columnSpecs, ",", false);
70 StringTokenizer rows = new StringTokenizer(rowSpecs, ",", false);
71
72 while (cols.hasMoreTokens())
73 this.columnSpecs.add(cols.nextToken());
74
75 while (rows.hasMoreTokens())
76 this.rowSpecs.add(rows.nextToken());
77
78 formLayout = new FormLayout(columnSpecs, rowSpecs);
79
80 }
81
82 private void buildLayout() throws IllegalArgumentException
83 {
84 formLayout = new FormLayout(delimit(columnSpecs), delimit(rowSpecs));
85
86
87 for (Iterator i = componentsToNames.keySet().iterator(); i.hasNext();)
88 {
89 Component component = (Component) i.next();
90 String componentName = componentsToNames.get(component);
91 CellConstraints constraints = componentConstraints.get(componentName);
92 formLayout.addLayoutComponent(component, constraints);
93 }
94 }
95
96 private String delimit(List<String> values)
97 {
98 StringBuffer buffer = new StringBuffer();
99
100 for (int index = 0; index < values.size(); index++)
101 {
102 buffer.append(values.get(index));
103 if (index < values.size() - 1)
104 buffer.append(",");
105 }
106
107 return buffer.toString();
108 }
109
110 protected Map<Component, String> getComponentsToNames()
111 {
112 return Collections.unmodifiableMap(componentsToNames);
113 }
114
115 /***
116 * Registers the value of the name property
117 *
118 * @param name
119 * The value of the property
120 */
121 public void setName(String name)
122 {
123 this.name = name;
124 }
125
126 /***
127 * Returns the value of the name property
128 *
129 * @return The value
130 */
131 public String getName()
132 {
133 return this.name;
134 }
135
136 /***
137 * Returns custom properties for the component. If no custom props exist then
138 * an empty map will be returned.
139 */
140 public Map<String, Object> getCustomProperties(String componentName)
141 {
142 return componentNameToCustomProps.containsKey(componentName) ? componentNameToCustomProps
143 .get(componentName)
144 : new HashMap<String, Object>();
145 }
146
147 /***
148 * Set a user defined property for this component so that the tool can manage
149 * the properties of the component thus reducing the burden on the user
150 */
151 public void setProperty(String componentName, String property, Object value)
152 {
153 Map<String, Object> customProps = componentNameToCustomProps.get(componentName);
154 if (customProps == null)
155 {
156 customProps = new HashMap<String, Object>();
157 componentNameToCustomProps.put(componentName, customProps);
158 }
159 customProps.put(property, value);
160 }
161
162 public void setCellConstraints(String componentName,
163 CellConstraints constraints)
164 {
165 componentConstraints.put(name, constraints);
166
167 for (Iterator i = componentsToNames.keySet().iterator(); i.hasNext();)
168 {
169 Component component = (Component) i.next();
170 String thisName = componentsToNames.get(component);
171 if (thisName.equals(componentName))
172 {
173 formLayout.setConstraints(component, constraints);
174 break;
175 }
176 }
177 }
178
179 public LinkedHashMap<String, CellConstraints> getCellConstraints()
180 {
181 return componentConstraints;
182 }
183
184 public void addComponent(String componentName, ComponentDef componentDef,
185 CellConstraints constraints)
186 {
187 componentConstraints.put(componentName, constraints);
188 componentNameToComponentDef.put(componentName, componentDef);
189 }
190
191 public ComponentDef getComponentDef(String componentName)
192 {
193 return componentNameToComponentDef.get(componentName);
194 }
195
196 public String getColumnSpecsString()
197 {
198 StringBuffer buffer = new StringBuffer();
199 for (Iterator i = columnSpecs.iterator(); i.hasNext();)
200 {
201 buffer.append(i.next());
202 if (i.hasNext())
203 buffer.append(",");
204 }
205
206 return buffer.toString();
207 }
208
209 public String getRowSpecsString()
210 {
211 StringBuffer buffer = new StringBuffer();
212 for (Iterator i = rowSpecs.iterator(); i.hasNext();)
213 {
214 buffer.append(i.next());
215 if (i.hasNext())
216 buffer.append(",");
217 }
218
219 return buffer.toString();
220 }
221
222 public int getRowCount()
223 {
224 return rowSpecs.size();
225 }
226
227 public int getColumnCount()
228 {
229 return columnSpecs.size();
230 }
231
232 public List<String> getRowSpecs()
233 {
234 return this.rowSpecs;
235 }
236
237 public List<String> getColumnSpecs()
238 {
239 return this.columnSpecs;
240 }
241
242 public void constraintsChanged(String name, CellConstraints constraints)
243 {
244 componentConstraints.put(name, constraints);
245 }
246
247 public CellConstraints getCellConstraints(String name)
248 {
249 return componentConstraints.get(name);
250 }
251
252 public void addCellConstraints(String name, CellConstraints constraints)
253 {
254 componentConstraints.put(name, constraints);
255 }
256
257 public CellConstraints removeCellConstraints(String name)
258 {
259 CellConstraints constraints = (CellConstraints) componentConstraints
260 .remove(name);
261 return constraints;
262 }
263
264 public void addColumnSpec(String columnSpec) throws IllegalArgumentException
265 {
266 columnSpecs.add(columnSpec);
267 buildLayout();
268 }
269
270 public String getRowSpec(int index)
271 {
272 return rowSpecs.get(index);
273 }
274
275 public String getColumnSpec(int index)
276 {
277 return columnSpecs.get(index);
278 }
279
280 public void setRowSpec(int index, String rowSpec)
281 throws IllegalArgumentException
282 {
283 rowSpecs.set(index, rowSpec);
284 buildLayout();
285 }
286
287 public void setColumnSpec(int index, String columnSpec)
288 throws IllegalArgumentException
289 {
290 columnSpecs.set(index, columnSpec);
291 buildLayout();
292 }
293
294 public void addRowSpec(String rowSpec) throws IllegalArgumentException
295 {
296 rowSpecs.add(rowSpec);
297 buildLayout();
298 }
299
300 public String removeRowSpec(int index)
301 {
302 String rowSpec = (String) rowSpecs.remove(index);
303 try
304 {
305 buildLayout();
306 }
307 catch (IllegalArgumentException e)
308 {
309 throw new RuntimeException(e);
310 }
311
312 return rowSpec;
313 }
314
315 public String removeColumnSpec(int index)
316 {
317 String spec = columnSpecs.remove(index);
318 try
319 {
320 buildLayout();
321 }
322 catch (IllegalArgumentException e)
323 {
324 throw new RuntimeException(e);
325 }
326
327 return spec;
328 }
329
330 public void addRowSpec(int index, String rowSpec)
331 throws IllegalArgumentException
332 {
333 rowSpecs.add(index, rowSpec);
334 buildLayout();
335 }
336
337 public void addColumnSpec(int index, String columnSpec)
338 throws IllegalArgumentException
339 {
340 columnSpecs.add(index, columnSpec);
341 buildLayout();
342 }
343
344
345
346 public String getComponentName(Component component)
347 {
348 return componentsToNames.get(component);
349 }
350
351 /***
352 * Returns the component with the given name or null if not found
353 */
354 public Component getComponentByName(String name)
355 {
356 for (Component component : componentsToNames.keySet())
357 {
358 String testName = componentsToNames.get(component);
359 if (testName.equals(name))
360 return component;
361 }
362 return null;
363 }
364
365 public CellConstraints getComponentConstraints(Component component)
366 {
367 String name = componentsToNames.get(component);
368 if (name == null)
369 throw new RuntimeException("Unable to find name for component "
370 + component);
371 return componentConstraints.get(name);
372 }
373
374
375 public void addLayoutComponent(String name, java.awt.Component comp)
376 {
377 throw new RuntimeException(
378 "This method should not be called. Call addLayoutComponent (Component, Object) instead");
379 }
380
381 public float getLayoutAlignmentX(java.awt.Container target)
382 {
383 return formLayout.getLayoutAlignmentX(target);
384 }
385
386 public float getLayoutAlignmentY(java.awt.Container target)
387 {
388 return formLayout.getLayoutAlignmentY(target);
389 }
390
391 public FormLayout.LayoutInfo getLayoutInfo(java.awt.Container container)
392 {
393
394 return this.formLayout.getLayoutInfo(container);
395 }
396
397 public void invalidateLayout(java.awt.Container target)
398 {
399 formLayout.invalidateLayout(target);
400 }
401
402 public void layoutContainer(java.awt.Container parent)
403 {
404 formLayout.layoutContainer(parent);
405 }
406
407 public java.awt.Dimension maximumLayoutSize(java.awt.Container target)
408 {
409 return formLayout.maximumLayoutSize(target);
410 }
411
412 public java.awt.Dimension minimumLayoutSize(java.awt.Container parent)
413 {
414 return formLayout.minimumLayoutSize(parent);
415 }
416
417 public java.awt.Dimension preferredLayoutSize(java.awt.Container parent)
418 {
419 return formLayout.preferredLayoutSize(parent);
420 }
421
422 public void removeLayoutComponent(java.awt.Component comp)
423 {
424 String componentName = componentsToNames.get(comp);
425 componentsToNames.remove(comp);
426 componentConstraints.remove(componentName);
427 formLayout.removeLayoutComponent(comp);
428 }
429
430 public void addLayoutComponent(java.awt.Component comp, Object constraints)
431 {
432 if (!(constraints instanceof String))
433 throw new RuntimeException(
434 "The constraints must be a String name which should reference a CellConstraints entry in the xml file");
435 String componentName = (String) constraints;
436 CellConstraints cellConstraints = componentConstraints.get(componentName);
437 if (cellConstraints == null)
438 {
439 System.out.println("Warning : " + componentName
440 + " was added without constraints");
441 cellConstraints = new CellConstraints();
442 componentConstraints.put(componentName, cellConstraints);
443 comp.setVisible(false);
444 }
445 else
446 {
447
448 Map<String, Object> customProps = componentNameToCustomProps
449 .get(componentName);
450 if (customProps != null)
451 {
452 for (String prop : customProps.keySet())
453 {
454 Object value = customProps.get(prop);
455
456 try
457 {
458 BeanInfo beanInfo = Introspector.getBeanInfo(comp.getClass());
459 PropertyDescriptor[] props = beanInfo.getPropertyDescriptors();
460 for (int index = 0; index < props.length; index++)
461 {
462 PropertyDescriptor propertyDescriptor = props[index];
463 if (propertyDescriptor.getName().equals(prop))
464 {
465 Method writeMethod = propertyDescriptor.getWriteMethod();
466 writeMethod.invoke(comp, new Object[] { value });
467 break;
468 }
469 }
470 }
471 catch (Exception e)
472 {
473 throw new RuntimeException(e);
474 }
475 }
476 }
477 }
478
479 componentsToNames.put(comp, componentName);
480 formLayout.addLayoutComponent(comp, cellConstraints);
481 }
482
483 private class LocationScore implements Comparable<LocationScore>
484 {
485 public int score;
486
487 public int row;
488
489 public int col;
490
491 public int width;
492
493 public LocationScore(int score, int row, int col, int width)
494 {
495 this.score = score;
496 this.row = row;
497 this.col = col;
498 this.width = width;
499 }
500
501 public int compareTo(LocationScore testScore)
502 {
503 return this.score < testScore.score ? -1
504 : this.score > testScore.score ? 1 : 0;
505 }
506 }
507
508 public static void main(String[] args)
509 {
510 }
511
512 }