/* $Id: Column.c,v 1.2 1997/05/10 09:21:31 archer Exp $
 *	COLUMN.C - General purpose geometry managing object
 *
 * The column lists a number of widgets in a single column. All objects are
 * forced to the same width, and locked in their X-position.
 */
#include <Widget/FormP.h>


/**
 ** Internal:COLUMN_RECURSIVE_RESIZE
 **	Recursively change the various widgets
 **/
static int column_recursive_resize(X11_widget col, X11_widget o,
							int y, int margin)
{
int	b;
int	x;
int	w, h;
int	d;
/*
 * End of recursion
 */
	if (o == 0)
		return col->h - (col->border2 + y + margin);
	if (o->unmanaged)
		return column_recursive_resize(col, o->sibling, y, margin);
/*
 * Add the margin around widget
 */
	if (margin < o->margin_h)
		margin = o->margin_h;
	y += margin;
	margin = o->margin_h;
/*
 * Recursively move widgets around
 */
	d = column_recursive_resize(col, o->sibling, y + o->h, margin);
/*
 * Now guess where we are, and our size
 */
	x = o->margin_w;
	w = col->w - (x * 2);
	h = o->h;
	if (d && !o->fixed_h) {
		h += d;
		if (h >= o->h_min)
			d = 0;
		else {
			d = h - o->h_min;
			h = o->h_min;
		}
	}
	y += d;
/*
 * Move around
 */
	if (x != o->x || y != o->y) {
		o->x = x;
		o->y = y;
		if (o->id)
			XMoveWindow(x11__screen, o->id, x, y);
	}
/*
 * Resize
 */
	if (w != o->w || h != o->h) {
		o->w = w;
		o->h = h;
		(*o->on_resize_window)(o, (XEvent *)0);
	}
/*
 * End of recursion
 */
	return d;
}


/**
 ** Internal: COLUMN_RESIZE
 **	Geometry of a column has changed...
 **/
static void column_resize(X11_widget wdg, XEvent *dummy)
{
/*
 * Resize the XWindow object
 */
	x11__core_resize(wdg, dummy);
/*
 * Now, apply recursively the moves & resizes
 */
	(void)column_recursive_resize(wdg, wdg->child, 0, 0);
}


/**
 ** Internal: COLUMN_GEOMETRY
 **	Apply geometry from a column
 **/
static void column_geometry(X11_widget wdg, XEvent *dummy)
{
X11_widget	child;
unsigned int	w, w_min;
unsigned int	h, h_min;
unsigned int	margin;
unsigned int	value;
unsigned int	border2;
int		x;
/*
 * Initial values
 */
	margin    = 0;
	w = w_min = 0;
	h = h_min = 0;
	wdg->fixed_w = True;
	wdg->fixed_h = True;
/*
 * Each child is scanned for this...
 */
	for (child = wdg->child; child; child = child->sibling) {
		if (child->unmanaged)
			continue;
		(*child->on_geometry_check)(child, dummy);
/*
 * What has the child to say?
 */
		border2 = child->border2;
		if (margin < child->margin_h)
			margin = child->margin_h;
		h     += margin + border2 + child->h;
		h_min += margin + border2 + child->h_min;
/*
 * Fixed sizes?
 */
		if (!child->fixed_w)
			wdg->fixed_w = False;
		if (!child->fixed_h)
			wdg->fixed_h = False;
/*
 * New margin applicable
 */
		margin = child->margin_h;
		x = 2 * child->margin_w;
/*
 * Now, new widths
 */
		value = child->w + border2 + x;
		if (value > w)
			w = value;
		value = child->w_min + border2 + x;
		if (value > w_min)
			w_min = value;
	}
	h     += margin + wdg->border2;
	h_min += margin + wdg->border2;
	w     += wdg->border2;
	w_min += wdg->border2;
/*
 * Then, check the sizes...
 */
	if (w < w_min)
		w = w_min;
	if (h < h_min)
		h = h_min;
/*
 * Apply new geometry
 */
	wdg->w_min = w_min;
	wdg->h_min = h_min;
	if (wdg->w >= w_min && !wdg->fixed_w)
		w = wdg->w;
	if (wdg->h >= h_min && !wdg->fixed_h)
		h = wdg->h;
	if (wdg->fixed_w)
		w = w_min;
	if (wdg->fixed_h)
		h = h_min;
/*
 * New default size
 */
	if (wdg->w != w || wdg->h != h) {
		wdg->w = w;
		wdg->h = h;
		column_resize(wdg, dummy);
	}
}


/**
 ** X11_COLUMN
 **	Create a column window
 **/
X11_widget X11_Column(X11_widget parent, char *name)
{
x11__form	*object;
/*
 * Default name
 */
	if (!name)
		name = "column";
/*
 * Get resource
 */
	object = allocator(x11__form);
	x11__core_setup(&object->core, parent, "Column", name);
/*
 * Initialize fields
 */
	object->core.on_geometry_check = column_geometry;
	object->core.on_resize_window  = column_resize;
	x11__resource_basic(&object->core);
/*
 * Special look and feel initializations
 */
	object->core.is_active  = parent->is_active;
	object->core.can_active = parent->can_active;
/*
 * Ok
 */
	return (X11_widget)object;
}
