KickJava   Java API By Example, From Geeks To Geeks.

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


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.lang.reflect.Method JavaDoc;
25 import javax.swing.JButton JavaDoc;
26 import javax.swing.JSplitPane 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  * Dedicated layout support class for JSplitPane.
36  * @author Tomas Pavek
37  */

38
39 public class JSplitPaneSupport extends AbstractLayoutSupport {
40
41     private static Method JavaDoc setLeftComponentMethod;
42     private static Method JavaDoc setRightComponentMethod;
43     private static Method JavaDoc setTopComponentMethod;
44     private static Method JavaDoc setBottomComponentMethod;
45
46     private static final String JavaDoc LEFT_TOP_BUTTON = "cp_left_top_button"; // NOI18N
47
private static final String JavaDoc RIGHT_BOTTOM_BUTTON = "cp_right_bottom_button"; // NOI18N
48

49     /** Gets the supported layout manager class - JSplitPane.
50      * @return the class supported by this delegate
51      */

52     public Class JavaDoc getSupportedClass() {
53         return JSplitPane JavaDoc.class;
54     }
55     
56     /** This method calculates layout constraints for a component dragged
57      * over a container (or just for mouse cursor being moved over container,
58      * without any component).
59      * @param container instance of a real container over/in which the
60      * component is dragged
61      * @param containerDelegate effective container delegate of the container
62      * @param component the real component being dragged, not needed here
63      * @param index position (index) of the component in its container;
64      * not needed here
65      * @param posInCont position of mouse in the container
66      * @param posInComp position of mouse in the dragged component; not needed
67      * @return new LayoutConstraints object corresponding to the position of
68      * the component in the container
69      */

70     public LayoutConstraints getNewConstraints(Container container,
71                                                Container containerDelegate,
72                                                Component component,
73                                                int index,
74                                                Point posInCont,
75                                                Point posInComp)
76     {
77         if (!(container instanceof JSplitPane JavaDoc))
78             return null;
79
80         JSplitPane JavaDoc splitPane = (JSplitPane JavaDoc) container;
81         Dimension sz = splitPane.getSize();
82         int orientation = splitPane.getOrientation();
83
84     JButton JavaDoc left = (JButton JavaDoc) splitPane.getClientProperty(LEFT_TOP_BUTTON);
85     JButton JavaDoc right = (JButton JavaDoc) splitPane.getClientProperty(RIGHT_BOTTOM_BUTTON);
86     
87         if ( (left == null && right == null) ||
88          (left != null && right != null) )
89     {
90         String JavaDoc freePosition;
91             if (orientation == JSplitPane.HORIZONTAL_SPLIT) {
92                 if (posInCont.x <= sz.width / 2)
93                     freePosition = JSplitPane.LEFT;
94         else
95                     freePosition = JSplitPane.RIGHT;
96             }
97             else {
98                 if (posInCont.y <= sz.height / 2)
99                     freePosition = JSplitPane.TOP;
100         else
101                     freePosition = JSplitPane.BOTTOM;
102             }
103             assistantParams = freePosition;
104         return new SplitConstraints(freePosition);
105     }
106
107         assistantParams = findFreePosition();
108     return new SplitConstraints(assistantParams);
109     }
110
111     private String JavaDoc assistantParams;
112     public String JavaDoc getAssistantContext() {
113         return "splitPaneLayout"; // NOI18N
114
}
115
116     public Object JavaDoc[] getAssistantParams() {
117         return new Object JavaDoc[] {assistantParams};
118     }
119
120     /** This method paints a dragging feedback for a component dragged over
121      * a container (or just for mouse cursor being moved over container,
122      * without any component).
123      * @param container instance of a real container over/in which the
124      * component is dragged
125      * @param containerDelegate effective container delegate of the container
126      * @param component the real component being dragged; not needed here
127      * @param newConstraints component layout constraints to be presented
128      * @param newIndex component's index position to be presented; not needed
129      * @param g Graphics object for painting (with color and line style set)
130      * @return whether any feedback was painted (true in this case)
131      */

132     public boolean paintDragFeedback(Container container,
133                                      Container containerDelegate,
134                                      Component component,
135                                      LayoutConstraints newConstraints,
136                                      int newIndex,
137                                      Graphics g)
138     {
139         if (!(container instanceof JSplitPane JavaDoc))
140             return false;
141     
142         String JavaDoc position = (String JavaDoc) newConstraints.getConstraintsObject();
143         if (position == null)
144             return false;
145         
146         JSplitPane JavaDoc splitPane = (JSplitPane JavaDoc) container;
147         int orientation = splitPane.getOrientation();
148
149         Dimension sz = splitPane.getSize();
150         Insets insets = container.getInsets();
151         sz.width -= insets.left + insets.right;
152         sz.height -= insets.top + insets.bottom;
153
154         Rectangle rect = new Rectangle(insets.left, insets.top, sz.width, sz.height);
155
156         if (orientation == JSplitPane.HORIZONTAL_SPLIT) {
157             Component left = splitPane.getLeftComponent();
158             Component right = splitPane.getRightComponent();
159             
160             if (position == JSplitPane.LEFT) {
161                 if ((right == null) || (right == component)) {
162                     rect.width = sz.width / 2;
163                 }
164                 else {
165                     rect.width = right.getBounds().x - rect.x;
166                 }
167             }
168             else {
169                 if ((left == null) || (left == component)) {
170                     rect.x = insets.left + sz.width / 2;
171                     rect.width = sz.width - rect.x;
172                 }
173                 else {
174                     rect.x = left.getBounds().x + left.getBounds().width;
175                     rect.width = sz.width - rect.x;
176                 }
177             }
178         }
179         else {
180             Component top = splitPane.getTopComponent();
181             Component bottom = splitPane.getBottomComponent();
182             
183             if (position == JSplitPane.TOP) {
184                 if ((bottom == null) || (bottom == component)) {
185                     rect.height /= 2;
186                 }
187                 else {
188                     rect.height = bottom.getBounds().y - rect.y;
189                 }
190             }
191             else {
192                 if ((top == null) || (top == component)) {
193                     rect.y = insets.top + sz.height / 2;
194                     rect.height = sz.height - rect.y;
195                 }
196                 else {
197                     rect.y = top.getBounds().y + top.getBounds().height;
198                     rect.height = sz.height - rect.y;
199                 }
200             }
201         }
202         g.drawRect(rect.x, rect.y, rect.width, rect.height);
203         return true;
204     }
205
206     /** Adds real components to given container (according to layout
207      * constraints stored for the components).
208      * @param container instance of a real container to be added to
209      * @param containerDelegate effective container delegate of the container
210      * @param components components to be added
211      * @param index position at which to add the components to container
212      */

213     public void addComponentsToContainer(Container container,
214                                          Container containerDelegate,
215                                          Component[] components,
216                                          int index)
217     {
218         if (!(container instanceof JSplitPane JavaDoc))
219             return;
220     
221         for (int i=0; i < components.length; i++) {
222         JSplitPane JavaDoc splitPane = (JSplitPane JavaDoc) container;
223         
224             int descPos = convertPosition(getConstraints(i + index));
225             if (descPos == 0) {
226         if(splitPane.getClientProperty(LEFT_TOP_BUTTON)==null) {
227             // store the defaul swing button, so we can fall back to it
228
// if component[i] will be removed later...
229
splitPane.putClientProperty(LEFT_TOP_BUTTON, splitPane.getLeftComponent());
230         }
231         splitPane.setLeftComponent(components[i]);
232         }
233         else if (descPos == 1) {
234         if(splitPane.getClientProperty(RIGHT_BOTTOM_BUTTON)==null) {
235             // store the defaul swing button, so we can fall back to it
236
// if component[i] will be removed later...
237
splitPane.putClientProperty(RIGHT_BOTTOM_BUTTON, splitPane.getRightComponent());
238         }
239         splitPane.setRightComponent(components[i]);
240         }
241                 
242         }
243     }
244
245     /** Removes a real component from a real container.
246      * @param container instance of a real container
247      * @param containerDelegate effective container delegate of the container
248      * @param component component to be removed
249      * @return whether it was possible to remove the component (some containers
250      * may not support removing individual components reasonably)
251      */

252     public boolean removeComponentFromContainer(Container container,
253                                                 Container containerDelegate,
254                                                 Component component)
255     {
256     if( !(containerDelegate instanceof JSplitPane JavaDoc) ) {
257         return false; // should not happen
258
}
259     
260     JSplitPane JavaDoc splitPane = (JSplitPane JavaDoc) containerDelegate;
261     
262     if( component == splitPane.getLeftComponent() ) {
263         if( super.removeComponentFromContainer(container, containerDelegate, component) ) {
264         JButton JavaDoc left = (JButton JavaDoc) splitPane.getClientProperty(LEFT_TOP_BUTTON);
265         if( left != null ) {
266             // fall back to the default swing setting
267
splitPane.setLeftComponent(left);
268             splitPane.putClientProperty(LEFT_TOP_BUTTON, null);
269         }
270         return true;
271         }
272     } else if ( component == splitPane.getRightComponent() ) {
273         if( super.removeComponentFromContainer(container, containerDelegate, component) ) {
274         JButton JavaDoc right = (JButton JavaDoc) splitPane.getClientProperty(RIGHT_BOTTOM_BUTTON);
275         if( right != null ) {
276             // fall back to the default swing setting
277
splitPane.setRightComponent(right);
278             splitPane.putClientProperty(RIGHT_BOTTOM_BUTTON, null);
279         }
280         return true;
281         }
282     }
283     
284         return false;
285     }
286
287     /** Removes all components from given real container.
288      * @param container instance of a real container to be cleared
289      * @param containerDelegate effective container delegate of the container
290      * (e.g. like content pane of JFrame)
291      * @return whether it was possible to clear the container (some containers
292      * may not support this)
293      */

294     public boolean clearContainer(Container container,
295                                   Container containerDelegate)
296     {
297
298     // don't remove components which are a default part of JSplitPane
299

300     JSplitPane JavaDoc splitPane = (JSplitPane JavaDoc) container;
301     JButton JavaDoc left = (JButton JavaDoc) splitPane.getClientProperty(LEFT_TOP_BUTTON);
302     JButton JavaDoc right = (JButton JavaDoc) splitPane.getClientProperty(RIGHT_BOTTOM_BUTTON);
303     
304     if(left != null) {
305         // left/top component has already been set -> remove it
306
removeComponentFromContainer(container, containerDelegate, splitPane.getLeftComponent());
307     }
308     if(right != null) {
309         // right/bottom component has already been set -> remove it
310
removeComponentFromContainer(container, containerDelegate, splitPane.getRightComponent());
311     }
312     
313         return true;
314     }
315     
316     
317     // ------
318

319     /** This method is used for scanning code structures and recognizing
320      * components added to containers and their constraints. It's called from
321      * initialize method. When a relevant code statement is found, then the
322      * CodeExpression of component is get and added to component, and also the
323      * layout constraints information is read.
324      * @param statement CodeStatement to be tested if it contains relevant code
325      * @param componentCode CodeGroup to be filled with all component code
326      * @return CodeExpression representing found component; null if the
327      * statement is not relevant
328      */

329     protected CodeExpression readComponentCode(CodeStatement statement,
330                                                CodeGroup componentCode)
331     {
332         CodeExpression[] params = statement.getStatementParameters();
333         if (params.length != 1)
334             return null;
335
336         String JavaDoc position;
337
338         Object JavaDoc connectingObject = statement.getMetaObject();
339         if (getSetLeftComponentMethod().equals(connectingObject))
340             position = JSplitPane.LEFT;
341         else if (getSetRightComponentMethod().equals(connectingObject))
342             position = JSplitPane.RIGHT;
343         else if (getSetTopComponentMethod().equals(connectingObject))
344             position = JSplitPane.TOP;
345         else if (getSetBottomComponentMethod().equals(connectingObject))
346             position = JSplitPane.BOTTOM;
347         else return null;
348
349         SplitConstraints constr = new SplitConstraints(position);
350         getConstraintsList().add(constr);
351
352         componentCode.addStatement(statement);
353
354         return params[0];
355     }
356
357     /** Creates code for a component added to the layout (opposite to
358      * readComponentCode method).
359      * @param componentCode CodeGroup to be filled with complete component code
360      * (code for initializing the layout constraints and adding the
361      * component to the layout)
362      * @param componentExpression CodeExpression object representing component
363      * @param index position of the component in the layout
364      */

365     protected void createComponentCode(CodeGroup componentCode,
366                                        CodeExpression componentExpression,
367                                        int index)
368     {
369         LayoutConstraints constr = getConstraints(index);
370         if (!(constr instanceof SplitConstraints))
371             return; // should not happen
372

373         ((SplitConstraints)constr).createComponentCode(
374                                componentCode,
375                                getLayoutContext().getContainerCodeExpression(),
376                                componentExpression);
377     }
378
379     /** This method is called to get a default component layout constraints
380      * metaobject in case it is not provided (e.g. in addComponents method).
381      * @return the default LayoutConstraints object for the supported layout;
382      * null if no component constraints are used
383      */

384     protected LayoutConstraints createDefaultConstraints() {
385         return new SplitConstraints(findFreePosition());
386     }
387
388     // ------------
389

390     private int convertPosition(LayoutConstraints desc) {
391         Object JavaDoc position = desc.getConstraintsObject();
392         if (JSplitPane.LEFT.equals(position) || JSplitPane.TOP.equals(position))
393             return 0;
394         if (JSplitPane.RIGHT.equals(position) || JSplitPane.BOTTOM.equals(position))
395             return 1;
396         return -1;
397     }
398
399     private String JavaDoc findFreePosition() {
400         int leftTop = 0, rightBottom = 0;
401         int orientation = JSplitPane.HORIZONTAL_SPLIT;
402     
403         for (int i=0, n=getComponentCount(); i < n; i++) {
404             LayoutConstraints constraints = getConstraints(i);
405             if (!(constraints instanceof SplitConstraints))
406                 continue;
407
408             int constrPos = convertPosition(constraints);
409             if (constrPos == 0)
410                 leftTop++;
411             else if (constrPos == 1)
412                 rightBottom++;
413         }
414
415         if (leftTop == 0 || leftTop < rightBottom)
416             return orientation == JSplitPane.HORIZONTAL_SPLIT ?
417                 JSplitPane.LEFT : JSplitPane.TOP;
418         else
419             return orientation == JSplitPane.HORIZONTAL_SPLIT ?
420                 JSplitPane.RIGHT : JSplitPane.BOTTOM;
421     }
422
423     // --------
424

425     private static Method JavaDoc getSetLeftComponentMethod() {
426         if (setLeftComponentMethod == null)
427             setLeftComponentMethod = getAddMethod("setLeftComponent"); // NOI18N
428
return setLeftComponentMethod;
429     }
430
431     private static Method JavaDoc getSetRightComponentMethod() {
432         if (setRightComponentMethod == null)
433             setRightComponentMethod = getAddMethod("setRightComponent"); // NOI18N
434
return setRightComponentMethod;
435     }
436
437     private static Method JavaDoc getSetTopComponentMethod() {
438         if (setTopComponentMethod == null)
439             setTopComponentMethod = getAddMethod("setTopComponent"); // NOI18N
440
return setTopComponentMethod;
441     }
442
443     private static Method JavaDoc getSetBottomComponentMethod() {
444         if (setBottomComponentMethod == null)
445             setBottomComponentMethod = getAddMethod("setBottomComponent"); // NOI18N
446
return setBottomComponentMethod;
447     }
448
449     private static Method JavaDoc getAddMethod(String JavaDoc name) {
450         try {
451             return JSplitPane JavaDoc.class.getMethod(name,
452                                               new Class JavaDoc[] { Component.class });
453         }
454         catch (NoSuchMethodException JavaDoc ex) { // should not happen
455
ex.printStackTrace();
456         }
457         return null;
458     }
459
460     // -----------
461

462     /** LayoutConstraints implementation holding component position in
463      * JSplitPane.
464      */

465     public static class SplitConstraints implements LayoutConstraints {
466         private String JavaDoc position;
467
468         private Node.Property[] properties;
469
470         private CodeExpression containerExpression;
471         private CodeExpression componentExpression;
472         private CodeGroup componentCode;
473
474         public SplitConstraints(String JavaDoc position) {
475             this.position = position;
476         }
477
478         public Node.Property[] getProperties() {
479             if (properties == null) {
480                 properties = new Node.Property[] {
481                     new FormProperty(
482                             "SplitConstraints splitPosition", // NOI18N
483
String JavaDoc.class,
484                             getBundle().getString("PROP_splitPos"), // NOI18N
485
getBundle().getString("HINT_splitPos")) // NOI18N
486
{
487                         public Object JavaDoc getTargetValue() {
488                             return position;
489                         }
490                         public void setTargetValue(Object JavaDoc value) {
491                             position = (String JavaDoc)value;
492                         }
493                         public PropertyEditor getExpliciteEditor() {
494                             return new SplitPositionEditor();
495                         }
496                         protected void propertyValueChanged(Object JavaDoc old,
497                                                             Object JavaDoc current) {
498                             if (isChangeFiring())
499                                 updateCode();
500                             super.propertyValueChanged(old, current);
501                         }
502                         public void setPropertyContext(
503                             org.netbeans.modules.form.FormPropertyContext ctx)
504                         { // disabling this method due to limited persistence
505
} // capabilities (compatibility with previous versions)
506
}
507                 };
508                 properties[0].setValue("NOI18N", Boolean.TRUE); // NOI18N
509
}
510
511             return properties;
512         }
513
514         public Object JavaDoc getConstraintsObject() {
515             return position;
516         }
517
518         public LayoutConstraints cloneConstraints() {
519             return new SplitConstraints(position);
520         }
521
522         private void createComponentCode(CodeGroup compCode,
523                                          CodeExpression contExp,
524                                          CodeExpression compExp)
525         {
526             componentCode = compCode;
527             containerExpression = contExp;
528             componentExpression = compExp;
529             updateCode();
530         }
531
532         private void updateCode() {
533             if (componentCode == null)
534                 return;
535
536             CodeStructure.removeStatements(
537                 componentCode.getStatementsIterator());
538             componentCode.removeAll();
539
540             Method JavaDoc addMethod;
541             if (JSplitPane.LEFT.equals(position))
542                 addMethod = getSetLeftComponentMethod();
543             else if (JSplitPane.RIGHT.equals(position))
544                 addMethod = getSetRightComponentMethod();
545             else if (JSplitPane.TOP.equals(position))
546                 addMethod = getSetTopComponentMethod();
547             else if (JSplitPane.BOTTOM.equals(position))
548                 addMethod = getSetBottomComponentMethod();
549             else return;
550
551             componentCode.addStatement(
552                     CodeStructure.createStatement(
553                            containerExpression,
554                            addMethod,
555                            new CodeExpression[] { componentExpression }));
556         }
557     }
558
559     static class SplitPositionEditor extends PropertyEditorSupport {
560         private final String JavaDoc[] values = {
561             JSplitPane.LEFT,
562             JSplitPane.RIGHT,
563             JSplitPane.TOP,
564             JSplitPane.BOTTOM
565         };
566
567         public String JavaDoc[] getTags() {
568             return values;
569         }
570
571         public String JavaDoc getAsText() {
572             return (String JavaDoc)getValue();
573         }
574
575         public void setAsText(String JavaDoc str) {
576             for (int i = 0; i < values.length; i++)
577                 if (str.equals(values[i])) {
578                     setValue(str);
579                     break;
580                 }
581         }
582     }
583     
584 }
585
Popular Tags