KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > form > layoutdesign > support > SwingLayoutCodeGenerator


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.form.layoutdesign.support;
21
22 import java.io.*;
23 import java.awt.*;
24 import java.util.*;
25 import java.util.List JavaDoc;
26 import javax.swing.*;
27
28 import org.netbeans.modules.form.layoutdesign.*;
29
30 /**
31  * Generates Java layout code based on the passed layout model.
32  *
33  * @author Jan Stola
34  */

35 public class SwingLayoutCodeGenerator {
36     private static final String JavaDoc LAYOUT_VAR_NAME = "layout"; // NOI18N
37
/** Layout model of the form. */
38     private LayoutModel layoutModel;
39     private String JavaDoc layoutVarName;
40     private boolean useLayoutLibrary;
41
42     /**
43      * Maps from component ID to <code>ComponentInfo</code>.
44      */

45     private Map/*<String,ComponentInfo>*/ componentIDMap;
46
47     /**
48      * Creates new <code>SwingLayoutCodeGenerator</code>.
49      *
50      * @param layoutModel layout model of the form.
51      */

52     public SwingLayoutCodeGenerator(LayoutModel layoutModel) {
53         componentIDMap = new HashMap/*<String,ComponentInfo>*/();
54         this.layoutModel = layoutModel;
55     }
56
57     /**
58      * Generates Java layout code for the specified container. The generated
59      * code is written to the <code>writer</code>.
60      *
61      * @param writer the writer to generate the code into.
62      * @param container container whose code should be generated.
63      * @param contVarName code expression for the container.
64      * @param compIds IDs of subcomponents.
65      * @param compVarNames code expressions of subcomponents.
66      */

67     public void generateContainerLayout(Writer writer, LayoutComponent container,
68         String JavaDoc contExprStr, String JavaDoc contVarName, ComponentInfo infos[],
69         boolean useLibrary) throws IOException {
70         useLayoutLibrary = useLibrary;
71         if (contVarName == null) {
72             layoutVarName = LAYOUT_VAR_NAME;
73         } else {
74             layoutVarName = contVarName + Character.toUpperCase(LAYOUT_VAR_NAME.charAt(0))
75                 + LAYOUT_VAR_NAME.substring(1);
76         }
77         fillMap(infos);
78         generateInstantiation(writer, contExprStr);
79         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
80         LayoutInterval horizontalInterval = container.getLayoutRoot(LayoutConstants.HORIZONTAL);
81         composeGroup(sb, horizontalInterval, true, true);
82         String JavaDoc horizontalGroup = sb.toString();
83         writer.write(layoutVarName + ".setHorizontalGroup(\n" + horizontalGroup + "\n);\n"); // NOI18N
84

85         sb = new StringBuffer JavaDoc();
86         composeLinks(sb, container, layoutVarName, LayoutConstants.HORIZONTAL);
87         String JavaDoc horizontalLinks = sb.toString();
88         writer.write(horizontalLinks);
89
90         sb = new StringBuffer JavaDoc();
91         LayoutInterval verticalInterval = container.getLayoutRoot(LayoutConstants.VERTICAL);
92         composeGroup(sb, verticalInterval, true, true);
93         String JavaDoc verticalGroup = sb.toString();
94         writer.write(layoutVarName + ".setVerticalGroup(\n" + verticalGroup + "\n);\n"); // NOI18N
95

96
97         sb = new StringBuffer JavaDoc();
98         composeLinks(sb, container, layoutVarName, LayoutConstants.VERTICAL);
99         String JavaDoc verticalLinks = sb.toString();
100         writer.write(verticalLinks);
101     }
102
103     /**
104      * Fills the <code>componentIDMap</code>.
105      *
106      * @param infos information about components.
107      */

108     private void fillMap(ComponentInfo[] infos) {
109         for (int counter = 0; counter < infos.length; counter++) {
110             componentIDMap.put(infos[counter].id, infos[counter]);
111         }
112     }
113     
114     /**
115      * Generates the "header" of the code e.g. instantiation of the layout
116      * and call to the <code>setLayout</code> method.
117      */

118     private void generateInstantiation(Writer writer, String JavaDoc contExprStr) throws IOException {
119         writer.write(getLayoutName() + " " + layoutVarName + " "); // NOI18N
120
writer.write("= new " + getLayoutName() + "(" + contExprStr + ");\n"); // NOI18N
121
writer.write(contExprStr + ".setLayout(" + layoutVarName + ");\n"); // NOI18N
122
}
123     
124     /**
125      * Generates layout code for a group that corresponds
126      * to the <code>interval</code>.
127      *
128      * @param layout buffer to generate the code into.
129      * @param interval layout model of the group.
130      */

131     private void composeGroup(StringBuffer JavaDoc layout, LayoutInterval interval,
132         boolean first, boolean last) throws IOException {
133         if (interval.isGroup()) {
134             int groupAlignment = interval.getGroupAlignment();
135             if (interval.isParallel()) {
136                 boolean notResizable = interval.getMaximumSize(false) == LayoutConstants.USE_PREFERRED_SIZE;
137                 String JavaDoc alignmentStr = convertAlignment(groupAlignment);
138                 layout.append(layoutVarName).append(".createParallelGroup("); // NOI18N
139
layout.append(alignmentStr);
140                 if (notResizable) {
141                     layout.append(", false"); // NOI18N
142
}
143                 layout.append(")"); // NOI18N
144
} else if (interval.isSequential()) {
145                 layout.append(layoutVarName).append(".createSequentialGroup()"); // NOI18N
146
} else {
147                 assert false;
148             }
149             if (interval.getSubIntervalCount() > 0) {
150                 layout.append("\n"); // NOI18N
151
}
152             Iterator subIntervals = interval.getSubIntervals();
153             while (subIntervals.hasNext()) {
154                 LayoutInterval subInterval = (LayoutInterval)subIntervals.next();
155                 fillGroup(layout, subInterval, first,
156                           last && (!interval.isSequential() || !subIntervals.hasNext()),
157                           groupAlignment);
158                 if (first && interval.isSequential()) {
159                     first = false;
160                 }
161                 if (subIntervals.hasNext()) {
162                     layout.append("\n"); // NOI18N
163
}
164             }
165         } else {
166             layout.append(layoutVarName).append(".createSequentialGroup()\n"); // NOI18N
167
fillGroup(layout, interval, true, true, LayoutConstants.DEFAULT);
168         }
169     }
170     
171     /**
172      * Generate layout code for one element in the group.
173      *
174      * @param layout buffer to generate the code into.
175      * @param interval layout model of the element.
176      * @param groupAlignment alignment of the enclosing group.
177      */

178     private void fillGroup(StringBuffer JavaDoc layout, LayoutInterval interval,
179         boolean first, boolean last, int groupAlignment) throws IOException {
180         if (interval.isGroup()) {
181             layout.append(getAddGroupStr());
182             int alignment = interval.getAlignment();
183             if ((alignment != LayoutConstants.DEFAULT) && interval.getParent().isParallel() && alignment != groupAlignment
184                     && alignment != LayoutConstants.BASELINE && groupAlignment != LayoutConstants.BASELINE) {
185                 String JavaDoc alignmentStr = convertAlignment(alignment);
186                 layout.append(alignmentStr).append(", "); // NOI18N
187
}
188             composeGroup(layout, interval, first, last);
189         } else {
190             int min = interval.getMinimumSize(false);
191             int pref = interval.getPreferredSize(false);
192             int max = interval.getMaximumSize(false);
193             if (interval.isComponent()) {
194                 layout.append(getAddComponentStr());
195                 int alignment = interval.getAlignment();
196                 LayoutComponent layoutComp = interval.getComponent();
197                 ComponentInfo info = (ComponentInfo)componentIDMap.get(layoutComp.getId());
198                 if (min == LayoutConstants.NOT_EXPLICITLY_DEFINED) {
199                     int dimension = (layoutComp.getLayoutInterval(LayoutConstants.HORIZONTAL) == interval) ? LayoutConstants.HORIZONTAL : LayoutConstants.VERTICAL;
200                     if ((dimension == LayoutConstants.HORIZONTAL) && info.clazz.getName().equals("javax.swing.JComboBox")) { // Issue 68612 // NOI18N
201
min = 0;
202                     } else if (pref >= 0) {
203                         int compMin = (dimension == LayoutConstants.HORIZONTAL) ? info.minSize.width : info.minSize.height;
204                         if (compMin > pref) {
205                             min = LayoutConstants.USE_PREFERRED_SIZE;
206                         }
207                     }
208                 }
209                 assert (info.variableName != null);
210                 if (interval.getParent().isSequential() || (alignment == LayoutConstants.DEFAULT) || (alignment == groupAlignment)
211                         || alignment == LayoutConstants.BASELINE || groupAlignment == LayoutConstants.BASELINE) {
212                     layout.append(info.variableName);
213                 } else {
214                     String JavaDoc alignmentStr = convertAlignment(alignment);
215                     if (useLayoutLibrary())
216                         layout.append(alignmentStr).append(", ").append(info.variableName); // NOI18N
217
else // in JDK the component comes first
218
layout.append(info.variableName).append(", ").append(alignmentStr); // NOI18N
219
}
220                 int status = SwingLayoutUtils.getResizableStatus(info.clazz);
221                 
222                 if (!((pref == LayoutConstants.NOT_EXPLICITLY_DEFINED) &&
223                     ((min == LayoutConstants.NOT_EXPLICITLY_DEFINED)
224                      || ((min == LayoutConstants.USE_PREFERRED_SIZE)
225                         && !info.sizingChanged
226                         && (status == SwingLayoutUtils.STATUS_NON_RESIZABLE))) &&
227                     ((max == LayoutConstants.NOT_EXPLICITLY_DEFINED)
228                      || ((max == LayoutConstants.USE_PREFERRED_SIZE)
229                         && !info.sizingChanged
230                         && (status == SwingLayoutUtils.STATUS_NON_RESIZABLE))
231                      || ((max == Short.MAX_VALUE)
232                         && !info.sizingChanged
233                         && (status == SwingLayoutUtils.STATUS_RESIZABLE))))) {
234                     layout.append(", "); // NOI18N
235
generateSizeParams(layout, min, pref, max);
236                 }
237             } else if (interval.isEmptySpace()) {
238                 if (interval.isDefaultPadding(false)) {
239                     if (first || last) {
240                         layout.append(getAddContainerGapStr());
241                     } else {
242                         layout.append(getAddPreferredGapStr());
243                         layout.append(getLayoutStyleName());
244                         if (!useLayoutLibrary())
245                             layout.append(".ComponentPlacement"); // NOI18N
246
layout.append(".RELATED"); // NOI18N
247
}
248                     if ((pref != LayoutConstants.NOT_EXPLICITLY_DEFINED)
249                         || ((max != LayoutConstants.NOT_EXPLICITLY_DEFINED)
250                             // NOT_EXPLICITLY_DEFINED is the same as USE_PREFERRED_SIZE in this case
251
&& (max != LayoutConstants.USE_PREFERRED_SIZE))) {
252                         if (!first && !last) {
253                             layout.append(',').append(' ');
254                         }
255                         layout.append(convertSize(pref)).append(", "); // NOI18N
256
layout.append(convertSize(max));
257                     }
258                 } else {
259                     if (min == LayoutConstants.USE_PREFERRED_SIZE) {
260                         min = pref;
261                     }
262                     if (max == LayoutConstants.USE_PREFERRED_SIZE) {
263                         max = pref;
264                     }
265                     layout.append(getAddGapStr());
266                     if (min < 0) min = pref; // min == GroupLayout.PREFERRED_SIZE
267
min = Math.min(pref, min);
268                     max = Math.max(pref, max);
269                     generateSizeParams(layout, min, pref, max);
270                 }
271             } else {
272                 assert false;
273             }
274         }
275         layout.append(")"); // NOI18N
276
}
277     
278     /**
279      * Generates minimum/preferred/maximum size parameters..
280      *
281      * @param layout buffer to generate the code into.
282      * @param min minimum size.
283      * @param pref preffered size.
284      * @param max maximum size.
285      */

286     private void generateSizeParams(StringBuffer JavaDoc layout, int min, int pref, int max) {
287         layout.append(convertSize(min)).append(", "); // NOI18N
288
layout.append(convertSize(pref)).append(", "); // NOI18N
289
layout.append(convertSize(max));
290     }
291
292     /**
293      * Converts alignment from the layout model constants
294      * to <code>GroupLayout</code> constants.
295      *
296      * @param alignment layout model alignment constant.
297      * @return <code>GroupLayout</code> alignment constant that corresponds
298      * to the given layout model one.
299      */

300     private String JavaDoc convertAlignment(int alignment) {
301         String JavaDoc groupAlignment = null;
302         switch (alignment) {
303             case LayoutConstants.LEADING: groupAlignment = "LEADING"; break; // NOI18N
304
case LayoutConstants.TRAILING: groupAlignment = "TRAILING"; break; // NOI18N
305
case LayoutConstants.CENTER: groupAlignment = "CENTER"; break; // NOI18N
306
case LayoutConstants.BASELINE: groupAlignment = "BASELINE"; break; // NOI18N
307
default: assert false; break;
308         }
309         return useLayoutLibrary() ?
310             getLayoutName() + "." + groupAlignment : // NOI18N
311
getLayoutName() + ".Alignment." + groupAlignment; // NOI18N
312
}
313     
314     /**
315      * Converts minimum/preferred/maximums size from the layout model constants
316      * to <code>GroupLayout</code> constants.
317      *
318      * @param size minimum/preferred/maximum size from layout model.
319      * @return minimum/preferred/maximum size or <code>GroupLayout</code> constant
320      * that corresponds to the given layout model one.
321      */

322     private String JavaDoc convertSize(int size) {
323         String JavaDoc convertedSize;
324         switch (size) {
325             case LayoutConstants.NOT_EXPLICITLY_DEFINED: convertedSize = getLayoutName() + ".DEFAULT_SIZE"; break; // NOI18N
326
case LayoutConstants.USE_PREFERRED_SIZE: convertedSize = getLayoutName() + ".PREFERRED_SIZE"; break; // NOI18N
327
case Short.MAX_VALUE: convertedSize = "Short.MAX_VALUE"; break; // NOI18N
328
default: assert (size >= 0); convertedSize = Integer.toString(size); break;
329         }
330         return convertedSize;
331     }
332
333     private void composeLinks(StringBuffer JavaDoc layout, LayoutComponent containerLC, String JavaDoc layoutVarName, int dimension) throws IOException {
334
335         Map linkSizeGroups = SwingLayoutUtils.createLinkSizeGroups(containerLC, dimension);
336         
337         Collection linkGroups = linkSizeGroups.values();
338         Iterator linkGroupsIt = linkGroups.iterator();
339         while (linkGroupsIt.hasNext()) {
340             List JavaDoc l = (List JavaDoc)linkGroupsIt.next();
341             // sort so that the generated line is always the same when no changes were made
342
Collections.sort(l, new Comparator() {
343                 public int compare(Object JavaDoc o1, Object JavaDoc o2) {
344                     String JavaDoc id1 =(String JavaDoc)o1;
345                     String JavaDoc id2 =(String JavaDoc)o2;
346                     ComponentInfo info1 = (ComponentInfo)componentIDMap.get(id1);
347                     ComponentInfo info2 = (ComponentInfo)componentIDMap.get(id2);
348                     return info1.variableName.compareTo(info2.variableName);
349                 }
350             });
351             if (l.size() > 1) {
352                 layout.append("\n\n" + layoutVarName + ".linkSize("); // NOI18N
353
if (!useLayoutLibrary()) {
354                     layout.append("javax.swing.SwingConstants"); // NOI18N
355
layout.append(dimension == LayoutConstants.HORIZONTAL ?
356                                   ".HORIZONTAL, " : ".VERTICAL, "); // NOI18N
357
}
358                 layout.append("new java.awt.Component[] {"); //NOI18N
359
Iterator i = l.iterator();
360                 boolean first = true;
361                 while (i.hasNext()) {
362                     String JavaDoc cid = (String JavaDoc)i.next();
363                     ComponentInfo info = (ComponentInfo)componentIDMap.get(cid);
364                     if (first) {
365                         first = false;
366                         layout.append(info.variableName);
367                     } else {
368                         layout.append(", " + info.variableName); // NOI18N
369
}
370                 }
371                 layout.append( "}"); // NOI18N
372
if (useLayoutLibrary()) {
373                     layout.append( ", "); // NOI18N
374
layout.append(getLayoutName());
375                     layout.append(dimension == LayoutConstants.HORIZONTAL ?
376                                   ".HORIZONTAL" : ".VERTICAL"); // NOI18N
377
}
378                 layout.append(");\n\n"); // NOI18N
379
}
380         }
381     }
382
383     /**
384      * Information about one component.
385      */

386     public static class ComponentInfo {
387         /** ID of the component. */
388         public String JavaDoc id;
389         /** Variable name of the component. */
390         public String JavaDoc variableName;
391         /** The component's class. */
392         public Class JavaDoc clazz;
393         /** The component's minimum size. */
394         public Dimension minSize;
395         /**
396          * Determines whether size properties (e.g. minimumSize, preferredSize
397          * or maximumSize properties of the component has been changed).
398          */

399         public boolean sizingChanged;
400     }
401
402     // -----
403
// type of generated code: swing-layout library vs JDK
404

405     boolean useLayoutLibrary() {
406         return useLayoutLibrary;
407     }
408
409     private String JavaDoc getLayoutName() {
410         return useLayoutLibrary() ? "org.jdesktop.layout.GroupLayout" : "javax.swing.GroupLayout"; // NOI18N
411
}
412
413     private String JavaDoc getLayoutStyleName() {
414         return useLayoutLibrary() ? "org.jdesktop.layout.LayoutStyle" : "javax.swing.LayoutStyle"; // NOI18N
415
}
416
417     private String JavaDoc getAddComponentStr() {
418         return useLayoutLibrary() ? ".add(" : ".addComponent("; // NOI18N
419
}
420
421     private String JavaDoc getAddGapStr() {
422         return useLayoutLibrary() ? ".add(" : ".addGap("; // NOI18N
423
}
424
425     private String JavaDoc getAddPreferredGapStr() {
426         return ".addPreferredGap("; // NOI18N
427
}
428
429     private String JavaDoc getAddContainerGapStr() {
430         return ".addContainerGap("; // NOI18N
431
}
432
433     private String JavaDoc getAddGroupStr() {
434         return useLayoutLibrary() ? ".add(" : ".addGroup("; // NOI18N
435
}
436 }
437
Popular Tags