
/*
 * GAD.C
 *
 * Gadget [re]construction
 */

#include "defs.h"

Prototype void    ReMakeEverything(void);
Prototype Gadget *MakeGadget(TplRegion *, Gadget *);
Prototype Gadget *MakeAllGadgets(void);
Prototype void    DisableGadgets(void);
Prototype void    EnableGadgets(void);
Prototype void    DisableExcl(Gadget *);
Prototype void    ReleaseExcl(Gadget *);
Prototype void    selectgad(Gadget *, short);

Prototype short   GadDisabled;

short     GadDisabled;

/***********************  ReMakeEverything()  ************************/
void
ReMakeEverything()
{
  MakeAllGadgets();
  RefreshGList(GList, Win, NULL, -1);
  GT_RefreshWindow(Win, NULL);
}

/***********************  MakeAllGadgets()  **************************/
Gadget *
MakeAllGadgets()
{
  TplRegion *rg;
  Gadget    *gad;

  if (GList)            /*  erase all */
  {
    if (Win)
    {
      short  cnt = 0;

      for (gad = GList; gad; ++cnt, gad = gad->NextGadget)
      {
        if (gad->GadgetType & GTYP_SYSGADGET)
          break;
      }
      RemoveGList(Win, GList, cnt);
      SetRast(Win->RPort, 0);
      RefreshWindowFrame(Win);
    }
    FreeGadgets(GList);
    GList = NULL;
  }

  if (gad = CreateContext(&GList))    /*  make new */
  {
    if (DDebug)
      printf("GLIST %08lx gad %08lx\n", GList, gad);

    for (rg = GetHead(&RegList); rg; rg = GetSucc(&rg->rg_Node))
    {
      if (!(rg->rg_LockedTo && (rg->rg_Type == RGT_LISTVIEW)))
        gad = MakeGadget(rg, gad);
    }

    for (rg = GetHead(&RegList); rg; rg = GetSucc(&rg->rg_Node))
    {
      if (rg->rg_LockedTo && (rg->rg_Type == RGT_LISTVIEW))
        gad = MakeGadget(rg, gad);
    }
  }

  if (Win)
  {
    AddGList(Win, GList, 0, -1, NULL);
    if (GadDisabled)
      DisableGadgets();
    else
      init_test();
  }
  return (gad);
}

/***********************  MakeGadget()  ****************************/
Gadget *
MakeGadget(rg, gad)
  TplRegion *rg;
  Gadget *gad;
{

  if ((rg->rg_Type == RGT_INVISIBLE) ||
      (rg->rg_Type == RGT_BEVELBOX))
    return (gad);

  short highlabel  = (rg->rg_SpecFlags & SPEC_HIGHLABEL) ? NG_HIGHLABEL : 0;
  NewGadget Ng;

  Ng.ng_LeftEdge   = rg->rg_Box.bo_Xs;
  Ng.ng_TopEdge    = rg->rg_Box.bo_Ys;
  Ng.ng_Width      = rg->rg_Box.bo_Xe - rg->rg_Box.bo_Xs + 1;
  Ng.ng_Height     = rg->rg_Box.bo_Ye - rg->rg_Box.bo_Ys + 1;
  Ng.ng_GadgetText = rg->rg_LabText;
  Ng.ng_TextAttr   = &rg->rg_TextAttr;
  Ng.ng_VisualInfo = VisInfo;
  Ng.ng_GadgetID   = rg->rg_Id;
  Ng.ng_Flags      = rg->rg_Flags | highlabel;
  Ng.ng_UserData   = rg;

  if (Ng.ng_Width < 8 || Ng.ng_Height < 8)
  {
    printf("Size Error %d %d\n", Ng.ng_Width, Ng.ng_Height);
    return (gad);
  }

  if (DDebug)
    printf("TYPE  %d\n", rg->rg_Type);

  switch (rg->rg_Type)
  {
  case RGT_BUTTON:
    rg->rg_Gad = CreateGadget(BUTTON_KIND, gad, &Ng,
                              GA_Disabled,     (rg->rg_SpecFlags & SPEC_DISABLED),
                              TAG_END);
    break;

  case RGT_STRING:
    TplRegion *trg = rg->rg_LockedTo;

    rg->rg_Gad = CreateGadget(STRING_KIND, gad, &Ng,
                              GTST_MaxChars,    rg->rg_BufSpace,
                              GTST_String,      rg->rg_DefText,
                              GA_Disabled,     (rg->rg_SpecFlags & SPEC_DISABLED),
                              TAG_END);
    break;

  case RGT_LISTVIEW:
    long showselect = (rg->rg_LockedTo)  ? (long)rg->rg_LockedTo->rg_Gad : NULL;

    rg->rg_Gad = CreateGadget(LISTVIEW_KIND, gad, &Ng,
                              GTLV_Labels,     &rg->rg_ListSet,
                              GTLV_Selected,    rg->rg_DefVal,
                              ((rg->rg_LockedTo)  ? GTLV_ShowSelected :
               (rg->rg_SpecFlags & SPEC_READONLY) ? GTLV_ShowSelected : TAG_IGNORE),
                                                showselect,
                              LAYOUTA_Spacing,  rg->rg_BufSpace,
                              TAG_END);
    break;

  case RGT_CYCLE:
    rg->rg_Gad = CreateGadget(CYCLE_KIND, gad, &Ng,
                              GTCY_Labels,      rg->rg_CycleAry,
                              GTCY_Active,      rg->rg_DefVal,
                              GA_Disabled,     (rg->rg_SpecFlags & SPEC_DISABLED),
                              TAG_END);
    break;

  case RGT_MX:
    rg->rg_Gad = CreateGadget(MX_KIND, gad, &Ng,
                              GTMX_Labels,      rg->rg_CycleAry,
                              GTMX_Active,      rg->rg_DefVal,
                              GTMX_Spacing,     rg->rg_BufSpace,
                              TAG_END);
    break;

  case RGT_CHECKBOX:
    rg->rg_Gad = CreateGadget(CHECKBOX_KIND, gad, &Ng,
                              GTCB_Checked,    (rg->rg_SpecFlags & SPEC_CHECKED),
                              GA_Disabled,     (rg->rg_SpecFlags & SPEC_DISABLED),
                              TAG_END);
    break;

  case RGT_INTEGER:
    rg->rg_Gad = CreateGadget(INTEGER_KIND, gad, &Ng,
                              GTIN_Number,      rg->rg_DefVal,
                              GTIN_MaxChars,   (rg->rg_BufSpace) ?
                                               (rg->rg_BufSpace  - 1) : 0,
                              GA_Disabled,     (rg->rg_SpecFlags & SPEC_DISABLED),
                              TAG_END);
    break;

  case RGT_TEXT:
    rg->rg_Gad = CreateGadget(TEXT_KIND, gad, &Ng,
                              GTTX_Text,       (rg->rg_DefText) ?
                                                rg->rg_DefText  : "",
                              GTTX_CopyText,    1,
                              GTTX_Border,     (rg->rg_SpecFlags & SPEC_BORDER),
                              TAG_END);
    break;

  case RGT_NUMBER:
    rg->rg_Gad = CreateGadget(NUMBER_KIND, gad, &Ng,
                              GTNM_Number,      rg->rg_DefVal,
                              GTNM_Border,     (rg->rg_SpecFlags & SPEC_BORDER),
                              TAG_END);
    break;

  case RGT_SLIDER:
    rg->rg_Gad = CreateGadget(SLIDER_KIND, gad, &Ng,
                              GTSL_Min,         0,
                              GTSL_Max,         rg->rg_MaxVal,
                              GTSL_Level,       rg->rg_DefVal,
                              GTSL_DispFunc,    DispFunc,
                              GTSL_LevelFormat, rg->rg_LabText,
                              GTSL_MaxLevelLen, rg->rg_BufSpace,
                              GTSL_LevelPlace,  rg->rg_Flags,
                              PGA_Freedom,     (rg->rg_SpecFlags &
                                                SPEC_VERTICAL) ?
                                                LORIENT_VERT : LORIENT_HORIZ,
                              GA_Disabled,     (rg->rg_SpecFlags & SPEC_DISABLED),
                              TAG_END);
    break;

  case RGT_SCROLLER:
    Box box = rg->rg_Box;
    short x = box.bo_Xe - box.bo_Xs;
    short y = box.bo_Ye - box.bo_Ys;
    x = (x >  7) ?  8 : x;
    y = (y > 15) ? 16 : y;

    rg->rg_Gad = CreateGadget(SCROLLER_KIND, gad, &Ng,
                              GTCY_Labels,      rg->rg_CycleAry,
                              GTSC_Total,       rg->rg_MaxVal,
                              GTSC_Top,         rg->rg_DefVal,
                              GTSC_Visible,     rg->rg_BufSpace,
                              GTSC_Arrows,     (rg->rg_SpecFlags &
                                                SPEC_VERTICAL) ? y : x,
                              PGA_Freedom,     (rg->rg_SpecFlags &
                                                SPEC_VERTICAL) ?
                                                LORIENT_HORIZ : LORIENT_VERT,
                              GA_Disabled,     (rg->rg_SpecFlags & SPEC_DISABLED),
                              TAG_END);

  case RGT_PALETTE:
    Box box = rg->rg_Box;
    short x = box.bo_Xe - box.bo_Xs;
    short y = box.bo_Ye - box.bo_Ys;
    x = (x >> 1) - 4;
    if ((y + 4) < x)
      x = y + 4;

    short val = (rg->rg_MaxVal > 15) ? 5 :
                (rg->rg_MaxVal >  7) ? 4 :
                (rg->rg_MaxVal >  3) ? 3 :
                (rg->rg_MaxVal >  1) ? 2 : 1;

    rg->rg_Gad = CreateGadget(PALETTE_KIND, gad, &Ng,
                              GTPA_Depth,       val,
                              GTPA_Color,       rg->rg_DefVal,
                              GTPA_ColorOffset, rg->rg_BufSpace,
                              GTPA_IndicatorWidth,  x,
                              GTPA_IndicatorHeight, y,
                              GA_Disabled,     (rg->rg_SpecFlags & SPEC_DISABLED),
                              TAG_END);
  default:
    break;
  }
  rg->rg_Gad->MutualExclude |= rg->rg_ExclGroup;
  return (rg->rg_Gad);
}

/***********************  DisableGadgets()  **************************/
void
DisableGadgets()
{
  TplRegion *rg;

  GadDisabled = 1;
  for (rg = GetHead(&RegList); rg; rg = GetSucc(&rg->rg_Node))
  {
    switch (rg->rg_Type)
    {
    case RGT_INVISIBLE:
    case RGT_LISTVIEW:
    case RGT_NUMBER:
    case RGT_TEXT:
    case RGT_MX:
      break;

    case RGT_BEVELBOX:
      short leftedge   = rg->rg_Box.bo_Xs;
      short topedge    = rg->rg_Box.bo_Ys;
      short width      = rg->rg_Box.bo_Xe - rg->rg_Box.bo_Xs + 1;
      short height     = rg->rg_Box.bo_Ye - rg->rg_Box.bo_Ys + 1;
      DrawBevelBox(Win->RPort, leftedge, topedge, width, height,
                        GT_VisualInfo, VisInfo,
                        ((rg->rg_SpecFlags & SPEC_RECESSED) ?
                                             GTBB_Recessed : TAG_IGNORE), TRUE,
                        TAG_END);
      break;

    default:
      GT_SetGadgetAttrs(rg->rg_Gad, Win, NULL,
                        GA_Disabled, 1,
                        TAG_END);
      break;
    }
  }
  GT_RefreshWindow(Win, NULL);
}

/***********************  EnableGadgets() ****************************/
void
EnableGadgets()
{
  TplRegion *rg;

  GadDisabled = 0;
  for (rg = GetHead(&RegList); rg; rg = GetSucc(&rg->rg_Node))
  {
    switch (rg->rg_Type)
    {
    case RGT_INVISIBLE:
    case RGT_LISTVIEW:
    case RGT_NUMBER:
    case RGT_TEXT:
      break;

    case RGT_MX:
      GT_SetGadgetAttrs(rg->rg_Gad, Win, NULL,
                        GTMX_Active, rg->rg_DefVal,
                        TAG_END);
      break;

    case RGT_BEVELBOX:
      short leftedge   = rg->rg_Box.bo_Xs;
      short topedge    = rg->rg_Box.bo_Ys;
      short width      = rg->rg_Box.bo_Xe - rg->rg_Box.bo_Xs + 1;
      short height     = rg->rg_Box.bo_Ye - rg->rg_Box.bo_Ys + 1;
      DrawBevelBox(Win->RPort, leftedge, topedge, width, height,
                        GT_VisualInfo, VisInfo,
                        ((rg->rg_SpecFlags & SPEC_RECESSED) ?
                                             GTBB_Recessed : TAG_IGNORE), TRUE,
                        TAG_END);
      break;

    case RGT_BUTTON:
      if (rg->rg_SpecFlags & SPEC_CHECKED)
        selectgad(rg->rg_Gad, RGT_BUTTON);

    default:
      if (!(rg->rg_SpecFlags & SPEC_DISABLED))
        GT_SetGadgetAttrs(rg->rg_Gad, Win, NULL,
                        GA_Disabled, 0,
                        TAG_END);
      break;
    }
  }
  GT_RefreshWindow(Win, NULL);
}

/***********************  ReleaseExcl(long  **************************/
void
ReleaseExcl(Gadget *gadget)
{
  long excl = gadget->MutualExclude;
  TplRegion *rg;

  for (rg = GetHead(&RegList); rg; rg = GetSucc(&rg->rg_Node))
  {
    Gadget *gad = rg->rg_Gad;
    if ((gad) && (gad != gadget))
    {
      if (excl & gad->MutualExclude)
        GT_SetGadgetAttrs(gad, Win, NULL,
                          GA_Disabled, 0,
                          TAG_END);
    }
  }
}

/***********************  DisableExcl(long  **************************/
void
DisableExcl(Gadget *gadget)
{
  long excl = gadget->MutualExclude;
  TplRegion *rg;
  for (rg = GetHead(&RegList); rg; rg = GetSucc(&rg->rg_Node))
  {
    Gadget *gad = rg->rg_Gad;
    if ((gad) && (gad != gadget))
    {
      short gad_pos;

      if (excl & gad->MutualExclude)
      {
        switch(rg->rg_Type)
        {
        case RGT_BUTTON:
        case RGT_CHECKBOX:
          if (!(gad->Flags & GFLG_SELECTED))
            break;
          if (DDebug)
            printf("%s exclgroup: %d\n", rg->rg_Node.ln_Name,
                                         rg->rg_ExclGroup);

          gad_pos     = RemoveGadget(Win, gad);
          gad->Flags -= GFLG_SELECTED;
          AddGadget(Win, gad, gad_pos);
          RefreshGList(gad, Win, NULL, 1);
          break;

        default:
          GT_SetGadgetAttrs(gad, Win, NULL,
                            GA_Disabled, 1,
                            TAG_END);
          break;
        }
      }
    }
  }
}

/***********************  selectgad  **************************/
void
selectgad(Gadget *gadget, short gad_type)
{
  short release = FALSE;

  switch(gad_type)
  {
  case RGT_CHECKBOX:
    if (!(gadget->Flags & GFLG_SELECTED))
      return;
    else
      break;

  case RGT_BUTTON:
    short gad_pos = RemoveGadget(Win, gadget);

    if (gadget->Flags & GFLG_SELECTED)
    {
      gadget->Flags -= GFLG_SELECTED;
      release = TRUE;
    }
    else
      gadget->Flags |= GFLG_SELECTED;

    AddGadget(Win, gadget, gad_pos);
    RefreshGList(gadget, Win, NULL, 1);
    break;

  default:
    return;
  }

  if (gadget->MutualExclude)
  {
    if (release)
      ReleaseExcl(gadget);
    else
      DisableExcl(gadget);
  }
}


