
#include "includes.h"
#include "installergui_data.h"

/********************************************************************
 *
 *  DESCRIPTION
 *
 *  create and show the ASKCHOICE panel; this is a number of
 *  MX buttons and related labels; the localenv->fe_Choices
 *  is a List, which holds all the labels (every node->ln_Name)
 *  and the related bitnumber (node->ln_Pri). see the installer
 *  documentation for more infos about the sense of this bitnumber.
 *  you should only use the first 32 nodes of the localenv->fe_Choices
 *  list, because the long value, which you must return, has only
 *  32 bits ;-)
 *
 *  IN:  application - pointer to the private application structure
 *       localenv - the local environment of the related ASKBOOL
 *                  function
 *
 *  OUT: a long value (see installer documentation, for how to build
 *       this value!)
 *
 */

/********************************************************************
 *
 *  STATIC
 *
 */

static void __asm __saveds askchoice_hookfun(register __a2 APTR, register __a1 APTR *);

static const struct Hook askchoice_hook = { { NULL, NULL }, (VOID *) askchoice_hookfun, NULL, NULL };

/********************************************************************
 *
 *  EXTERN
 *
 */

/********************************************************************
 *
 *  PUBLIC
 *
 */

/********************************************************************
 *
 *  CODE
 *
 */

long __asm igui_AskChoice(register __a0 APTR application,
                          register __a1 struct FunctionEnvironment *localenv)
{
  #ifdef DEBUG
  DEBUG_MAKRO
  #endif

  {
    struct Application *app = (struct Application *) application;

    // the return value of this function
    long retval = localenv->fe_Default.pa_Value;

    // for later use
    APTR innergroup,

         // store all the radio-buttons here
         choices[32],

         // the new object
         obj = GroupObject,
                 Child, TextObject,
                   MUIA_Frame, MUIV_Frame_None,
                   MUIA_Text_Contents, localenv->fe_Prompt.pa_Value,
                   MUIA_Text_SetMin, TRUE,
                   MUIA_Text_PreParse, "\33c",
                 End,
                 Child, innergroup = GroupObject,
                   MUIA_Group_Horiz, TRUE,
                   Child, HVSpace,
                     // here we will put the radio buttons later
                 End,
               End;

    // clear the choices array
    int i;
    for (i=0; i<32; i++) { choices[i] = NULL; }

    if (!obj) { app->app_Error = GUIERROR_NO_GUI_OBJECT; }
    else
    {
      // now dynamically create the labels and the radios and
      // put them together into the inner group!
      if (DoMethod(innergroup, MUIM_Group_InitChange))
      {
        int i,j;
        char *label;
        APTR radio;
        struct Node *choicenode = sav_GetHead((struct List *) &(localenv->fe_Choices));
        long num_choices = sav_ListLen((struct List *) &(localenv->fe_Choices)),
             columns = num_choices/10 + 1,
             rows = num_choices/columns,
             choice_id;

        // care for odd number of choices!
        if (num_choices > (rows * columns)) { rows++; }

        // go!
        for (j=1; j<=columns; j++)
        {
          APTR choicelist = GroupObject,
                              MUIA_Group_Columns, 2,
                              Child, HVSpace,
                              Child, HVSpace,
                            End;

          if (choicelist && DoMethod(choicelist, MUIM_Group_InitChange))
          {
            for (i=1; (i<=rows) && choicenode; i++)
            {
              // the node ln_Name holds the name, ln_Pri holds the related bit-number
              label = choicenode->ln_Name;
              choice_id = choicenode->ln_Pri;
              choicenode = sav_GetSucc(choicenode);

              DoMethod(choicelist, OM_ADDMEMBER, Label(label));
              DoMethod(choicelist, OM_ADDMEMBER, radio = guistuff_InitRadio((retval==choice_id), FALSE));

              // the hook
              if (radio)
              {
                choices[choice_id] = radio;
                SetAttrs(radio, MUIA_UserData, choice_id, TAG_DONE);
                DoMethod(radio, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
                         MUIV_Notify_Self, 4, MUIM_CallHook, &askchoice_hook, &choices, &retval);
              }
            }
            DoMethod(choicelist, OM_ADDMEMBER, HVSpace);
            DoMethod(choicelist, OM_ADDMEMBER, HVSpace);
            DoMethod(choicelist, MUIM_Group_ExitChange);
          }

          DoMethod(innergroup, OM_ADDMEMBER, choicelist);
        }

        // unteren space einfügen und fertig
        DoMethod(innergroup, OM_ADDMEMBER, HVSpace);
        DoMethod(innergroup, MUIM_Group_ExitChange);
      }

      // maybee BACK (if specified) or respect the swing mode
      if (localenv->fe_Back.pa_Value) { guistuff_SetBackButton(app, TRUE); }
      else if (!app->app_SWING_Mode)  { igui_NameCancel(app, (char *) app->app_GlobalEnv[GENV_ABORT_BUTTON]); }

      // add the content to the gui!
      guistuff_NewContent(app, obj);

      //
      igui_WaitApp(app);
    }

    // and done
    if (localenv->fe_Back.pa_Value) { guistuff_SetBackButton(app, FALSE); }

    igui_EmptyPanel(app);
    return(retval);
  }
}

/********************************************************************/

static void __asm __saveds askchoice_hookfun(register __a2 APTR obj, register __a1 APTR *data)
{
  // data[0] holds a pointer to the radio-array "choices"
  // data[1] holds the address of the "retval"

  #ifdef DEBUG
  DEBUG_MAKRO
  #endif

  SetAttrs(((APTR *) data[0])[*((ULONG *) data[1])], MUIA_Selected, FALSE, TAG_DONE);
  GetAttr(MUIA_UserData, obj, (APTR) data[1]);
}


