Mercurial > projects > dwt-mac
diff dwt/widgets/ToolBar.d @ 0:380af2bdd8e5
Upload of whole dwt tree
author | Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com> |
---|---|
date | Sat, 09 Aug 2008 17:00:02 +0200 |
parents | |
children | 649b8e223d5a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/widgets/ToolBar.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,444 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +module dwt.widgets.ToolBar; + +import dwt.dwthelper.utils; + + +import dwt.DWT; +import dwt.DWTException; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.internal.cocoa.NSRect; +import dwt.internal.cocoa.NSView; +import dwt.internal.cocoa.SWTView; + +/** + * Instances of this class support the layout of selectable + * tool bar items. + * <p> + * The item children that may be added to instances of this class + * must be of type <code>ToolItem</code>. + * </p><p> + * Note that although this class is a subclass of <code>Composite</code>, + * it does not make sense to add <code>Control</code> children to it, + * or set a layout on it. + * </p><p> + * <dl> + * <dt><b>Styles:</b></dt> + * <dd>FLAT, WRAP, RIGHT, HORIZONTAL, VERTICAL, SHADOW_OUT</dd> + * <dt><b>Events:</b></dt> + * <dd>(none)</dd> + * </dl> + * <p> + * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified. + * </p><p> + * IMPORTANT: This class is <em>not</em> intended to be subclassed. + * </p> + */ +public class ToolBar extends Composite { + int itemCount; + ToolItem [] items; + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + * <p> + * The style value is either one of the style constants defined in + * class <code>DWT</code> which is applicable to instances of this + * class, or must be built by <em>bitwise OR</em>'ing together + * (that is, using the <code>int</code> "|" operator) two or more + * of those <code>DWT</code> style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + * </p> + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> + * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> + * </ul> + * + * @see DWT#FLAT + * @see DWT#WRAP + * @see DWT#RIGHT + * @see DWT#HORIZONTAL + * @see DWT#SHADOW_OUT + * @see DWT#VERTICAL + * @see Widget#checkSubclass() + * @see Widget#getStyle() + */ +public ToolBar (Composite parent, int style) { + super (parent, checkStyle (style)); + + /* + * Ensure that either of HORIZONTAL or VERTICAL is set. + * NOTE: HORIZONTAL and VERTICAL have the same values + * as H_SCROLL and V_SCROLL so it is necessary to first + * clear these bits to avoid scroll bars and then reset + * the bits using the original style supplied by the + * programmer. + */ + if ((style & DWT.VERTICAL) !is 0) { + this.style |= DWT.VERTICAL; + } else { + this.style |= DWT.HORIZONTAL; + } +} + +static int checkStyle (int style) { + /* + * Even though it is legal to create this widget + * with scroll bars, they serve no useful purpose + * because they do not automatically scroll the + * widget's client area. The fix is to clear + * the DWT style. + */ + return style & ~(DWT.H_SCROLL | DWT.V_SCROLL); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (DWT.ERROR_INVALID_SUBCLASS); +} + +public Point computeSize (int wHint, int hHint, bool changed) { + checkWidget(); + int width = wHint, height = hHint; + if (wHint is DWT.DEFAULT) width = 0x7FFFFFFF; + if (hHint is DWT.DEFAULT) height = 0x7FFFFFFF; + int [] result = layout (width, height, false); + Point extent = new Point (result [1], result [2]); + if (wHint !is DWT.DEFAULT) extent.x = wHint; + if (hHint !is DWT.DEFAULT) extent.y = hHint; + return extent; +} + +void createHandle () { + SWTView widget = (SWTView)new SWTView().alloc(); + widget.initWithFrame(new NSRect()); +// widget.setDrawsBackground(false); + widget.setTag(jniRef); + view = widget; + parent.contentView().addSubview_(widget); +} + +void createItem (ToolItem item, int index) { + if (!(0 <= index && index <= itemCount)) error (DWT.ERROR_INVALID_RANGE); + if (itemCount is items.length) { + ToolItem [] newItems = new ToolItem [itemCount + 4]; + System.arraycopy (items, 0, newItems, 0, items.length); + items = newItems; + } + item.createWidget(); + view.addSubview_(item.view); + System.arraycopy (items, index, items, index + 1, itemCount++ - index); + items [index] = item; + relayout (); +} + +void createWidget () { + super.createWidget (); + items = new ToolItem [4]; + itemCount = 0; +} + +void destroyItem (ToolItem item) { + int index = 0; + while (index < itemCount) { + if (items [index] is item) break; + index++; + } + if (index is itemCount) return; + System.arraycopy (items, index + 1, items, index, --itemCount - index); + items [itemCount] = null; + NSView nsItem = item.view; + nsItem.removeFromSuperview(); + item.view = null; + relayout (); +} + +void enableWidget(bool enabled) { + super.enableWidget(enabled); + for (int i = 0; i < itemCount; i++) { + ToolItem item = items[i]; + if (item !is null) { + item.enableWidget(enabled); + } + } +} + +public Rectangle getClientArea () { + checkWidget(); + NSRect rect = view.bounds(); + return new Rectangle((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height); +} + +/** + * Returns the item at the given, zero-relative index in the + * receiver. Throws an exception if the index is out of range. + * + * @param index the index of the item to return + * @return the item at the given index + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ +public ToolItem getItem (int index) { + checkWidget(); + if (0 <= index && index < itemCount) return items [index]; + error (DWT.ERROR_INVALID_RANGE); + return null; +} + +/** + * Returns the item at the given point in the receiver + * or null if no such item exists. The point is in the + * coordinate system of the receiver. + * + * @param point the point used to locate the item + * @return the item at the given point + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the point is null</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ +public ToolItem getItem (Point pt) { + checkWidget(); + if (pt is null) error (DWT.ERROR_NULL_ARGUMENT); + for (int i=0; i<itemCount; i++) { + Rectangle rect = items [i].getBounds (); + if (rect.contains (pt)) return items [i]; + } + return null; +} + +/** + * Returns the number of items contained in the receiver. + * + * @return the number of items + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ +public int getItemCount () { + checkWidget(); + return itemCount; +} + +/** + * Returns an array of <code>ToolItem</code>s which are the items + * in the receiver. + * <p> + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + * </p> + * + * @return the items in the receiver + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ +public ToolItem [] getItems () { + checkWidget(); + ToolItem [] result = new ToolItem [itemCount]; + System.arraycopy (items, 0, result, 0, itemCount); + return result; +} + +/** + * Returns the number of rows in the receiver. When + * the receiver has the <code>WRAP</code> style, the + * number of rows can be greater than one. Otherwise, + * the number of rows is always one. + * + * @return the number of items + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ +public int getRowCount () { + checkWidget(); + Rectangle rect = getClientArea (); + return layout (rect.width, rect.height, false) [0]; +} + +/** + * Searches the receiver's list starting at the first item + * (index 0) until an item is found that is equal to the + * argument, and returns the index of that item. If no item + * is found, returns -1. + * + * @param item the search item + * @return the index of the item + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the tool item is null</li> + * <li>ERROR_INVALID_ARGUMENT - if the tool item has been disposed</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ +public int indexOf (ToolItem item) { + checkWidget(); + if (item is null) error (DWT.ERROR_NULL_ARGUMENT); + if (item.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT); + for (int i=0; i<itemCount; i++) { + if (items [i] is item) return i; + } + return -1; +} + +int [] layoutHorizontal (int width, int height, bool resize) { + int xSpacing = 0, ySpacing = 2; + int marginWidth = 0, marginHeight = 0; + int x = marginWidth, y = marginHeight; + int maxX = 0, rows = 1; + bool wrap = (style & DWT.WRAP) !is 0; + int itemHeight = 0; + Point [] sizes = new Point [itemCount]; + for (int i=0; i<itemCount; i++) { + Point size = sizes [i] = items [i].computeSize (); + itemHeight = Math.max (itemHeight, size.y); + } + for (int i=0; i<itemCount; i++) { + ToolItem item = items [i]; + Point size = sizes [i]; + if (wrap && i !is 0 && x + size.x > width) { + rows++; + x = marginWidth; + y += ySpacing + itemHeight; + } + if (resize) { + item.setBounds (x, y, size.x, itemHeight); + bool visible = x + size.x <= width && y + itemHeight <= height; + item.setVisible (visible); + Control control = item.control; + if (control !is null) { + int controlY = y + (itemHeight - size.y) / 2; + control.setBounds (x, controlY, size.x, itemHeight - (controlY - y)); + } + } + x += xSpacing + size.x; + maxX = Math.max (maxX, x); + } + + return new int [] {rows, maxX, y + itemHeight}; +} + +int [] layoutVertical (int width, int height, bool resize) { + int xSpacing = 2, ySpacing = 0; + int marginWidth = 0, marginHeight = 0; + int x = marginWidth, y = marginHeight; + int maxY = 0, cols = 1; + bool wrap = (style & DWT.WRAP) !is 0; + int itemWidth = 0; + Point [] sizes = new Point [itemCount]; + for (int i=0; i<itemCount; i++) { + Point size = sizes [i] = items [i].computeSize (); + itemWidth = Math.max (itemWidth, size.x); + } + for (int i=0; i<itemCount; i++) { + ToolItem item = items [i]; + Point size = sizes [i]; + if (wrap && i !is 0 && y + size.y > height) { + cols++; + x += xSpacing + itemWidth; + y = marginHeight; + } + if (resize) { + item.setBounds (x, y, itemWidth, size.y); + bool visible = x + itemWidth <= width && y + size.y <= height; + item.setVisible (visible); + Control control = item.control; + if (control !is null) { + int controlX = x + (itemWidth - size.x) / 2; + control.setBounds (controlX, y, itemWidth - (controlX - x), size.y); + } + } + y += ySpacing + size.y; + maxY = Math.max (maxY, y); + } + + return new int [] {cols, x + itemWidth, maxY}; +} + +int [] layout (int nWidth, int nHeight, bool resize) { + if ((style & DWT.VERTICAL) !is 0) { + return layoutVertical (nWidth, nHeight, resize); + } else { + return layoutHorizontal (nWidth, nHeight, resize); + } +} + +void relayout () { + if (drawCount !is 0) return; + Rectangle rect = getClientArea (); + layout (rect.width, rect.height, true); +} + +void releaseChildren (bool destroy) { + if (items !is null) { + for (int i=0; i<itemCount; i++) { + ToolItem item = items [i]; + if (item !is null && !item.isDisposed ()) { + item.release (false); + } + } + itemCount = 0; + items = null; + } + super.releaseChildren (destroy); +} + +void removeControl (Control control) { + super.removeControl (control); + for (int i=0; i<itemCount; i++) { + ToolItem item = items [i]; + if (item.control is control) item.setControl (null); + } +} + +int setBounds (int x, int y, int width, int height, bool move, bool resize) { + int result = super.setBounds (x, y, width, height, move, resize); + if ((result & RESIZED) !is 0) relayout (); + return result; +} + +public void setRedraw (bool redraw) { + checkWidget(); + super.setRedraw (redraw); + if (redraw && drawCount is 0) relayout(); +} + +}