/* widget-pane.m,
 */

#include <allegro.h>
#include <assert.h>
#include "gui/widget-pane.h"
#include "gui/gui-clip.h"


@implementation Pane
- (id) init
{
    [super init];
    handle_w = 10;
    return self;
}

- (id) free
{
    if (child[0]) child[0] = [child[0] free];
    if (child[1]) child[1] = [child[1] free];
    return [super free];
}

- (int) minWidth
{
    int w_ = handle_w;

    if (child[0]) w_ += [child[0] minWidth];
    if (child[1]) w_ += [child[1] minWidth];

    return w_;
}

- (int) minHeight
{
    int h_ = 0;

    if (child[0]) h_ = [child[0] minWidth];
    if (child[1]) h_ = MAX([child[1] minWidth], h_);

    return h_;
}

- (id) setX:(int)x_ Y:(int)y_ W:(int)w_ H:(int)h_
{
    int excess_w;

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

    if (child[0] && child[1]) {
	[child[0] setToMinDimensions];
	[child[1] setToMinDimensions];
	excess_w -= ([child[0] width] + handle_w + [child[1] width]);
	assert(excess_w >= 0);

	excess_w -= [child[0] incrementW:excess_w/2];
	[child[1] incrementW:excess_w];

	[child[0] setX:x Y:y W:-1 H:h];
	[child[1] setX:x+[child[0] width]+handle_w Y:y W:-1 H:h];
    }
    else if (child[0] && !child[1]) {
	[child[0] setX:x Y:y W:w H:h];
    }

    return self;
}

- (void) insertWidget:(Widget *)widget
{
    if (!child[0])
	child[0] = widget;
    else if (!child[1])
	child[1] = widget;
    else
	fprintf(stderr, "Out of room for pane %s\n", name);
}

- (void) receiveMessage:(int)msg :(int)data
{
    if (msg == MSG_REDRAW)
	flags |= FLAG_DIRTY;

    if (msg == MSG_MOUSE_PRESSED ||
	msg == MSG_MOUSE_HELD) {
	int mx = mouse_x;
	int left_width;

	left_width = mx - x - handle_w/2;

	if (left_width <= 1) left_width = 1;
	if (left_width >= w-handle_w-1) left_width = w-handle_w-1;

	[child[0] setX:-1 Y:-1 W:left_width H:-1];
	[child[1] setX:x+[child[0] width]+handle_w Y:-1 W:w-handle_w-[child[0] width] H:-1];

	flags |= FLAG_DIRTY;
	return;
    }

    /* Relay the message to all the children. */
    if (child[0]) [child[0] receiveMessage:msg :data];
    if (child[1]) [child[1] receiveMessage:msg :data];
}

- (BOOL) draw:(BITMAP *)bmp :(BOOL)marked_dirty
{
    clip_t old_clip;
    int i, x_, y_, w_, h_;

    marked_dirty = [super draw:bmp :marked_dirty];

    {				/* Handle */
	vline(bmp, x+[child[0] width]+handle_w/2-1, y, y+h-1, makecol(0xff, 0xff, 0xff));
	vline(bmp, x+[child[0] width]+handle_w/2+1, y, y+h-1, makecol(0xff, 0xff, 0xff));
    }

    save_clip(bmp, &old_clip);
    for (i = 0; i < 2; i++) {
	if (child[i]) {
	    [child[i] getX:&x_ Y:&y_ W:&w_ H:&h_];
	    set_clip_wh(bmp, x_, y_, w_, h_);
	    [child[i] draw:bmp :marked_dirty];
	}
    }
    restore_clip(bmp, &old_clip);

    return NO;
}

- (void) receiveMessage:(int)msg :(int)data fromChild:(Widget *)widget
{
    if (parent)
	[parent receiveMessage:msg :data fromChild:widget];
}

- (Widget *) getWidgetBounding:(int)mx :(int)my
{
    if ([super getWidgetBounding:mx :my]) {
	Widget *widget;

	if (child[0]) {
	    widget = [child[0] getWidgetBounding:mx :my];
	    if (widget)
		return widget;
	}

	if (child[1]) {
	    widget = [child[1] getWidgetBounding:mx :my];
	    if (widget)
		return widget;
	}

	/* Assume handle. */
	return self;
    }

    return nil;
}
@end
