/*------------------------------------------------------------\
|                                                             |
| Tool    :                   GRAAL                           |
|                                                             |
| File    :                   Map.c                           |
|                                                             |
| Authors :      Venot Frederic and Jacomme Ludovic           |
|                                                             |
| Date    :                  01.08.93                         |
|                                                             |
\------------------------------------------------------------*/

/*------------------------------------------------------------\
|                                                             |
|                         Include Files                       |
|                                                             |
\------------------------------------------------------------*/

# include <stdio.h>
# include <Xm/Xm.h>
# include <Xm/Form.h>
# include <Xm/Frame.h>
# include <Xm/PushB.h>
# include <Xm/DrawingA.h>
 
# include MUT_H
# include MPH_H
# include RDS_H
# include RPR_H
# include GSB_H
# include GRM_H
# include GTB_H
# include GMX_H
# include GMV_H

# include "GMV_map.h"

/*------------------------------------------------------------\
|                                                             |
|                           Constants                         |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                            Types                            |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                          Variables                          |
|                                                             |
\------------------------------------------------------------*/

   GraalPanelItem GraalViewMapPanel =

         {
           "Map",
           1,
           GRAAL_VIEW_MAP_X,
           GRAAL_VIEW_MAP_Y,
           190,
           200,
           0,
           0,
           (Widget)NULL,
           (Widget)NULL,
           (Widget)NULL,
           (Widget)NULL,
           (GraalPanelButtonItem *)NULL 
         };

   int GraalViewMapDefaultValues[ 4 ] =

         {
           GRAAL_VIEW_MAP_X, 
           GRAAL_VIEW_MAP_Y,
           190, 200
         };

/*------------------------------------------------------------\
|                                                             |
|                      Graphic Map Window                     |
|                                                             |
\------------------------------------------------------------*/

  Widget     GraalMapWindow;
  Widget     GraalMapButtonCompute;
  Widget     GraalMapButtonClose;

  Dimension  GraalMapDx    = 0;
  Dimension  GraalMapDy    = 0;

  static char GraalFirstEnterMap = GRAAL_TRUE;
  static char GraalFirstExpose   = GRAAL_TRUE;

/*------------------------------------------------------------\
|                                                             |
|                         Lambda Map                          |
|                                                             |
\------------------------------------------------------------*/

  float      GraalLambdaMapStep;

  long       GraalLambdaMapX;
  long       GraalLambdaMapY;
  long       GraalLambdaMapDx;
  long       GraalLambdaMapDy;

  long       GraalBoundMapX; 
  long       GraalBoundMapY; 
  long       GraalBoundMapDx; 
  long       GraalBoundMapDy; 

  long       GraalPixelMapX;
  long       GraalPixelMapY;

/*------------------------------------------------------------\
|                                                             |
|                            Expose                           |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                          Translation                        |
|                                                             |
\------------------------------------------------------------*/

  static String GraalMapEventTranslation =

    "<Btn1Up>:      CallbackMapEvent( 0 )\n\
     <Btn2Up>:      CallbackMapEvent( 1 )\n\
     <Btn3Up>:      CallbackMapEvent( 2 )";

/*------------------------------------------------------------\
|                                                             |
|                           Functions                         |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                         Event Callback                      |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                        CallbackCloseMap                     |
|                                                             |
\------------------------------------------------------------*/

  void CallbackCloseMap( MyWidget, ClientData, CallData )

       Widget  MyWidget;
       caddr_t ClientData;
       caddr_t CallData;
  {
    XtUnmanageChild( GraalViewMapPanel.PANEL );
  } 

/*------------------------------------------------------------\
|                                                             |
|                        CallbackMapCompute                   |
|                                                             |
\------------------------------------------------------------*/
 
  void CallbackMapCompute( MyWidget, ClientData, CallData )
 
       Widget  MyWidget;
       caddr_t ClientData;
       caddr_t CallData;
  {
    GraalComputeAndDisplayMap();
  }

/*------------------------------------------------------------\
|                                                             |
|                       CallbackMapEvent                      |
|                                                             |
\------------------------------------------------------------*/

  void CallbackMapEvent ( MyWidget, Event, Args, Argc )

       Widget        MyWidget;
       XButtonEvent *Event;
       String       *Args;
       int          *Argc;
  {
    Display  *EventDisplay;
    char      MouseEvent;
    long      X;
    long      Y;

    EventDisplay = Event->display;
    MouseEvent   = Args[ 0 ][ 0 ] - '0';

    X = Event->x;
    Y = GraalMapDy - Event->y;

    X = X + GraalPixelMapX;
    Y = Y + GraalPixelMapY;

    if ( X < 0 )
    {
      X = ((float)(X) / GraalLambdaMapStep) - 0.5 ;
    }
    else
    {   
      X = ((float)(X) / GraalLambdaMapStep) + 0.5 ;
    }

    if ( Y < 0 )
    {
      Y = ((float)(Y) / GraalLambdaMapStep) - 0.5 ;
    }
    else
    {   
      Y = ((float)(Y) / GraalLambdaMapStep) + 0.5 ;
    }

    switch ( MouseEvent )
    {
      case GRAAL_B1UP   : 
      case GRAAL_B2UP   :
      case GRAAL_B3UP   :

       GraalZoomCenter( X, Y );

       break;
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                     CallbackMapResize                       |
|                                                             |
\------------------------------------------------------------*/

  void CallbackMapResize( MyWidget, ClientData, CallData )

       Widget                       MyWidget;
       XtPointer                    ClientData;
       XmDrawingAreaCallbackStruct *CallData;
  {
    if ( ! GraalFirstExpose )
    {
      GraalSetMouseCursor( GraalGraphicWindow, GRAAL_WATCH_CURSOR  );
      GraalResizeMapWindow();
      GraalSetMouseCursor( GraalGraphicWindow, GRAAL_NORMAL_CURSOR );
    }
  }
  
/*------------------------------------------------------------\
|                                                             |
|                     CallbackMapExpose                       |
|                                                             |
\------------------------------------------------------------*/
  
  void CallbackMapExpose( MyWidget, ClientData, CallData )

       Widget                       MyWidget;
       XtPointer                    ClientData;
       XmDrawingAreaCallbackStruct *CallData;
  {
    XExposeEvent *ExposeEvent;

    ExposeEvent = (XExposeEvent *)CallData->event;

    if ( GraalFirstExpose )
    {
      GraalFirstExpose = GRAAL_FALSE;

      GraalInitializeMapWindow();
    }

    GraalRefreshMapWindow();
  }

/*------------------------------------------------------------\
|                                                             |
|                     Initialize Functions                    |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                     GraalsnitializeMapWindow                |
|                                                             |
\------------------------------------------------------------*/

  void GraalInitializeMapWindow()

  {
    XtVaGetValues( GraalMapWindow,
                   XmNwidth , &GraalMapDx,
                   XmNheight, &GraalMapDy,
                   NULL
                 );
 
    GraalInitializeLambdaMap();
  }

/*------------------------------------------------------------\
|                                                             |
|                     Graphic Window Functions                |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                       GraalRefreshMapWindow                 |
|                                                             |
\------------------------------------------------------------*/

  void GraalRefreshMapWindow()
  {
    GraalClearMapWindow();
    GraalDisplayLambdaMap();
  }

/*------------------------------------------------------------\
|                                                             |
|                       GraalClearMapWindow                   |
|                                                             |
\------------------------------------------------------------*/

  void GraalClearMapWindow()

  {
    XFillRectangle( XtDisplay( GraalMapWindow ),
                    XtWindow( GraalMapWindow ),
                    GraalBackgroundGC,
                    0, 0, GraalMapDx, GraalMapDy );
  }

/*------------------------------------------------------------\
|                                                             |
|                       GraalResizeMapWindow                  |
|                                                             |
\------------------------------------------------------------*/

  void GraalResizeMapWindow()

  {
    XtVaGetValues( GraalMapWindow,
                   XmNwidth,  &GraalMapDx,
                   XmNheight, &GraalMapDy,
                   NULL
                 );
 
    GraalComputeAndDisplayMap();
  }

/*------------------------------------------------------------\
|                                                             |
|                   GraalInitializeMapEvent                   |
|                                                             |
\------------------------------------------------------------*/

  void GraalInitializeMapEvent()

  {
    XtActionsRec NewActions;

    XtVaSetValues( GraalMapWindow,
                   XmNtranslations,
                   XtParseTranslationTable( GraalMapEventTranslation ),
                   NULL
                 );

    NewActions.string = "CallbackMapEvent";
    NewActions.proc   =  CallbackMapEvent;

    XtAppAddActions( GraalApplication, &NewActions, 1 );

    XtAddCallback( GraalMapWindow, 
                   XmNresizeCallback, 
                   CallbackMapResize, NULL );

    XtAddCallback( GraalMapWindow, 
                   XmNexposeCallback, 
                   CallbackMapExpose, NULL );
  }

/*------------------------------------------------------------\
|                                                             |
|                     Lambda Map Functions                    |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                GraalInitializeLambdaMap                     |
|                                                             |
\------------------------------------------------------------*/

  void GraalInitializeLambdaMap()

  {
    if ( ! GraalComputeBound() )
    {
      GraalBoundMapX  = GRAAL_DEFAULT_MAP_X;
      GraalBoundMapY  = GRAAL_DEFAULT_MAP_Y;
      GraalBoundMapDx = GRAAL_DEFAULT_MAP_DX;
      GraalBoundMapDy = GRAAL_DEFAULT_MAP_DY;
    }
    else
    {
      GraalBoundMapX  = GraalBoundXmin / RDS_LAMBDA;
      GraalBoundMapY  = GraalBoundYmin / RDS_LAMBDA;
      GraalBoundMapDx = GraalBoundXmax / RDS_LAMBDA;
      GraalBoundMapDy = GraalBoundYmax / RDS_LAMBDA;
      GraalBoundMapDx = GraalBoundMapDx - GraalBoundMapX;
      GraalBoundMapDy = GraalBoundMapDy - GraalBoundMapY;
    }

    GraalLambdaMapX  = GraalBoundMapX  - 2;
    GraalLambdaMapY  = GraalBoundMapY  - 2;
    GraalLambdaMapDx = GraalBoundMapDx + 4;
    GraalLambdaMapDy = GraalBoundMapDy + 4;

    GraalComputeLambdaMap();
  }

/*------------------------------------------------------------\
|                                                             |
|                 GraalComputeLambdaMap                       |
|                                                             |
\------------------------------------------------------------*/

  void GraalComputeLambdaMap()

  {
    long  Delta;
    float StepX;
    float StepY;

    StepX = (float)(GraalMapDx) / (float)(GraalLambdaMapDx);
    StepY = (float)(GraalMapDy) / (float)(GraalLambdaMapDy);

    if ( StepX < StepY )
    {
      GraalLambdaMapStep = StepX;
      Delta              = GraalLambdaMapDy; 
      GraalLambdaMapDy   = 1 + ( GraalMapDy / StepX );
      Delta              = ( GraalLambdaMapDy - Delta ) >> 1;
      GraalLambdaMapY    = GraalLambdaMapY - Delta;
    }
    else
    {
      GraalLambdaMapStep = StepY;
      Delta              = GraalLambdaMapDx; 
      GraalLambdaMapDx   = 1 + ( GraalMapDx / StepY );
      Delta              = ( GraalLambdaMapDx - Delta ) >> 1;
      GraalLambdaMapX    = GraalLambdaMapX - Delta;
    }

    GraalPixelMapX = (float)(GraalLambdaMapX) * GraalLambdaMapStep;
    GraalPixelMapY = (float)(GraalLambdaMapY) * GraalLambdaMapStep;
  }

/*------------------------------------------------------------\
|                                                             |
|                      GraalDisplayLambdaMap                  |
|                                                             |
\------------------------------------------------------------*/

  void GraalDisplayLambdaMap()
  {
    long X1;
    long Y1;
    long X2;
    long Y2;

    X1 = (float)( GraalBoundMapX                   ) * GraalLambdaMapStep;
    Y1 = (float)( GraalBoundMapY                   ) * GraalLambdaMapStep;
    X2 = (float)( GraalBoundMapX + GraalBoundMapDx ) * GraalLambdaMapStep;
    Y2 = (float)( GraalBoundMapY + GraalBoundMapDy ) * GraalLambdaMapStep;

    X1 = X1 - GraalPixelMapX;
    X2 = X2 - GraalPixelMapX;
    Y1 = Y1 - GraalPixelMapY;
    Y2 = Y2 - GraalPixelMapY;

    XDrawRectangle( XtDisplay( GraalMapWindow ),
                    XtWindow( GraalMapWindow ),
                    GraalLargeTextGC,
                    X1, GraalMapDy - Y2,
                    X2 - X1, Y2 - Y1 );

    X1 = GraalLambdaGridX + ( GraalLambdaGridDx >> 1 );
    Y1 = GraalLambdaGridY + ( GraalLambdaGridDy >> 1 );
    X1 = (float)( X1 ) * GraalLambdaMapStep;
    Y1 = (float)( Y1 ) * GraalLambdaMapStep;

    X1 = X1 - GraalPixelMapX;
    Y1 = Y1 - GraalPixelMapY;
    Y1 = GraalMapDy - Y1;

    if ( ( X1 > 0          ) && 
         ( Y1 > 0          ) &&
         ( X1 < GraalMapDx ) &&
         ( Y1 < GraalMapDy ) )
    {
      XDrawLine( XtDisplay( GraalMapWindow ),
                 XtWindow( GraalMapWindow ),
                 GraalLargeTextGC,
                 X1 - 2, Y1,
                 X1 + 2, Y1  );

      XDrawLine( XtDisplay( GraalMapWindow ),
                 XtWindow( GraalMapWindow ),
                 GraalLargeTextGC,
                 X1, Y1 - 2,
                 X1, Y1 + 2  );
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                      GraalBuildPanelMap                     |
|                                                             |
\------------------------------------------------------------*/

  void GraalBuildPanelMap()
  {
    Arg Args[3];

    XtSetArg( Args[0], XmNshadowType    , XmSHADOW_ETCHED_IN      );
    XtSetArg( Args[1], XmNdeleteResponse,          XmDESTROY      );
    XtSetArg( Args[2], XmNtitle         , GraalViewMapPanel.TITLE );

    GraalViewMapPanel.PANEL = 

      XmCreateFormDialog( GraalMainWindow, "GraalViewMapPanel", Args, 3);

    XtAddCallback( GraalViewMapPanel.PANEL, XmNdestroyCallback,
                   GraalDestroyDialogCallback, NULL  );

    GraalViewMapPanel.PANEL_FORM = 

      XtVaCreateManagedWidget( "GraalViewMapPanelForm",
                               xmFormWidgetClass,
                               GraalViewMapPanel.PANEL,
                               XmNtopAttachment    , XmATTACH_FORM,
                               XmNbottomAttachment , XmATTACH_FORM,
                               XmNleftAttachment   , XmATTACH_FORM,
                               XmNrightAttachment  , XmATTACH_FORM,
                               XmNfractionBase     , 100,
                               NULL
                             );
 
    GraalViewMapPanel.FRAME = 

      XtVaCreateManagedWidget( "GraalViewMapFrame",
                               xmFrameWidgetClass,
                               GraalViewMapPanel.PANEL_FORM, 
                               XmNtopAttachment    , XmATTACH_FORM,
                               XmNbottomAttachment , XmATTACH_FORM,
                               XmNleftAttachment   , XmATTACH_FORM,
                               XmNrightAttachment  , XmATTACH_FORM,
                               NULL
                             );
 
    GraalViewMapPanel.FORM = 

      XtVaCreateManagedWidget( "GraalViewMapForm",
                               xmFormWidgetClass,
                               GraalViewMapPanel.FRAME, 
                               XmNtopAttachment    , XmATTACH_FORM,
                               XmNbottomAttachment , XmATTACH_FORM,
                               XmNleftAttachment   , XmATTACH_FORM,
                               XmNrightAttachment  , XmATTACH_FORM,
                               XmNfractionBase     , 100,
                               NULL
                             );

    GraalMapButtonCompute = 

      XtVaCreateManagedWidget( "Compute",
                               xmPushButtonWidgetClass,
                               GraalViewMapPanel.FORM, 
                               XmNleftAttachment   , XmATTACH_POSITION,
                               XmNleftPosition     , 1,
                               XmNrightAttachment  , XmATTACH_POSITION,
                               XmNrightPosition    , 44,
                               XmNtopAttachment    , XmATTACH_POSITION,
                               XmNtopPosition      , 89,
                               XmNbottomAttachment , XmATTACH_POSITION,
                               XmNbottomPosition   , 99,
                               NULL
                             );
    GraalMapButtonClose = 

      XtVaCreateManagedWidget( "Close",
                               xmPushButtonWidgetClass,
                               GraalViewMapPanel.FORM, 
                               XmNleftAttachment   , XmATTACH_POSITION,
                               XmNleftPosition     , 45,
                               XmNrightAttachment  , XmATTACH_POSITION,
                               XmNrightPosition    , 99,
                               XmNtopAttachment    , XmATTACH_POSITION,
                               XmNtopPosition      , 89,
                               XmNbottomAttachment , XmATTACH_POSITION,
                               XmNbottomPosition   , 99,
                               NULL
                             );

    GraalMapWindow = 

      XtVaCreateManagedWidget( "GraalMapWindow",
                               xmDrawingAreaWidgetClass,
                               GraalViewMapPanel.FORM, 
                               XmNleftAttachment   , XmATTACH_POSITION,
                               XmNleftPosition     , 1,
                               XmNrightAttachment  , XmATTACH_POSITION,
                               XmNrightPosition    , 99,
                               XmNtopAttachment    , XmATTACH_POSITION,
                               XmNtopPosition      , 1,
                               XmNbottomAttachment , XmATTACH_POSITION,
                               XmNbottomPosition   , 88,
                               XmNbackground       , 1,
                               XmNforeground       , 0,
                               NULL
                             );

    XtAddCallback( GraalMapButtonCompute, 
                   XmNactivateCallback,
                   CallbackMapCompute, NULL );

    XtAddCallback( GraalMapButtonClose, 
                   XmNactivateCallback,
                   CallbackCloseMap, NULL );

    XtVaSetValues( GraalViewMapPanel.PANEL,
                   XmNheight, GraalViewMapPanel.HEIGHT,
                   XmNwidth , GraalViewMapPanel.WIDTH,
                   XmNx     , GraalViewMapPanel.X,
                   XmNy     , GraalViewMapPanel.Y,
                   NULL );
  }

/*------------------------------------------------------------\
|                                                             |
|                     GraalEnterMapPanel                      |
|                                                             |
\------------------------------------------------------------*/

  void GraalEnterMapPanel()

  {
    XtManageChild( GraalViewMapPanel.PANEL );

    if ( GraalViewMapPanel.COMPUTE == 1 )
    {
      XtVaSetValues( GraalViewMapPanel.PANEL,
                     XmNheight, GraalViewMapPanel.HEIGHT,
                     XmNwidth , GraalViewMapPanel.WIDTH,
                     XmNx     , GraalViewMapPanel.X,
                     XmNy     , GraalViewMapPanel.Y,
                     NULL );

      GraalFirstEnterMap        = GRAAL_FALSE;
      GraalViewMapPanel.COMPUTE = 0;
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                     GraalComputeAndDisplayMap               |
|                                                             |
\------------------------------------------------------------*/

  void GraalComputeAndDisplayMap()

  {
    if ( ! GraalFirstEnterMap )
    {
      GraalInitializeLambdaMap();
      GraalClearMapWindow();
      GraalDisplayLambdaMap();
    }
  }
