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

File        : c.main

Date        : Saturday 22nd May 2021

Author      : Gavin Cawley

Description : Application used to gain understanding of colourtran_setGCOL.
              It was also written to experiment with various aspects of the
              colour system and with the dbox library, so it probably isn't
              written in the most idiomatic or efficient manner.  

To do       : (i) Re-implement dialogue as a standard window?

History     : 16/05/2021 - v1.0  - basic working version
              22/05/2021 - v1.10 - Now caches colour numbers for efficiency,
                                   unknown even processor added to detect
                                   mode and palette changes so they can be
                                   re-cached.  Background colours partially 
                                   implemented.  General refactoring and
                                   improvements to comments.  Both windows
                                   appear/dissapear together.  Anomation is
                                   paused while not visible.

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

#include <stdlib.h>

#include "wimp.h"
#include "wimpt.h"
#include "resspr.h"
#include "baricon.h"
#include "res.h"
#include "event.h"
#include "menu.h"
#include "win.h"
#include "template.h"

#include "graphicswin.h"
#include "dialogbox.h"

   
#define APP_NAME "SetGCOL"
#define MENU_ITEMS ">Info,Quit"
                    
#define IMENU_INFO 1
#define IMENU_QUIT 2

menu imenu;

GraphicsWindow *gw;  

DialogBox *dialogBox;


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

Function    : info_about

Parameters  : void

Returns     : void

Description : Display program information dialog box.  
 
*******************************************************************************/

static void info_about(void)
{
   dbox d = dbox_new("ProgInfo");

   if (d != NULL)
   {
      dbox_show(d);        
      dbox_fillin(d);       
      dbox_dispose(&d);     
   }
}

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

Function    : ipremenuproc

Parameters  : void * - pointer to workspace

Returns     : menu

Description : Function called to prepare menu.   
 
*******************************************************************************/

static menu ipremenuproc(void *handle)
{
   return imenu;
}

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

Function    : imenuproc

Parameters  : void * - pointer to workspace
              chat * - menu item that has been hit 

Returns     : void

Description : Process a menu click.  
 
*******************************************************************************/

static void imenuproc(void *handle, char *hit)
{
   switch (hit[0])  
   {                
      case IMENU_INFO:
      {
         info_about();

         break;
      }
      case IMENU_QUIT:
      {
         exit(EXIT_SUCCESS);

         break;
      }
   }
}

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

Function    : icon_left_click

Parameters  : wimp_i - handle of the icon clicked

Returns     : void

Description : Function called when the mouse is clicked over the icon on the
              icon bar       

Notes       : As this function doesn't have a handle argument, like other
              handlers registered with the WIMP, we seem forced to make the
              pointer to the struct defining the graphics window a global
              variable, which is something I would like to have avoided.
 
*******************************************************************************/

static void icon_left_click(wimp_i icon)
{
   BOOL filling = TRUE;

   // open graphics window

   wimp_wstate win_state;

   wimpt_complain(wimp_get_wind_state(gw->handle, &win_state));

   gui_open(gw, &(win_state.o));

   // display dialogue box and process events until dismissed

   dbox_showstatic(dialogBox->handle);

   while (filling)
   {
      wimp_i icon = dbox_fillin(dialogBox->handle);

      switch (icon)
      {
         case dbox_CLOSE:
         {
            filling = FALSE;

            break;
         }
      }
   }

   gui_close(gw);
                
   dbox_hide(dialogBox->handle);   
}

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

Function    : unknownEventProcessor

Parameters  : wimp_eventstr* - pointer to struct describing the event
              void*          - pointer to struct defining the graphics window

Returns     : BOOL - indicates whether event was handled fully 

Description : Process events not associated with a specific window or dialogue
              box.  Currently this just detects mode and palette changes so
              that the colour numbers used in the GUI can be re-cached.
 
*******************************************************************************/

BOOL unknownEventProcessor(wimp_eventstr *e, void *handle)
{
   GraphicsWindow *gw = (GraphicsWindow*)handle;
             
   switch (e->e)
   {
      case wimp_ESEND:
      case wimp_ESENDWANTACK:
      {     
         switch (e->data.msg.hdr.action)
         {
            case wimp_MMODECHANGE:
            {                 
               wimpt_checkmode();

               // fall through
            }
            case wimp_PALETTECHANGE:
            {                    
               gui_cacheColours(gw);

               return TRUE;
            }
         }   
      }
      default:
      {
         return FALSE;
      }
   }
}                       

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

Function    : main

Parameters  : void

Returns     : int - indicate EXIT_SUCCESS or EXIT_FAILURE 

Description : Main part of the application, consisting of initialisation code,
              main event loop and finalisation code.  
 
*******************************************************************************/

int main(void)
{
   wimpt_init(APP_NAME);

   res_init(APP_NAME);   

   template_init();      

   dbox_init();     

   gw = gui_create(8);

   dialogBox = dialogBox_create(gw);        

   baricon("!SetGCOL", (int)resspr_area(), icon_left_click);

   imenu = menu_new(APP_NAME, MENU_ITEMS);
                    
   if (imenu == NULL)
   {
      return EXIT_FAILURE;
   }

   if (!event_attachmenumaker(win_ICONBAR, ipremenuproc, imenuproc, NULL))
   {
      return EXIT_FAILURE;
   } 

   win_add_unknown_event_processor(unknownEventProcessor, gw);    

   // main even processing loop

   while (TRUE) 
   {
      event_process();
   }
                    
   gui_close(gw);

   wimp_closedown();

   return EXIT_SUCCESS;
}

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