
/*
 * Control_panel.c -- opens a small window giving user general options.
 * $Revision: 1.3
 */

#include "header.h"
#include "prog-protos.h"
#include <intuition/intuitionbase.h>

/* Prototypes */
Prototype BOOL open_control_panel (struct HolePrefs *);
Prototype void close_control_panel (void);

/* Shared variables */
Prototype struct HolePanel *panel;

Local struct Gadget *create_gadgets (struct NewGadget *);
Local void refresh_window (void);
Local BOOL initialise (void);

/* Globals */
struct Gadget *glist	= NULL;
struct Screen *pubsc	= NULL;
struct HolePanel *panel = NULL;
struct IBox *winsize	= NULL;
struct IBox *basbox;	= NULL;
struct RastPort *TextRP = NULL;
struct TextFont *font	= NULL;
struct DisplayInfo *di	= NULL;
APTR *vi		= NULL;    /* VisualInfo */

/* Statics */
static const char *msg_ignoreprot = "Ignore Protection";
static const char *msg_confirm	  = "Confirm deletion";
static const char *msg_limit	  = "Delete Limit";
static const char *but_snapshot   = "Snapshot";
static const char *but_unsnapshot = "UnSnapshot";
static const char *but_save	  = "Save";
static const char *but_use	  = "Use";
static const char *but_cancel	  = "Cancel";
static const char *but_quit	  = "Quit";
static const char *but_about	  = "About";

/* Fill patterns */
static const UWORD white_grey[] =
{
    0x0000, 0x0000,
    0x9999, 0x9999,
};

static const UWORD blue_grey[] =
{
    0xAAAA, 0xAAAA,
    0xAAAA, 0xAAAA,
};

/* Functions */
/* General startup - returns TRUE if ok */
BOOL initialise (void)
{
    unless (winsize = malloc (sizeof (struct IBox)))    return (FALSE);
    unless (basbox  = malloc (sizeof (struct IBox)))    return (FALSE);
    unless (panel = malloc (sizeof (struct HolePanel))) return (FALSE);
    unless (pubsc = LockPubScreen ("Workbench"))        return (FALSE);
    unless (TextRP = malloc (sizeof (struct RastPort))) return (FALSE);
    unless (di = malloc (sizeof (struct DisplayInfo)))  return (FALSE);
    unless (GetDisplayInfoData (NULL, (UBYTE *)di,
	    sizeof (struct DisplayInfo), DTAG_DISP,
	    GetVPModeID (&(pubsc->ViewPort))))          return (FALSE);
    /* Open the font into a rastport so we can use TextLength() */
    unless (font = OpenFont (pubsc->Font))              return (FALSE);
    InitRastPort (TextRP);
    SetFont (TextRP, font);
    vi = GetVisualInfo (pubsc, TAG_END);

    return (TRUE);
}

void close_control_panel (void)
{
    if (panel && panel->window) CloseWindow (panel->window);
    if (glist)   FreeGadgets (glist);
    if (vi)      FreeVisualInfo (vi);
    if (font)    CloseFont (font);
    if (di)      free (di);
    if (TextRP)  free (TextRP);
    if (pubsc)   UnlockPubScreen (NULL, pubsc);
    if (panel)   free (panel);
    if (basbox)  free (basbox);
    if (winsize) free (winsize);

    /* Tell everyone that the panel has closed down */
    panel = glist = vi = font = di = TextRP = pubsc = basbox = winsize = NULL;
}

BOOL open_control_panel (struct HolePrefs *prefs_p)
{
    if (panel->window)    /* If window is already opened */
    {
	WindowToFront (panel->window);
	ActivateWindow (panel->window);
	return (TRUE);
    }

    unless (initialise()) goto fail;

    panel->prefs = *prefs_p;   /* put initial preferences into HolePanel struct */
    struct NewGadget ng;

    winsize->Left   = pubsc->WBorLeft;	/* border at left edge of window */
    winsize->Top    = pubsc->WBorTop + pubsc->Font->ta_YSize + 1;
    winsize->Width  = pubsc->WBorRight + winsize->Left;
    winsize->Height = pubsc->WBorBottom + winsize->Top;

    ng.ng_TextAttr = pubsc->Font;
    ng.ng_VisualInfo = vi;
    unless (create_gadgets (&ng)) goto fail;

    /* Find position of mouse pointer, so window can open over it */
    {
	ULONG IBaseLock = LockIBase (0);
	winsize->Left = IntuitionBase->MouseX - (winsize->Width / 2);
	winsize->Top  = IntuitionBase->MouseY - (winsize->Height / 2);
	UnlockIBase (IBaseLock);
    }
    unless (panel->window = OpenWindowTags
    (
	NULL,
	WA_Left,	    winsize->Left,
	WA_Top, 	    winsize->Top,
	WA_Width,	    winsize->Width,
	WA_Height,	    winsize->Height,
	WA_MinWidth,	    winsize->Width,
	WA_MinHeight,	    winsize->Height,
	WA_RMBTrap,	    TRUE,
	WA_AutoAdjust,	    TRUE,
	WA_PubScreen,	    pubsc,
	WA_SmartRefresh,    TRUE,
	WA_DepthGadget,     TRUE,
	WA_IDCMP,	    IDCMP_GADGETUP,
	WA_DragBar,	    TRUE,
	WA_Activate,	    TRUE,
	WA_Title,	    "Black Hole Options",
	TAG_DONE)
    ) goto fail;

    AddGList (panel->window, glist, ((UWORD) -1), ((UWORD) -1), NULL);
    refresh_window();
    RefreshGList (glist, panel->window, NULL, ((UWORD) -1));

    GT_RefreshWindow (panel->window, NULL); /* Perform the GadTools initial refresh */

    return (TRUE);

    fail:
    close_control_panel();
    return (FALSE);
}

void refresh_window (void)
{
    /* Fill window with nice white/grey stipple pattern */
    SetAfPt (panel->window->RPort, white_grey, -1); /* set up rp for pattern fill */
    RectFill (panel->window->RPort,
	pubsc->WBorLeft,
	pubsc->WBorTop + pubsc->Font->ta_YSize + 1,
	winsize->Width - pubsc->WBorRight -1,
	winsize->Height - pubsc->WBorBottom -1
    );

    /* Fill indented box with blue/grey pattern */
    SetAfPt (panel->window->RPort, blue_grey, -1);
    RectFill (panel->window->RPort,
	basbox->Left,
	basbox->Top,
	basbox->Left + basbox->Width -1,
	basbox->Top  + basbox->Height -1
    );

    DrawBevelBox (panel->window->RPort,
	basbox->Left,
	basbox->Top,
	basbox->Width,
	basbox->Height,
	GTBB_Recessed, TRUE,
	GT_VisualInfo, vi,
	TAG_DONE
    );
}

/* Macro to shorten a lot of lines in the next function */
#define textlen(x) (TextLength (TextRP, (x), strlen (x)))

struct Gadget *create_gadgets (struct NewGadget *ng)
{
    struct Gadget *gad = NULL;
    int but_width, but_height, xspace, yspace;

    /* Work out size of buttons, making them square. */
    but_height = (TextRP->TxHeight * 3)/2; /* 3/2 times font height */
    but_width = (but_height * di->Resolution.y) / di->Resolution.x;

    xspace = but_width / 2;	/* general spacing value */
    yspace = but_height / 2;

    gad = CreateContext (&glist);

    winsize->Left    += xspace;     /* Top corner of winsize is where corner */
    winsize->Top     += yspace;     /* of Quit button will go.		     */

    /* Now set up the IBox struct for the 3D box that surrounds some options */
    /* I am going to pray that the Snapshot/UnSnapshot line will be the largest! */
    basbox->Left      = winsize->Left;
    basbox->Top       = winsize->Top + but_height + yspace;
    basbox->Width     = textlen (but_snapshot) + textlen (but_unsnapshot);
    basbox->Width    += (3 * xspace) + (2 * but_width);

    /* Standard settings for most gadgets */
    ng->ng_Height     = but_height;
    ng->ng_Flags      = PLACETEXT_IN;

    /* Up in the corner on Piccalo, Quit! */
    if (gad)
    {
	ng->ng_LeftEdge   = winsize->Left;
	ng->ng_TopEdge	  = winsize->Top;
	ng->ng_Width	  = but_width + textlen (but_quit);
	ng->ng_GadgetText = but_quit;
	if (gad = CreateGadget (BUTTON_KIND, gad, ng, TAG_END))
	    gad->UserData = (APTR)GAD_QUIT;
    }

    /* Over on the right on guitar, About. Oh yes and he's broken a string! */
    if (gad)
    {
	ng->ng_Width	  = but_width + textlen (but_about);
	ng->ng_LeftEdge   = winsize->Left + basbox->Width - ng->ng_Width;
	ng->ng_GadgetText = but_about;
	if (gad = CreateGadget (BUTTON_KIND, gad, ng, TAG_END))
	    gad->UserData = (APTR)GAD_ABOUT;
    }

    /* The next three want the text to their right */
    ng->ng_Flags = PLACETEXT_RIGHT;

    /* Delete Limit */
    if (gad)
    {
	ng->ng_Width	  = textlen ("555") + but_width;
	ng->ng_LeftEdge   = winsize->Left + xspace;
	ng->ng_TopEdge	  = winsize->Top + (2 * yspace) + but_height;
	ng->ng_GadgetText = msg_limit;
	if (gad = CreateGadget (INTEGER_KIND, gad, ng,
	    GTIN_Number,    panel->prefs.deletelimit,
	    GTIN_MaxChars,  2,
	    TAG_END
	))
	{
	    gad->UserData = (APTR)GAD_LIMIT;
	    panel->gad_limit = gad;
	}
    }

    /* Then a line below, Confirm Deletion */
    if (gad)    /* has to read some fields from it, so it must exist */
    {
	ng->ng_Width	  = but_width;
	ng->ng_TopEdge	  = yspace + gad->TopEdge + gad->Height;
	ng->ng_GadgetText = msg_confirm;
	if (gad = CreateGadget (CHECKBOX_KIND, gad, ng,
	    GTCB_Checked, panel->prefs.confirm,
	    TAG_END
	))
	{
	    gad->UserData = (APTR)GAD_CONFIRM;
	    panel->gad_confirm = gad;
	}
    }

    /* Ignore Protection */
    if (gad)
    {
	ng->ng_TopEdge	  = yspace + gad->TopEdge + gad->Height;
	ng->ng_GadgetText = msg_ignoreprot;
	if (gad = CreateGadget (CHECKBOX_KIND, gad, ng,
	    GTCB_Checked, panel->prefs.ignore_prot,
	    TAG_END
	))
	{
	    gad->UserData = (APTR)GAD_IGNORE;
	    panel->gad_ignore_prot = gad;
	}
    }

    /* Go back to putting text inside the hitbox */
    ng->ng_Flags = PLACETEXT_IN;

    /* UnSnapShot button */
    if (gad)
    {
	ng->ng_TopEdge	  = yspace + gad->TopEdge + gad->Height;
	ng->ng_LeftEdge   = winsize->Left + xspace;
	ng->ng_Width	  = but_width + textlen (but_unsnapshot);
	ng->ng_GadgetText = but_unsnapshot;
	if (gad = CreateGadget (BUTTON_KIND, gad, ng, TAG_END))
	    gad->UserData = (APTR)GAD_UNSNAP;
    }

    /* Now on drums, Sammy the Snapshot button. */
    if (gad)
    {
	ng->ng_LeftEdge   = winsize->Left + (2 * xspace) + gad->Width;
	ng->ng_Width	  = but_width + textlen (but_snapshot);
	ng->ng_GadgetText = but_snapshot;
	if (gad = CreateGadget (BUTTON_KIND, gad, ng, TAG_END))
	    gad->UserData = (APTR)GAD_SNAP;
    }

    if (gad) basbox->Height = gad->TopEdge + but_height + yspace - basbox->Top;

    /* And down below on Timpani, Save, Use and Cancel. Keep bonging, guys! */
    if (gad)
    {
	int right_edge_save, left_edge_cancel;

	ng->ng_TopEdge	  = (2 * yspace) + gad->TopEdge + gad->Height;

	ng->ng_LeftEdge   = winsize->Left;
	ng->ng_Width	  = but_width + textlen (but_save);
	ng->ng_GadgetText = but_save;
	right_edge_save   = ng->ng_LeftEdge + ng->ng_Width;
	if (gad = CreateGadget (BUTTON_KIND, gad, ng, TAG_END))
	    gad->UserData = (APTR)GAD_SAVE;


	ng->ng_Width	  = but_width + textlen (but_cancel);
	ng->ng_LeftEdge   = winsize->Left + basbox->Width - ng->ng_Width;
	ng->ng_GadgetText = but_cancel;
	left_edge_cancel  = ng->ng_LeftEdge;
	if (gad = CreateGadget (BUTTON_KIND, gad, ng, TAG_END))
	    gad->UserData = (APTR)GAD_CANCEL;

	ng->ng_Width	  = but_width + textlen (but_use);
	ng->ng_LeftEdge   = (right_edge_save + left_edge_cancel - ng->ng_Width) / 2;
	ng->ng_GadgetText = but_use;
	if (gad = CreateGadget (BUTTON_KIND, gad, ng, TAG_END))
	    gad->UserData = (APTR)GAD_USE;
    }

    /* Set up size of window itself */
    winsize->Width   += (2 * xspace);
    winsize->Width   += basbox->Width;

    winsize->Height  += (2 * but_height) + (4 * yspace);
    winsize->Height  += basbox->Height;

    return (gad);
}

#undef textlen(x)


