KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > form > layoutsupport > delegates > BoxLayoutSupport


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.layoutsupport.delegates;
21
22 import java.awt.*;
23 import java.beans.*;
24 import java.util.*;
25 import javax.swing.*;
26 import java.lang.reflect.Constructor JavaDoc;
27
28 import org.openide.nodes.Node;
29
30 import org.netbeans.modules.form.layoutsupport.*;
31 import org.netbeans.modules.form.codestructure.*;
32 import org.netbeans.modules.form.FormProperty;
33
34 /**
35  * Support class for BoxLayout. This is an example of support for layout
36  * manager which is not a JavaBean - some general functionality from
37  * AbstractLayoutSupport must be overridden and handled differently.
38  *
39  * @author Tran Duc Trung, Tomas Pavek
40  */

41 // Expects ltr orientation of the designer
42
public class BoxLayoutSupport extends AbstractLayoutSupport
43 {
44     private int axis = BoxLayout.LINE_AXIS;
45
46     private FormProperty[] properties;
47
48     private static Constructor JavaDoc boxLayoutConstructor;
49
50     /** Gets the supported layout manager class - BoxLayout.
51      * @return the class supported by this delegate
52      */

53     public Class JavaDoc getSupportedClass() {
54         return BoxLayout.class;
55     }
56
57     /** This method is called after a property of the layout is changed by
58      * the user. The delagate implementation may check whether the layout is
59      * valid after the change and throw PropertyVetoException if the change
60      * should be reverted.
61      * @param ev PropertyChangeEvent object describing the change
62      */

63     public void acceptContainerLayoutChange(PropertyChangeEvent ev)
64         throws PropertyVetoException
65     { // accept any change, just need to update the BoxLayout instance;
66
// since it has no properties, it must be create again
67
updateLayoutInstance();
68         super.acceptContainerLayoutChange(ev);
69     }
70
71     /** This method calculates position (index) for a component dragged
72      * over a container (or just for mouse cursor being moved over container,
73      * without any component).
74      * @param container instance of a real container over/in which the
75      * component is dragged
76      * @param containerDelegate effective container delegate of the container
77      * (for layout managers we always use container delegate instead of
78      * the container)
79      * @param component the real component being dragged; not needed here
80      * @param index position (index) of the component in its current container;
81      * not needed here
82      * @param posInCont position of mouse in the container delegate
83      * @param posInComp position of mouse in the dragged component;
84      * not needed here
85      * @return index corresponding to the position of the component in the
86      * container
87      */

88     public int getNewIndex(Container container,
89                            Container containerDelegate,
90                            Component component,
91                            int index,
92                            Point posInCont,
93                            Point posInComp)
94     {
95         if (!(containerDelegate.getLayout() instanceof BoxLayout))
96             return -1;
97         
98         assistantParams = 0;
99         Component[] components = containerDelegate.getComponents();
100         for (int i = 0; i < components.length; i++) {
101             if (components[i] == component) {
102                 assistantParams--;
103                 continue;
104             }
105             Rectangle b = components[i].getBounds();
106             if ((axis == BoxLayout.X_AXIS) || (axis == BoxLayout.LINE_AXIS)) {
107                 if (posInCont.x < b.x + b.width / 2) {
108                     assistantParams += i;
109                     return i;
110                 }
111             }
112             else {
113                 if (posInCont.y < b.y + b.height / 2) {
114                     assistantParams += i;
115                     return i;
116                 }
117             }
118         }
119         
120         assistantParams += components.length;
121         return components.length;
122     }
123
124     private int assistantParams;
125     public String JavaDoc getAssistantContext() {
126         return "boxLayout"; // NOI18N
127
}
128
129     public Object JavaDoc[] getAssistantParams() {
130         return new Object JavaDoc[] {Integer.valueOf(assistantParams+1)};
131     }
132
133
134     /** This method paints a dragging feedback for a component dragged over
135      * a container (or just for mouse cursor being moved over container,
136      * without any component).
137      * @param container instance of a real container over/in which the
138      * component is dragged
139      * @param containerDelegate effective container delegate of the container
140      * (for layout managers we always use container delegate instead of
141      * the container)
142      * @param component the real component being dragged, not needed here
143      * @param newConstraints component layout constraints to be presented;
144      * not used for BoxLayout
145      * @param newIndex component's index position to be presented
146      * @param g Graphics object for painting (with color and line style set)
147      * @return whether any feedback was painted (true in this case)
148      */

149     public boolean paintDragFeedback(Container container,
150                                      Container containerDelegate,
151                                      Component component,
152                                      LayoutConstraints newConstraints,
153                                      int newIndex,
154                                      Graphics g)
155     {
156         if (!(containerDelegate.getLayout() instanceof BoxLayout))
157             return false;
158
159         Component[] components = containerDelegate.getComponents();
160         Rectangle rect;
161
162         if ((components.length == 0) || ((components.length == 1) && (components[0] == component))) {
163             Insets ins = containerDelegate.getInsets();
164             rect = (axis == BoxLayout.X_AXIS || axis == BoxLayout.LINE_AXIS) ?
165                    new Rectangle(ins.left,
166                                  ins.top + (containerDelegate.getHeight()
167                                      - ins.top - ins.bottom - 20) / 2,
168                                  30, 20) :
169                    new Rectangle(ins.left + (containerDelegate.getWidth()
170                                      - ins.left - ins.right - 30) / 2,
171                                  ins.top,
172                                  30, 20);
173         }
174         else if (newIndex < 0 || newIndex >= components.length) {
175             Component comp = components[components.length - 1];
176             if (comp == component) {
177                 comp = components[components.length - 2];
178             }
179             Rectangle b = comp.getBounds();
180             rect = (axis == BoxLayout.X_AXIS || axis == BoxLayout.LINE_AXIS) ?
181                    new Rectangle(b.x + b.width - 10, b.y, 20, b.height) :
182                    new Rectangle(b.x, b.y + b.height - 10, b.width, 20);
183         }
184         else {
185             Rectangle b = components[newIndex].getBounds();
186             rect = (axis == BoxLayout.X_AXIS || axis == BoxLayout.LINE_AXIS) ?
187                    new Rectangle(b.x - 10, b.y, 20, b.height) :
188                    new Rectangle(b.x, b.y - 10, b.width, 20);
189         }
190
191         g.drawRect(rect.x, rect.y, rect.width, rect.height);
192
193         return true;
194     }
195
196     /** Sets up the layout (without adding components) on a real container,
197      * according to the internal metadata representation. This method must
198      * override AbstractLayoutSupport because BoxLayout instance cannot
199      * be used universally - new instance must be created for each container.
200      * @param container instance of a real container to be set
201      * @param containerDelegate effective container delegate of the container;
202      * for layout managers we always use container delegate instead of
203      * the container
204      */

205     public void setLayoutToContainer(Container container,
206                                      Container containerDelegate)
207     {
208         containerDelegate.setLayout(cloneLayoutInstance(container,
209                                                         containerDelegate));
210     }
211
212     public void addComponentsToContainer(Container container,
213                                          Container containerDelegate,
214                                          Component[] components,
215                                          int index) {
216         // Issue 63955 and JDK bug 4294758
217
((LayoutManager2)containerDelegate.getLayout()).invalidateLayout(containerDelegate);
218         super.addComponentsToContainer(container, containerDelegate, components, index);
219     }
220
221     // ------------
222

223     /** Creates a default instance of LayoutManager (for internal use).
224      * This method must override AbstractLayoutSupport because BoxLayout is not
225      * a bean (so it cannot be created automatically).
226      * @return new instance of BoxLayout
227      */

228     protected LayoutManager createDefaultLayoutInstance() {
229         return new BoxLayout(new JPanel(), BoxLayout.LINE_AXIS);
230     }
231
232     /** Cloning method - creates a clone of the reference LayoutManager
233      * instance (for external use). This method must override
234      * AbstractLayoutSupport because BoxLayout is not a bean (so it cannot be
235      * cloned automatically).
236      * @param container instance of a real container in whose container
237      * delegate the layout manager will be probably used
238      * @param containerDelegate effective container delegate of the container
239      * @return cloned instance of BoxLayout
240      */

241     protected LayoutManager cloneLayoutInstance(Container container,
242                                                 Container containerDelegate)
243     {
244         return new BoxLayout(containerDelegate, axis);
245     }
246
247     /** This method is to read the layout manager bean code (i.e. code for
248      * constructor and properties). As the BoxLayout is not a bean, this
249      * method must override AbstractLayoutSupport.
250      * @param layoutExp CodeExpressin of the layout manager
251      * @param layoutCode CodeGroup to be filled with relevant initialization
252      * code; not needed here because BoxLayout is represented only by
253      * a single constructor code expression and no statements
254      */

255     protected void readInitLayoutCode(CodeExpression layoutExp,
256                                       CodeGroup layoutCode)
257     {
258         CodeExpression[] params = layoutExp.getOrigin().getCreationParameters();
259         if (params.length == 2) {
260             FormCodeSupport.readPropertyExpression(
261                                 params[1], getProperties()[0], false);
262             updateLayoutInstance();
263         }
264     }
265
266     /** Creates code structures for a new layout manager (opposite to
267      * readInitLayoutCode). As the BoxLayout is not a bean, this method must
268      * override from AbstractLayoutSupport.
269      * @param layoutCode CodeGroup to be filled with relevant
270      * initialization code; not needed here because BoxLayout is
271      * represented only by a single constructor code expression and
272      * no statements
273      * @return new CodeExpression representing the BoxLayout
274      */

275     protected CodeExpression createInitLayoutCode(CodeGroup layoutCode) {
276         CodeStructure codeStructure = getCodeStructure();
277
278         CodeExpression[] params = new CodeExpression[2];
279         params[0] = getLayoutContext().getContainerDelegateCodeExpression();
280         params[1] = codeStructure.createExpression(
281                         FormCodeSupport.createOrigin(getProperties()[0]));
282
283         return codeStructure.createExpression(getBoxLayoutConstructor(),
284                                               params);
285     }
286
287     /** Since BoxLayout is not a bean, we must specify its properties
288      * explicitly. This method is called from getPropertySets() implementation
289      * to obtain the default property set for the layout (assuming there's only
290      * one property set). So it woul be also possible to override (more
291      * generally) getPropertySets() instead.
292      * @return array of properties of the layout manager
293      */

294     protected FormProperty[] getProperties() {
295         if (properties == null) {
296             // we cannot use RADProperty because "axis" is not a real
297
// bean property - we must create a special FormProperty
298
properties = new FormProperty[1];
299
300             properties[0] = new FormProperty(
301                                 "axis", // NOI18N
302
Integer.TYPE,
303                                 getBundle().getString("PROP_axis"), // NOI18N
304
getBundle().getString("HINT_axis")) // NOI18N
305
{
306                 public Object JavaDoc getTargetValue() {
307                     return new Integer JavaDoc(axis);
308                 }
309
310                 public void setTargetValue(Object JavaDoc value) {
311                     int ax = ((Integer JavaDoc)value).intValue();
312                     if (ax == BoxLayout.X_AXIS || ax == BoxLayout.Y_AXIS
313                             || ax == BoxLayout.LINE_AXIS || ax == BoxLayout.PAGE_AXIS) {
314                         axis = ax;
315                     }
316                 }
317
318                 public boolean supportsDefaultValue() {
319                     return true;
320                 }
321
322                 public Object JavaDoc getDefaultValue() {
323                     return new Integer JavaDoc(BoxLayout.LINE_AXIS);
324                 }
325
326                 public PropertyEditor getExpliciteEditor() {
327                     return new BoxAxisEditor();
328                 }
329             };
330             // [!!]
331
// properties[0].setPropertyContext(
332
// new FormPropertyContext.DefaultImpl(getContainer().getFormModel()));
333
}
334
335         return properties;
336     }
337
338     /** Method to obtain just one propetry of given name. Must be override
339      * AbstractLayoutSupport because alternative properties are used for
340      * BoxLayout (see getProperties method)
341      * @return layout property of given name
342      */

343     protected Node.Property getProperty(String JavaDoc propName) {
344         return "axis".equals(propName) ? getProperties()[0] : null; // NOI18N
345
}
346
347     // --------
348

349     private static Constructor JavaDoc getBoxLayoutConstructor() {
350         if (boxLayoutConstructor == null) {
351             try {
352                 boxLayoutConstructor = BoxLayout.class.getConstructor(
353                                 new Class JavaDoc[] { Container.class, Integer.TYPE });
354             }
355             catch (NoSuchMethodException JavaDoc ex) { // should not happen
356
ex.printStackTrace();
357             }
358         }
359         return boxLayoutConstructor;
360     }
361
362     // --------------
363

364     /** PropertyEditor for axis property of BoxLayoutSupport.
365      */

366     public static final class BoxAxisEditor extends PropertyEditorSupport {
367         private final String JavaDoc[] tags = {
368             getBundle().getString("VALUE_axis_line"), // NOI18N
369
getBundle().getString("VALUE_axis_page"), // NOI18N
370
getBundle().getString("VALUE_axis_x"), // NOI18N
371
getBundle().getString("VALUE_axis_y") // NOI18N
372
};
373         private final Integer JavaDoc[] values = {
374             new Integer JavaDoc(BoxLayout.LINE_AXIS),
375             new Integer JavaDoc(BoxLayout.PAGE_AXIS),
376             new Integer JavaDoc(BoxLayout.X_AXIS),
377             new Integer JavaDoc(BoxLayout.Y_AXIS)
378         };
379         private final String JavaDoc[] javaInitStrings = {
380             "javax.swing.BoxLayout.LINE_AXIS", // NOI18N
381
"javax.swing.BoxLayout.PAGE_AXIS", // NOI18N
382
"javax.swing.BoxLayout.X_AXIS", // NOI18N
383
"javax.swing.BoxLayout.Y_AXIS" // NOI18N
384
};
385
386         public String JavaDoc[] getTags() {
387             return tags;
388         }
389
390         public String JavaDoc getAsText() {
391             Object JavaDoc value = getValue();
392             for (int i=0; i<values.length; i++) {
393                 if (values[i].equals(value)) return tags[i];
394             }
395             return null;
396         }
397
398         public void setAsText(String JavaDoc str) {
399             for (int i=0; i<values.length; i++) {
400                 if (tags[i].equals(str)) {
401                     setValue(values[i]);
402                     break;
403                 }
404             }
405         }
406
407         public String JavaDoc getJavaInitializationString() {
408             Object JavaDoc value = getValue();
409             for (int i=0; i < values.length; i++)
410                 if (values[i].equals(value))
411                     return javaInitStrings[i];
412             return null;
413         }
414     }
415 }
416
Popular Tags