KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > custom > SashForm


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.swt.custom;
12
13
14 import org.eclipse.swt.*;
15 import org.eclipse.swt.widgets.*;
16 import org.eclipse.swt.graphics.*;
17
18 /**
19  * The SashForm is a composite control that lays out its children in a
20  * row or column arrangement (as specified by the orientation) and places
21  * a Sash between each child. One child may be maximized to occupy the
22  * entire size of the SashForm. The relative sizes of the children may
23  * be specified using weights.
24  * <p>
25  * <dl>
26  * <dt><b>Styles:</b></dt>
27  * <dd>HORIZONTAL, VERTICAL, SMOOTH</dd>
28  * </dl>
29  * </p>
30  */

31 public class SashForm extends Composite {
32
33     public int SASH_WIDTH = 3;
34
35     int sashStyle;
36     Sash[] sashes = new Sash[0];
37     // Remember background and foreground
38
// colors to determine whether to set
39
// sashes to the default color (null) or
40
// a specific color
41
Color background = null;
42     Color foreground = null;
43     Control[] controls = new Control[0];
44     Control maxControl = null;
45     Listener sashListener;
46     static final int DRAG_MINIMUM = 20;
47
48 /**
49  * Constructs a new instance of this class given its parent
50  * and a style value describing its behavior and appearance.
51  * <p>
52  * The style value is either one of the style constants defined in
53  * class <code>SWT</code> which is applicable to instances of this
54  * class, or must be built by <em>bitwise OR</em>'ing together
55  * (that is, using the <code>int</code> "|" operator) two or more
56  * of those <code>SWT</code> style constants. The class description
57  * lists the style constants that are applicable to the class.
58  * Style bits are also inherited from superclasses.
59  * </p>
60  *
61  * @param parent a widget which will be the parent of the new instance (cannot be null)
62  * @param style the style of widget to construct
63  *
64  * @exception IllegalArgumentException <ul>
65  * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
66  * </ul>
67  * @exception SWTException <ul>
68  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
69  * </ul>
70  *
71  * @see SWT#HORIZONTAL
72  * @see SWT#VERTICAL
73  * @see #getStyle()
74  */

75 public SashForm(Composite parent, int style) {
76     super(parent, checkStyle(style));
77     super.setLayout(new SashFormLayout());
78     sashStyle = ((style & SWT.VERTICAL) != 0) ? SWT.HORIZONTAL : SWT.VERTICAL;
79     if ((style & SWT.BORDER) != 0) sashStyle |= SWT.BORDER;
80     if ((style & SWT.SMOOTH) != 0) sashStyle |= SWT.SMOOTH;
81     sashListener = new Listener() {
82         public void handleEvent(Event e) {
83             onDragSash(e);
84         }
85     };
86 }
87 static int checkStyle (int style) {
88     int mask = SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
89     return style & mask;
90 }
91 /**
92  * Returns SWT.HORIZONTAL if the controls in the SashForm are laid out side by side
93  * or SWT.VERTICAL if the controls in the SashForm are laid out top to bottom.
94  *
95  * @return SWT.HORIZONTAL or SWT.VERTICAL
96  */

97 public int getOrientation() {
98     //checkWidget();
99
return (sashStyle & SWT.VERTICAL) != 0 ? SWT.HORIZONTAL : SWT.VERTICAL;
100 }
101 public int getStyle() {
102     int style = super.getStyle();
103     style |= getOrientation() == SWT.VERTICAL ? SWT.VERTICAL : SWT.HORIZONTAL;
104     if ((sashStyle & SWT.SMOOTH) != 0) style |= SWT.SMOOTH;
105     return style;
106 }
107 /**
108  * Answer the control that currently is maximized in the SashForm.
109  * This value may be null.
110  *
111  * @return the control that currently is maximized or null
112  */

113 public Control getMaximizedControl(){
114     //checkWidget();
115
return this.maxControl;
116 }
117 /**
118  * Answer the relative weight of each child in the SashForm. The weight represents the
119  * percent of the total width (if SashForm has Horizontal orientation) or
120  * total height (if SashForm has Vertical orientation) each control occupies.
121  * The weights are returned in order of the creation of the widgets (weight[0]
122  * corresponds to the weight of the first child created).
123  *
124  * @return the relative weight of each child
125  *
126  * @exception SWTException <ul>
127  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
128  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
129  * </ul>
130  */

131
132 public int[] getWeights() {
133     checkWidget();
134     Control[] cArray = getControls(false);
135     int[] ratios = new int[cArray.length];
136     for (int i = 0; i < cArray.length; i++) {
137         Object JavaDoc data = cArray[i].getLayoutData();
138         if (data != null && data instanceof SashFormData) {
139             ratios[i] = (int)(((SashFormData)data).weight * 1000 >> 16);
140         } else {
141             ratios[i] = 200;
142         }
143     }
144     return ratios;
145 }
146 Control[] getControls(boolean onlyVisible) {
147     Control[] children = getChildren();
148     Control[] result = new Control[0];
149     for (int i = 0; i < children.length; i++) {
150         if (children[i] instanceof Sash) continue;
151         if (onlyVisible && !children[i].getVisible()) continue;
152
153         Control[] newResult = new Control[result.length + 1];
154         System.arraycopy(result, 0, newResult, 0, result.length);
155         newResult[result.length] = children[i];
156         result = newResult;
157     }
158     return result;
159 }
160 void onDragSash(Event event) {
161     Sash sash = (Sash)event.widget;
162     int sashIndex = -1;
163     for (int i= 0; i < sashes.length; i++) {
164         if (sashes[i] == sash) {
165             sashIndex = i;
166             break;
167         }
168     }
169     if (sashIndex == -1) return;
170
171     Control c1 = controls[sashIndex];
172     Control c2 = controls[sashIndex + 1];
173     Rectangle b1 = c1.getBounds();
174     Rectangle b2 = c2.getBounds();
175     
176     Rectangle sashBounds = sash.getBounds();
177     Rectangle area = getClientArea();
178     boolean correction = false;
179     if (getOrientation() == SWT.HORIZONTAL) {
180         correction = b1.width < DRAG_MINIMUM || b2.width < DRAG_MINIMUM;
181         int totalWidth = b2.x + b2.width - b1.x;
182         int shift = event.x - sashBounds.x;
183         b1.width += shift;
184         b2.x += shift;
185         b2.width -= shift;
186         if (b1.width < DRAG_MINIMUM) {
187             b1.width = DRAG_MINIMUM;
188             b2.x = b1.x + b1.width + sashBounds.width;
189             b2.width = totalWidth - b2.x;
190             event.x = b1.x + b1.width;
191             event.doit = false;
192         }
193         if (b2.width < DRAG_MINIMUM) {
194             b1.width = totalWidth - DRAG_MINIMUM - sashBounds.width;
195             b2.x = b1.x + b1.width + sashBounds.width;
196             b2.width = DRAG_MINIMUM;
197             event.x = b1.x + b1.width;
198             event.doit = false;
199         }
200         Object JavaDoc data1 = c1.getLayoutData();
201         if (data1 == null || !(data1 instanceof SashFormData)) {
202             data1 = new SashFormData();
203             c1.setLayoutData(data1);
204         }
205         Object JavaDoc data2 = c2.getLayoutData();
206         if (data2 == null || !(data2 instanceof SashFormData)) {
207             data2 = new SashFormData();
208             c2.setLayoutData(data2);
209         }
210         ((SashFormData)data1).weight = (((long)b1.width << 16) + area.width - 1) / area.width;
211         ((SashFormData)data2).weight = (((long)b2.width << 16) + area.width - 1) / area.width;
212     } else {
213         correction = b1.height < DRAG_MINIMUM || b2.height < DRAG_MINIMUM;
214         int totalHeight = b2.y + b2.height - b1.y;
215         int shift = event.y - sashBounds.y;
216         b1.height += shift;
217         b2.y += shift;
218         b2.height -= shift;
219         if (b1.height < DRAG_MINIMUM) {
220             b1.height = DRAG_MINIMUM;
221             b2.y = b1.y + b1.height + sashBounds.height;
222             b2.height = totalHeight - b2.y;
223             event.y = b1.y + b1.height;
224             event.doit = false;
225         }
226         if (b2.height < DRAG_MINIMUM) {
227             b1.height = totalHeight - DRAG_MINIMUM - sashBounds.height;
228             b2.y = b1.y + b1.height + sashBounds.height;
229             b2.height = DRAG_MINIMUM;
230             event.y = b1.y + b1.height;
231             event.doit = false;
232         }
233         Object JavaDoc data1 = c1.getLayoutData();
234         if (data1 == null || !(data1 instanceof SashFormData)) {
235             data1 = new SashFormData();
236             c1.setLayoutData(data1);
237         }
238         Object JavaDoc data2 = c2.getLayoutData();
239         if (data2 == null || !(data2 instanceof SashFormData)) {
240             data2 = new SashFormData();
241             c2.setLayoutData(data2);
242         }
243         ((SashFormData)data1).weight = (((long)b1.height << 16) + area.height - 1) / area.height;
244         ((SashFormData)data2).weight = (((long)b2.height << 16) + area.height - 1) / area.height;
245     }
246     if (correction || (event.doit && event.detail != SWT.DRAG)) {
247         c1.setBounds(b1);
248         sash.setBounds(event.x, event.y, event.width, event.height);
249         c2.setBounds(b2);
250     }
251 }
252 /**
253  * If orientation is SWT.HORIZONTAL, lay the controls in the SashForm
254  * out side by side. If orientation is SWT.VERTICAL, lay the
255  * controls in the SashForm out top to bottom.
256  *
257  * @param orientation SWT.HORIZONTAL or SWT.VERTICAL
258  *
259  * @exception SWTException <ul>
260  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
261  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
262  * <li>ERROR_INVALID_ARGUMENT - if the value of orientation is not SWT.HORIZONTAL or SWT.VERTICAL
263  * </ul>
264  */

265 public void setOrientation(int orientation) {
266     checkWidget();
267     if (getOrientation() == orientation) return;
268     if (orientation != SWT.HORIZONTAL && orientation != SWT.VERTICAL) {
269         SWT.error(SWT.ERROR_INVALID_ARGUMENT);
270     }
271     sashStyle &= ~(SWT.HORIZONTAL | SWT.VERTICAL);
272     sashStyle |= orientation == SWT.VERTICAL ? SWT.HORIZONTAL : SWT.VERTICAL;
273     for (int i = 0; i < sashes.length; i++) {
274         sashes[i].dispose();
275         sashes[i] = new Sash(this, sashStyle);
276         sashes[i].setBackground(background);
277         sashes[i].setForeground(foreground);
278         sashes[i].addListener(SWT.Selection, sashListener);
279     }
280     layout(false);
281 }
282 public void setBackground (Color color) {
283     super.setBackground(color);
284     background = color;
285     for (int i = 0; i < sashes.length; i++) {
286         sashes[i].setBackground(background);
287     }
288 }
289 public void setForeground (Color color) {
290     super.setForeground(color);
291     foreground = color;
292     for (int i = 0; i < sashes.length; i++) {
293         sashes[i].setForeground(foreground);
294     }
295 }
296 /**
297  * Sets the layout which is associated with the receiver to be
298  * the argument which may be null.
299  * <p>
300  * Note: No Layout can be set on this Control because it already
301  * manages the size and position of its children.
302  * </p>
303  *
304  * @param layout the receiver's new layout or null
305  *
306  * @exception SWTException <ul>
307  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
308  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
309  * </ul>
310  */

311 public void setLayout (Layout layout) {
312     checkWidget();
313     return;
314 }
315 /**
316  * Specify the control that should take up the entire client area of the SashForm.
317  * If one control has been maximized, and this method is called with a different control,
318  * the previous control will be minimized and the new control will be maximized.
319  * If the value of control is null, the SashForm will minimize all controls and return to
320  * the default layout where all controls are laid out separated by sashes.
321  *
322  * @param control the control to be maximized or null
323  *
324  * @exception SWTException <ul>
325  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
326  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
327  * </ul>
328  */

329 public void setMaximizedControl(Control control){
330     checkWidget();
331     if (control == null) {
332         if (maxControl != null) {
333             this.maxControl = null;
334             layout(false);
335             for (int i= 0; i < sashes.length; i++){
336                 sashes[i].setVisible(true);
337             }
338         }
339         return;
340     }
341     
342     for (int i= 0; i < sashes.length; i++){
343         sashes[i].setVisible(false);
344     }
345     maxControl = control;
346     layout(false);
347 }
348
349 /**
350  * Specify the relative weight of each child in the SashForm. This will determine
351  * what percent of the total width (if SashForm has Horizontal orientation) or
352  * total height (if SashForm has Vertical orientation) each control will occupy.
353  * The weights must be positive values and there must be an entry for each
354  * non-sash child of the SashForm.
355  *
356  * @param weights the relative weight of each child
357  *
358  * @exception SWTException <ul>
359  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
360  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
361  * <li>ERROR_INVALID_ARGUMENT - if the weights value is null or of incorrect length (must match the number of children)</li>
362  * </ul>
363  */

364 public void setWeights(int[] weights) {
365     checkWidget();
366     Control[] cArray = getControls(false);
367     if (weights == null || weights.length != cArray.length) {
368         SWT.error(SWT.ERROR_INVALID_ARGUMENT);
369     }
370     
371     int total = 0;
372     for (int i = 0; i < weights.length; i++) {
373         if (weights[i] < 0) {
374             SWT.error(SWT.ERROR_INVALID_ARGUMENT);
375         }
376         total += weights[i];
377     }
378     if (total == 0) {
379         SWT.error(SWT.ERROR_INVALID_ARGUMENT);
380     }
381     for (int i = 0; i < cArray.length; i++) {
382         Object JavaDoc data = cArray[i].getLayoutData();
383         if (data == null || !(data instanceof SashFormData)) {
384             data = new SashFormData();
385             cArray[i].setLayoutData(data);
386         }
387         ((SashFormData)data).weight = (((long)weights[i] << 16) + total - 1) / total;
388     }
389
390     layout(false);
391 }
392 }
393
Popular Tags