#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>

#include <iostream>

#include "sopnamsp.h"
#include "pisysdep.h"
#include PIAPP_H
#include PIWIN_H 
#include PIMENU_H 
#include PISTDWDG_H 
#include PIBWDG_H

/*  Composante graphique de trace de chaine de lignes et de fleches */

// ---- Declaration de la classe LineDrawWdg --------
class LineDrawWdg : public PIBaseWdg
{
public:
// Les methodes ...

                  LineDrawWdg(PIContainerGen *par, char *nom,
                         int sx=10, int sy=10, int px=0, int py=0);
  virtual         ~LineDrawWdg();

// Traitement des evenements   
//  virtual void   Resize();
  virtual void   Draw(PIGraphic* g, int x0, int y0, int dx, int dy);

  virtual void   But1Press(int x, int y);
  virtual void   Keyboard(int key, PIKeyModifier kmod);

protected:
  PIColors mCol;
  int mArrSz;
};

// ---- Declaration de la classe ArrowDrawWdg --------
class ArrowDrawWdg : public LineDrawWdg
{
public:
// Les methodes ...

                  ArrowDrawWdg(PIContainerGen *par, char *nom,
                         int sx=10, int sy=10, int px=0, int py=0);
  virtual         ~ArrowDrawWdg();

// Traitement des evenements   
//  virtual void   Resize();
  virtual void   Draw(PIGraphic* g, int x0, int y0, int dx, int dy);

  //  virtual void   But1Press(int x, int y);
  //  virtual void   Keyboard(int key, PIKeyModifier kmod);

};



/* ........................................................... */
/*     Classe LineDrawWdg (Implementation des methodes)             */
/* ........................................................... */

/* --Methode-- */
LineDrawWdg::LineDrawWdg(PIContainerGen *par, char *nom,
                       int sx, int sy, int px, int py) 
: PIBaseWdg(par, nom, sx, sy, px, py)

{
  mCol = PI_Black;
  mArrSz = 7;
  ActivateKeyboard();
  ActivateButton(1);
}

/* --Methode-- */
LineDrawWdg::~LineDrawWdg()
{
}
 

/* --Methode-- */
void LineDrawWdg::Draw(PIGraphicGen* g, int /*x0*/, int /*y0*/, int /*dx*/, int /*dy*/)
{
PILineAtt latt;

if (g->kind() != PI_PSFileGraphics ) EraseWindow();
g->SelForeground(mCol);

g->SelLine(PI_NormalLine);
g->DrawLine(10,20, 160, 20);
g->DrawString(200,20,"PI_NormalLine");

g->SelLine(PI_ThinLine);
g->DrawLine(10,40, 160, 40);
g->DrawString(200,40,"PI_ThinLine");

g->SelLine(PI_ThickLine);
g->DrawLine(10,60, 160, 60);
g->DrawString(200,60,"PI_ThickLine");

latt = PILineAtt(6);
g->SelLine(latt);
g->DrawLine(10,80, 160, 80);
g->DrawString(200,80,"PILineAtt(6)");

g->SelLine(PI_DashedLine);
g->DrawLine(10,100, 160, 100);
g->DrawString(200,100,"PI_DashedLine");

g->SelLine(PI_DottedLine);
g->DrawLine(10,120, 160, 120);
g->DrawString(200,120,"PI_DottedLine");

g->SelLine(PI_DashDottedLine);
g->DrawLine(10,140, 160, 140);
g->DrawString(200,140,"PI_DashDottedLine");

latt = PILineAtt(3,PI_LineDashDotted);
g->SelLine(latt);
g->DrawLine(10,160, 160, 160);
g->DrawString(200,160,"PILineAtt(3,PI_LineDashDotted)");

return;
}

/* --Methode-- */
void LineDrawWdg::Keyboard(int key, PIKeyModifier kmod)
{

bool fgref = true;
switch (key) {
 case 'd':
   mCol = PI_Black;
   break;
 case 'r':
   mCol = PI_Red;
   break;
 case 'b':
   mCol = PI_Blue;
   break;
 case 'g':
   mCol = PI_Green;
   break;
 case 'y':
   mCol = PI_Yellow;
   break;
 case 'm':
   mCol = PI_Magenta;
   break;
 case '1':
   mArrSz = 5;
   break;
 case '2':
   mArrSz = 6;
   break;
 case '3':
   mArrSz = 7;
   break;
 case '4':
   mArrSz = 8;
   break;
 case '5':
   mArrSz = 9;
   break;
 case '6':
   mArrSz = 10;
   break;
   
 default:
   fgref = false;
}

if (fgref) Refresh(); 

return;
}
/* --Methode-- */
void LineDrawWdg::But1Press(int x, int y)
{
  Send(Msg(), PIMsg_Active);
}


/* ........................................................... */
/*     Classe ArrowDrawWdg (Implementation des methodes)             */
/* ........................................................... */

/* --Methode-- */
ArrowDrawWdg::ArrowDrawWdg(PIContainerGen *par, char *nom,
                       int sx, int sy, int px, int py) 
: LineDrawWdg(par, nom, sx, sy, px, py)

{
}

/* --Methode-- */
ArrowDrawWdg::~ArrowDrawWdg()
{
}
 

/* --Methode-- */
void ArrowDrawWdg::Draw(PIGraphicGen* g, int /*x0*/, int /*y0*/, int /*dx*/, int /*dy*/)
{
PILineAtt latt;
 double x1[12], x2[12];
 double y1[12], y2[12];
 double x0[6]={70,210,350,70,210,350};
 double y0[6]={70,70,70,210,210,210};
 double r1=15, r2=60;
 PILineTypes lt[6] = {PI_NormalLine, PI_ThinLine, PI_ThinLine,
		      PI_NormalLine, PI_ThinLine, PI_ThinLine};
 PIArrowMarker amk[6] = 
   {PI_BasicArrowMarker, PI_BasicArrowMarker, PI_TriangleArrowMarker,  
    PI_FTriangleArrowMarker, PI_ArrowShapedArrowMarker, PI_FArrowShapedArrowMarker};

if (g->kind() != PI_PSFileGraphics ) EraseWindow();
g->SelForeground(mCol);
int i,j,k;
for(k=0; k<6; k++) {
  g->SelLine(lt[k]);
  g->SelArrowMarker(mArrSz,amk[k]);
  for(i=0; i<12; i++) {
    x1[i] = x0[k] + cos(i*M_PI/6.)*r1; 
    x2[i] = x0[k] + cos(i*M_PI/6.)*r2; 
    y1[i] = y0[k] + sin(i*M_PI/6.)*r1; 
    y2[i] = y0[k] + sin(i*M_PI/6.)*r2; 
    if (k != 1)  g->DrawArrowMarker(x1[i], y1[i], x2[i], y2[i], true);
    else  g->DrawArrowMarker(x2[i], y2[i], x1[i], y1[i], true);
  }
}

g->DrawArrowMarker(10, 300, 150, 300, true);
g->DrawString(200, 300, " ArrowDrawWdg");
return;
}

/* ........................................................... */
/*                       Classe PITApp                         */
/* ........................................................... */
class PITApp : public PIApplication {
public:
     PITApp(int narg=0, char* arg[]=NULL);
     ~PITApp();
     virtual void   Process(PIMessage msg, PIMsgHandler* sender, void* data=NULL);
private :
  PIMenu* m[2];
  PIText* txt;
  PIWindow* mcurwin;
  PSFile *mPS;
};


/* --Methode-- */
PITApp::PITApp(int narg, char* arg[])
: PIApplication(300, 100, narg, arg)
{

//  Menus, les numeros ds AppendItem sont les numeros de messages
//  qui seront passes a Process() et permettent d'identifier l'action

//  Creation du premier menu  

m[0] = new PIMenu(Menubar(),"Actions");
m[0]->AppendItem("LineDrawWdg", 10101);
m[0]->AppendItem("ArrowDrawWdg", 10102);
m[0]->AppendItem("->eps", 10111);
m[0]->AppendItem("->ps", 10112);
m[0]->AppendItem("Exit", 10105);
// On accroche le menu au Menubar
AppendMenu(m[0]);


// Creation d' zone texte multiligne
txt = new PIText(MainWin(), "mltext", true, true, 290, 90, 5, 5);
txt->SetBinding(PIBK_elastic,PIBK_elastic,PIBK_elastic,PIBK_elastic);
// txt->SetMutiLineMode(true);
txt->SetTextEditable(false);
txt->SetText("");
txt->SetText("LineDrawWdg/Keyboard: d,r,g,b,y, - 1,2...,6 \n (black,red,blue,green,yellow,magenta - Arrow Size) ");

mcurwin = NULL;
mPS = new PSFile("piline.ps", PI_Auto);
SetReady();
}

/* --Methode-- */
PITApp::~PITApp()
{
delete m[0]; 
delete txt;
delete mPS;
}  

static int numpsf = 0;
static int nbwin = 0;
/* --Methode-- */
void PITApp::Process(PIMessage msg, PIMsgHandler* sender, void* /*data*/)
{

char strg[256];

// Gestion des actions en fonctions des messages

if ( ( ModMsg(msg) == PIMsg_Active) || (ModMsg(msg) == PIMsg_Close) ) {
  PIWdg *sndw;
  sndw = (PIWdg *)sender;      
  if (sndw->kind() ==  PIWindow::ClassId)  {
    if (ModMsg(msg) == PIMsg_Close)  { 
      delete (PIWindow *)sender;  
      mcurwin = NULL;  
      }
    else mcurwin = (PIWindow *)sender;
  }
}

else switch(UserMsg(msg))    {

    case 10101: // Creation d'un LineDrawWdg
      {
      nbwin++;
      sprintf(strg, "Creation LineDrawWdg   \n Fenetre No %d ", nbwin);
      sprintf(strg,"LineDraw - %d", nbwin);
      PIWindow* wp = new PIWindow(this, strg, PIWK_normal,  350, 250, 150, 150);
      wp->SetAutoDelChilds(true);
      LineDrawWdg* exb  = new LineDrawWdg(wp, "LineDraw", 350, 250, 0, 0);
      exb->SetBinding(PIBK_fixed,PIBK_elastic,PIBK_elastic,PIBK_elastic);
      wp->SetUserData(exb);
      wp->Show();
      }
    break;

    case 10102: // Creation d'un ArrowDrawWdg
      {
      nbwin++;
      sprintf(strg, "Creation ArrowDrawWdg   \n Fenetre No %d ", nbwin);
      sprintf(strg,"ArrowDraw - %d", nbwin);
      PIWindow* wp = new PIWindow(this, strg, PIWK_normal,  420, 350, 150, 150);
      wp->SetAutoDelChilds(true);
      ArrowDrawWdg* exb  = new ArrowDrawWdg(wp, "ArrowDraw", 420, 350, 0, 0);
      exb->SetBinding(PIBK_fixed,PIBK_elastic,PIBK_elastic,PIBK_elastic);
      wp->SetUserData(exb);
      wp->Show();
      }
    break;


    case 10111:          // -> eps
      if (mcurwin) {
        char buff[64];
        sprintf(buff, "piline_%d.eps", numpsf);        numpsf++;
        printf("Creating EPS File %s (Encapsulated PostScript) \n", buff);
        PSFile *mps;
	mps = new PSFile(buff);
	mcurwin->PSPrint(mps,0,0);
	delete mps;
        }
      break;    
    
    case 10112:          // -> eps
      if (mcurwin) {
        printf("Current Window to Postscript file piline.ps \n");
	mcurwin->PSPrint(mPS,0,0);
        }
      break;        

    case 10105:          // Sortie d'application
      Stop();
      break;

  }
return;
}


// ................................................................
//                   programme principal 
// ................................................................

int main(int narg, char *arg[])
{
if ( (narg > 1) && (strcmp(arg[1],"-h") == 0) ) {
  printf("pilinetst : LineDrawWdg  test \n");
  printf("  Usage : pilinetst [Xt options] \n");
  }
//  Creation de l'objet application et appel de Run()
PITApp* app = new PITApp(narg, arg);
// puts("appel de Application.Run() ... ");
app->Run();

delete app;
exit(0);
}


