/*******************************************************************************
 * 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 intrinsic.mx.core.UIComponent;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;

public class Sash extends Control {
	int lastX, lastY, startX, startY;
	Cursor sizeCursor;
	boolean dragging;
	private final static int INCREMENT = 1;
	private final static int PAGE_INCREMENT = 9;

public Sash (Composite parent, int style) {
	super (parent, checkStyle (style));
	int cursorStyle = (style & SWT.VERTICAL) != 0 ? SWT.CURSOR_SIZEWE : SWT.CURSOR_SIZENS;
	sizeCursor = display.getSystemCursor(cursorStyle);
}

public void addSelectionListener (SelectionListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener(listener);
	addListener(SWT.Selection,typedListener);
	addListener(SWT.DefaultSelection,typedListener);
}

static int checkStyle (int style) {
	/*
	* Only supports smooth dragging.
	*/
	style |= SWT.SMOOTH;
	return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
}

public Point computeSize (int wHint, int hHint, boolean changed) {
	checkWidget();
	int width = 0, height = 0;
	if ((style & SWT.HORIZONTAL) != 0) {
		width += DEFAULT_WIDTH;  height += 5;
	} else {
		width += 5; height += DEFAULT_HEIGHT;
	}
	if (wHint != SWT.DEFAULT) width = wHint;
	if (hHint != SWT.DEFAULT) height = hHint;
	return new Point (width, height);
}

void createHandle () {
	intrinsic.mx.containers.Canvas widget = new intrinsic.mx.containers.Canvas();
	// Note that the color is needed for hit test
	widget.setStyle ("backgroundColor", 0xFFFFFF);
	object = widget;
}

boolean sendFocusEvent(int type) {
	boolean result = super.sendFocusEvent (type);
	if (!isDisposed ()) return false;
	if (type == SWT.FocusIn) {
		Point location = getLocation();
		lastX = location.x;
		lastY = location.y;
	}
	return result;
}

boolean sendKeyEvent(int type, Event keyEvent) {
	boolean result = super.sendKeyEvent(type, keyEvent);
	if (isDisposed ()) return false;
	if (!result) return result;
	if (type != SWT.KeyDown) return result;
	switch (keyEvent.keyCode) {
		case SWT.UP:
		case SWT.LEFT:
		case SWT.DOWN:
		case SWT.RIGHT: {
			int xChange = 0, yChange = 0;
			int stepSize = PAGE_INCREMENT;
			if ((keyEvent.stateMask & SWT.CONTROL) != 0) stepSize = INCREMENT;
			if ((style & SWT.VERTICAL) != 0) {
				if (keyEvent.keyCode == SWT.UP || keyEvent.keyCode == SWT.DOWN) break;
				xChange = SWT.LEFT == 123 ? -stepSize : stepSize;
			} else {
				if (keyEvent.keyCode == SWT.LEFT || keyEvent.keyCode == SWT.RIGHT) break;
				yChange = SWT.UP == 126 ? -stepSize : stepSize;
			}
			
			Rectangle bounds = getBounds ();
			int width = bounds.width, height = bounds.height;
			Rectangle parentBounds = parent.getBounds ();
			int parentWidth = parentBounds.width;
			int parentHeight = parentBounds.height;
			int newX = lastX, newY = lastY;
			if ((style & SWT.VERTICAL) != 0) {
				newX = Math.min (Math.max (0, lastX + xChange), parentWidth - width);
			} else {
				newY = Math.min (Math.max (0, lastY + yChange), parentHeight - height);
			}
			if (newX == lastX && newY == lastY) return result;
			Event event = new Event ();
			event.x = newX;
			event.y = newY;
			event.width = width;
			event.height = height;
			sendEvent (SWT.Selection, event);
			if (isDisposed ()) break;
			if (event.doit) {
				setBounds (event.x, event.y, width, height);
				if (isDisposed ()) break;
				lastX = event.x;
				lastY = event.y;
				if (isDisposed ()) return result;
				int cursorX = event.x, cursorY = event.y;
				if ((style & SWT.VERTICAL) != 0) {
					cursorY += height / 2;
				} else {
					cursorX += width / 2;
				}
				display.setCursorLocation (parent.toDisplay (cursorX, cursorY));
			}
			break;
		}
	}	
	return result;
}

boolean sendMouseEvent (int type, Event mouseEvent, boolean send) {
	boolean result = super.sendMouseEvent (type, mouseEvent, send);
	int x = mouseEvent.x, y = mouseEvent.y;
	int controlX = (int)object.x;
	int controlY = (int)object.y;
	int width = (int)object.width;
	int height = (int)object.height;
	UIComponent parentComponent = parent.topComponent ();
	int parentWidth = (int)parentComponent.width;
	int parentHeight = (int)parentComponent.height;
	switch (type) {
		case SWT.MouseDown:
			if (mouseEvent.button != 1 || mouseEvent.count != 1) break;
			startX = x;
			startY = y;
			Event event = new Event ();
			event.x = controlX;
			event.y = controlY;
			event.width = width;
			event.height = height;
			sendEvent (SWT.Selection, event);
			if (isDisposed ()) return result;
			if (event.doit) {
				lastX = event.x;
				lastY = event.y;
				dragging = true;
		 		setBounds (event.x, event.y, width, height);
		 		}
			break;
		case SWT.MouseUp:
			if (!dragging) break;
			dragging = false;
			event = new Event ();
			event.x = lastX;
			event.y = lastY;
			event.width = width;
			event.height = height;
			sendEvent (SWT.Selection, event);
			if (isDisposed ()) return result;
			if (event.doit) {
				setBounds (event.x, event.y, width, height);
			}
			break;
		case SWT.MouseMove:
			if (!dragging) break;
			int newX = lastX, newY = lastY;
			if ((style & SWT.VERTICAL) != 0) {
				newX = Math.min (Math.max (0, x + controlX - startX), parentWidth - width);
			} else {
				newY = Math.min (Math.max (0, y + controlY - startY), parentHeight - height);
			}
			if (newX == lastX && newY == lastY) return result;
			event = new Event ();
			event.x = newX;
			event.y = newY;
			event.width = width;
			event.height = height;
			sendEvent (SWT.Selection, event);
			if (isDisposed ()) return result;
			if (event.doit) {
				lastX = event.x;
				lastY = event.y;
				setBounds (event.x, event.y, width, height);
			}
			break;
		 }
		 return result;
}

Cursor findCursor() {
	Cursor cursor = super.findCursor ();
	if (cursor != null) return cursor;
	return sizeCursor;
}

boolean hooksMouse (int type) {
	switch (type) {
		case SWT.MouseDown:
		case SWT.MouseUp:
		case SWT.MouseMove:
			return true;
	}
	return super.hooksMouse (type);
}

void releaseWidget () {
	super.releaseWidget ();
	sizeCursor = null;
}

public void removeSelectionListener (SelectionListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook(SWT.Selection, listener);
	eventTable.unhook(SWT.DefaultSelection,listener);
}

}
