package org.eclipse.swt.widgets;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved
 */

import org.eclipse.swt.internal.photon.*;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.events.*;

public class Scale extends Control {


public Scale (Composite parent, int style) {
	super (parent, checkStyle (style));
}

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) {
	return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
}

public Point computeSize (int wHint, int hHint, boolean changed) {
	checkWidget();
	PhDim_t dim = new PhDim_t();
	if (!OS.PtWidgetIsRealized (handle)) OS.PtExtentWidget (handle);
	OS.PtWidgetPreferredSize(handle, dim);
	int width = dim.w * 7; int height = dim.h;
	if (wHint != SWT.DEFAULT || hHint != SWT.DEFAULT) {
		PhRect_t rect = new PhRect_t ();
		PhArea_t area = new PhArea_t ();
		rect.lr_x = (short) (wHint - 1);
		rect.lr_y = (short) (hHint - 1);
		OS.PtSetAreaFromWidgetCanvas (handle, rect, area);
		if (wHint != SWT.DEFAULT) width = area.size_w;
		if (hHint != SWT.DEFAULT) height = area.size_h;
	}
	return new Point (width, height);
}

void createHandle (int index) {
	state |= HANDLE;
	Display display = getDisplay ();
	int clazz = display.PtSlider;
	int parentHandle = parent.handle;
	int [] args = {
		OS.Pt_ARG_MAXIMUM, 100, 0,
		OS.Pt_ARG_PAGE_INCREMENT, 10, 0,
		OS.Pt_ARG_SLIDER_SIZE, 10, 0,
		OS.Pt_ARG_ORIENTATION, (style & SWT.HORIZONTAL) != 0 ? OS.Pt_HORIZONTAL : OS.Pt_VERTICAL, 0,
		OS.Pt_ARG_FILL_COLOR, display.WIDGET_BACKGROUND, 0,
		OS.Pt_ARG_RESIZE_FLAGS, 0, OS.Pt_RESIZE_XY_BITS,
	};
	handle = OS.PtCreateWidget (clazz, parentHandle, args.length / 3, args);
	if (handle == 0) error (SWT.ERROR_NO_HANDLES);
}

public int getIncrement () {
	checkWidget();
	int [] args = {OS.Pt_ARG_INCREMENT, 0, 0};
	OS.PtGetResources (handle, args.length / 3, args);
	return args [1];
}

public int getMaximum () {
	checkWidget();
	int [] args = {OS.Pt_ARG_MAXIMUM, 0, 0};
	OS.PtGetResources (handle, args.length / 3, args);
	return args [1];
}

public int getMinimum () {
	checkWidget();
	int [] args = {OS.Pt_ARG_MINIMUM, 0, 0};
	OS.PtGetResources (handle, args.length / 3, args);
	return args [1];
}

public int getPageIncrement () {
	checkWidget();
	int [] args = {OS.Pt_ARG_PAGE_INCREMENT, 0, 0};
	OS.PtGetResources (handle, args.length / 3, args);
	return args [1];
}

public int getSelection () {
	checkWidget();
	int [] args = {OS.Pt_ARG_SCROLL_POSITION, 0, 0};
	OS.PtGetResources (handle, args.length / 3, args);
	return args [1];
}

void hookEvents () {
	int windowProc = getDisplay ().windowProc;
	OS.PtAddCallback (handle, OS.Pt_CB_SLIDER_MOVE, windowProc, SWT.Selection);
}

int processPaint (int damage) {
	OS.PtSuperClassDraw (OS.PtSlider (), handle, damage);
	return super.processPaint (damage);
}

int processSelection (int info) {
	if (info == 0) return OS.Pt_CONTINUE;
	sendEvent(SWT.Selection);
	return OS.Pt_CONTINUE;
}

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);	
}

public void setIncrement (int value) {
	checkWidget();
	int [] args = {OS.Pt_ARG_INCREMENT, value, 0};
	OS.PtSetResources (handle, args.length / 3, args);
}

public void setMaximum (int value) {
	checkWidget();
	int [] args = {OS.Pt_ARG_MAXIMUM, value - 1, 0};
	OS.PtSetResources (handle, args.length / 3, args);
}

public void setMinimum (int value) {
	checkWidget();
	int [] args = {OS.Pt_ARG_MINIMUM, value, 0};
	OS.PtSetResources (handle, args.length / 3, args);
}

public void setPageIncrement (int value) {
	checkWidget();
	int [] args = {OS.Pt_ARG_PAGE_INCREMENT, value, 0};
	OS.PtSetResources (handle, args.length / 3, args);
}

public void setSelection (int value) {
	checkWidget();
	int [] args = {OS.Pt_ARG_SCROLL_POSITION, value, 0};
	OS.PtSetResources (handle, args.length / 3, args);
}

}
