/* $Id: Boundingbox.c,v 1.4 1997/05/10 09:21:30 archer Exp $
 *	BOUNDINGBOX.C - Handle Bounding boxes objects
 */
#include <Widget/BoundingBoxP.h>
#include <Widget/drawP.h>


/**
 ** Internal: EXPOSE
 **	Draw around the bounded box
 **/
static void bounding_expose(X11_widget wdg, XEvent *dummy)
{
int	v;
/*
 * Start drawing
 */
	x11__draw_start(wdg);
/*
 * Label offsets the drawing
 */
	if (W_LABEL->w) {
		v = 1 + (wdg->shadow_thickness * 2);
		if (v < W_LABEL->h)
			v = W_LABEL->h;
		v /= 2;
		v -= wdg->shadow_thickness;
		x11__y_top += v;
		x11__y_h   -= v;
	}
/*
 * Draw box
 */
	if (x11__is_monochrome) {
		x11__draw_nothing(wdg->shadow_thickness);
		x11__draw_lined(wdg->border_color, 1);
		x11__draw_nothing(wdg->shadow_thickness);
	} else {
		x11__shadows_gc();
		x11__draw_downshadow(wdg->shadow_thickness);
		x11__draw_nothing(1);
		x11__draw_upshadow(wdg->shadow_thickness);
	}
/*
 * Draw label, if needed
 */
	if (W_LABEL->w) {
		x11__x_left += 1 + wdg->shadow_thickness;
		x11__y_top   = 0;
		v = W_LABEL->w + 2 * wdg->shadow_thickness;
		XClearArea(x11__screen, wdg->id, x11__x_left, 0, v, W_LABEL->h,
									False);
		x11__x_left += wdg->shadow_thickness;
		x11__x_w = 0;
		x11__y_h = 0;
		x11__label_draw_active(W_LABEL);
	}
}


/**
 ** Internal: BOUNDING_RESIZE
 **	Grow and shuffle internal widget around
 **/
static void bounding_resize(X11_widget wdg, XEvent *dummy)
{
X11_widget	child;
int		w, wc;
int		m, v;
int		x, y, xc;
/*
 * Resize ourselves first
 */
	x11__core_resize(wdg, dummy);
/*
 * Resize/move the contained items?
 */
	w = wdg->w - wdg->border2;
	m = 1 + (wdg->shadow_thickness * 2);
	w -= 2*m;
	x  = m;
	if (W_LABEL->w) {
		v  = (W_LABEL->h > m) ? W_LABEL->h : m;
		y  = v;
	} else {
		y  = m;
	}
	m  = wdg->margin_inside;
	x += m;
	y += m;
	w -= 2*m;
/*
 * Now loop on all contained objects
 */
	for (child = wdg->child; child; child = child->sibling) {
		y += child->margin_h;
/*
 * Any hints? Margins? Something else?
 */
		if (child->fixed_x) {
			xc = x + child->hint_x;
			wc = w - child->hint_x - child->margin_w;
		} else
			if (child->fixed_w) {
				xc = x + (w - child->w_min) / 2;
				wc = child->w_min;
			} else {
				xc = x + child->margin_w;
				wc = w - 2 * child->margin_w;
			}
/*
 * Relocate?
 */
		if (child->x != xc || child->y != y) {
			child->x = xc;
			child->y = y;
			if (child->id)
				XMoveWindow(x11__screen, child->id, xc, y);
		}
/*
 * Resize?
 */
		if (child->fixed_w)
			wc = child->w_min;
		if (child->w != wc || child->h != child->h_min) {
			child->w = wc;
			child->h = child->h_min;
			(*child->on_resize_window)(child, dummy);
		}
		y += child->h_min;
	}
}


/**
 ** Internal: BOUNDING_GEOMETRY
 **	Compute the geometry of the bounding box, from its children
 **/
static void bounding_geometry(X11_widget wdg, XEvent *dummy)
{
X11_widget	child;
unsigned int	w, h;
unsigned int	w_min, h_min;
unsigned int	m, v;
/*
 * Start with 0 size
 */
	w_min = 0;
	h_min = 0;
	w     = 0;
	wdg->fixed_h = True;
	wdg->fixed_w = True;
/*
 * Pass down the geometry request to the children
 */
	m = 0;
	for (child = wdg->child; child; child = child->sibling) {
		(*child->on_geometry_check)(child, dummy);
		if (child->fixed_x)
			m = child->hint_x;
		else
			m = child->margin_w;
		m += child->margin_w;
		v = child->w + m;
		if (v > w)
			w = v;
		v = child->w_min + m;
		if (v > w_min)
			w_min = v;
		m = child->margin_h;
		h_min += child->h_min + m;
		if (!child->fixed_w)
			wdg->fixed_w = False;
	}
/*
 * Global margins
 */
	h_min += m;
	m = wdg->margin_inside * 2;
	w     += m;
	w_min += m;
	h_min += m;
	m = 1 + (wdg->shadow_thickness * 2);
/*
 * Add the label, if any
 */
	x11__label_size(W_LABEL);
	if (W_LABEL->w) {
		v = W_LABEL->h;
		if (v < m)
			v = m;
		h_min += v + m;
		v = W_LABEL->w + (4 * m);
		if (v > w)
			w = v;
		if (v > w_min)
			w_min = v;
	} else
		h_min += 2 * m;
	m *= 2;
	m += wdg->border2;
/*
 * Finish the box
 */
	w     += m;
	w_min += m;
	h_min += wdg->border2;
	wdg->w_min = w_min;
	wdg->h_min = h_min;
/*
 * Grow
 */
	if (wdg->w < w || wdg->h != h_min) {
		wdg->w = w;
		wdg->h = h_min;
		(*wdg->on_resize_window)(wdg, dummy);
	}
}


/**
 ** X11_BOUNDING_BOX
 **	Create a Bounding box window
 **/
X11_widget X11_BoundingBox(X11_widget parent, char *name, char *title)
{
x11__boundingbox	*object;
/*
 * Get resource
 */
	object = allocator(x11__boundingbox);
	x11__core_setup(&object->label.core, parent, "BoundingBox", name);
/*
 * Initialize fields
 */
	object->label.core.event_mask        = ExposureMask;
	object->label.core.on_expose         = bounding_expose;
	object->label.core.on_geometry_check = bounding_geometry;
	object->label.core.on_resize_window  = bounding_resize;
/*
 * Default values
 */
	object->label.core.shadow_thickness = 1;
	object->label.core.margin_inside    = 0;
/*
 * Properties as specified by resources
 */
	x11__label_resources(&object->label, x11__font_helvetica12, title);
/*
 * Finished
 */
	return OBJECT_P;
}
