#include <stdlib.h>
#include <stdio.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


/*  Exemple d'utilisation PIBaseWdg - 
    Creation d'une nouvelle composante graphique  */

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

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

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

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

private:
  struct rect {
    PIGrCoord x,y;
    PIGrCoord dx,dy;
    PIColors col;
  };
  typedef list<rect> RectList;  // Liste de rectangles
  RectList rlist;
  int mcol;
  int x1, x2, y1, y2;
};


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

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

{
mcol = 0;  // numero de couleur
x1 = x2 = y1 = y2 = 0;
ActivateKeyboard();  
ActivateButton(1);
ActivateMove(1);     
}

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

/* --Methode-- */
void ExBWdg::Draw(PIGraphicGen* g, int /*x0*/, int /*y0*/, int /*dx*/, int /*dy*/)
{
EraseWindow();
g->SelForeground(PI_Black);
g->SelFont(PI_NormalSizeFont, PI_BoldFont);
g->DrawString(10,20,"Button-1 to draw rectangles ");
g->DrawString(10,40,"<Alt>C to clear all ");

RectList::iterator it;

//  Boucle sur les rectangles
for (it = rlist.begin(); it != rlist.end(); it++) {
  g->SelForeground((*it).col);  // selection couleur
  g->DrawFBox((*it).x, (*it).y, (*it).dx, (*it).dy );  // trace de rectangle 
  }
return;
}

static PIColors collist[15] = {
                 PI_Black, PI_Grey,
                 PI_Red, PI_Blue, PI_Green,  
                 PI_Yellow, PI_Magenta, 
                 PI_Cyan, PI_Turquoise, PI_NavyBlue, 
                 PI_Orange, PI_SiennaRed, PI_Purple,  
                 PI_LimeGreen, PI_Gold };

static char strbuff[128];
/* --Methode-- */
void ExBWdg::But1Press(int x, int y)
{
SelPointerShape(PI_CrossPointer);
// Initialisation pour trace d'un rectangle elastique  (en mode XOR)
mWGrC->SelForeground(PI_Magenta);
mWGrC->SelGOMode(PI_GOXOR);
mWGrC->SelLine(PI_ThinLine);
x1 = x2 = x;
y1 = y2 = y;
return;
}
/* --Methode-- */
void ExBWdg::Ptr1Move(int x, int y)
{
// On efface le rectangle 
mWGrC->DrawBox(x1, y1, x2-x1, y2-y1);
x2 = x;   y2 = y;
// On trace le nouveau
mWGrC->DrawBox(x1, y1, x2-x1, y2-y1);
}

/* --Methode-- */
void ExBWdg::But1Release(int x, int y)
{
SelPointerShape(PI_ArrowPointer);
// On efface le rectangle 
mWGrC->DrawBox(x1, y1, x2-x1, y2-y1);
mWGrC->SelGOMode(PI_GOCopy);
// On ajoute le rectangle dans la liste
rect r;
r.col = collist[mcol];
mcol = (mcol+1)%15;  
r.x = x1; r.y = y1;  r.dx = x-x1;  r.dy = y-y1;
rlist.push_back(r);
mWGrC->SelForeground(r.col);
mWGrC->DrawFBox(r.x, r.y, r.dx, r.dy);
return;
}

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

if ( (kmod == PIKM_Alt) && ( (key == 'c') || (key == 'C') ) ) {
// On efface tout 
  rlist.erase(rlist.begin(), rlist.end());
// On rafraichit la fenetre
  Refresh();
}
return;
}


//  ----- Declaration de notre classe PIApplication (PITApp) -------
//  ----------- PIApplication (PITApp) class declaration -----------

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;
  PILabel *lab;
};




/* ........................................................... */
/*               Classe PITApp (methodes)                      */
/* ........................................................... */


/* --Methode-- */
PITApp::PITApp(int narg, char* arg[])
: PIApplication(250, 60, 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 menu  
m = new PIMenu(Menubar(),"Fichier");
m->AppendItem("New BaseWdg", 10101);
m->AppendItem("Exit", 10105);
// On accroche le menu au Menubar
AppendMenu(m);
// Creation d' un label
lab = new PILabel(this->MainWin(), "xp2 - PI New Widget creation", 240, 40, 5, 10);


SetReady();
}

/* --Methode-- */
PITApp::~PITApp()
{
delete m; 
delete lab; 
}  

static int nbwin = 0;
/* --Methode-- */
void PITApp::Process(PIMessage msg, PIMsgHandler* sender, void* /*data*/)
{
// Gestion des actions en fonctions des messages
switch(UserMsg(msg))    {

    case 10101:     // On cree une fenetre et une ExBWdg et on les affiche
      {
      nbwin++;
      char strg[64];
      sprintf(strg,"Window %d - ExBwdg", nbwin);
      PIWindow* wp = new PIWindow(this, strg, PIWK_normal,  250, 250, 150, 150);
      wp->SetAutoDelChilds(true);
      ExBWdg* exb  = new ExBWdg(wp, "bwdg", 250, 250, 0, 0);
      exb->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_fixed,PIBK_fixed);
      wp->Show();
      }
      break;

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

    default :
     break;
    
  }
return;
}


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

int main(int narg, char *arg[])
{
if ( (narg > 1) && (strcmp(arg[1],"-h") == 0) ) {
  printf("xp0 : simple PI example program \n");
  printf("  Usage : xp0 [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);
}



