/**************************************************************************

    This file is part of xcpaint, a pixmap editor for xclass
    Copyright (C) 1997, Hector Peraza.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

**************************************************************************/

#include "OXDialogs.h"


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

OXSizeDialog::OXSizeDialog(const OXWindow *p, const OXWindow *main,
                           int w, int h, unsigned long options,
                           int dlg_type, int *retw, int *reth) :
  OXTransientFrame(p, main, w, h, options) {
    int i, ax, ay;
    Window wdummy;  

    _dlgType = dlg_type;

    ret_width  = retw;
    ret_height = reth;

    ChangeOptions((GetOptions() & ~VERTICAL_FRAME) | HORIZONTAL_FRAME);
  
    _f1 = new OXCompositeFrame(this, 60, 20, VERTICAL_FRAME | FIXED_WIDTH);
    _f2 = new OXCompositeFrame(this, 60, 20, HORIZONTAL_FRAME);

    _f2->SetLayoutManager(new O2ColsLayout(_f2, 5));

    _okButton = new OXTextButton(_f1, new OHotString("&OK"), ID_OK);
    _cancelButton = new OXTextButton(_f1, new OHotString("&Cancel"), ID_CANCEL);

    _f1->Resize(_okButton->GetDefaultWidth()+40, GetDefaultHeight());
              
    _okButton->Associate(this);
    _cancelButton->Associate(this);
              
    _l1 = new OLayoutHints(LHINTS_TOP | LHINTS_EXPAND_X, 2, 2, 0, 3);
    _l2 = new OLayoutHints(LHINTS_TOP | LHINTS_RIGHT, 5, 5, 15, 10);
    _l3 = new OLayoutHints(LHINTS_TOP | LHINTS_LEFT, 10, 10, 15, 15);

    _f1->AddFrame(_okButton, _l1);
    _f1->AddFrame(_cancelButton, _l1);
    AddFrame(_f1, _l2);

    _widthLabel  = new OXLabel(_f2, new OHotString("&Width:"));
    _heightLabel = new OXLabel(_f2, new OHotString("&Height:"));

    _widthTE = new OXTextEntry(_f2, _widthTB = new OTextBuffer(10));
    _widthTE->Associate(this);
    _widthTE->Resize(60, _widthTE->GetDefaultHeight());

    _heightTE = new OXTextEntry(_f2, _heightTB = new OTextBuffer(10));
    _heightTE->Associate(this);
    _heightTE->Resize(60, _heightTE->GetDefaultHeight());

    if (ret_width) {
      char tmp[20];
      sprintf(tmp, "%d", *ret_width);
      _widthTB->AddText(0, tmp);
    }
    if (ret_height) {
      char tmp[20];
      sprintf(tmp, "%d", *ret_height);
      _heightTB->AddText(0, tmp);
    }

    _f2->AddFrame(_widthLabel, NULL);
    _f2->AddFrame(_widthTE, NULL);
    _f2->AddFrame(_heightLabel, NULL);
    _f2->AddFrame(_heightTE, NULL);
    AddFrame(_f2, _l3);

    SetMWMHints(MWM_DECOR_ALL | MWM_DECOR_MAXIMIZE | MWM_DECOR_MENU,
              MWM_FUNC_ALL | MWM_FUNC_MAXIMIZE | MWM_FUNC_RESIZE,
              MWM_INPUT_MODELESS);
    MapSubwindows();
    Resize(GetDefaultSize());
    
    // position relative to the parent's window
    XTranslateCoordinates(GetDisplay(),
                          main->GetId(), GetParent()->GetId(),
                          (((OXFrame *) main)->GetWidth() - _w) >> 1,
                          (((OXFrame *) main)->GetHeight() - _h) >> 1,
                          &ax, &ay, &wdummy);
    Move(ax, ay);

    switch (_dlgType) {
      case DIALOG_RESIZE:    SetWindowName("Resize image to..."); break;
      case DIALOG_RESCALE:   SetWindowName("Rescale image to..."); break;
      case DIALOG_NEW_IMAGE: SetWindowName("Create new image..."); break;
    }

    MapWindow();
    _client->WaitFor(this);
}
    
OXSizeDialog::~OXSizeDialog() {
  delete _okButton;
  delete _cancelButton;
  delete _widthTE; delete _widthLabel;    
  delete _heightTE; delete _heightLabel;    
  delete _f2; delete _f1;
  delete _l1; delete _l2; delete _l3;
}

void OXSizeDialog::CloseWindow() {
  if (ret_width) *ret_width = -1;
  if (ret_height) *ret_height = -1;
  delete this;
}

int OXSizeDialog::ProcessMessage(long msg, long parm1, long parm2) {
  const char *str;
          
  switch(GET_MSG(msg)) {
    case XC_COMMAND:
        
      switch(GET_SUBMSG(msg)) {
        case CM_BUTTON:
          switch(parm1) {
            case ID_OK:
              str = _widthTB->GetString();
              if (ret_width) *ret_width = atoi(str);
              str = _heightTB->GetString();
              if (ret_height) *ret_height = atoi(str);
              delete this;
              break;

            case ID_CANCEL:
              if (ret_width) *ret_width = -1;
              if (ret_height) *ret_height = -1;
              delete this;
              break;
          }
          break;

        default:
          break;
      }
      break;  
    
    default:
      break;
  }

  return True;
}         

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

OXTextDialog::OXTextDialog(const OXWindow *p, const OXWindow *main,
                           int w, int h, unsigned long options,
                           char *rtxt, char *rfnt) :
  OXTransientFrame(p, main, w, h, options) {
    int i, ax, ay;
    Window wdummy;  

    ret_text = rtxt;
    ret_font = rfnt;

    ChangeOptions((GetOptions() & ~VERTICAL_FRAME) | HORIZONTAL_FRAME);
  
    _f1 = new OXCompositeFrame(this, 60, 20, VERTICAL_FRAME | FIXED_WIDTH);
    _f2 = new OXCompositeFrame(this, 60, 20, HORIZONTAL_FRAME);

    _f2->SetLayoutManager(new O2ColsLayout(_f2, 5));

    _okButton = new OXTextButton(_f1, new OHotString("&OK"), ID_OK);
    _cancelButton = new OXTextButton(_f1, new OHotString("&Cancel"), ID_CANCEL);

    _f1->Resize(_okButton->GetDefaultWidth()+40, GetDefaultHeight());
              
    _okButton->Associate(this);
    _cancelButton->Associate(this);
              
    _l1 = new OLayoutHints(LHINTS_TOP | LHINTS_EXPAND_X, 2, 2, 0, 3);
    _l2 = new OLayoutHints(LHINTS_TOP | LHINTS_RIGHT, 5, 5, 15, 10);
    _l3 = new OLayoutHints(LHINTS_TOP | LHINTS_LEFT, 10, 10, 15, 15);

    _f1->AddFrame(_okButton, _l1);
    _f1->AddFrame(_cancelButton, _l1);
    AddFrame(_f1, _l2);

    _textLabel  = new OXLabel(_f2, new OHotString("&Text:"));
    _fontLabel = new OXLabel(_f2, new OHotString("&Font:"));

    _textTE = new OXTextEntry(_f2, _textTB = new OTextBuffer(200));
    _textTE->Associate(this);
    _textTE->Resize(200, _textTE->GetDefaultHeight());

    _fontTE = new OXTextEntry(_f2, _fontTB = new OTextBuffer(200));
    _fontTE->Associate(this);
    _fontTE->Resize(200, _fontTE->GetDefaultHeight());

    if (ret_text) _textTB->AddText(0, ret_text);
    if (ret_font) _fontTB->AddText(0, ret_font);

    _f2->AddFrame(_textLabel, NULL);
    _f2->AddFrame(_textTE, NULL);
    _f2->AddFrame(_fontLabel, NULL);
    _f2->AddFrame(_fontTE, NULL);
    AddFrame(_f2, _l3);

    SetMWMHints(MWM_DECOR_ALL | MWM_DECOR_MAXIMIZE | MWM_DECOR_MENU,
              MWM_FUNC_ALL | MWM_FUNC_MAXIMIZE | MWM_FUNC_RESIZE,
              MWM_INPUT_MODELESS);
    MapSubwindows();
    Resize(GetDefaultSize());
    
    // position relative to the parent's window
    XTranslateCoordinates(GetDisplay(),
                          main->GetId(), GetParent()->GetId(),
                          (((OXFrame *) main)->GetWidth() - _w) >> 1,
                          (((OXFrame *) main)->GetHeight() - _h) >> 1,
                          &ax, &ay, &wdummy);
    Move(ax, ay);

    SetWindowName("Enter text...");

    MapWindow();
    _client->WaitFor(this);
}

OXTextDialog::~OXTextDialog() {
  delete _okButton;
  delete _cancelButton;
  delete _textTE; delete _textLabel;    
  delete _fontTE; delete _fontLabel;    
  delete _f2; delete _f1;
  delete _l1; delete _l2; delete _l3;
}

void OXTextDialog::CloseWindow() {
  if (ret_text) *ret_text = '\0';
  if (ret_font) *ret_font = '\0';
  delete this;
}

int OXTextDialog::ProcessMessage(long msg, long parm1, long parm2) {
  const char *str;
          
  switch(GET_MSG(msg)) {
    case XC_COMMAND:
        
      switch(GET_SUBMSG(msg)) {
        case CM_BUTTON:
          switch(parm1) {
            case ID_OK:
              str = _textTB->GetString();
              if (ret_text) strcpy(ret_text, str);
              str = _fontTB->GetString();
              if (ret_font) strcpy(ret_font, str);
              delete this;
              break;

            case ID_CANCEL:
              if (ret_text) *ret_text = '\0';
              if (ret_font) *ret_font = '\0';
              delete this;
              break;
          }
          break;

        default:
          break;
      }
      break;  
    
    default:
      break;
  }

  return True;
}         

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

O2ColsLayout::O2ColsLayout(OXCompositeFrame *main, int sep) {
  _main = main;
  _list = _main->GetListAddr();
  _sep  = sep;
}

void O2ColsLayout::Layout() {
  ODimension csize, c1size(0,0), c2size(0,0);
  int x = 0, y = 0, h, count = 0;
  SListFrameElt *ptr;

  for (ptr=*_list; ptr != NULL; ptr=ptr->next) {
    ++count;
    csize = ptr->frame->GetDefaultSize();
    c1size.w = max(c1size.w, csize.w);
    c1size.h = max(c1size.h, csize.h);
    ptr = ptr->next;
    if (ptr == NULL) break;
    csize = ptr->frame->GetDefaultSize();
    c2size.w = max(c2size.w, csize.w);
    c2size.h = max(c2size.h, csize.h);
  }

  h = max(c1size.h, c2size.h);

  for (ptr=*_list; ptr != NULL; ptr=ptr->next) {
    csize = ptr->frame->GetDefaultSize();
    ptr->frame->Move(x, y+((h-csize.h)>>1));
    ptr->frame->Layout();
    ptr = ptr->next;
    if (ptr == NULL) break;
    csize = ptr->frame->GetDefaultSize();
    ptr->frame->Move(x+_sep+c1size.w, y+((h-csize.h)>>1));
    ptr->frame->Layout();
    y += h+_sep;
  }
}

ODimension O2ColsLayout::GetDefaultSize() const {
  ODimension size, csize, c1size(0,0), c2size(0,0);
  int count = 0;
  SListFrameElt *ptr;

  for (ptr=*_list; ptr != NULL; ptr=ptr->next) {
    ++count;
    csize = ptr->frame->GetDefaultSize();
    c1size.w = max(c1size.w, csize.w);
    c1size.h = max(c1size.h, csize.h);
    ptr = ptr->next;
    if (ptr == NULL) break;
    csize = ptr->frame->GetDefaultSize();
    c2size.w = max(c2size.w, csize.w);
    c2size.h = max(c2size.h, csize.h);
  }

  size.w = c1size.w + _sep + c2size.w;
  size.h = (max(c1size.h, c2size.h) + _sep) * count;

  return size;
}
