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

#include "pisysdep.h"
#include PISTDWDG_H

#include "picontainerx.h"

// ------- Pb de gestion du focus-keyboard  Motif-PIBaseWdg -------
// ** Note du 26/02/98 - Reza 
// Je desactive pour le moment XmNnavigationType et XmNtraversalOn
// afin d'ameliorer la gestion du focus-keyboard entre Widget Motif
// et objet Peida - Cela semble avoir un effet secondaire - 
// Il faut que la souris reste dans le widget Text pour taper dedans
// ** Note du 30/04/98 - Reza
// J'ai modifie le mecanisme de gestion des evenements pour PIBaseWdg
// en passant par un EventHandler - Le probleme de gestion du 
// focus-keyboard n'a pour autant pas ete resolu
// Je reactive XmNtraversalOn pour les PIText - Le probleme 
// d'attribution du focus-keyboard au PIBaseWdg reste si on 
// met PIText et un PIBaseWdg ds un meme conteneur


/************* PILabelX ************/
#include <Xm/Label.h>


/* --Methode-- */
PILabelX::PILabelX(PIContainerGen *par, const char *nom,
                   int sx, int sy, int px, int py)
: PILabelGen(par, nom, sx, sy, px, py)
{
Arg warg[3];
int n = 0;
CreateXtWdg(nom, xmLabelWidgetClass, NULL, sx, sy, px, py);
SetBorderWidth(0);
XtSetArg(warg[n], XmNrecomputeSize, FALSE); n++;
XtSetArg(warg[n],XmNnavigationType,XmNONE);  n++;
XtSetArg(warg[n],XmNtraversalOn,FALSE);  n++;
XtSetValues(XtWdg(), warg, n);
Manage();
}

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

/* --Methode-- */
void PILabelX::SetLabel(string const& lab)
{
XmString xmstr;
xmstr = XmStringLtoRCreate((char *)lab.c_str(), XmSTRING_DEFAULT_CHARSET);
int n=0;
Arg warg[2];

XtSetArg(warg[n], XmNlabelString, xmstr); n++;
XtSetValues(XtWdg(), warg, n);
XmStringFree(xmstr);
return;
}


/************* PIButtonX ************/
#include <Xm/PushB.h>
#include <Xm/ArrowB.h>

// Fonctions privees (CallBack)
static void button_action(Widget w, XtPointer *usd, XtPointer *calld);
static void button_press(Widget w, XtPointer *usd, XmAnyCallbackStruct *calld);

/* Nouvelle-Fonction */
void  button_action(Widget , XtPointer *usd, XtPointer *)
{
PIButtonX *pib;
pib = (PIButtonX *) usd ;
pib->Send(pib->Msg(),PIMsg_Click,NULL);
return;
}

/* Nouvelle-Fonction */
void  button_press(Widget, XtPointer *usd, XmAnyCallbackStruct *calld)
{
PIButtonX *pib;
pib = (PIButtonX *) usd ;
pib->Send(pib->Msg(),PIMsg_Press,NULL);
pib->myevt = *(calld->event);
pib->myevt.type = pib->myevt.xbutton.type = ButtonRelease;
pib->myevt.xbutton.serial += 10;
PIXSetLastEventTimeSerial(calld->event->xbutton.time,  calld->event->xbutton.serial);

return;
}


/* --Methode-- */
PIButtonX::PIButtonX(PIContainerGen *par, const char *nom, PIMessage msg, 
                     int sx, int sy, int px, int py)
: PIButtonGen(par, nom, msg, sx, sy, px, py)
{

Arg  warg[6];
int n = 0;

XtSetArg(warg[n],XmNhighlightThickness, 0);  n++;
XtSetArg(warg[n], XmNrecomputeSize, FALSE);  n++;
XtSetArg(warg[n],XmNnavigationType,XmNONE);  n++;
XtSetArg(warg[n],XmNtraversalOn,FALSE);  n++;
CreateXtWdg(nom, xmPushButtonWidgetClass, NULL, sx, sy, px, py);

/*
if (bsgn == PIBtn_Label)
  CreateXtWdg(nom, xmPushButtonWidgetClass, NULL, sx, sy, px, py);
else
  {
  CreateXtWdg(nom, xmArrowButtonWidgetClass, NULL, sx, sy, px, py);
  switch (bsgn)
    {
    case PIBtn_ArrowUp :
      XtSetArg(warg[n], XmNarrowDirection, XmARROW_UP);  n++;
      break;
    case PIBtn_ArrowDown :
      XtSetArg(warg[n], XmNarrowDirection, XmARROW_DOWN);  n++;
      break;
    case PIBtn_ArrowLeft :
      XtSetArg(warg[n], XmNarrowDirection, XmARROW_LEFT);  n++;
      break;
    case PIBtn_ArrowRight :
      XtSetArg(warg[n], XmNarrowDirection, XmARROW_RIGHT);  n++;
      break;
    }
  }
*/
XtSetValues(XtWdg(), warg, n);
XtAddCallback(XtWdg(), XmNactivateCallback, 
              (XtCallbackProc)button_action, (XtPointer)this);

mAcP = false;
SetBorderWidth(0);
Manage();
}

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

/* --Methode-- */
void PIButtonX::SetLabel(string const& lab)
{
XmString xmstr;
xmstr = XmStringLtoRCreate((char *)lab.c_str(), XmSTRING_DEFAULT_CHARSET);
int n=0;
Arg warg[2];

XtSetArg(warg[n], XmNlabelString, xmstr); n++;
XtSetValues(XtWdg(), warg, n);
XmStringFree(xmstr);
return;
}

/* --Methode-- */
void PIButtonX::ActivatePress(bool acp)
{
if (mAcP == acp)  return; 
    
if (mAcP)
  XtRemoveCallback(XtWdg(), XmNarmCallback, 
                   (XtCallbackProc)button_press, (XtPointer)this);
else 
  XtAddCallback(XtWdg(), XmNarmCallback, 
                (XtCallbackProc)button_press, (XtPointer)this);
mAcP = acp;
return;
}       


/* --Methode-- */
void PIButtonX::ReleaseButton()
{
XPutBackEvent(myevt.xbutton.display, &myevt);
return;
}


/************* PITextX ************/
#include <Xm/Text.h>

/* --Methode-- */
PITextX::PITextX(PIContainerGen *par, const char *nom,
                 int sx, int sy, int px, int py)
: PITextGen(par, nom, sx, sy, px, py)
{
Arg warg[3];
int n = 0;
CreateXtWdg(nom, xmTextWidgetClass, NULL, sx, sy, px, py);
mtext = XtWdg();
XtSetArg(warg[n],XmNnavigationType,XmNONE);  n++;
// XtSetArg(warg[n],XmNtraversalOn,FALSE);  n++;
XtSetValues(mtext, warg, n);
SetMutiLineMode(false);
SetTextEditable(true);
Manage();
}

/* --Methode-- */
PITextX::PITextX(PIContainerGen *par, const char *nom, bool vsb, bool hsb,
                 int sx, int sy, int px, int py)
: PITextGen(par, nom, vsb, hsb, sx, sy, px, py)
{
Arg warg[10];
int n = 0;
XtSetArg(warg[n],XmNeditMode, XmMULTI_LINE_EDIT);  n++; 
XtSetArg(warg[n],XmNscrollBarDisplayPolicy, XmSTATIC); n++;
XtSetArg(warg[n],XmNnavigationType,XmNONE);  n++;
if (vsb) 
  XtSetArg(warg[n],XmNscrollHorizontal, True); n++;
if (hsb)
  XtSetArg(warg[n],XmNscrollVertical, True); n++;

// **ATTENTION** Il vaut mieux creer avec les bonnes tailles au depart Reza 09/99 
//     .....   C'est fait par CreateXtWdg( ... )

XtSetArg(warg[n],XmNwidth,sx);  n++;
XtSetArg(warg[n],XmNheight,sy);  n++;
XtSetArg(warg[n],XmNx,px);  n++;
XtSetArg(warg[n],XmNy,py);  n++;

// XtSetArg(warg[n],XmNtraversalOn,FALSE);  n++;

mtext = XmCreateScrolledText(((PIWdgX *)par)->XtWdg(), (char *)nom, warg, n);   // const_cast
XtManageChild(mtext);
XtWdg() = XtParent(mtext); 

// XtWdg() = mtext;   Modif Reza 09/99
// SetSize(sx, sy);
// SetPos(px, py);

wmis = k_wmi_normal ;
stmng = 0;

// **ATTENTION** A ne pas oublier , fait par CreateXtWdg Reza 09/99 
SetBinding(PIBK_free, PIBK_free, PIBK_free, PIBK_free);
par->ChildAdd(this);

SetTextEditable(true);
Manage();
}

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

/* --Methode-- */
void PITextX::SetText(string const& s)
{
XmTextSetString(mtext, (char *)s.c_str());
return;
}

/* --Methode-- */
string PITextX::GetText() const
{
char *txtb;
txtb = XmTextGetString(mtext);
string s(txtb);
XtFree(txtb);
return(s);
}

/* --Methode-- */
void PITextX::SetMutiLineMode(bool mlm)
{
Arg  warg[2];
int n = 0;

if (mlm)
  { XtSetArg(warg[n],XmNeditMode, XmMULTI_LINE_EDIT);  n++; }
else
  { XtSetArg(warg[n],XmNeditMode, XmSINGLE_LINE_EDIT);  n++; }

XtSetValues(mtext, warg, n);
return;
}

/* --Methode-- */
void PITextX::SetTextEditable(bool te)
{
Arg  warg[2];
int n = 0;

if (te)
  { XtSetArg(warg[n],XmNeditable, TRUE);  n++; }
else
  { XtSetArg(warg[n],XmNeditable, FALSE);  n++; }

XtSetValues(mtext, warg, n);
return;
}

// Fonction privee (CallBack)
static void text_action(Widget w, XtPointer *usd, XtPointer *calld);

void  text_action(Widget, XtPointer *usd, XtPointer *)
{
PIText *pit;

pit = (PIText *) usd ;
pit->Send(pit->Msg(), PIMsg_DataChanged, NULL);
}


/* --Methode-- */
void PITextX::SetMsg(PIMessage msg)
{

if (Msg() && !msg)
  XtRemoveCallback(mtext, XmNactivateCallback, 
                   (XtCallbackProc)text_action, (XtPointer)this);
if (!Msg() && msg)
  XtAddCallback(mtext, XmNactivateCallback, 
                (XtCallbackProc)text_action, (XtPointer)this);

PIWdg::SetMsg(msg);
}


/************* PICheckBoxX ************/
#include <Xm/ToggleB.h>

// Fonction prive (CallBack)
static void toggb_action(Widget w, XtPointer *usd, XmToggleButtonCallbackStruct* calld);

//  Variable globale d'etat de checkbox pour Send(...)
static bool toggb_state = false;

/* Nouvelle-Fonction */
void  toggb_action(Widget , XtPointer *usd, XmToggleButtonCallbackStruct* calld)
{
PICheckBoxX *picb;
picb = (PICheckBoxX *) usd ;
if (calld->set == True)   picb->mSt = true;
else picb->mSt = false;
toggb_state = picb->mSt;
picb->Send(picb->Msg(), PIMsg_DataChanged, (void *)(&toggb_state));
return;
}

/* --Methode-- */
PICheckBoxX::PICheckBoxX(PIContainerGen *par, const char *nom, PIMessage msg,
                         int sx, int sy, int px, int py)
: PICheckBoxGen(par, nom, msg, sx, sy, px, py)
{
CreateXtWdg(nom, xmToggleButtonWidgetClass, NULL, sx, sy, px, py);
XtAddCallback(XtWdg(), XmNvalueChangedCallback,
             (XtCallbackProc) toggb_action, (XtPointer)this);
Arg warg[4];
int n = 0;
XtSetArg(warg[n],XmNhighlightThickness, 0); n++;
XtSetArg(warg[n],XmNnavigationType,XmNONE);  n++;
XtSetArg(warg[n],XmNtraversalOn,FALSE);  n++;
XtSetValues(XtWdg(), warg, n);
SetState(false);
Manage();
}


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


/* --Methode-- */
void PICheckBoxX::SetState(bool st)
{
Arg warg[2];
mSt = st;
if (st) XtSetArg(warg[0],XmNset, True);
else XtSetArg(warg[0],XmNset, False);
XtSetValues(XtWdg(), warg, 1);
return;
}

/* --Methode-- */
bool PICheckBoxX::GetState()
{
return(mSt);
}


/************* PIScaleX ************/
#include <Xm/Scale.h>

// Fonction prive (CallBack)
static void scale_action(Widget w, XtPointer *usd, 
                         XmScaleCallbackStruct *calld);
// Variable globale pour contenir valeur de Scale a l'appel de Send;
static int scale_value=0;
 
void  scale_action(Widget, XtPointer *usd, 
                         XmScaleCallbackStruct *calld)
{
PIScale *pis;

pis = (PIScale *) usd ;
pis->CBSetVal(calld->value);
scale_value = calld->value;
pis->Send(pis->Msg(), PIMsg_DataChanged, (void *)(&scale_value));
return;
}

/* --Methode-- */
PIScaleX::PIScaleX(PIContainerGen *par, const char *nom, PIMessage msg,
                   int dir, int sx, int sy, int px, int py)
: PIScaleGen(par, nom, msg, dir, sx, sy, px, py)
{
int n=0;
Arg warg[8];
XtSetArg(warg[n], XmNshowValue, TRUE); n++;
XtSetArg(warg[n],XmNnavigationType,XmNONE);  n++;
XtSetArg(warg[n],XmNtraversalOn,FALSE);  n++;
if (dir == kSDirLtoR) {
  XtSetArg(warg[n], XmNorientation, XmHORIZONTAL); n++;
  XtSetArg(warg[n], XmNprocessingDirection, XmMAX_ON_RIGHT); n++;
  }
else if (dir == kSDirRtoL) {
  XtSetArg(warg[n], XmNorientation, XmHORIZONTAL); n++;
  XtSetArg(warg[n], XmNprocessingDirection, XmMAX_ON_LEFT); n++;
  }
else if (dir == kSDirDownUp) {
  XtSetArg(warg[n], XmNorientation, XmVERTICAL); n++;
  XtSetArg(warg[n], XmNprocessingDirection, XmMAX_ON_TOP); n++;
  }
else { // kSDirUpDown
  XtSetArg(warg[n], XmNorientation, XmVERTICAL); n++;
  XtSetArg(warg[n], XmNprocessingDirection, XmMAX_ON_BOTTOM); n++;
  }
// Il ne faut pas attribuer une valeur a XmNscaleWidth et XmNscaleHeight
// Elles sont calculees automatiquement et repondent alors correctement aux resize
// (Il faut laisser donc leur valeur par defaut=0)   Reza 28/10/98 
// XtSetArg(warg[n], XmNscaleWidth, sx); n++;
// XtSetArg(warg[n], XmNscaleHeight, sy); n++;
// XtSetArg(warg[n], XmNstringDirection, XmSTRING_DIRECTION_R_TO_L); n++;
CreateXtWdg(nom, xmScaleWidgetClass, NULL, sx, sy, px, py, warg, n);

SetMinMax(1, 100);
SetValue(1);

XtAddCallback(XtWdg(), XmNvalueChangedCallback, 
             (XtCallbackProc) scale_action, (XtPointer)this);
Manage();
}

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

/* --Methode-- */
void PIScaleX::SetMinMax(int min, int max)
{
if (min >= max)  max = min+10;
if (mVal < min)  mVal = min;
if (mVal > max)  mVal = max;
int n=0;
Arg warg[3];
XtSetArg(warg[n], XmNminimum, min); n++;
XtSetArg(warg[n], XmNmaximum, max); n++;
XtSetArg(warg[n], XmNvalue, mVal); n++;
XtSetValues(XtWdg(), warg, n);
mMin = min;   mMax = max;
return;
}

/* --Methode-- */
void PIScaleX::GetMinMax(int& min, int& max)
{
min = mMin;   max = mMax;
return;
}

/* --Methode-- */
void PIScaleX::SetValue(int val)
{
int n=0;
if (val < mMin)  val = mMin;
if (val > mMax)  val = mMax;
Arg warg[2];
XtSetArg(warg[n], XmNvalue, val); n++;
XtSetValues(this->sdw, warg, n);
return;
}

/* --Methode-- */
int  PIScaleX::GetValue()
{
int val;
int n=0;
Arg warg[2];
XtSetArg(warg[n], XmNvalue, &val); n++;
XtGetValues(this->sdw, warg, n);
mVal = val;
return(mVal);
}

/* --Methode-- */
void  PIScaleX::CBSetVal(int val)
{
mVal = val;
return;
}



/************* PIScrollBarX ************/

#include <Xm/ScrollBar.h>

// Fonction prive (CallBack)
static void scrollbar_action(Widget w, XtPointer *usd, 
                             XmScrollBarCallbackStruct *calld);
static void scrollbar_drag(Widget w, XtPointer *usd, 
                           XmScrollBarCallbackStruct *calld);
// Variable globale pour contenir valeur de Scale a l'appel de Send;
static int scroll_value=0;

void  scrollbar_action(Widget, XtPointer *usd, 
                       XmScrollBarCallbackStruct *calld)
{
PIScrollBar *pis;

pis = (PIScrollBar *) usd ;
pis->CBSetVal(calld->value);
pis->Send(pis->Msg(), PIMsg_DataChanged, (void *)(&scroll_value));
return;
}

void  scrollbar_drag(Widget, XtPointer *usd, 
                       XmScrollBarCallbackStruct *calld)
{
PIScrollBar *pis;

pis = (PIScrollBar *) usd ;
pis->CBSetVal(calld->value);
pis->Send(pis->Msg(), PIMsg_Drag, (void *)(&scroll_value));
return;
}

/* --Methode-- */
PIScrollBarX::PIScrollBarX(PIContainerGen *par, const char *nom, PIMessage msg,
                           int dir, int sx, int sy, int px, int py)
: PIScrollBarGen(par, nom, msg, dir, sx, sy, px, py)
{
int n=0;
Arg warg[6];

XtSetArg(warg[n],XmNnavigationType,XmNONE);  n++;
XtSetArg(warg[n],XmNtraversalOn,FALSE);  n++;
if (dir == kSDirLtoR) {
  XtSetArg(warg[n], XmNorientation, XmHORIZONTAL); n++;
  XtSetArg(warg[n], XmNprocessingDirection, XmMAX_ON_RIGHT); n++;
  }
else if (dir == kSDirRtoL) {
  XtSetArg(warg[n], XmNorientation, XmHORIZONTAL); n++;
  XtSetArg(warg[n], XmNprocessingDirection, XmMAX_ON_LEFT); n++;
  }
else if (dir == kSDirDownUp) {
  XtSetArg(warg[n], XmNorientation, XmVERTICAL); n++;
  XtSetArg(warg[n], XmNprocessingDirection, XmMAX_ON_TOP); n++;
  }
else { // kSDirUpDown
  XtSetArg(warg[n], XmNorientation, XmVERTICAL); n++;
  XtSetArg(warg[n], XmNprocessingDirection, XmMAX_ON_BOTTOM); n++;
  }
CreateXtWdg(nom, xmScrollBarWidgetClass, NULL, sx, sy, px, py, warg, n);
mAcD = false;
mVal = -1;
mMin = mMax = 0;
mSz = 10;
mDir = dir;
SetMinMax(1, 100);
SetSlSize(10);
SetValue(1);
XtAddCallback(XtWdg(), XmNvalueChangedCallback, 
             (XtCallbackProc) scrollbar_action, (XtPointer)this);
Manage();
}

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


/* --Methode-- */
void PIScrollBarX::ActivateDrag(bool acd)
{
if (mAcD == acd)  return; 
    
if (mAcD)
  XtRemoveCallback(XtWdg(), XmNdragCallback, 
                   (XtCallbackProc)scrollbar_drag, (XtPointer)this);
else 
  XtAddCallback(XtWdg(), XmNdragCallback, 
                (XtCallbackProc)scrollbar_drag, (XtPointer)this);
mAcD = acd;
return;
}       

/* --Methode-- */
void PIScrollBarX::SetMinMax(int min, int max)
{
if (min >= max)  max = min+100;
if (mVal < min)  mVal = min;
if (mVal > max-mSz)  mVal = max-mSz;
//DBG printf("PIScrollBarX::SetMinMax(%d %d )  %d  Sz=%d \n", min, max, mVal, mSz);
int n=0;
Arg warg[3];
XtSetArg(warg[n], XmNminimum, min); n++;
XtSetArg(warg[n], XmNmaximum, max); n++;
XtSetArg(warg[n], XmNvalue, mVal); n++;
XtSetValues(XtWdg(), warg, n);
mMin = min;   mMax = max;
//DBG printf("--OUT-OF-- PIScrollBarX::SetMinMax(%d %d )  %d  Sz=%d \n", min, max, mVal, mSz);
return;
}

/* --Methode-- */
void PIScrollBarX::GetMinMax(int& min, int& max)
{
min = mMin;   max = mMax;
return;
}

/* --Methode-- */
void PIScrollBarX::SetValue(int val)
{
int n=0;
if (val < mMin)  val = mMin;
if (val > mMax-mSz)  val = mMax-mSz;
Arg warg[2];
//DBG printf("PIScrollBarX::SetValue(%d -> %d) \n", val, val0);
XtSetArg(warg[n], XmNvalue, val); n++;
XtSetValues(this->sdw, warg, n);
mVal = val;
//DBG printf("--OUT-OF---PIScrollBarX::SetValue(%d -> %d) \n", val, val0);
return;
}

/* --Methode-- */
int  PIScrollBarX::GetValue()
{
int val;
int n=0;
Arg warg[2];
XtSetArg(warg[n], XmNvalue, &val); n++;
XtGetValues(this->sdw, warg, n);
mVal = val;
return(mVal);
}

/* --Methode-- */
void PIScrollBarX::SetSlSize(int sz)
{
int n=0;
Arg warg[4];
int szl;

szl = mMax-mMin;
if (sz > szl)  sz = szl;
szl /= 100;
if (szl < 1)  szl = 1;
if (sz < szl)  sz = szl;
szl = sz/10;
if (szl < 1)  szl = 1;
//DBG printf("PIScrollBarX::SetSlSize(%d ) \n", sz);
XtSetArg(warg[n], XmNsliderSize, sz); n++;
XtSetArg(warg[n], XmNpageIncrement, sz); n++;
XtSetArg(warg[n], XmNincrement, szl); n++;
if (mVal < mMin)  mVal = mMin;
if (mVal > mMax-sz)  mVal = mMax-sz;
XtSetArg(warg[n], XmNvalue, mVal); n++;
XtSetValues(this->sdw, warg, n);
//DBG printf("---OUT-OF---PIScrollBarX::SetSlSize(%d ) -> mVal= %d (cv1,2=%d %d)\n", sz,mVal, cv1, cv2);
mSz = sz;
return;
}

/* --Methode-- */
int  PIScrollBarX::GetSlSize()
{
int sz;
int n=0;
Arg warg[2];
XtSetArg(warg[n], XmNsliderSize, &sz); n++;
XtGetValues(this->sdw, warg, n);
mSz = sz;
return(mSz);
}


/* --Methode-- */
void  PIScrollBarX::CBSetVal(int val)
{
mVal = val;
scroll_value = mVal;
//DBG printf("PIScrollBarX::CBSetVal(%d) %d -> %d \n", mDir, val, mVal);
return;
}

