KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > xam > ui > layout > JSplitterBar


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-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.xml.xam.ui.layout;
21
22 import java.awt.Component JavaDoc;
23 import java.awt.Container JavaDoc;
24 import java.awt.Cursor JavaDoc;
25 import java.awt.Dimension JavaDoc;
26 import java.awt.Frame JavaDoc;
27 import java.awt.Graphics JavaDoc;
28 import java.awt.Insets JavaDoc;
29 import java.awt.Point JavaDoc;
30 import java.awt.Rectangle JavaDoc;
31 import java.awt.Window JavaDoc;
32 import java.awt.event.MouseEvent JavaDoc;
33 import javax.swing.JPanel JavaDoc;
34 import javax.swing.JScrollPane JavaDoc;
35 import javax.swing.JViewport JavaDoc;
36 import javax.swing.SwingUtilities JavaDoc;
37
38 /**
39  * A class that implements a splitter bar. It is only intended to be used
40  * in a SplitterLayout. Because it is dervied from Panel, a JSplitterBar
41  * can do anything a normal panel can do. However, if you add any
42  * components to this panel, the scroll handle will not be accessible. In a
43  * case like this, you need to explicitly add a JSplitterSpace component to the
44  * JSplitterBar, guaranteeing a place for the handle to be available.
45  * <p/>
46  * <p>Use this code at your own risk! MageLang Institute is not
47  * responsible for any damage caused directly or indirctly through
48  * use of this code.
49  * <p><p>
50  * <b>SOFTWARE RIGHTS</b>
51  * <p/>
52  * MageLang support classes, version 1.0, MageLang Institute
53  * <p/>
54  * We reserve no legal rights to this code--it is fully in the
55  * public domain. An individual or company may do whatever
56  * they wish with source code distributed with it, including
57  * including the incorporation of it into commerical software.
58  * <p/>
59  * <p>However, this code cannot be sold as a standalone product.
60  * <p/>
61  * We encourage users to develop software with this code. However,
62  * we do ask that credit is given to us for developing it
63  * By "credit", we mean that if you use these components or
64  * incorporate any source code into one of your programs
65  * (commercial product, research project, or otherwise) that
66  * you acknowledge this fact somewhere in the documentation,
67  * research report, etc... If you like these components and have
68  * developed a nice tool with the output, please mention that
69  * you developed it using these components. In addition, we ask that
70  * the headers remain intact in our source code. As long as these
71  * guidelines are kept, we expect to continue enhancing this
72  * system and expect to make other tools available as they are
73  * completed.
74  * <p/>
75  * The MageLang Support Classes Gang:
76  *
77  * @author <a HREF="http:www.scruz.net/~thetick">Scott Stanchfield</a>, <a HREF=http://www.MageLang.com>MageLang Institute</a>
78  * @version MageLang Support Classes 1.0, MageLang Insitute, 1997
79  * @see SplitterLayout
80  * @see JSplitterSpace
81  *
82  * @author Santhosh Kumar - santhosh@in.fiorano.com
83  *
84  * @author Jeri Lockhart - jeri.lockhart@sun.com
85  * Modified for use in the NbColumnView widget. Only Horizontal layout is supported.
86  * When the user moves the splitter bar to the left, the column that is adjacent to the
87  * left maintains its minimum size.
88  * When the user moves the splitter bar to the right, the columns to the right of the
89  * splitter bar, maintain their widths.
90  *
91  * mouseDrag() - creates a visible bar to show where the splitter can be dragged.
92  * The limit of leftward dragging is the boundary of the min size of the column to the left
93  * of the splitter.
94  * The limit of rightward dragging is the parent container's right boundary.
95  *
96  * mouseRelease() - sets the bounds of the actual splitter. Calls
97  * checkOtherComponents().
98  *
99  * checkOtherComponenets() - For leftward drag: Make the column to the left of
100  * this splitter more narrow. Then, set the bounds of the columns and splitters
101  * to the right of this splitter so that they are relocated by the correct
102  * offset to the left, maintaining their respective widths.
103  *
104  * For rightward drag: Make the column to the left of this splitter wider.
105  * Then, set the bounds of the columns and splitters to the right of this splitter
106  * so that they are relocated by the correct offset towards the right,
107  * maintaining their respective widths.
108  *
109  */

110 public class JSplitterBar extends JPanel JavaDoc{
111     
112     static final long serialVersionUID = 1L;
113     static final Cursor JavaDoc VERT_CURSOR = new Cursor JavaDoc(Cursor.N_RESIZE_CURSOR);
114     static final Cursor JavaDoc HORIZ_CURSOR = new Cursor JavaDoc(Cursor.E_RESIZE_CURSOR);
115     static final Cursor JavaDoc DEF_CURSOR = new Cursor JavaDoc(Cursor.DEFAULT_CURSOR);
116     private int orientation = SplitterLayout.HORIZONTAL;
117     
118     private boolean alreadyDrawn = false;
119     private Rectangle JavaDoc originalBounds = null;
120     private Window JavaDoc wBar;
121     private boolean mouseInside = false;
122     
123     /**
124      * Creates a new SpliiterBar
125      */

126     public JSplitterBar(){
127         addMouseMotionListener(new SplitterBarMouseMotionListener(this));
128         addMouseListener(new SplitterBarMouseListener(this));
129     }
130     
131     private void checkOtherComponents(){
132         //System.out.println("checkOtherComponents start");
133
Rectangle JavaDoc currBounds = getBounds(); // get current position
134
Component JavaDoc comps[] = getParent().getComponents();
135         
136         // orientation == HORIZONTAL
137
if(currBounds.x<originalBounds.x){ // moved left
138
//System.out.println("checkOtherComponents moved left");
139
int offset = originalBounds.x - currBounds.x;
140             //System.out.println("checkOtherComnponents offset" + offset);
141
for (int i = 0; i < comps.length; i++){
142                 if (comps[i] == this){
143                     // make left column more narrow
144
assert i-1>-1:"There should be a column to the left of this splitter";
145                     if (i-1 > -1){
146                         Rectangle JavaDoc oldB = comps[i-1].getBounds();
147                         //System.out.println("checkOtherComponents left col orig bounds " + oldB);
148
comps[i-1].setBounds(oldB.x, oldB.y, oldB.width-offset, oldB.height);
149                         //System.out.println("checkOtherComponents make left comp narrower" + (i-1));
150
}
151                     // move left all columns and splitters to the right of this splitter
152
// set all visible
153
for (int k = i+1; k < comps.length; k++){
154                         Rectangle JavaDoc old = comps[k].getBounds();
155                         //System.out.println("checkOtherComponents " + k + " orig bounds " + old);
156
comps[k].setBounds(old.x-offset, old.y, old.width, old.height);
157                         //System.out.println("checkOtherComponents move right comps to the left, set bounds "+ comps[k] + " " + comps[k].getBounds());
158
comps[k].setVisible(true);
159                         
160                     }
161                 }
162             }
163         } // HORIZONTAL -- end moved left
164
else if(currBounds.x>originalBounds.x){ // moved right
165
//System.out.println("checkOtherComponents moved right");
166
int offset = currBounds.x - originalBounds.x;
167             //System.out.println("checkOtherComnponents offset" + offset);
168
// widen the column to the left of this splitter
169
Component JavaDoc left = null;
170             int thisIdx = -1;
171             for (int i = 0; i < comps.length; i++){
172                 if(comps[i] == this){
173                     thisIdx = i;
174                     assert i>0:"There should be a column to the left of this splitter.";
175                     if (i-1 > -1){
176                         left = comps[i-1];
177                         Rectangle JavaDoc old = left.getBounds();
178                         left.setBounds(old.x, old.y, old.width+offset, old.height);
179                         //System.out.println("checkOtherComponents set bounds "+ (i-1) + " " + left.getBounds());
180
}
181                 }
182             }
183             
184             // relocate the columns and splitters to the right of this splitter
185
if (thisIdx+1 < comps.length) {
186                 for (int j = thisIdx+1; j < comps.length; j++){
187                     Rectangle JavaDoc old = comps[j].getBounds();
188                     comps[j].setBounds(old.x+offset, old.y, old.width, old.height);
189                     //System.out.println("checkOtherComponents set bounds "+ j + " " + comps[j].getBounds());
190
}
191             }
192         } // HORIZONTAL -- moved right
193
} // checkComponents()
194

195     
196     void mouseDrag(MouseEvent JavaDoc e){
197         if (SplitterLayout.dragee == null) {
198             SplitterLayout.dragee = this;
199         } else if (SplitterLayout.dragee != this) {
200             return;
201         }
202         // The NbColumnView mainParentPanel is in a scrollpane
203
Container JavaDoc cp = getParent(); // this is the NbColumnView mainParentPanel
204
Container JavaDoc viewport = cp.getParent();
205         Rectangle JavaDoc viewRect = null;
206         Rectangle JavaDoc columnViewRect = null;
207         Component JavaDoc columnView = null;
208 // int vBarWidth = 0;
209
if (viewport instanceof JViewport JavaDoc){
210             JScrollPane JavaDoc scrollPane = (JScrollPane JavaDoc)((JViewport JavaDoc)viewport).getParent();
211 // vBarWidth = scrollPane.getVerticalScrollBar().getPreferredSize().width;
212
// System.out.println("vBar width " + vBarWidth);
213
viewRect = ((JViewport JavaDoc)viewport).getViewRect();
214             ////System.out.println("mouseDrag: viewRect " + viewRect); //
215
columnView = ((JViewport JavaDoc)viewport).getParent().getParent();
216             if (columnView != null) {
217                 columnViewRect = columnView.getBounds();
218                 ////System.out.println("mouseDrag: columnViewRect " +columnViewRect );
219
} else {
220                 // We would get NPE if we continued.
221
return;
222             }
223         } else {
224             // We would get NPE if we continued.
225
return;
226         }
227         Component JavaDoc c = getParent();
228 // Point fl = c.getLocationOnScreen(); // location of this bar on screen
229
while(c.getParent()!=null){
230             c = c.getParent();
231         }
232         ////System.out.println("mouseDrag parent bounds " + c.getBounds()); // Main IDE window org.netbeans.core.windows.view.ui.MainWindow
233
if(!alreadyDrawn && c instanceof Frame JavaDoc){
234             originalBounds = getBounds();
235             wBar = new Window JavaDoc((Frame JavaDoc)c);
236             wBar.setBackground(getBackground().darker());
237         }
238         ////System.out.println("mouseDrag mainParentPanel cp " + cp);
239
// Dimension parentDim = cp.getSize();
240
Rectangle JavaDoc parentRect = cp.getBounds(); // this could be bigger than the scrollpane
241
////System.out.println("mouseDrag: cp parentRect " + parentRect);
242
Point JavaDoc l = getLocationOnScreen();
243         Insets JavaDoc insets = cp.getInsets();
244         ////System.out.println("mouseDrag insets " + insets);
245
parentRect.height -= insets.top+insets.bottom;
246 // Rectangle r = getBounds(); // mouse event is relative to this...
247
////System.out.println("mouseDrag l " + l);
248
////System.out.println("mouseDrag e.getX " + e.getX());
249
int x = l.x+e.getX();
250         ////System.out.println("mouseDrag x " + x);
251
// int y = l.y;
252
Point JavaDoc viewRectLocation = viewRect.getLocation();
253         ////System.out.println("mouseDrag: viewRect location " + viewRectLocation);
254
SwingUtilities.convertPointToScreen(viewRectLocation, viewport);
255         ////System.out.println("mouseDrag: viewRect screen location " + viewRectLocation);
256
Point JavaDoc columnViewRectLocation = columnViewRect.getLocation();
257         ////System.out.println("mouseDrag: columnViewRect location " + columnViewRectLocation);
258
SwingUtilities.convertPointToScreen(columnViewRectLocation, columnView);
259         ////System.out.println("mouseDrag: columnViewRect screen location " + columnViewRectLocation);
260
int y = viewRectLocation.y;
261         // right boundary is the right location of the
262
// viewport or the column view minus the width of the vertical scrollbar
263
//
264
// System.out.println("JSplitterBar width "+ this.getWidth());
265
int rightBoundaryScreenPos = columnViewRectLocation.x + columnViewRect.width - this.getWidth();
266         ////System.out.println("mouseDrag view width " + viewRect.width);
267
////System.out.println("mouseDrag columView width "+ columnViewRect.width);
268
////System.out.println("mouseDrag: rightBoundaryScreenPos "+ rightBoundaryScreenPos);
269

270         // don't let x be less than the min size boundary position of the left-adjacent column
271
// there should always be a column to the left of this bar
272
int leftBoundaryScreenPos = 0;
273         Component JavaDoc left = null;
274         Component JavaDoc[] comps = getParent().getComponents();
275         for (Component JavaDoc comp:comps){
276             if (comp == this){
277                 Dimension JavaDoc min = left.getMinimumSize();
278                 Point JavaDoc p = left.getLocationOnScreen();
279                 // use the larger of the viewport left position or the neighbor's minimum size boundary
280
// (the neighbor may be scrolled to the left and partially hidden)
281
////System.out.println("mouseDrag: left neighbor's boundary " + (p.x+ min.width));
282
////System.out.println("mouseDrag: columnView left " + columnViewRectLocation.x);
283
leftBoundaryScreenPos = Math.max(p.x+min.width,columnViewRectLocation.x);
284                 break;
285             }
286             left = comp;
287         }
288         ////System.out.println("mouseDrag leftBoundaryScreenPos " + leftBoundaryScreenPos);
289
if (x<leftBoundaryScreenPos){
290             x = leftBoundaryScreenPos;
291             ////System.out.println("mouseDrag x=leftBoundaryScreenPos");
292
}
293         else if(x>rightBoundaryScreenPos){
294             x = rightBoundaryScreenPos;
295             ////System.out.println("mouseDrag x=rightBoundaryScreenPos");
296
}
297         wBar.setBounds(x, y,
298                 3 ,
299                 columnViewRect.height);
300         //System.out.println("mouseDrag wBar bounds " + wBar.getBounds());
301
if(!alreadyDrawn){
302             wBar.setVisible(true);
303             alreadyDrawn = true;
304         }
305     }
306     
307     void mouseEnter(MouseEvent JavaDoc e){
308         if(SplitterLayout.dragee!=null) return;
309         setCursor(HORIZ_CURSOR);
310         mouseInside = true;
311         invalidate();
312         validate();
313         repaint();
314     }
315     
316     void mouseExit(MouseEvent JavaDoc e){
317         if(SplitterLayout.dragee!=null) return;
318         setCursor(DEF_CURSOR);
319         mouseInside = false;
320         invalidate();
321         validate();
322         repaint();
323     }
324     
325     void mouseRelease(MouseEvent JavaDoc e){
326         if(alreadyDrawn){
327             if(SplitterLayout.dragee!=this) return;
328             SplitterLayout.dragee = null;
329             Point JavaDoc p = wBar.getLocationOnScreen();
330             SwingUtilities.convertPointFromScreen(p, getParent());
331             wBar.setVisible(false);
332             wBar.dispose();
333             wBar = null;
334             alreadyDrawn = false;
335             Rectangle JavaDoc r = getBounds(); // mouse event is relative to this...
336
r.x += e.getX();
337 // //System.out.println("mouseReleased converted point "+ p);
338
// //System.out.println("mouseRelease bounds of this spliltter " + r);
339
setLocation(p.x, r.y);
340             setCursor(DEF_CURSOR);
341             
342             // check to see if we need to move other splitters and hide other
343
// components that are controlled by the layout
344
// First -- find what component this one is
345

346             checkOtherComponents();
347             mouseInside = false;
348             invalidate();
349             getParent().validate();
350             SplitterLayout.dragee = null;
351         }
352     }
353     
354     /**
355      * Paints the image of a JSplitterBar. If nothing was added to
356      * the JSplitterBar, this image will only be a thin, 3D raised line that
357      * will act like a handle for moving the JSplitterBar.
358      * If other components were added the JSplitterBar, the thin 3D raised
359      * line will onlty appear where JSplitterSpace components were added.
360      */

361     public void paint(Graphics JavaDoc g){
362         super.paint(g);
363         g.setColor(getBackground());
364 // if(mouseInside)
365
// g.setColor(Color.yellow);
366
// else
367
// g.setColor(Colors.lightSkyBlue3);
368
Component JavaDoc c[] = getComponents();
369         if(c!=null && c.length>0)
370             for(int i = 0; i<c.length; i++){
371             if(c[i] instanceof JSplitterSpace){
372                 // only draw boxes where JSplitterSpace components appear
373
Rectangle JavaDoc r = c[i].getBounds();
374                 g.fill3DRect(r.x+r.width/2-1, r.y+2, 3, r.y+r.height-5, true);
375             }
376             } else{
377             Rectangle JavaDoc r = getBounds();
378             g.fill3DRect(r.width/2-1, 2, 3, r.height-5, true);
379             }
380     }
381     
382     
383     
384     /**
385      * Called by AWT to update the image produced by the JSplitterBar
386      */

387     public void update(Graphics JavaDoc g){
388         paint(g);
389     }
390 }
Popular Tags