#include 
/********************************************************************
 *	Parameters
 */
displayitem str = "";
boolean active = true;
boolean busy = false;
boolean defaulted = false;
boolean abbreviated = false;
persist(str);
persist(abreviated);
persist(active);
persist(defaulted);
#define MAR	(OLButtonCapW + 4)
#define MAR2	(OLButtonCapW2 + 8)
/********************************************************************
 *	Dimensions
 */
boolean fixedheight = true;
float h = OLButtonH;
float minwidth()
{
	return preferredwidth();
}
float preferredheight()
{
	return abbreviated ? OLButH : OLButtonH;
}
float preferredwidth()
{
	float W;
	if (abbreviated)
		return OLButW;
	gsave();
	setfont(textfont);
	W = DIWidth(str) + OLButtonCapW2 + 10;
	grestore();
	return preferredwidth = W;
}
/********************************************************************
 *	Action
 */
void action()
{
	Send Action(DIString(str));
}
/********************************************************************
 *	Painting
 */
void path()
{
	if (abbreviated)
		rectpath(0,0,OLButW,OLButH);
	else
		rectpath(0,0,w,OLButtonH);
}
void PaintLabel(displayitem i)
{
	setcolor(FG);
	setfont(textfont);
	if (justification == /Centered)
		DIPaintCentered(i,MAR,2,w - MAR2,OLButtonH-4);
	else
		DIPaintLeft(i,MAR,2,w - MAR2,OLButtonH-4);
}
void PaintDefaultRing()
{
	OLButtonDefault(w);
}
void PaintButton(boolean down)
{
	if (abbreviated) {
		OLBut(down);
	} else {
		OLButton(down,w);
		PaintLabel(str);
		if ((!down) && defaulted)
			PaintDefaultRing();
	}
	if (!active) {
		setcolor(BG);
		path();
		OLStipple();
	}
}
/********************************************************************
 *	Events
 */
void OnSelect()
{
	if ((!busy) && active)
		super.OnSelect();
}
/********************************************************************
 *	Changing the state
 */
void setlabel(displayitem i)
{
	unpromote(/preferredwidth);
	str = i;
	if (!abbreviated)
		gexec(/Paint);
}
void setabbreviated(boolean val)
{
	if (abbreviated != val) {
		softpromote(/abbreviated,val);
		damage();
	}
}
void setdefaultchoice(boolean val)
{
	if (defaulted != val) {
		softpromote(/defaulted,val);
		if (!abbreviated)
			gexec(/Paint);
	}
}
void setvisualstate(name state)
{
	switch (state) {
	case /Active:
		if ((!active) || busy) {
			unpromote(/busy);
			unpromote(/active);
			gexec(/Paint);
		}
		break;
	case /Busy:
		if ((!active) || (!busy)) {
			busy = true;
			unpromote(/active);
			gexec(/Paint);
		}
		break;
	case /Inactive:
		if (active || busy) {
			unpromote(/busy);
			active = false;
			gexec(/Paint);
		}
		break;
	default:
		break;
	}
}