/* widget-scrollbar.m,
 */

#include <allegro.h>		/* XXX */
#include "gui-mouse.h"
#include "widget-scrollbar.h"


/*------------------------------------------------------------*/
/* Abstract Scrollbar Class.                                  */
/*------------------------------------------------------------*/

@implementation Scrollbar
- (id) free
{
    int i;

    for (i = 0; i < SCROLLBAR_NUM_BUTTONS; i++)
	if (button[i]) button[i] = [button[i] free];

    if (slider) slider = [slider free];
    return [super free];
}

- (Widget *) getWidgetBounding:(int)mx :(int)my
{
    int i;

    for (i = 0; i < SCROLLBAR_NUM_BUTTONS; i++) {
	Widget *widget = [button[i] getWidgetBounding:mx :my];
	if (widget) return widget;
    }

    return [slider getWidgetBounding:mx :my];
}

- (void) receiveMessage:(int)msg :(int)data
{
    int i;

    if (msg == MSG_REDRAW)
	flags |= FLAG_DIRTY;

    if (slider)
	[slider receiveMessage:msg :data];

    for (i = 0; i < SCROLLBAR_NUM_BUTTONS; i++)
	if (button[i])
	    [button[i] receiveMessage:msg :data];
}

- (void) receiveMessage:(int)msg :(int)data fromChild:(Widget *)child
{
    if (msg == slider_message)
	if (parent)
	    [parent receiveMessage:msg :data fromChild:self];

    if (msg == MSG_MOUSE_HELD) {
	if (data == GUI_MOUSE_LMB) {
	    int oldpos = [slider sliderHandlePosition];
	    int pos = 0;

	    if (child == button[0] || child == button[2])
		pos = -[self buttonStepSize];
	    if (child == button[1] || child == button[3])
		pos = [self buttonStepSize];

	    if (pos) {
		[slider setHandlePosition:oldpos+pos];
		pos = [slider sliderHandlePosition];
		[self receiveMessage:slider_message :pos fromChild:self];
	    }
	}
    }
}

/* Button related. */
- (int) buttonStepSize { return MAX(1, [slider sliderPrecision]/30); }

/* Slider related. */
- (Slider *)slider { return slider; }
- (id) setHandlePosition:(int)pos { [slider setHandlePosition:pos]; return self; }
- (id) setSliderPrecision:(int)precision { [slider setSliderPrecision:precision]; return self; }
- (int) sliderPrecision { return [slider sliderPrecision]; }
@end


/*------------------------------------------------------------*/
/* Horizontal Scrollbar.                                      */
/*------------------------------------------------------------*/


@implementation HScrollbar
- (id) init
{
    int i;

    [super init];

    max_height = 22;

    for (i = 0; i < SCROLLBAR_NUM_BUTTONS; i++)
	button[i] = [[[Button new] setHPadding:0 VPadding:0] setParentWidget:self];

    slider = [[[[[HSlider new]
		    setHandleW:50]
		   setHPadding:0 VPadding:0]
		  setDrawBackground:NO]
		 setParentWidget:self];

    slider_message = MSG_HSLIDER;

    return self;
}

- (id) setX:(int)x_ Y:(int)y_ W:(int)w_ H:(int)h_
{
    int xx, yy, bs;

    [super setX:x_ Y:y_ W:w_ H:h_];

    xx = x+h_padding;
    yy = y+v_padding;
    bs = h-2*v_padding;
    [slider    setX:xx+bs*2 Y:yy W:w-4*bs H:bs];

    [button[0] setX:xx      Y:yy W:bs H:bs];
    [button[1] setX:xx+bs   Y:yy W:bs H:bs];

    xx = x+w-h_padding;
    [button[2] setX:xx-bs*2 Y:yy W:bs H:bs];
    [button[3] setX:xx-bs   Y:yy W:bs H:bs];

    return self;
}
@end


/*------------------------------------------------------------*/
/* Vertical Scrollbar.                                        */
/*------------------------------------------------------------*/


@implementation VScrollbar
- (id) init
{
    int i;
    [super init];

    max_width = 22;

    for (i = 0; i < SCROLLBAR_NUM_BUTTONS; i++)
	button[i] = [[[Button new] setHPadding:0 VPadding:0] setParentWidget:self];

    slider = [[[[[VSlider new] 
		    setHandleH:50]
		   setHPadding:0 VPadding:0] 
		  setDrawBackground:NO]
		 setParentWidget:self];

    slider_message = MSG_VSLIDER;

    return self;
}

- (id) setX:(int)x_ Y:(int)y_ W:(int)w_ H:(int)h_
{
    int xx, yy, bs;

    [super setX:x_ Y:y_ W:w_ H:h_];

    xx = x+h_padding;
    yy = y+v_padding;
    bs = w-2*h_padding;
    [slider    setX:xx Y:yy+bs*2 W:bs H:h-4*bs];

    [button[0] setX:xx Y:yy      W:bs H:bs];
    [button[1] setX:xx Y:yy+bs   W:bs H:bs];

    yy = y+h-v_padding;
    [button[2] setX:xx Y:yy-bs*2 W:bs H:bs];
    [button[3] setX:xx Y:yy-bs   W:bs H:bs];

    return self;
}
@end
