package org.eclipse.swt.widgets;

/*
 * Copyright (c) 2000, 2002 IBM Corp.  All rights reserved.
 * This file is made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 */

import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;

/**
 * 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</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 lastFocusId;
	ToolItem [] items;
	ImageList imageList, disabledImageList, hotImageList;
	static final int ToolBarProc;
	static final TCHAR ToolBarClass = new TCHAR (0, OS.TOOLBARCLASSNAME, true);
	static {
		WNDCLASS lpWndClass = new WNDCLASS ();
		OS.GetClassInfo (0, ToolBarClass, lpWndClass);
		ToolBarProc = lpWndClass.lpfnWndProc;
	}
	
	/*
	* From the Windows SDK for TB_SETBUTTONSIZE:
	*
	*   "If an application does not explicitly
	*	set the button size, the size defaults
	*	to 24 by 22 pixels". 
	*/
	static final int DEFAULT_WIDTH = 24;
	static final int DEFAULT_HEIGHT = 22;

/**
 * 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#FLAT
 * @see SWT#WRAP
 * @see SWT#RIGHT
 * @see SWT#HORIZONTAL
 * @see SWT#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 & SWT.VERTICAL) != 0) {
		this.style |= SWT.VERTICAL;
	} else {
		this.style |= SWT.HORIZONTAL;
	}
}

int callWindowProc (int msg, int wParam, int lParam) {
	if (handle == 0) return 0;
	/*
	* Bug in Windows.  For some reason, during the processing
	* of WM_SYSCHAR, the tool bar window proc does not call the
	* default window proc causing mnemonics for the menu bar
	* to be ignored.  The fix is to always call the default
	* window proc for WM_SYSCHAR.
	*/
	if (msg == OS.WM_SYSCHAR) {
		return OS.DefWindowProc (handle, msg, wParam, lParam);
	}
	return OS.CallWindowProc (ToolBarProc, handle, msg, wParam, lParam);
}

static int checkStyle (int style) {
	/*
	* On Windows, only flat tool bars can be traversed.
	*/
	if ((style & SWT.FLAT) == 0) style |= SWT.NO_FOCUS;
	
	/*
	* A vertical tool bar cannot wrap because TB_SETROWS
	* fails when the toobar has TBSTYLE_WRAPABLE.
	*/
	/*
	* This code is intentionally commented.
	*/
	//if ((style & SWT.VERTICAL) != 0) style &= ~SWT.WRAP;
	
	/*
	* The TB_SETROWS calls are currently commented, so force
	* the wrap style if this bar is vertical.
	*/
	if ((style & SWT.VERTICAL) != 0) style |= SWT.WRAP;
		
	/*
	* 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 ();
	if (layout != null) {
		return super.computeSize (wHint, hHint, changed);
	}
	int width = 0, height = 0;
	RECT oldRect = new RECT ();
	OS.GetWindowRect (handle, oldRect);
	int oldWidth = oldRect.right - oldRect.left;
	int oldHeight = oldRect.bottom - oldRect.top;
	int newWidth = wHint, newHeight = hHint;
	if (newWidth == SWT.DEFAULT) newWidth = 0x3FFF;
	if (newHeight == SWT.DEFAULT) newHeight = 0x3FFF;
	int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOREDRAW | OS.SWP_NOZORDER;
	OS.SetWindowPos (handle, 0, 0, 0, newWidth, newHeight, flags);
	int count = OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
	if (count != 0) {
		RECT rect = new RECT ();
		OS.SendMessage (handle, OS.TB_GETITEMRECT, count - 1, rect);
		width = Math.max (width, rect.right);
		height = Math.max (height, rect.bottom);
	}
	OS.SetWindowPos (handle, 0, 0, 0, oldWidth, oldHeight, flags);
	/*
	* From the Windows SDK for TB_SETBUTTONSIZE:
	*
	*   "If an application does not explicitly
	*	set the button size, the size defaults
	*	to 24 by 22 pixels". 
	*/
	if (width == 0) width = DEFAULT_WIDTH;
	if (height == 0) height = DEFAULT_HEIGHT;
	if (wHint != SWT.DEFAULT) width = wHint;
	if (hHint != SWT.DEFAULT) height = hHint;
	Rectangle trim = computeTrim (0, 0, width, height);
	width = trim.width;  height = trim.height;
	return new Point (width, height);
}


public Rectangle computeTrim (int x, int y, int width, int height) {
	checkWidget ();
	Rectangle trim = super. computeTrim (x, y, width, height);
	int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
	if ((bits & OS.CCS_NODIVIDER) == 0) trim.height += 2;
	return trim;
}

void createHandle () {
	super.createHandle ();
	state &= ~CANVAS;

	/*
	* Feature in Windows.  Despite the fact that the
	* tool tip text contains \r\n, the tooltip will
	* not honour the new line unless TTM_SETMAXTIPWIDTH
	* is set.  The fix is to set TTM_SETMAXTIPWIDTH to
	* a large value.
	*/
	int hwndToolTip = OS.SendMessage (handle, OS.TB_GETTOOLTIPS, 0, 0);	
	/*
	* This line is intentionally commented.  The tool
	* bar currently sets this value to 300 so it is
	* not necessary to set TTM_SETMAXTIPWIDTH.
	*/
//	OS.SendMessage (hwndToolTip, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);

	/*
	* Feature in Windows.  When the tool tip control is
	* created, the parent of the tool tip is the shell.
	* If SetParent () is used to reparent the tool bar
	* into a new shell, the tool tip is not reparented
	* and pops up underneath the new shell.  The fix is
	* to make sure the tool tip is a topmost window.
	*/
	/*
	* Bug in Windows 98 and NT.  Setting the tool tip to be the
	* top most window using HWND_TOPMOST can result in a parent
	* dialog shell being moved behind its parent if the dialog
	* has a sibling that is currently on top.  The fix is to lock
	* the z-order of the active window.
	*/
	Display display = getDisplay ();
	int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOSIZE;
	display.lockActiveWindow = true;
	OS.SetWindowPos (hwndToolTip, OS.HWND_TOPMOST, 0, 0, 0, 0, flags);
	display.lockActiveWindow = false;

	/*
	* 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.
	*/
	int hFont = OS.GetStockObject (OS.SYSTEM_FONT);
	OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);

	/* Set the button struct, bitmap and button sizes */
	OS.SendMessage (handle, OS.TB_BUTTONSTRUCTSIZE, TBBUTTON.sizeof, 0);
	OS.SendMessage (handle, OS.TB_SETBITMAPSIZE, 0, 0);
	OS.SendMessage (handle, OS.TB_SETBUTTONSIZE, 0, 0);

	/* Set the extended style bits */
	int bits = OS.TBSTYLE_EX_DRAWDDARROWS;
	OS.SendMessage (handle, OS.TB_SETEXTENDEDSTYLE, 0, bits);
}

void createItem (ToolItem item, int index) {
	int count = OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 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) {
		ToolItem [] newItems = new ToolItem [items.length + 4];
		System.arraycopy (items, 0, newItems, 0, items.length);
		items = newItems;
	}
	int bits = item.widgetStyle ();
	TBBUTTON lpButton = new TBBUTTON ();
	lpButton.idCommand = id;
	lpButton.fsStyle = (byte) bits;
	lpButton.fsState = (byte) OS.TBSTATE_ENABLED;
	
	/*
	* Bug in Windows.  Despite the fact that the image list
	* index has never been set for the item, Windows always
	* assumes that the image index for the item is valid.
	* When an item is inserted, the image index is zero.
	* Therefore, when the first image is inserted and is
	* assigned image index zero, every item draws with this
	* image.  The fix is to set the image index to none
	* when the item is created.  This is not necessary in
	* the case when the item has the BTNS_SEP style because
	* separators cannot show images.
	*/
	if ((bits & OS.BTNS_SEP) == 0) lpButton.iBitmap = OS.I_IMAGENONE;
	if (OS.SendMessage (handle, OS.TB_INSERTBUTTON, index, lpButton) == 0) {
		error (SWT.ERROR_ITEM_NOT_ADDED);
	}
	items [item.id = id] = item;
	/*
	* This code is intentionally commented.
	*/
//	if ((style & SWT.VERTICAL) != 0) {
//		OS.SendMessage (handle, OS.TB_SETROWS, count+1, 0);
//	}
	layoutItems ();
}

void createWidget () {
	super.createWidget ();
	items = new ToolItem [4];
	lastFocusId = -1;
}

int defaultBackground () {
	if (OS.IsWinCE) return OS.GetSysColor (OS.COLOR_BTNFACE);
	return super.defaultBackground ();
}

void destroyItem (ToolItem item) {
	TBBUTTONINFO info = new TBBUTTONINFO ();
	info.cbSize = TBBUTTONINFO.sizeof;
	info.dwMask = OS.TBIF_IMAGE | OS.TBIF_STYLE;
	int index = OS.SendMessage (handle, OS.TB_GETBUTTONINFO, item.id, info);
	/*
	* Feature in Windows.  For some reason, a tool item that has
	* the style BTNS_SEP does not return I_IMAGENONE when queried
	* for an image index, despite the fact that no attempt has been
	* made to assign an image to the item.  As a result, operations
	* on an image list that use the wrong index cause random results.	
	* The fix is to ensure that the tool item is not a separator
	* before using the image index.  Since separators cannot have
	* an image and one is never assigned, this is not a problem.
	*/
	if ((info.fsStyle & OS.BTNS_SEP) == 0 && info.iImage != OS.I_IMAGENONE) {
		if (imageList != null) imageList.put (info.iImage, null);
		if (hotImageList != null) hotImageList.put (info.iImage, null);
		if (disabledImageList != null) disabledImageList.put (info.iImage, null);
	}
	int result = OS.SendMessage (handle, OS.TB_DELETEBUTTON, index, 0);
	if (item.id == lastFocusId) lastFocusId = -1;
	items [item.id] = null;
	item.id = -1;
	int count = OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
	if (count == 0) {
		Display display = getDisplay ();
		if (imageList != null) {
			OS.SendMessage (handle, OS.TB_SETIMAGELIST, 0, 0);
			display.releaseToolImageList (imageList);
		}
		if (hotImageList != null) {
			OS.SendMessage (handle, OS.TB_SETHOTIMAGELIST, 0, 0);
			display.releaseToolHotImageList (hotImageList);
		}
		if (disabledImageList != null) {
			OS.SendMessage (handle, OS.TB_SETDISABLEDIMAGELIST, 0, 0);
			display.releaseToolDisabledImageList (disabledImageList);
		}
		imageList = hotImageList = disabledImageList = null;
		items = new ToolItem [4];
	}
	/*
	* This code is intentionally commented.
	*/
//	if ((style & SWT.VERTICAL) != 0) {
//		OS.SendMessage (handle, OS.TB_SETROWS, count-1, 0);
//	}
	layoutItems ();
}

ImageList getDisabledImageList () {
	return disabledImageList;
}

ImageList getHotImageList () {
	return hotImageList;
}

ImageList getImageList () {
	return imageList;
}

/**
 * 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 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 ToolItem getItem (int index) {
	checkWidget ();
	int count = OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
	if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);	
	TBBUTTON lpButton = new TBBUTTON ();
	int result = OS.SendMessage (handle, OS.TB_GETBUTTON, index, lpButton);
	if (result == 0) error (SWT.ERROR_CANNOT_GET_ITEM);
	return items [lpButton.idCommand];
}

/**
 * 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 listener is null</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 ToolItem getItem (Point point) {
	checkWidget ();
	if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
	ToolItem [] items = getItems ();
	for (int i=0; i<items.length; i++) {
		Rectangle rect = items [i].getBounds ();
		if (rect.contains (point)) return items [i];
	}
	return null;
}

/**
 * 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 OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
}

/**
 * Returns an array of <code>TabItem</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 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 ToolItem [] getItems () {
	checkWidget ();
	int count = OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
	TBBUTTON lpButton = new TBBUTTON ();
	ToolItem [] result = new ToolItem [count];
	for (int i=0; i<count; i++) {
		int code = OS.SendMessage (handle, OS.TB_GETBUTTON, i, lpButton);
		result [i] = items [lpButton.idCommand];
	}
	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 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 getRowCount () {
	checkWidget ();
	return OS.SendMessage (handle, OS.TB_GETROWS, 0, 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 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 (ToolItem item) {
	checkWidget ();
	if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
	return OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, item.id, 0);
}

void layoutItems () {
	for (int i=0; i<items.length; i++) {
		ToolItem item = items [i];
		if (item != null) item.resizeControl ();
	}
}

boolean mnemonicHit (char ch) {
	int key = wcsToMbcs (ch);
	int [] id = new int [1];
	if (OS.SendMessage (handle, OS.TB_MAPACCELERATOR, key, id) == 0) {
		return false;
	}
	if (!setTabGroupFocus ()) return false;
	int index = OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, id [0], 0);
	if (index == -1) return false;
	OS.SendMessage (handle, OS.TB_SETHOTITEM, index, 0);
	items [id [0]].click (false);
	return true;
}

boolean mnemonicMatch (char ch) {
	int key = wcsToMbcs (ch);
	int [] id = new int [1];
	return OS.SendMessage (handle, OS.TB_MAPACCELERATOR, key, id) != 0;
}

void releaseWidget () {
	for (int i=0; i<items.length; i++) {
		ToolItem item = items [i];
		if (item != null && !item.isDisposed ()) {
			item.releaseImages ();
			item.releaseWidget ();
		}
	}
	items = null;
	Display display = getDisplay ();
	if (imageList != null) {
		OS.SendMessage (handle, OS.TB_SETIMAGELIST, 0, 0);
		display.releaseToolImageList (imageList);
	}
	if (hotImageList != null) {
		OS.SendMessage (handle, OS.TB_SETHOTIMAGELIST, 0, 0);
		display.releaseToolHotImageList (hotImageList);
	}
	if (disabledImageList != null) {
		OS.SendMessage (handle, OS.TB_SETDISABLEDIMAGELIST, 0, 0);
		display.releaseToolDisabledImageList (disabledImageList);
	}
	imageList = hotImageList = disabledImageList = null;
	super.releaseWidget ();
}

void setBounds (int x, int y, int width, int height, int flags) {
	/*
	* Feature in Windows.  For some reason, when a tool bar is
	* repositioned more than once using DeferWindowPos () into
	* the same HDWP, the toolbar redraws more than once, defeating
	* the puropse of DeferWindowPos ().  The fix is to end the
	* defered positioning before the next tool bar is added,
	* ensuring that only one tool bar position is deferred at
	* any given time.
	*/
	if (parent.hdwp != 0) {
		if (drawCount == 0 && OS.IsWindowVisible (handle)) {
			int oldHdwp = parent.hdwp;
			parent.hdwp = 0;
			OS.EndDeferWindowPos (oldHdwp);
			int count = parent.getChildrenCount ();
			parent.hdwp = OS.BeginDeferWindowPos (count);
		}
	}
	super.setBounds (x, y, width, height, flags);
}

void setDefaultFont () {
	super.setDefaultFont ();
	OS.SendMessage (handle, OS.TB_SETBITMAPSIZE, 0, 0);
	OS.SendMessage (handle, OS.TB_SETBUTTONSIZE, 0, 0);
}

void setDisabledImageList (ImageList imageList) {
	if (disabledImageList == imageList) return;
	int hImageList = 0;
	if ((disabledImageList = imageList) != null) {
		hImageList = disabledImageList.getHandle ();
	}
	OS.SendMessage (handle, OS.TB_SETDISABLEDIMAGELIST, 0, hImageList);
}

void setHotImageList (ImageList imageList) {
	if (hotImageList == imageList) return;
	int hImageList = 0;
	if ((hotImageList = imageList) != null) {
		hImageList = hotImageList.getHandle ();
	}
	OS.SendMessage (handle, OS.TB_SETHOTIMAGELIST, 0, hImageList);
}

void setImageList (ImageList imageList) {
	if (this.imageList == imageList) return;
	int hImageList = 0;
	if ((this.imageList = imageList) != null) {
		hImageList = imageList.getHandle ();
	}
	OS.SendMessage (handle, OS.TB_SETIMAGELIST, 0, hImageList);
}

boolean setTabItemFocus () {
	int index = 0;
	while (index < items.length) {
		ToolItem item = items [index];
		if (item != null && (item.style & SWT.SEPARATOR) == 0) {
			if (item.getEnabled ()) break;
		}
		index++;
	}
	if (index == items.length) return false;
	return super.setTabItemFocus ();
}

int toolTipHandle () {
	return OS.SendMessage (handle, OS.TB_GETTOOLTIPS, 0, 0);
}

String toolTipText (NMTTDISPINFO hdr) {
	if ((hdr.uFlags & OS.TTF_IDISHWND) != 0) {
		return null;
	}
	int index = hdr.idFrom;
	int hwndToolTip = toolTipHandle ();
	if (hwndToolTip == hdr.hwndFrom) {
		if ((0 <= index) && (index < items.length)) {
			ToolItem item = items [index];
			if (item != null) return item.toolTipText;
		}
	}
	return super.toolTipText (hdr);
}

int widgetStyle () {
	int bits = super.widgetStyle () | OS.CCS_NODIVIDER | OS.CCS_NORESIZE | OS.TBSTYLE_TOOLTIPS;
	if ((style & SWT.WRAP) != 0) bits |= OS.TBSTYLE_WRAPABLE;
	if ((style & SWT.FLAT) != 0) bits |= OS.TBSTYLE_FLAT;
	if ((style & SWT.RIGHT) != 0) bits |= OS.TBSTYLE_LIST;
	return bits;
}

TCHAR windowClass () {
	return ToolBarClass;
}

int windowProc () {
	return ToolBarProc;
}

LRESULT WM_GETDLGCODE (int wParam, int lParam) {
	LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
	/*
	* Return DLGC_BUTTON so that mnemonics will be
	* processed without needing to press the ALT key
	* when the widget has focus.
	*/
	if (result != null) return result;
	return new LRESULT (OS.DLGC_BUTTON);
}

LRESULT WM_COMMAND (int wParam, int lParam) {
	/*
	* Feature in Windows.  When the toolbar 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_KEYDOWN (int wParam, int lParam) {
	LRESULT result = super.WM_KEYDOWN (wParam, lParam);
	if (result != null) return result;
	switch (wParam) {
		case OS.VK_RETURN:
		case OS.VK_SPACE:
			int index = OS.SendMessage (handle, OS.TB_GETHOTITEM, 0, 0);
			if (index != -1) {
				TBBUTTON lpButton = new TBBUTTON ();
				int code = OS.SendMessage (handle, OS.TB_GETBUTTON, index, lpButton);
				if (code != 0) {
					items [lpButton.idCommand].click (wParam == OS.VK_RETURN);
					return LRESULT.ZERO;
				}
			}
	}
	return result;
}

LRESULT WM_KILLFOCUS (int wParam, int lParam) {
	int index = OS.SendMessage (handle, OS.TB_GETHOTITEM, 0, 0);
	TBBUTTON lpButton = new TBBUTTON ();
	int code = OS.SendMessage (handle, OS.TB_GETBUTTON, index, lpButton);
	if (code != 0) lastFocusId = lpButton.idCommand;
	return super.WM_KILLFOCUS (wParam, lParam);
}

LRESULT WM_NOTIFY (int wParam, int lParam) {
	/*
	* Feature in Windows.  When the toolbar 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_SETFOCUS (int wParam, int lParam) {
	LRESULT result = super.WM_SETFOCUS (wParam, lParam);
	if (lastFocusId != -1 && handle == OS.GetFocus ()) {
		int index = OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, lastFocusId, 0); 
		OS.SendMessage (handle, OS.TB_SETHOTITEM, index, 0);
	}
	return result;
}

LRESULT WM_SIZE (int wParam, int lParam) {
	LRESULT result = super.WM_SIZE (wParam, lParam);
	/*
	* It is possible (but unlikely), that application
	* code could have disposed the widget in the resize
	* event.  If this happens, end the processing of the
	* Windows message by returning the result of the
	* WM_SIZE message.
	*/
	if (isDisposed ()) return result;
	layoutItems ();
	return result;
}

LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) {
	LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
	if (result != null) return result;
	/*
	* Bug in Windows.  When a flat tool bar is wrapped,
	* Windows draws a horizontal separator between the
	* rows.  The tool bar does not draw the first or
	* the last two pixels of this separator.  When the
	* toolbar is resized to be bigger, only the new
	* area is drawn and the last two pixels, which are
	* blank are drawn over by separator.  This leaves
	* garbage on the screen.  The fix is to damage the
	* pixels.
	*/
	if (drawCount != 0) return result;
	if ((style & SWT.WRAP) == 0) return result;
	if (!OS.IsWindowVisible (handle)) return result;
	if (OS.SendMessage (handle, OS.TB_GETROWS, 0, 0) == 1) {
		return result;
	}
	WINDOWPOS lpwp = new WINDOWPOS ();
	OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
	if ((lpwp.flags & (OS.SWP_NOSIZE | OS.SWP_NOREDRAW)) != 0) {
		return result;
	}
	RECT oldRect = new RECT ();
	OS.GetClientRect (handle, oldRect);
	RECT newRect = new RECT ();
	OS.SetRect (newRect, 0, 0, lpwp.cx, lpwp.cy);
	OS.SendMessage (handle, OS.WM_NCCALCSIZE, 0, newRect);
	int oldWidth = oldRect.right - oldRect.left;
	int newWidth = newRect.right - newRect.left;
	if (newWidth > oldWidth) {
		RECT rect = new RECT ();
		rect.left = oldWidth - 2;
		rect.right = oldWidth;
		rect.bottom = newRect.bottom - newRect.top;
		OS.InvalidateRect (handle, rect, false);
	}
	return result;
}

LRESULT wmCommandChild (int wParam, int lParam) {
	ToolItem child = items [wParam & 0xFFFF];
	if (child == null) return null;
	return child.wmCommandChild (wParam, lParam);
}

LRESULT wmNotifyChild (int wParam, int lParam) {
	NMHDR hdr = new NMHDR ();
	OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
	switch (hdr.code) {
		case OS.TBN_DROPDOWN:
			NMTOOLBAR lpnmtb = new NMTOOLBAR ();
			OS.MoveMemory (lpnmtb, lParam, NMTOOLBAR.sizeof);
			ToolItem child = items [lpnmtb.iItem];
			if (child != null) {
				Event event = new Event ();
				event.detail = SWT.ARROW;
				child.postEvent (SWT.Selection, event);
				return null;
			}
			break;
	}
	return super.wmNotifyChild (wParam, lParam);
}

}
