/*******************************************************************************
 * Copyright (c) 2000, 2012 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.win32.*;
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 {
	CoolItem [] items;
	CoolItem [] originalItems;
	boolean locked;
	boolean ignoreResize;
	static final long /*int*/ ReBarProc;
	static final TCHAR ReBarClass = new TCHAR (0, OS.REBARCLASSNAME, true);
	static {
		INITCOMMONCONTROLSEX icex = new INITCOMMONCONTROLSEX ();
		icex.dwSize = INITCOMMONCONTROLSEX.sizeof;
		icex.dwICC = OS.ICC_COOL_CLASSES;
		OS.InitCommonControlsEx (icex);
		WNDCLASS lpWndClass = new WNDCLASS ();
		OS.GetClassInfo (0, ReBarClass, lpWndClass);
		ReBarProc = lpWndClass.lpfnWndProc;
	}
	static final int SEPARATOR_WIDTH = 2;
	static final int MAX_WIDTH = 0x7FFF;
	static final int DEFAULT_COOLBAR_WIDTH = 0;
	static final int DEFAULT_COOLBAR_HEIGHT = 0;

/**
 * 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));
	/*
	* 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.
	* 
	* NOTE: The CCS_VERT style cannot be applied when the
	* widget is created because of this conflict.
	*/
	if ((style & SWT.VERTICAL) != 0) {
		this.style |= SWT.VERTICAL;
		int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
		OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.CCS_VERT);
	} else {
		this.style |= SWT.HORIZONTAL;
	}
}

long /*int*/ callWindowProc (long /*int*/ hwnd, int msg, long /*int*/ wParam, long /*int*/ lParam) {
	if (handle == 0) return 0;
	return OS.CallWindowProc (ReBarProc, hwnd, msg, wParam, lParam);
}

static int checkStyle (int style) {
	style |= SWT.NO_FOCUS;
	/*
	* 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);
}

public Point computeSize (int wHint, int hHint, boolean changed) {
	checkWidget ();
	int width = 0, height = 0;
	int border = getBorderWidth ();
	int newWidth = wHint == SWT.DEFAULT ? 0x3FFF : wHint + (border * 2);
	int newHeight = hHint == SWT.DEFAULT ? 0x3FFF : hHint + (border * 2);
	int count = (int)/*64*/OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
	if (count != 0) {
		ignoreResize = true;
		boolean redraw = false;
		if (OS.IsWindowVisible (handle)) {
			if (OS.COMCTL32_MAJOR >= 6) {
				redraw = true;
				OS.UpdateWindow (handle);
				OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
			} else {
				redraw = getDrawing();
				if (redraw) {
					OS.UpdateWindow (handle);
					OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
				}
			}
		}	
		RECT oldRect = new RECT ();
		OS.GetWindowRect (handle, oldRect);
		int oldWidth = oldRect.right - oldRect.left;
		int oldHeight = oldRect.bottom - oldRect.top;
		int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOREDRAW | OS.SWP_NOZORDER;	
		SetWindowPos (handle, 0, 0, 0, newWidth, newHeight, flags);
		RECT rect = new RECT ();
		OS.SendMessage (handle, OS.RB_GETRECT, count - 1, rect);
		height = Math.max (height, rect.bottom);
		SetWindowPos (handle, 0, 0, 0, oldWidth, oldHeight, flags);
		REBARBANDINFO rbBand = new REBARBANDINFO ();
		rbBand.cbSize = REBARBANDINFO.sizeof;
		rbBand.fMask = OS.RBBIM_IDEALSIZE | OS.RBBIM_STYLE;
		int rowWidth = 0;
		for (int i = 0; i < count; i++) {
			OS.SendMessage(handle, OS.RB_GETBANDINFO, i, rbBand);
			if ((rbBand.fStyle & OS.RBBS_BREAK) != 0) {
				width = Math.max(width, rowWidth);
				rowWidth = 0;
			}
			rowWidth += rbBand.cxIdeal + getMargin (i);
		}
		width = Math.max(width, rowWidth);
		if (redraw) {
			if (OS.COMCTL32_MAJOR >= 6) {
				OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
			} else {
				OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
			}
		}
		ignoreResize = false;
	}
	if (width == 0) width = DEFAULT_COOLBAR_WIDTH;
	if (height == 0) height = DEFAULT_COOLBAR_HEIGHT;
	if ((style & SWT.VERTICAL) != 0) {
		int tmp = width;
		width = height;
		height = tmp;
	}
	if (wHint != SWT.DEFAULT) width = wHint;
	if (hHint != SWT.DEFAULT) height = hHint;
	height += border * 2;
	width += border * 2;	
	return new Point (width, height);
}

void createHandle () {
	super.createHandle ();
	state &= ~(CANVAS | THEME_BACKGROUND);
	
	/*
	* Feature in Windows.  When the control is created,
	* it does not use the default system font.  A new HFONT
	* is created and destroyed when the control is destroyed.
	* This means that a program that queries the font from
	* this control, uses the font in another control and then
	* destroys this control will have the font unexpectedly
	* destroyed in the other control.  The fix is to assign
	* the font ourselves each time the control is created.
	* The control will not destroy a font that it did not
	* create.
	*/
	long /*int*/ hFont = OS.GetStockObject (OS.SYSTEM_FONT);
	OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
}

void createItem (CoolItem item, int index) {
	int count = (int)/*64*/OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
	if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
	int id = 0;
	while (id < items.length && items [id] != null) id++;
	if (id == items.length) {
		CoolItem [] newItems = new CoolItem [items.length + 4];
		System.arraycopy (items, 0, newItems, 0, items.length);
		items = newItems;
	}
	long /*int*/ hHeap = OS.GetProcessHeap ();
	long /*int*/ lpText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, TCHAR.sizeof);
	REBARBANDINFO rbBand = new REBARBANDINFO ();
	rbBand.cbSize = REBARBANDINFO.sizeof;
	rbBand.fMask = OS.RBBIM_TEXT | OS.RBBIM_STYLE | OS.RBBIM_ID;
	rbBand.fStyle = OS.RBBS_VARIABLEHEIGHT | OS.RBBS_GRIPPERALWAYS;
	if ((item.style & SWT.DROP_DOWN) != 0) {
		rbBand.fStyle |= OS.RBBS_USECHEVRON;
	}
	rbBand.lpText = lpText;
	rbBand.wID = id;

	/*
	* Feature in Windows.  When inserting an item at end of a row,
	* sometimes, Windows will begin to place the item on the right
	* side of the cool bar.  The fix is to resize the new items to
	* the maximum size and then resize the next to last item to the
	* ideal size.
	*/
	int lastIndex = getLastIndexOfRow (index - 1);
	boolean fixLast = index == lastIndex + 1;
	if (fixLast) {  	
		rbBand.fMask |= OS.RBBIM_SIZE;
		rbBand.cx = MAX_WIDTH; 
	}
	
	/*
	* Feature in Windows. Is possible that the item at index zero
	* has the RBBS_BREAK flag set. When a new item is inserted at
	* position zero, the previous item at position zero moves to
	* a new line.  The fix is to detect this case and clear the
	* RBBS_BREAK flag on the previous item before inserting the
	* new item.
	*/
	if (index == 0 && count > 0) {
		getItem (0).setWrap (false); 
	}
	
	/* Insert the item */
	if (OS.SendMessage (handle, OS.RB_INSERTBAND, index, rbBand) == 0) {
		error (SWT.ERROR_ITEM_NOT_ADDED);
	}
	
	/* Resize the next to last item to the ideal size */
	if (fixLast) {  	
		resizeToPreferredWidth (lastIndex);
	}
	
	OS.HeapFree (hHeap, 0, lpText);
	items [item.id = id] = item;
	int length = originalItems.length;
	CoolItem [] newOriginals = new CoolItem [length + 1];
	System.arraycopy (originalItems, 0, newOriginals, 0, index);
	System.arraycopy (originalItems, index, newOriginals, index + 1, length - index);
	newOriginals [index] = item;
	originalItems = newOriginals;
}

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

void destroyItem (CoolItem item) {
	int index = (int)/*64*/OS.SendMessage (handle, OS.RB_IDTOINDEX, item.id, 0);
	int count = (int)/*64*/OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
	if (count != 0) {
		int lastIndex = getLastIndexOfRow (index);
		if (index == lastIndex) {
			/*
			* Feature in Windows.  If the last item in a row is
			* given its ideal size, it will be placed at the far
			* right hand edge of the coolbar.  It is preferred
			* that the last item appear next to the second last
			* item.  The fix is to size the last item of each row 
			* so that it occupies all the available space to the
			* right in the row.
			*/
			resizeToMaximumWidth (lastIndex - 1);
		}						
	}	
		
	/*
	* Feature in Windows.  When Windows removed a rebar
	* band, it makes the band child invisible.  The fix
	* is to show the child.
	*/		
	Control control = item.control;
	boolean wasVisible = control != null && !control.isDisposed() && control.getVisible ();

	/*
	* When a wrapped item is being deleted, make the next
	* item in the row wrapped in order to preserve the row.
	* In order to avoid an unnecessary layout, temporarily
	* ignore WM_SIZE.  If the next item is wrapped then a
	* row will be deleted and the WM_SIZE is necessary.
	*/
	CoolItem nextItem = null;
	if (item.getWrap ()) {
		if (index + 1 < count) {
			nextItem = getItem (index + 1);
			ignoreResize = !nextItem.getWrap ();
		}
	}
	if (OS.SendMessage (handle, OS.RB_DELETEBAND, index, 0) == 0) {
		error (SWT.ERROR_ITEM_NOT_REMOVED);
	}
	items [item.id] = null;
	item.id = -1;
	if (ignoreResize) {
		nextItem.setWrap (true);
		ignoreResize = false;
	}
	
	/* Restore the visible state of the control */
	if (wasVisible) control.setVisible (true);
	
	index = 0;
	while (index < originalItems.length) {
		if (originalItems [index] == item) break;
		index++;
	}
	int length = originalItems.length - 1;
	CoolItem [] newOriginals = new CoolItem [length];
	System.arraycopy (originalItems, 0, newOriginals, 0, index);
	System.arraycopy (originalItems, index + 1, newOriginals, index, length - index);
	originalItems = newOriginals;
}

void drawThemeBackground (long /*int*/ hDC, long /*int*/ hwnd, RECT rect) {
	if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
		if (background == -1 && (style & SWT.FLAT) != 0) {
			Control control = findBackgroundControl ();
			if (control != null && control.backgroundImage != null) {
				fillBackground (hDC, control.getBackgroundPixel (), rect);
				return;
			}
		}
	}
	RECT rect2 = new RECT ();
	OS.GetClientRect (handle, rect2);
	OS.MapWindowPoints (handle, hwnd, rect2, 2);
	POINT lpPoint = new POINT ();
	OS.SetWindowOrgEx (hDC, -rect2.left, -rect2.top, lpPoint);
	OS.SendMessage (handle, OS.WM_PRINT, hDC, OS.PRF_CLIENT | OS.PRF_ERASEBKGND);
	OS.SetWindowOrgEx (hDC, lpPoint.x, lpPoint.y, null);
}

Control findThemeControl () {
	if ((style & SWT.FLAT) != 0) return this;
	return background == -1 && backgroundImage == null ? this : super.findThemeControl ();
}

int getMargin (int index) {
	int margin = 0;
	if (OS.COMCTL32_MAJOR >= 6) {
		MARGINS margins = new MARGINS ();
		OS.SendMessage (handle, OS.RB_GETBANDMARGINS, 0, margins);
		margin += margins.cxLeftWidth + margins.cxRightWidth;
	}
	RECT rect = new RECT ();
	OS.SendMessage (handle, OS.RB_GETBANDBORDERS, index, rect);
	if ((style & SWT.FLAT) != 0) {
		/*
		* Bug in Windows.  When the style bit  RBS_BANDBORDERS is not set
		* the rectangle returned by RBS_BANDBORDERS is four pixels too small.
		* The fix is to add four pixels to the result.
		*/	
		if ((style & SWT.VERTICAL) != 0) {
			margin += rect.top + 4;
		} else {
			margin += rect.left + 4;
		}
	} else {
		if ((style & SWT.VERTICAL) != 0) {
			margin += rect.top + rect.bottom;
		} else {
			margin += rect.left + rect.right;
		}
	}
	if ((style & SWT.FLAT) == 0) {
		if (!isLastItemOfRow (index)) {
			margin += CoolBar.SEPARATOR_WIDTH;
		}
	}
	return margin;
}

/**
 * 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 ();
	int count = (int)/*64*/OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
	if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
	REBARBANDINFO rbBand = new REBARBANDINFO ();
	rbBand.cbSize = REBARBANDINFO.sizeof;
	rbBand.fMask = OS.RBBIM_ID;
	OS.SendMessage (handle, OS.RB_GETBANDINFO, index, rbBand);
	return items [rbBand.wID];
}

/**
 * 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 (int)/*64*/OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
}

/**
 * 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 ();
	int count = (int)/*64*/OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
	int [] indices = new int [count];
	REBARBANDINFO rbBand = new REBARBANDINFO ();
	rbBand.cbSize = REBARBANDINFO.sizeof;
	rbBand.fMask = OS.RBBIM_ID;
	for (int i=0; i<count; i++) {
		OS.SendMessage (handle, OS.RB_GETBANDINFO, i, rbBand);
		CoolItem item = items [rbBand.wID];
		int index = 0;
		while (index<originalItems.length) {
			if (originalItems [index] == item) break;
			index++;
		}
		if (index == originalItems.length) error (SWT.ERROR_CANNOT_GET_ITEM);
		indices [i] = index;
	}
	return indices;
}

/**
 * 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 ();
	int count = (int)/*64*/OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
	CoolItem [] result = new CoolItem [count];
	REBARBANDINFO rbBand = new REBARBANDINFO ();
	rbBand.cbSize = REBARBANDINFO.sizeof;
	rbBand.fMask = OS.RBBIM_ID;
	for (int i=0; i<count; i++) {
		OS.SendMessage (handle, OS.RB_GETBANDINFO, i, rbBand);
		result [i] = items [rbBand.wID];
	}
	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 count = (int)/*64*/OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
	Point [] sizes = new Point [count];
	REBARBANDINFO rbBand = new REBARBANDINFO ();
	rbBand.cbSize = REBARBANDINFO.sizeof;
	rbBand.fMask = OS.RBBIM_CHILDSIZE;
	int separator = (style & SWT.FLAT) == 0 ? SEPARATOR_WIDTH : 0;
	MARGINS margins = new MARGINS ();
	for (int i=0; i<count; i++) {
		RECT rect = new RECT ();
		OS.SendMessage (handle, OS.RB_GETRECT, i, rect);
		OS.SendMessage (handle, OS.RB_GETBANDINFO, i, rbBand);
		if (OS.COMCTL32_MAJOR >= 6) {
			OS.SendMessage (handle, OS.RB_GETBANDMARGINS, 0, margins);
			rect.left -= margins.cxLeftWidth;
			rect.right += margins.cxRightWidth;
		}
		if (!isLastItemOfRow(i)) rect.right += separator;
		if ((style & SWT.VERTICAL) != 0) {
			sizes [i] = new Point (rbBand.cyChild, rect.right - rect.left);
		} else {
			sizes [i] = new Point (rect.right - rect.left, rbBand.cyChild);
		}
	}
	return sizes;
}

int getLastIndexOfRow (int index) {
	int count = (int)/*64*/OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
	if (count == 0) return -1;
	REBARBANDINFO rbBand = new REBARBANDINFO ();	
	rbBand.cbSize = REBARBANDINFO.sizeof;
	rbBand.fMask = OS.RBBIM_STYLE;
	for (int i=index + 1; i<count; i++) {
		OS.SendMessage (handle, OS.RB_GETBANDINFO, i, rbBand);
		if ((rbBand.fStyle & OS.RBBS_BREAK) != 0) {
			return i - 1;
		}
	}
	return count - 1;
}

boolean isLastItemOfRow (int index) {
	int count = (int)/*64*/OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
	if (index + 1 == count) return true;
	REBARBANDINFO rbBand = new REBARBANDINFO ();
	rbBand.cbSize = REBARBANDINFO.sizeof;
	rbBand.fMask = OS.RBBIM_STYLE;
	OS.SendMessage (handle, OS.RB_GETBANDINFO, index + 1, rbBand);
	return (rbBand.fStyle & OS.RBBS_BREAK) != 0;
}

/**
 * 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 locked;
}

/**
 * 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 ();
	CoolItem [] items = getItems ();
	int [] indices = new int [items.length];
	int count = 0;
	for (int i=0; i<items.length; i++) {
		if (items [i].getWrap ()) indices [count++] = i;	
	}
	int [] result = new int [count];
	System.arraycopy (indices, 0, result, 0, count);
	return result;
}

/**
 * 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);
	return (int)/*64*/OS.SendMessage (handle, OS.RB_IDTOINDEX, item.id, 0);
}

void resizeToPreferredWidth (int index) {
	/*
	* Bug in Windows.  When RB_GETBANDBORDERS is sent
	* with an index out of range, Windows GP's.  The
	* fix is to ensure the index is in range.
	*/
	int count = (int)/*64*/OS.SendMessage(handle, OS.RB_GETBANDCOUNT, 0, 0);
	if (0 <= index && index < count) {
		REBARBANDINFO rbBand = new REBARBANDINFO();
		rbBand.cbSize = REBARBANDINFO.sizeof;
		rbBand.fMask = OS.RBBIM_IDEALSIZE;
		OS.SendMessage (handle, OS.RB_GETBANDINFO, index, rbBand);
		RECT rect = new RECT ();
		OS.SendMessage (handle, OS.RB_GETBANDBORDERS, index, rect);
		rbBand.cx = rbBand.cxIdeal + rect.left;
		if ((style & SWT.FLAT) == 0) rbBand.cx += rect.right;
		rbBand.fMask = OS.RBBIM_SIZE;
		OS.SendMessage (handle, OS.RB_SETBANDINFO, index, rbBand);
	}
}

void resizeToMaximumWidth (int index) {
	REBARBANDINFO rbBand = new REBARBANDINFO();
	rbBand.cbSize = REBARBANDINFO.sizeof;
	rbBand.fMask = OS.RBBIM_SIZE;
	rbBand.cx = MAX_WIDTH;
	OS.SendMessage (handle, OS.RB_SETBANDINFO, index, rbBand);
}	

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

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

void reskinChildren (int flags) {
	if (items != null) {
		for (int i=0; i<items.length; i++) {
			CoolItem item = items [i];
			if (item != null) item.reskin (flags);
		}
	}
	super.reskinChildren (flags);
}

void setBackgroundPixel (int pixel) {
	if (pixel == -1) pixel = defaultBackground ();
	OS.SendMessage (handle, OS.RB_SETBKCOLOR, 0, pixel);
	setItemColors ((int)/*64*/OS.SendMessage (handle, OS.RB_GETTEXTCOLOR, 0, 0), pixel);
	/*
	* Feature in Windows.  For some reason, Windows
	* does not fully erase the coolbar area and coolbar
	* items when you set the background.  The fix is
	* to invalidate the coolbar area.
	*/
	if (!OS.IsWindowVisible (handle)) return;
	if (OS.IsWinCE) {
		OS.InvalidateRect (handle, null, true);
	} else {
		int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
		OS.RedrawWindow (handle, null, 0, flags);
	}
}

void setForegroundPixel (int pixel) {
	if (pixel == -1) pixel = defaultForeground ();
	OS.SendMessage (handle, OS.RB_SETTEXTCOLOR, 0, pixel);
	setItemColors (pixel, (int)/*64*/OS.SendMessage (handle, OS.RB_GETBKCOLOR, 0, 0));
}

void setItemColors (int foreColor, int backColor) {
	int count = (int)/*64*/OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
	REBARBANDINFO rbBand = new REBARBANDINFO ();
	rbBand.cbSize = REBARBANDINFO.sizeof;
	rbBand.fMask = OS.RBBIM_COLORS;
	rbBand.clrFore = foreColor;
	rbBand.clrBack = backColor;
	for (int i=0; i<count; i++) {
		OS.SendMessage (handle, OS.RB_SETBANDINFO, i, rbBand);
	}
}

/**
 * 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 ();
	setRedraw (false);
	setItemOrder (itemOrder);
	setWrapIndices (wrapIndices);
	setItemSizes (sizes);
	setRedraw (true);
}

/*
 * 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) {
	if (itemOrder == null) error (SWT.ERROR_NULL_ARGUMENT);
	int itemCount = (int)/*64*/OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
	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;
	}
	
	REBARBANDINFO rbBand = new REBARBANDINFO ();
	rbBand.cbSize = REBARBANDINFO.sizeof;
	for (int i=0; i<itemOrder.length; i++) {
		int id = originalItems [itemOrder [i]].id;
		int index = (int)/*64*/OS.SendMessage (handle, OS.RB_IDTOINDEX, id, 0);
		if (index != i) {
			int lastItemSrcRow = getLastIndexOfRow (index);
			int lastItemDstRow = getLastIndexOfRow (i);									
			if (index == lastItemSrcRow) {
				resizeToPreferredWidth (index);
			} 
			if (i == lastItemDstRow) {
				resizeToPreferredWidth (i);
			}	
			
			/* Move the item */
			OS.SendMessage (handle, OS.RB_MOVEBAND, index, i);

			if (index == lastItemSrcRow && index - 1 >= 0) {
				resizeToMaximumWidth (index - 1);
			}
			if (i == lastItemDstRow) {
				resizeToMaximumWidth (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);
	int count = (int)/*64*/OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
	if (sizes.length != count) error (SWT.ERROR_INVALID_ARGUMENT);
	REBARBANDINFO rbBand = new REBARBANDINFO ();
	rbBand.cbSize = REBARBANDINFO.sizeof;
	rbBand.fMask = OS.RBBIM_ID;
	for (int i=0; i<count; i++) {
		OS.SendMessage (handle, OS.RB_GETBANDINFO, i, rbBand);
		items [rbBand.wID].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 ();
	this.locked = locked;
	int count = (int)/*64*/OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
	REBARBANDINFO rbBand = new REBARBANDINFO ();
	rbBand.cbSize = REBARBANDINFO.sizeof;
	rbBand.fMask = OS.RBBIM_STYLE;
	for (int i=0; i<count; i++) {
		OS.SendMessage (handle, OS.RB_GETBANDINFO, i, rbBand);
		if (locked) {
			rbBand.fStyle |= OS.RBBS_NOGRIPPER;
		} else {
			rbBand.fStyle &= ~OS.RBBS_NOGRIPPER;
		}
		OS.SendMessage (handle, OS.RB_SETBANDINFO, i, rbBand);
	}
}

/**
 * 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);
		}	
	}
	setRedraw (false);
	CoolItem [] items = getItems ();
	for (int i=0; i<items.length; i++) {
		CoolItem item = items [i];
		if (item.getWrap ()) {
			resizeToPreferredWidth (i - 1);
			item.setWrap (false);
		}
	}
	resizeToMaximumWidth (count - 1);
	for (int i=0; i<indices.length; i++) {
		int index = indices [i];
		if (0 <= index && index < items.length) {
			CoolItem item = items [index];
			item.setWrap (true);
			resizeToMaximumWidth (index - 1);
		}
	}
	setRedraw (true);
}

int widgetStyle () {
	int bits = super.widgetStyle () | OS.CCS_NODIVIDER | OS.CCS_NORESIZE;
	bits |= OS.RBS_VARHEIGHT | OS.RBS_DBLCLKTOGGLE;
	if ((style & SWT.FLAT) == 0) bits |= OS.RBS_BANDBORDERS; 
	return bits;
}

TCHAR windowClass () {
	return ReBarClass;
}

long /*int*/ windowProc () {
	return ReBarProc;
}

LRESULT WM_COMMAND (long /*int*/ wParam, long /*int*/ lParam) {
	/*
	* Feature in Windows.  When the coolbar window
	* proc processes WM_COMMAND, it forwards this
	* message to its parent.  This is done so that
	* children of this control that send this message 
	* type to their parent will notify not only
	* this control but also the parent of this control,
	* which is typically the application window and
	* the window that is looking for the message.
	* If the control did not forward the message, 
	* applications would have to subclass the control 
	* window to see the message. Because the control
	* window is subclassed by SWT, the message
	* is delivered twice, once by SWT and once when
	* the message is forwarded by the window proc.
	* The fix is to avoid calling the window proc 
	* for this control.
	*/
	LRESULT result = super.WM_COMMAND (wParam, lParam);
	if (result != null) return result;
	return LRESULT.ZERO;
}

LRESULT WM_ERASEBKGND (long /*int*/ wParam, long /*int*/ lParam) {
	LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
	/*
	* Feature in Windows.  For some reason, Windows
	* does not fully erase the area that the cool bar
	* occupies when the size of the cool bar is larger
	* than the space occupied by the cool bar items.
	* The fix is to erase the cool bar background.
	* 
	* NOTE: On versions of Windows prior to XP, for
	* some reason, the cool bar draws separators in
	* WM_ERASEBKGND.  Therefore it is essential to run
	* the cool bar window proc after the background has
	* been erased.
	*/
	if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
		drawBackground (wParam);
		return null;
	}
	return result;
}

LRESULT WM_NOTIFY (long /*int*/ wParam, long /*int*/ lParam) {
	/*
	* Feature in Windows.  When the cool bar window
	* proc processes WM_NOTIFY, it forwards this
	* message to its parent.  This is done so that
	* children of this control that send this message 
	* type to their parent will notify not only
	* this control but also the parent of this control,
	* which is typically the application window and
	* the window that is looking for the message.
	* If the control did not forward the message, 
	* applications would have to subclass the control 
	* window to see the message. Because the control
	* window is subclassed by SWT, the message
	* is delivered twice, once by SWT and once when
	* the message is forwarded by the window proc.
	* The fix is to avoid calling the window proc 
	* for this control.
	*/
	LRESULT result = super.WM_NOTIFY (wParam, lParam);
	if (result != null) return result;
	return LRESULT.ZERO;
}

LRESULT WM_SETREDRAW (long /*int*/ wParam, long /*int*/ lParam) {
	LRESULT result = super.WM_SETREDRAW (wParam, lParam);
	if (result != null) return result;
	/*
	* Feature in Windows.  When redraw is turned off, the rebar
	* control does not call the default window proc.  This means
	* that the rebar will redraw and children of the rebar will
	* also redraw.  The fix is to call both the rebar window proc
	* and the default window proc.
	*
	* NOTE: The rebar control can resize itself in WM_SETREDRAW.
	* When redraw is turned off by the default window proc, this
	* can leave pixel corruption in the parent.  The fix is to
	* detect the size change and damage the previous area in the
	* parent.
	* 
	* NOTE:  In version 6.00 of COMCTL32.DLL, when WM_SETREDRAW
	* is off, we cannot detect that the size has changed causing
	* pixel corruption.  The fix is to disallow WM_SETREDRAW by
	* not running the default window proc or the rebar window
	* proc.
	*/
	if (OS.COMCTL32_MAJOR >= 6) return LRESULT.ZERO;
	Rectangle rect = getBounds ();		
	long /*int*/ code = callWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
	OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
	if (!rect.equals (getBounds ())) {
		parent.redraw (rect.x, rect.y, rect.width, rect.height, true);
	}
	return new LRESULT (code);
}

LRESULT WM_SIZE (long /*int*/ wParam, long /*int*/ lParam) {
	if (ignoreResize) {
		long /*int*/ code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam);
		if (code == 0) return LRESULT.ZERO;
		return new LRESULT (code);
	}
	//TEMPORARY CODE
//	if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
//		if (background == -1 && (style & SWT.FLAT) == 0) {
//			OS.InvalidateRect (handle, null, true);
//		}
//	}
	return super.WM_SIZE (wParam, lParam);
}

LRESULT wmNotifyChild (NMHDR hdr, long /*int*/ wParam, long /*int*/ lParam) {
	switch (hdr.code) {
		case OS.RBN_BEGINDRAG: {
			int pos = OS.GetMessagePos ();
			POINT pt = new POINT ();
			OS.POINTSTOPOINT (pt, pos);
			OS.ScreenToClient (handle, pt);
			int button = display.lastButton != 0 ? display.lastButton : 1;
			if (!sendDragEvent (button, pt.x, pt.y)) return LRESULT.ONE;
			break;
		}
		case OS.RBN_CHILDSIZE: {
			/*
			* Bug in Windows.  When Windows sets the size of the rebar band
			* child and the child is a combo box, the size of the drop down
			* portion of the combo box is resized to zero.  The fix is to set
			* the size of the control to the current size after the rebar has
			* already resized it.  If the control is not a combo, this does
			* nothing.  If the control is a combo, the drop down portion is
			* recalculated.
			*/
			NMREBARCHILDSIZE lprbcs  = new NMREBARCHILDSIZE ();
			OS.MoveMemory (lprbcs, lParam, NMREBARCHILDSIZE.sizeof);
			if (lprbcs.uBand != -1) {
				CoolItem item = items [lprbcs.wID];
				Control control = item.control;
				if (control != null) {
					int width = lprbcs.rcChild_right - lprbcs.rcChild_left;
					int height = lprbcs.rcChild_bottom - lprbcs.rcChild_top;
					control.setBounds (lprbcs.rcChild_left, lprbcs.rcChild_top, width, height);
				}
			}
			break;
		}
		case OS.RBN_HEIGHTCHANGE: {
			if (!ignoreResize) {
				Point size = getSize ();
				int border = getBorderWidth ();
				int barHeight = (int)/*64*/OS.SendMessage (handle, OS.RB_GETBARHEIGHT, 0, 0);
				if ((style & SWT.VERTICAL) != 0) {
					setSize (barHeight + 2 * border, size.y);
				} else {
					setSize (size.x, barHeight + 2 * border);
				}
			}
			break;
		}
		case OS.RBN_CHEVRONPUSHED: {
			NMREBARCHEVRON lpnm = new NMREBARCHEVRON ();
			OS.MoveMemory (lpnm, lParam, NMREBARCHEVRON.sizeof);
			CoolItem item = items [lpnm.wID];
			if (item != null) {
				Event event = new Event();
				event.detail = SWT.ARROW;
				if ((style & SWT.VERTICAL) != 0) {
					event.x = lpnm.right;
					event.y = lpnm.top;
				} else {
					event.x = lpnm.left;
					event.y = lpnm.bottom;
				}
				item.sendSelectionEvent(SWT.Selection, event, false);
			}
			break;
		}
		case OS.NM_CUSTOMDRAW: {
			/*
			* Bug in Windows.  On versions of Windows prior to XP,
			* drawing the background color in NM_CUSTOMDRAW erases
			* the separators.  The fix is to draw the background
			* in WM_ERASEBKGND.
			*/
			if (OS.COMCTL32_MAJOR < 6) break;
			if (findBackgroundControl () != null || (style & SWT.FLAT) != 0) {
				NMCUSTOMDRAW nmcd = new NMCUSTOMDRAW ();
				OS.MoveMemory (nmcd, lParam, NMCUSTOMDRAW.sizeof);
				switch (nmcd.dwDrawStage) {
					case OS.CDDS_PREERASE:
						return new LRESULT (OS.CDRF_SKIPDEFAULT | OS.CDRF_NOTIFYPOSTERASE);
					case OS.CDDS_POSTERASE:
						drawBackground (nmcd.hdc);
						break;
				}
			}
			break;
		}
	}
	return super.wmNotifyChild (hdr, wParam, lParam);
}
}
