001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.swt.widgets;
011:
012: import org.eclipse.swt.*;
013: import org.eclipse.swt.graphics.*;
014:
015: /**
016: * Instances of this class represent a selectable user interface object
017: * that represents a expandable item in a expand bar.
018: * <p>
019: * <dl>
020: * <dt><b>Styles:</b></dt>
021: * <dd>(none)</dd>
022: * <dt><b>Events:</b></dt>
023: * <dd>(none)</dd>
024: * </dl>
025: * </p><p>
026: * IMPORTANT: This class is <em>not</em> intended to be subclassed.
027: * </p>
028: *
029: * @see ExpandBar
030: *
031: * @since 3.2
032: */
033: public class ExpandItem extends Item {
034: ExpandBar parent;
035: Control control;
036: boolean expanded;
037: int x, y, width, height;
038: int imageHeight, imageWidth;
039: static final int TEXT_INSET = 6;
040: static final int BORDER = 1;
041: static final int CHEVRON_SIZE = 24;
042:
043: /**
044: * Constructs a new instance of this class given its parent
045: * and a style value describing its behavior and appearance.
046: * <p>
047: * The style value is either one of the style constants defined in
048: * class <code>SWT</code> which is applicable to instances of this
049: * class, or must be built by <em>bitwise OR</em>'ing together
050: * (that is, using the <code>int</code> "|" operator) two or more
051: * of those <code>SWT</code> style constants. The class description
052: * lists the style constants that are applicable to the class.
053: * Style bits are also inherited from superclasses.
054: * </p>
055: *
056: * @param parent a composite control which will be the parent of the new instance (cannot be null)
057: * @param style the style of control to construct
058: *
059: * @exception IllegalArgumentException <ul>
060: * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
061: * </ul>
062: * @exception SWTException <ul>
063: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
064: * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
065: * </ul>
066: *
067: * @see Widget#checkSubclass
068: * @see Widget#getStyle
069: */
070: public ExpandItem(ExpandBar parent, int style) {
071: this (parent, style, checkNull(parent).getItemCount());
072: }
073:
074: /**
075: * Constructs a new instance of this class given its parent, a
076: * style value describing its behavior and appearance, and the index
077: * at which to place it in the items maintained by its parent.
078: * <p>
079: * The style value is either one of the style constants defined in
080: * class <code>SWT</code> which is applicable to instances of this
081: * class, or must be built by <em>bitwise OR</em>'ing together
082: * (that is, using the <code>int</code> "|" operator) two or more
083: * of those <code>SWT</code> style constants. The class description
084: * lists the style constants that are applicable to the class.
085: * Style bits are also inherited from superclasses.
086: * </p>
087: *
088: * @param parent a composite control which will be the parent of the new instance (cannot be null)
089: * @param style the style of control to construct
090: * @param index the zero-relative index to store the receiver in its parent
091: *
092: * @exception IllegalArgumentException <ul>
093: * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
094: * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
095: * </ul>
096: * @exception SWTException <ul>
097: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
098: * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
099: * </ul>
100: *
101: * @see Widget#checkSubclass
102: * @see Widget#getStyle
103: */
104: public ExpandItem(ExpandBar parent, int style, int index) {
105: super (parent, style);
106: this .parent = parent;
107: parent.createItem(this , style, index);
108: }
109:
110: static ExpandBar checkNull(ExpandBar control) {
111: if (control == null)
112: SWT.error(SWT.ERROR_NULL_ARGUMENT);
113: return control;
114: }
115:
116: public void dispose() {
117: if (isDisposed())
118: return;
119: //if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
120: parent.destroyItem(this );
121: super .dispose();
122: parent = null;
123: control = null;
124: }
125:
126: void drawChevron(GC gc, int x, int y) {
127: int[] polyline1, polyline2;
128: if (expanded) {
129: int px = x + 4 + 5;
130: int py = y + 4 + 7;
131: polyline1 = new int[] { px, py, px + 1, py, px + 1, py - 1,
132: px + 2, py - 1, px + 2, py - 2, px + 3, py - 2,
133: px + 3, py - 3, px + 3, py - 2, px + 4, py - 2,
134: px + 4, py - 1, px + 5, py - 1, px + 5, py, px + 6,
135: py };
136: py += 4;
137: polyline2 = new int[] { px, py, px + 1, py, px + 1, py - 1,
138: px + 2, py - 1, px + 2, py - 2, px + 3, py - 2,
139: px + 3, py - 3, px + 3, py - 2, px + 4, py - 2,
140: px + 4, py - 1, px + 5, py - 1, px + 5, py, px + 6,
141: py };
142: } else {
143: int px = x + 4 + 5;
144: int py = y + 4 + 4;
145: polyline1 = new int[] { px, py, px + 1, py, px + 1, py + 1,
146: px + 2, py + 1, px + 2, py + 2, px + 3, py + 2,
147: px + 3, py + 3, px + 3, py + 2, px + 4, py + 2,
148: px + 4, py + 1, px + 5, py + 1, px + 5, py, px + 6,
149: py };
150: py += 4;
151: polyline2 = new int[] { px, py, px + 1, py, px + 1, py + 1,
152: px + 2, py + 1, px + 2, py + 2, px + 3, py + 2,
153: px + 3, py + 3, px + 3, py + 2, px + 4, py + 2,
154: px + 4, py + 1, px + 5, py + 1, px + 5, py, px + 6,
155: py };
156: }
157: gc.setForeground(display
158: .getSystemColor(SWT.COLOR_TITLE_FOREGROUND));
159: gc.drawPolyline(polyline1);
160: gc.drawPolyline(polyline2);
161: }
162:
163: void drawItem(GC gc, boolean drawFocus) {
164: int headerHeight = parent.getBandHeight();
165: Display display = getDisplay();
166: gc.setForeground(display
167: .getSystemColor(SWT.COLOR_TITLE_BACKGROUND));
168: gc.setBackground(display
169: .getSystemColor(SWT.COLOR_TITLE_BACKGROUND_GRADIENT));
170: gc.fillGradientRectangle(x, y, width, headerHeight, true);
171: if (expanded) {
172: gc
173: .setForeground(display
174: .getSystemColor(SWT.COLOR_TITLE_BACKGROUND_GRADIENT));
175: gc.drawLine(x, y + headerHeight, x, y + headerHeight
176: + height - 1);
177: gc.drawLine(x, y + headerHeight + height - 1,
178: x + width - 1, y + headerHeight + height - 1);
179: gc.drawLine(x + width - 1, y + headerHeight + height - 1, x
180: + width - 1, y + headerHeight);
181: }
182: int drawX = x;
183: if (image != null) {
184: drawX += ExpandItem.TEXT_INSET;
185: if (imageHeight > headerHeight) {
186: gc.drawImage(image, drawX, y + headerHeight
187: - imageHeight);
188: } else {
189: gc.drawImage(image, drawX, y
190: + (headerHeight - imageHeight) / 2);
191: }
192: drawX += imageWidth;
193: }
194: if (text.length() > 0) {
195: drawX += ExpandItem.TEXT_INSET;
196: Point size = gc.stringExtent(text);
197: gc.setForeground(parent.getForeground());
198: gc.drawString(text, drawX, y + (headerHeight - size.y) / 2,
199: true);
200: }
201: int chevronSize = ExpandItem.CHEVRON_SIZE;
202: drawChevron(gc, x + width - chevronSize, y
203: + (headerHeight - chevronSize) / 2);
204: if (drawFocus) {
205: gc.drawFocus(x + 1, y + 1, width - 2, headerHeight - 2);
206: }
207: }
208:
209: /**
210: * Returns the control that is shown when the item is expanded.
211: * If no control has been set, return <code>null</code>.
212: *
213: * @return the control
214: *
215: * @exception SWTException <ul>
216: * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
217: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
218: * </ul>
219: */
220: public Control getControl() {
221: checkWidget();
222: return control;
223: }
224:
225: /**
226: * Returns <code>true</code> if the receiver is expanded,
227: * and false otherwise.
228: *
229: * @return the expanded state
230: *
231: * @exception SWTException <ul>
232: * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
233: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
234: * </ul>
235: */
236: public boolean getExpanded() {
237: checkWidget();
238: return expanded;
239: }
240:
241: /**
242: * Returns the height of the receiver's header
243: *
244: * @return the height of the header
245: *
246: * @exception SWTException <ul>
247: * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
248: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
249: * </ul>
250: */
251: public int getHeaderHeight() {
252: checkWidget();
253: return Math.max(parent.getBandHeight(), imageHeight);
254: }
255:
256: /**
257: * Gets the height of the receiver.
258: *
259: * @return the height
260: *
261: * @exception SWTException <ul>
262: * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
263: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
264: * </ul>
265: */
266: public int getHeight() {
267: checkWidget();
268: return height;
269: }
270:
271: /**
272: * Returns the receiver's parent, which must be a <code>ExpandBar</code>.
273: *
274: * @return the receiver's parent
275: *
276: * @exception SWTException <ul>
277: * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
278: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
279: * </ul>
280: */
281: public ExpandBar getParent() {
282: checkWidget();
283: return parent;
284: }
285:
286: int getPreferredWidth(GC gc) {
287: int width = ExpandItem.TEXT_INSET * 2 + ExpandItem.CHEVRON_SIZE;
288: if (image != null) {
289: width += ExpandItem.TEXT_INSET + imageWidth;
290: }
291: if (text.length() > 0) {
292: width += gc.stringExtent(text).x;
293: }
294: return width;
295: }
296:
297: void redraw() {
298: int headerHeight = parent.getBandHeight();
299: if (imageHeight > headerHeight) {
300: parent.redraw(x + ExpandItem.TEXT_INSET, y + headerHeight
301: - imageHeight, imageWidth, imageHeight, false);
302: }
303: parent.redraw(x, y, width, headerHeight + height, false);
304: }
305:
306: void setBounds(int x, int y, int width, int height, boolean move,
307: boolean size) {
308: redraw();
309: int headerHeight = parent.getBandHeight();
310: if (move) {
311: if (imageHeight > headerHeight) {
312: y += (imageHeight - headerHeight);
313: }
314: this .x = x;
315: this .y = y;
316: redraw();
317: }
318: if (size) {
319: this .width = width;
320: this .height = height;
321: redraw();
322: }
323: if (control != null && !control.isDisposed()) {
324: if (move)
325: control.setLocation(x + BORDER, y + headerHeight);
326: if (size)
327: control.setSize(Math.max(0, width - 2 * BORDER), Math
328: .max(0, height - BORDER));
329: }
330: }
331:
332: /**
333: * Sets the control that is shown when the item is expanded.
334: *
335: * @param control the new control (or null)
336: *
337: * @exception IllegalArgumentException <ul>
338: * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
339: * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li>
340: * </ul>
341: * @exception SWTException <ul>
342: * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
343: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
344: * </ul>
345: */
346: public void setControl(Control control) {
347: checkWidget();
348: if (control != null) {
349: if (control.isDisposed())
350: error(SWT.ERROR_INVALID_ARGUMENT);
351: if (control.parent != parent)
352: error(SWT.ERROR_INVALID_PARENT);
353: }
354: this .control = control;
355: if (control != null) {
356: control.setVisible(expanded);
357: int headerHeight = parent.getBandHeight();
358: control.setBounds(x + BORDER, y + headerHeight, Math.max(0,
359: width - 2 * BORDER), Math.max(0, height - BORDER));
360: }
361: }
362:
363: /**
364: * Sets the expanded state of the receiver.
365: *
366: * @param expanded the new expanded state
367: *
368: * @exception SWTException <ul>
369: * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
370: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
371: * </ul>
372: */
373: public void setExpanded(boolean expanded) {
374: checkWidget();
375: this .expanded = expanded;
376: parent.showItem(this );
377: }
378:
379: public void setImage(Image image) {
380: super .setImage(image);
381: int oldImageHeight = imageHeight;
382: if (image != null) {
383: Rectangle bounds = image.getBounds();
384: imageHeight = bounds.height;
385: imageWidth = bounds.width;
386: } else {
387: imageHeight = imageWidth = 0;
388: }
389: if (oldImageHeight != imageHeight) {
390: parent.layoutItems(parent.indexOf(this ), true);
391: } else {
392: redraw();
393: }
394: }
395:
396: /**
397: * Sets the height of the receiver. This is height of the item when it is expanded,
398: * excluding the height of the header.
399: *
400: * @param height the new height
401: *
402: * @exception SWTException <ul>
403: * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
404: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
405: * </ul>
406: */
407: public void setHeight(int height) {
408: checkWidget();
409: if (height < 0)
410: return;
411: setBounds(0, 0, width, height, false, true);
412: if (expanded)
413: parent.layoutItems(parent.indexOf(this ) + 1, true);
414: }
415:
416: public void setText(String string) {
417: super.setText(string);
418: redraw();
419: }
420: }
|