/*******************************************************************************
 * Copyright (c) 2000, 2008 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
 *******************************************************************************/
package org.eclipse.swt.widgets;


import org.eclipse.swt.internal.wpf.*;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;

/**
 * Instances of this class provide an area for dynamically
 * positioning the items they contain.
 * <p>
 * The item children that may be added to instances of this class
 * must be of type <code>CoolItem</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, HORIZONTAL, VERTICAL</dd>
 * <dt><b>Events:</b></dt>
 * <dd>(none)</dd>
 * </dl>
 * </p><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>
 * 
 * @see <a href="http://www.eclipse.org/swt/snippets/#coolbar">CoolBar snippets</a>
 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 * @noextend This class is not intended to be subclassed by clients.
 */

public class CoolBar extends Composite {
	Control [] children;
	CoolItem [] items;
	int parentingHandle;
	int itemCount, childCount;
	
	//TEMPORARY CODE
	static boolean IsVertical;

/**
 * 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>SWT</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>SWT</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 SWTException <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 SWT
 * @see SWT#FLAT
 * @see SWT#HORIZONTAL
 * @see SWT#VERTICAL
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public CoolBar (Composite parent, int style) {
	super (parent, checkStyle (style));
	if ((style & SWT.VERTICAL) != 0) {
		this.style |= SWT.VERTICAL;
	} else {
		this.style |= SWT.HORIZONTAL;
	}
}

static int checkStyle (int style) {
	style |= SWT.NO_FOCUS;
	IsVertical = (style & SWT.V_SCROLL) != 0;
	/*
	* 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 SWT style.
	*/
	return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
}

protected void checkSubclass () {
	if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
}

void addChild (Control widget) {
	super.addChild (widget);
	if (childCount == children.length) {
		Control [] newChildren = new Control [childCount + 4];
		System.arraycopy (children, 0, newChildren, 0, childCount);
		children = newChildren;
	}
	children [childCount++] = widget;
}

public Point computeSize (int wHint, int hHint, boolean changed) {
	checkWidget ();
	return computeSize (handle, wHint, hHint, changed);
}

void createHandle () {
	parentingHandle = OS.gcnew_Canvas ();
	if (parentingHandle == 0) error (SWT.ERROR_NO_HANDLES);
	handle = OS.gcnew_ToolBarTray ();
	if (handle == 0) error (SWT.ERROR_NO_HANDLES);
	int children = OS.Panel_Children (parentingHandle);
	OS.UIElementCollection_Add (children, handle);
	OS.GCHandle_Free (children);
	if (IsVertical) OS.ToolBarTray_Orientation (handle, OS.Orientation_Vertical);
}

void createItem (CoolItem item, int index) {
	if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE);
	item.createWidget ();
	int toolbars = OS.ToolBarTray_ToolBars (handle);
	int itemHandle = item.topHandle ();
	OS.IList_Insert (toolbars, index, item.topHandle ());
	int count = OS.ICollection_Count (toolbars);
	if (itemCount == count) error (SWT.ERROR_ITEM_NOT_ADDED);
	int band = 0;
	int bandIndex = 0;
	if (index != itemCount) {
		band = OS.ToolBar_Band (items [index].topHandle ());
		bandIndex = OS.ToolBar_BandIndex (items [index].topHandle ());
		for (int i=0; i<count; i++) {
			int current = OS.IList_default (toolbars, i);
			int currentBand = OS.ToolBar_Band (current);
			int currentIndex = OS.ToolBar_BandIndex (current);
			if (currentBand == band && currentIndex >= bandIndex) {
				OS.ToolBar_BandIndex (current, currentIndex + 1);
			}
			OS.GCHandle_Free (current);
		}
	} else {
		if (itemCount > 0) {
			int [] log2vis = logicalToVisualIndices ();
			int lastItem = items [log2vis [itemCount - 1]].topHandle ();
			band = OS.ToolBar_Band (lastItem);
			bandIndex = OS.ToolBar_BandIndex (lastItem) + 1;
		}
	}
	OS.ToolBar_Band (itemHandle, band);
	OS.ToolBar_BandIndex (itemHandle, bandIndex);
	OS.GCHandle_Free (toolbars);
	if (itemCount == items.length) {
		CoolItem [] newItems = new CoolItem [items.length + 4];
		System.arraycopy (items, 0, newItems, 0, items.length);
		items = newItems;
	}
	System.arraycopy (items, index, items, index + 1, itemCount - index);
	items [index] = item;	
	itemCount++;
}

void createWidget () {
	super.createWidget ();
	items = new CoolItem [4];
	children = new Control [4];
}

int defaultBackground () {
	return OS.Colors_Transparent;
}

void deregister () {
	super.deregister ();
	display.removeWidget (parentingHandle);
}

void destroyItem (CoolItem item) {
	int toolbars = OS.ToolBarTray_ToolBars (handle);
	int itemHandle = item.topHandle ();
	int band =  OS.ToolBar_Band (itemHandle);
	int bandIndex = OS.ToolBar_BandIndex (itemHandle);
	OS.IList_Remove (toolbars, itemHandle);
	int count = OS.ICollection_Count (toolbars);
	if (itemCount == count) error (SWT.ERROR_ITEM_NOT_REMOVED);
	itemCount--;
	for (int i=0; i<itemCount; i++) {
		int current = OS.IList_default (toolbars, i);
		int currentBand = OS.ToolBar_Band (current);
		int currentIndex = OS.ToolBar_BandIndex (current);
		if (currentBand == band && currentIndex >= bandIndex) {
			OS.ToolBar_BandIndex (current, currentIndex - 1);
		}
		OS.GCHandle_Free (current);
	}
	OS.GCHandle_Free (toolbars);
	int index = 0;
	while (index < items.length) {
		if (items [index] == item) break;
		index++;
	}
	System.arraycopy (items, index + 1, items, index, itemCount - index);
	items [itemCount] = null;
}

Control [] _getChildren () {
	// return children in reverse order.
	Control[] result = new Control [childCount];
	for (int i =0; i < childCount; i++) {
		result [childCount - i - 1] = children [i]; 
	}
	return result;
}

int [] logicalToVisualIndices () {
	int [] bandLengths = new int [4];
	for (int i = 0; i < itemCount; i++) {
		int topHandle = items [i].topHandle ();
		int band = OS.ToolBar_Band (topHandle);
		int bandIndex = OS.ToolBar_BandIndex (topHandle);
		if (band >= bandLengths.length) {
			int [] newLengths = new int [band + 4];
			System.arraycopy (bandLengths, 0, newLengths, 0, bandLengths.length);
			bandLengths = newLengths;
		}
		if (bandIndex + 1 > bandLengths [band]) bandLengths [band] = bandIndex + 1;
	}
	int [] result = new int [itemCount];
	for (int i = 0; i < itemCount; i++) {
		int topHandle = items [i].topHandle ();
		int band = OS.ToolBar_Band (topHandle);
		int bandIndex = OS.ToolBar_BandIndex (topHandle);
		int index = bandIndex;
		for (int j=0; j<band; j++) index += bandLengths [j];
		result [index] = i;
	}
	return result;
}

/**
 * Returns the item that is currently displayed at the given,
 * zero-relative index. Throws an exception if the index is
 * out of range.
 *
 * @param index the visual index of the item to return
 * @return the item at the given visual 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 SWTException <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 CoolItem getItem (int index) {
	checkWidget ();
	if (index < 0 || index >= itemCount) error (SWT.ERROR_INVALID_RANGE);
	int [] log2vis = logicalToVisualIndices ();
	return items [log2vis [index]];
}

/**
 * Returns the number of items contained in the receiver.
 *
 * @return the number of items
 *
 * @exception SWTException <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 zero-relative ints that map
 * the creation order of the receiver's items to the
 * order in which they are currently being displayed.
 * <p>
 * Specifically, the indices of the returned array represent
 * the current visual order of the items, and the contents
 * of the array represent the creation order of the items.
 * </p><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 current visual order of the receiver's items
 *
 * @exception SWTException <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 [] getItemOrder () {
	checkWidget ();
	return logicalToVisualIndices ();
}

/**
 * Returns an array of <code>CoolItem</code>s in the order
 * in which they are currently being displayed.
 * <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 receiver's items in their current visual order
 *
 * @exception SWTException <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 CoolItem [] getItems () {
	checkWidget ();
	CoolItem [] result = new CoolItem [itemCount];
	int [] log2vis = logicalToVisualIndices ();
	for (int i = 0; i < itemCount; i++) {
		result [i] = items [log2vis [i]];
	}
	return result;
}

/**
 * Returns an array of points whose x and y coordinates describe
 * the widths and heights (respectively) of the items in the receiver
 * in the order in which they are currently being displayed.
 *
 * @return the receiver's item sizes in their current visual order
 *
 * @exception SWTException <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 Point [] getItemSizes () {
	checkWidget ();	
	int [] log2vis = logicalToVisualIndices ();
	Point [] result = new Point [itemCount];
	for (int i = 0; i < itemCount; i++) {
		result [i] = items [log2vis [i]].getSize ();
	}
	return result;
}

Point getLocation (Control child) {
	int topHandle = child.topHandle ();
	int point = OS.gcnew_Point (0, 0);
	if (point == 0) error (SWT.ERROR_NO_HANDLES);
	int location = OS.UIElement_TranslatePoint (topHandle, point, handle);
	int x = (int) OS.Point_X (location);
	int y = (int) OS.Point_Y (location);
	OS.GCHandle_Free (point);
	OS.GCHandle_Free (location);
	return new Point (x, y);
}

/**
 * Returns whether or not the receiver is 'locked'. When a coolbar
 * is locked, its items cannot be repositioned.
 *
 * @return true if the coolbar is locked, false otherwise
 *
 * @exception SWTException <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>
 * 
 * @since 2.0
 */
public boolean getLocked () {
	checkWidget ();
	return OS.ToolBarTray_IsLocked (handle);
}

/**
 * Returns an array of ints that describe the zero-relative
 * indices of any item(s) in the receiver that will begin on
 * a new row. The 0th visible item always begins the first row,
 * therefore it does not count as a wrap index.
 *
 * @return an array containing the receiver's wrap indices, or an empty array if all items are in one row
 *
 * @exception SWTException <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 [] getWrapIndices () {
	checkWidget ();
	int bands = 1;
	int [] bandLengths = new int [4];
	for (int i = 0; i < itemCount; i++) {
		int topHandle = items [i].topHandle ();
		int band = OS.ToolBar_Band (topHandle);
		int bandIndex = OS.ToolBar_BandIndex (topHandle);
		if (band >= bandLengths.length) {
			int [] newLengths = new int [band + 4];
			System.arraycopy (bandLengths, 0, newLengths, 0, bandLengths.length);
			bandLengths = newLengths;
		}
		if (band != 0 && bandLengths [band] == 0) bands ++;
		if (bandIndex + 1 > bandLengths [band]) bandLengths [band] = bandIndex + 1;
	}
	if (bands == 1) return new int [0];
	int [] result = new int [bands-1];
	int sum = 0;
	for (int i = 0; i < result.length; i++) {
		sum += bandLengths [i];
		result [i] = sum;
	}
	return result;
}

void HandleSizeChanged (int sender, int e) {
	postEvent (SWT.Resize);
}

void hookEvents () {
	super.hookEvents ();
	int handler = OS.gcnew_SizeChangedEventHandler (jniRef, "HandleSizeChanged");
	OS.FrameworkElement_SizeChanged (handle, handler);
	OS.GCHandle_Free (handler);
}

/**
 * Searches the receiver's items in the order they are currently
 * being displayed, 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 visual order index of the search item, or -1 if the item is not found
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the item is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the item is disposed</li>
 * </ul>
 * @exception SWTException <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 (CoolItem item) {
	checkWidget ();
	if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (item.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
	for (int i = 0; i < itemCount; i++) {
		if (item.equals (items [i])) {
			int [] log2vis = logicalToVisualIndices ();
			return log2vis [i];
		}
	}
	return -1;
}

int parentingHandle () {
	return parentingHandle;
}

void register () {
	super.register ();
	display.addWidget (parentingHandle, this);
}

void releaseChildren (boolean destroy) {
	for (int i=0; i<itemCount; i++) {
		CoolItem item = items [i];
		if (item != null && !item.isDisposed ()) item.release (false);
	}
	super.releaseChildren (destroy);
}

void releaseHandle () {
	super.releaseHandle ();
	if (parentingHandle != 0) OS.GCHandle_Free (parentingHandle);
	parentingHandle = 0;
}

void removeChild (Control control) {
	super.removeChild (control);
	int index = 0;
	while (index < childCount) {
		if (children [index] == control) break;
		index++;
	}
	if (index == childCount) return;
	System.arraycopy (children, index+1, children, index, --childCount - index);
	children [childCount] = null;
}

void removeControl (Control control) {
	super.removeControl (control);
	for (int i=0; i<itemCount; i++) {
		CoolItem item = items [i];
		if (item.control == control) {
			item.setControl (null);
			break;
		}
	}
}

int setBounds (int x, int y, int width, int height, int flags) {
	int result = super.setBounds (x, y, width, height, flags);
	if ((result & RESIZED) != 0) {
		if ((style & SWT.VERTICAL) != 0) {
			OS.FrameworkElement_Height (handle, height);
		} else {
			OS.FrameworkElement_Width (handle, width);
		}
	}
	return result;
}

/**
 * Sets the receiver's item order, wrap indices, and item sizes
 * all at once. This method is typically used to restore the
 * displayed state of the receiver to a previously stored state.
 * <p>
 * The item order is the order in which the items in the receiver
 * should be displayed, given in terms of the zero-relative ordering
 * of when the items were added.
 * </p><p>
 * The wrap indices are the indices of all item(s) in the receiver
 * that will begin on a new row. The indices are given in the order
 * specified by the item order. The 0th item always begins the first
 * row, therefore it does not count as a wrap index. If wrap indices
 * is null or empty, the items will be placed on one line.
 * </p><p>
 * The sizes are specified in an array of points whose x and y
 * coordinates describe the new widths and heights (respectively)
 * of the receiver's items in the order specified by the item order.
 * </p>
 *
 * @param itemOrder an array of indices that describe the new order to display the items in
 * @param wrapIndices an array of wrap indices, or null
 * @param sizes an array containing the new sizes for each of the receiver's items in visual order
 *
 * @exception SWTException <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>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if item order or sizes is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if item order or sizes is not the same length as the number of items</li>
 * </ul>
 */
public void setItemLayout (int [] itemOrder, int [] wrapIndices, Point [] sizes) {
	checkWidget ();
	setItemOrder (itemOrder);
	setWrapIndices (wrapIndices);
	setItemSizes (sizes);
}

/*
 * Sets the order that the items in the receiver should 
 * be displayed in to the given argument which is described
 * in terms of the zero-relative ordering of when the items
 * were added.
 *
 * @param itemOrder the new order to display the items in
 *
 * @exception SWTException <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>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the item order is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the item order is not the same length as the number of items</li>
 * </ul>
 */
void setItemOrder (int [] itemOrder) {
	checkWidget ();
	if (itemOrder == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (itemOrder.length != itemCount) error (SWT.ERROR_INVALID_ARGUMENT);
	/* Ensure that itemOrder does not contain any duplicates. */
	boolean [] set = new boolean [itemCount];
	for (int i=0; i<itemOrder.length; i++) {
		int index = itemOrder [i];
		if (index < 0 || index >= itemCount) error (SWT.ERROR_INVALID_RANGE);
		if (set [index]) error (SWT.ERROR_INVALID_ARGUMENT);
		set [index] = true;
	}
	for (int i=0; i<itemCount; i++) {
		CoolItem item = items [itemOrder [i]];
		int itemHandle = item.topHandle (); 
		OS.ToolBar_Band (itemHandle, 0);
		OS.ToolBar_BandIndex (itemHandle, i);
	}
}

/*
 * Sets the width and height of the receiver's items to the ones
 * specified by the argument, which is an array of points whose x
 * and y coordinates describe the widths and heights (respectively)
 * in the order in which the items are currently being displayed.
 *
 * @param sizes an array containing the new sizes for each of the receiver's items in visual order
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the array of sizes is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the array of sizes is not the same length as the number of items</li>
 * </ul>
 * @exception SWTException <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>
 */
void setItemSizes (Point [] sizes) {
	if (sizes == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (sizes.length != itemCount) error (SWT.ERROR_INVALID_ARGUMENT);
	int [] log2vis = logicalToVisualIndices ();
	for (int i=0; i<itemCount; i++) {
		items [log2vis [i]].setSize (sizes [i].x, sizes [i].y);
	}
}

/**
 * Sets whether or not the receiver is 'locked'. When a coolbar
 * is locked, its items cannot be repositioned.
 *
 * @param locked lock the coolbar if true, otherwise unlock the coolbar
 *
 * @exception SWTException <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>
 * 
 * @since 2.0
 */
public void setLocked (boolean locked) {
	checkWidget ();
	OS.ToolBarTray_IsLocked (handle, locked);
}

/**
 * Sets the indices of all item(s) in the receiver that will
 * begin on a new row. The indices are given in the order in
 * which they are currently being displayed. The 0th item
 * always begins the first row, therefore it does not count
 * as a wrap index. If indices is null or empty, the items
 * will be placed on one line.
 *
 * @param indices an array of wrap indices, or null
 *
 * @exception SWTException <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 void setWrapIndices (int [] indices) {
	checkWidget ();
	if (indices == null) indices = new int [0];
	int count = getItemCount ();
	for (int i=0; i<indices.length; i++) {
		if (indices [i] < 0 || indices [i] >= count) {
			error (SWT.ERROR_INVALID_RANGE);
		}	
	}
	sortAscending (indices);
	int [] log2vis = logicalToVisualIndices ();
	int band = 0;
	int bandIndex = 0;
	int wrapIndex = 0;
	for (int i = 0; i < itemCount; i++) {
		int wrap = indices.length > wrapIndex ? indices [wrapIndex] : itemCount;
		if (i == wrap) {
			if (wrap != 0) {
				band ++;
				bandIndex = 0;
			}
			wrapIndex ++;
		}
		int topHandle = items [log2vis [i]].topHandle ();
		OS.ToolBar_Band (topHandle, band);
		OS.ToolBar_BandIndex (topHandle, bandIndex);
		bandIndex ++;
	}
}

int topHandle () {
	return parentingHandle;
}
}
