// $Source: /usr/local/SimSoft/Sfx3D/src/gts/gtsgui.cpp,v $
// $Revision: 1.3 $
// $Author: baum $
// $Date: 2001/12/04 16:27:05 $
//
// Login name of the user who locked the revision
// $Locker:  $
// Tag name used to checkout the file
// $Name: Release-14 $
// State assigned to revision
// $State: Exp $
//
//
// $Log: gtsgui.cpp,v $
// Revision 1.3  2001/12/04 16:27:05  baum
// -Verschiedene Bugs entfernt
//
// Revision 1.2  2001/11/29 15:18:10  baum
// -Realzeitsteuerung eingebaut
// -Handsteuerung eingebaut
//

/*** Windows headers ***/
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
//#include <winnt.h>
#endif /*WIN32*/

#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "MathDefs.h"
#include "DynArray.h"
#include "Messager.h"
#include "Strings.h"
#include "FileSys.h"
#include "StrmSet.h"
#include "IniFile.h"

#include "Vec3D.h"

#include "XGraph/XGraph.h"
#include "XGraph/AllViews.h"

#include "gtsglob.h"
#include "gtsbst.h"
#include "gtsgui.h"
#include "gtsini.h"
#include "gtsmdat.h"
#include "gtsmlog.h"
#include "gtsmexp.h"
#include "gtsglob.h"

/**< Rudi: 2004-01-06: ergaenzt, sonst LINKEN in VC6 nicht moeglich.*/
#include "gtsmabl.h"
#include "gtsmgra.h"

#include "tcl.h"
#include "tk.h"
#include "tix.h"

char rev[] = "Release: 14 ";

//==================================================================
//    Implementation
//    for class SFXViewHandler
//==================================================================

SFXViewHandler::SFXViewHandler (Tcl_Interp* interp) :
    ObjInterp     (interp),
    ObjWinHeight  (300),
    ObjWinWidth   (300),
    ObjBgColor    (1.0, 1.0, 1.0),
    ObjGridSize   (2.0),
    ObjGridWrap   (),
    ObjFlaeche    (Vec3D(0.0, 0.0, 0.0), Vec3D(20.0, 16.0, 0.0)),
    ObjMinFlaeche (ObjFlaeche),
    ObjCamPos     (),
    ObjCamFocus   (),
    ObjAnsicht    (0),
    ObjCamUp      (EY)
{
/*
//  ObjWinWidth  = IniFile::DefIniFile->readInt ("GRAFIK", "WinWidth", 300);
//  ObjWinHeight = IniFile::DefIniFile->readInt ("GRAFIK", "WinHeight", 300);
  unsigned colIndex = IniFile::DefIniFile->readInt ("GRAFIK", "BackgroundColor", 0);
  switch (colIndex) {
    case 0:   ObjBgColor = RGBAColor (1.0, 1.0, 1.0); break;
    case 1:   ObjBgColor = RGBAColor (0.0, 0.0, 0.0); break;
    case 2:   ObjBgColor = RGBAColor (1.0, 0.0, 0.0); break;
    case 3:   ObjBgColor = RGBAColor (0.0, 1.0, 0.0); break;
    case 4:   ObjBgColor = RGBAColor (1.0, 1.0, 0.0); break;
    case 5:   ObjBgColor = RGBAColor (0.0, 0.0, 1.0); break;
    case 6:   ObjBgColor = RGBAColor (1.0, 0.0, 1.0); break;
    case 7:   ObjBgColor = RGBAColor (0.0, 1.0, 1.0); break;
    case 8:   ObjBgColor = RGBAColor (0.25, 0.25, 0.25); break;
    case 9:   ObjBgColor = RGBAColor (0.75, 0.75, 0.75); break;
    default : ObjBgColor = RGBAColor (1.0, 1.0, 1.0); break;
  }
*/

  ObjWinWidth  = IniFile::DefIniFile.readInt ("GTS", "WinWidth", 300);
  ObjWinHeight = IniFile::DefIniFile.readInt ("GTS", "WinHeight", 300);
  ObjGridWrap =
  WrapBox(Vec3D(ObjFlaeche.Min.X()- ObjGridSize, ObjFlaeche.Min.Y()- ObjGridSize, -0.01),
          Vec3D(ObjFlaeche.Max.X()+ ObjGridSize, ObjFlaeche.Max.Y()+ ObjGridSize, -0.01));
} // ENDE SFXViewHandler

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SFXViewHandler::~SFXViewHandler ()
{  }

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SFXViewHandler::createView (int xPos, int yPos)
{
  GTSView = new ToglView (xPos, yPos, ObjWinWidth, ObjWinHeight, ObjBgColor,
                          ".action.draw.drawZ", ".menu.extra.ansichtseinstell");
  GTSView->setCallback (&GTSCB);
  // 1. Kamera-Position
  // 2. BlickrichtungsMittelpunkt
  // 3. Vektor fuer oben
  ObjCamPos   = Vec3D (0.0, 0.0, 40.0);
  GTSView->Camera()->setCamera (ObjCamPos, ObjCamFocus, ObjCamUp);
  GTSView->setGrid (ObjGridSize,
                    Vec3D (ObjGridWrap.Min.X (), ObjGridWrap.Min.Y (), -0.01),
                    Vec3D (ObjGridWrap.Max.X (), ObjGridWrap.Max.Y (), -0.01));
  GTSSpace->insertView (*GTSView);
  GTSView->setToOrthogonalProj ();
  GTSView->lightOn ();
  GTSView->flush ();
} // ENDE createView

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SFXViewHandler::Ansicht (Ustring richtung)
{
  double camDist = GTSView->Camera()->ViewDir ().len ();
  if      (richtung == Ustring ("AnsichtLinks")) {
    ObjCamPos = ObjCamFocus + (-EX * camDist);
    ObjCamUp = EZ;
  }
  else if (richtung == Ustring ("AnsichtRechts")) {
    ObjCamPos = ObjCamFocus + (EX * camDist);
    ObjCamUp = EZ;
  }
  else if (richtung == Ustring ("AnsichtOben")) {
    ObjCamPos = ObjCamFocus + (EY * camDist);
    ObjCamUp = EZ;
  }
  else if (richtung == Ustring ("AnsichtUnten")) {
    ObjCamPos = ObjCamFocus + (-EY * camDist);
    ObjCamUp = EZ;
  }
  else if (richtung == Ustring ("AnsichtDefault")) {
    ObjCamPos = ObjCamFocus + (EZ * camDist);
    ObjCamUp = EY;
    GTSView->Camera()->setCamera (ObjCamPos, ObjCamFocus, ObjCamUp);
    berechneLayoutFlaeche  ();
    berechneCameraPosition ();
  }

  GTSView->Camera()->setCamera (ObjCamPos, ObjCamFocus, ObjCamUp);
  GTSView->flush ();
}  //  ENDE Ansicht

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SFXViewHandler::poseView ()
{
  setRasterWeite (ObjGridSize);
  berechneCameraPosition ();
} // ENDE poseView

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const float& SFXViewHandler::getRasterWeite ()
{
  return ObjGridSize;
} // ENDE getRasterWeite

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SFXViewHandler::setRasterWeite (float const weite)
{
  ObjGridSize = weite;
  berechneLayoutFlaeche();
  int xminSteps = (int) Round((ObjFlaeche.Min.X() - ObjGridSize)/ObjGridSize);
  int xmaxSteps = (int) Round((ObjFlaeche.Max.X() + ObjGridSize)/ObjGridSize);
  int yminSteps = (int) Round((ObjFlaeche.Min.Y() - ObjGridSize)/ObjGridSize);
  int ymaxSteps = (int) Round((ObjFlaeche.Max.Y() + ObjGridSize)/ObjGridSize);

  ObjGridWrap =
  WrapBox(Vec3D(xminSteps * ObjGridSize, yminSteps * ObjGridSize, -0.01),
          Vec3D(xmaxSteps * ObjGridSize, ymaxSteps * ObjGridSize, -0.01));
  GTSView->setGrid (ObjGridSize, Vec3D (ObjGridWrap.Min.X (), ObjGridWrap.Min.Y (), -0.01),
                                 Vec3D (ObjGridWrap.Max.X (), ObjGridWrap.Max.Y (), -0.01));
  GTSView->flush ();
} // ENDE setRasterWeite

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SFXViewHandler::berechneCameraPosition ()
{
  WrapBox neu = ObjFlaeche;
  Vec3D focus = neu.Min + ((neu.Max - neu.Min) * 0.5);
  Vec3D distance = Vec3D (GTSView->Camera ()->ViewDir ().unit () *
                         (((neu.Max - neu.Min)).len () /
                         (Angle (GTSView->Camera ()->VisualAngle ()).tan ())));
  GTSView->Camera ()->setCamera (focus - distance, focus,
                                 GTSView->Camera ()->CameraUp ());
  ObjCamPos   = focus - distance;
  ObjCamFocus = focus;
  ObjCamUp    = GTSView->Camera ()->CameraUp ();
} // ENDE berechneCameraPosition

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SFXViewHandler::berechneLayoutFlaeche ()
{
  WrapBox neu;
  if (!BausteinListe->Leer())
  {
    neu = BausteinListe->getFlaeche ();
    neu.sort ();
//    ObjFlaeche = neu;

    neu.Min = Vec3D (neu.Min.X (), neu.Min.Y (), 0.0);
    neu.Max = Vec3D (neu.Max.X (), neu.Max.Y (), 0.0);
    double xmin = ObjMinFlaeche.Min.X();
    double xmax = ObjMinFlaeche.Max.X();
    double ymin = ObjMinFlaeche.Min.Y();
    double ymax = ObjMinFlaeche.Max.Y();
    if (neu.Min.X() < ObjMinFlaeche.Min.X()) xmin = neu.Min.X();
    if (neu.Max.X() > ObjMinFlaeche.Max.X()) xmax = neu.Max.X();
    if (neu.Min.Y() < ObjMinFlaeche.Min.Y()) ymin = neu.Min.Y();
    if (neu.Max.Y() > ObjMinFlaeche.Max.Y()) ymax = neu.Max.Y();
    ObjFlaeche.Min = Vec3D (xmin, ymin, 0.0);
    ObjFlaeche.Max = Vec3D (xmax, ymax, 0.0);

  }
} // ENDE berechneLayoutFlaeche

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

EXTERN void TkpDisplayWarning _ANSI_ARGS_((char *msg, char *title));

extern TIX_DECLARE_CMD(DlgDatei);
extern TIX_DECLARE_CMD(DlgGrafik);
extern TIX_DECLARE_CMD(DlgLogik);
extern TIX_DECLARE_CMD(DlgAblaufplan);
extern TIX_DECLARE_CMD(DlgExperiment);

static Tix_TclCmd commands[] = {
    {"DlgDatei",      DlgDatei},
    {"DlgGrafik",     DlgGrafik},
    {"DlgLogik",      DlgLogik},
    {"DlgAblaufplan", DlgAblaufplan},
    {"DlgExperiment", DlgExperiment},

    /*
     * Make sure this list is terminated by a NULL element
     */
    {(char *) NULL,             (Tix_CmdProc)NULL} 
};

int Tcl_AppInit (Tcl_Interp *interp) 
{
  if (Tcl_Init(interp) == TCL_ERROR) {
    goto error;
  }
  if (Tk_Init(interp) == TCL_ERROR) {
    goto error;
  }
  if (Tix_Init(interp) == TCL_ERROR) {
    goto error;
  }
  Tcl_StaticPackage(interp, "Tix", Tix_Init, Tk_SafeInit);

  Tix_CreateCommands(interp, commands, (ClientData) NULL,
        (void (*)_ANSI_ARGS_((ClientData))) NULL);
   
  ToglView::setup (interp);

  sprintf (DlgBuffer, "%sGts.tcl", FileSystem::ExePath ());
  Tix_SetRcFileName(interp, DlgBuffer);

#ifndef WIN32
  Tcl_AddErrorInfo(interp, "");
  char lbuf[255];
  sprintf (lbuf, "source %s", DlgBuffer);
  if (Tcl_Eval (interp, lbuf) == TCL_ERROR) {
      TkpDisplayWarning(Tcl_GetVar(interp, "errorInfo",
         TCL_GLOBAL_ONLY), "Error in startup script");
    return TCL_ERROR;
  }
  Tcl_ResetResult(interp);
#endif

  GTSInterpreter = interp;
  return TCL_OK;

error:
  MessageBeep(MB_ICONEXCLAMATION);
  MessageBox(NULL, Tcl_GetStringResult(interp), "Error in Wish",
     MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
  ExitProcess(1);
  /* we won't reach this, but we need the return */
  return TCL_ERROR;
} // Tcl_AppInit
