/***************************************************************************
                      kstcurvedialog_i.cpp  -  Part of KST
                             -------------------
    begin                :
    copyright            : (C) 2003 The University of Toronto
                           (C) 2003 C. Barth Netterfield
    email                :
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

// include files for Qt

// include files for KDE
#include <kcombobox.h>
#include <kdebug.h>
#include <kmessagebox.h>

// application specific includes
#include "curveappearancewidget.h"
#include "curveplacementwidget.h"
#include "kstcurvedialog_i.h"
#include "kstviewwindow.h"
#include "vectorselector.h"

#define DIALOGTYPE KstCurveDialogI
#define DTYPE "Curve"
#include "dataobjectdialog.h"

static const QString& defaultTag = KGlobal::staticQString("<Auto Name>");

KstCurveDialogI *KstCurveDialogI::_inst = 0L;
static KStaticDeleter<KstCurveDialogI> _cuInst;

KstCurveDialogI *KstCurveDialogI::globalInstance() {
  if (!_inst) {
    _inst = _cuInst.setObject(new KstCurveDialogI);
  }
return _inst;
}


KstCurveDialogI::KstCurveDialogI(QWidget* parent,
                                 const char* name, bool modal, WFlags fl)
  : KstCurveDialog(parent, name, modal, fl) {
  Init();

  connect(_xVector, SIGNAL(newVectorCreated(const QString&)),
          this, SIGNAL(modified()));
  connect(_yVector, SIGNAL(newVectorCreated(const QString&)),
          this, SIGNAL(modified()));
  connect(_xError, SIGNAL(newVectorCreated(const QString&)),
          this, SIGNAL(modified()));
  connect(_yError, SIGNAL(newVectorCreated(const QString&)),
          this, SIGNAL(modified()));

  _xError->provideNoneVector(true);
  _yError->provideNoneVector(true);
}

KstCurveDialogI::~KstCurveDialogI() {
  DP = 0L;
}

KstVCurvePtr KstCurveDialogI::_getPtr(const QString &tagin) {
  KstVCurveList c = kstObjectSubList<KstDataObject, KstVCurve>(KST::dataObjectList);

  // Will be null if not found
  return *c.findTag(tagin);
}

void KstCurveDialogI::updateWindow() {
  _curvePlacement->update();
}

void KstCurveDialogI::_fillFieldsForEdit() {
  if ( DP == 0L ) {
    return; // shouldn't be needed
  }

  DP->readLock();

  _tagName->setText(DP->tagName());

  _xVector->setSelection(DP->xVTag());
  _yVector->setSelection(DP->yVTag());
  _xError->setSelection(DP->xETag());
  _yError->setSelection(DP->yETag());

  //_curveAppearance->set(DP);
  _curveAppearance->setValue(DP->hasLines(), DP->hasPoints(), 
			     DP->hasBars(), DP->color(),
			     DP->Point.type(), DP->lineWidth(), 
			     DP->lineStyle(), DP->barStyle());
  
  DP->readUnlock();

  _curvePlacement->hide();

  adjustSize();
  resize(minimumSizeHint());
  setFixedHeight(height());
}

void KstCurveDialogI::_fillFieldsForNew() {
  KstVCurveList curves =
    kstObjectSubList<KstDataObject, KstVCurve>(KST::dataObjectList);

  /* set tag name */
  _tagName->setText(defaultTag);

  /* set the curve placement window  */
  _curvePlacement->update();

  //for some reason the lower widget needs to be shown first to prevent overlapping?
  _curveAppearance->hide();
  _curvePlacement->show();
  _curveAppearance->show();
  _curveAppearance->reset();

  adjustSize();
  resize(minimumSizeHint());
  setFixedHeight(height());
}

void KstCurveDialogI::update() {
  _curvePlacement->update();
  _xVector->update();
  _yVector->update();
  _xError->update();
  _yError->update();
}

bool KstCurveDialogI::new_I() {
  //KstWriteLocker ml(&KST::vectorList.lock());
  if (_xVector->selectedVector().isEmpty() ||
      _yVector->selectedVector().isEmpty()) {
    KMessageBox::sorry(this, i18n("New curve not made: define vectors first."));
    return false;
  }

  KstVectorList::Iterator VX, VY;
  KstVectorList::Iterator EX, EY;

  /* find VX and VY */
  KST::vectorList.lock().readLock();
  VX = KST::vectorList.findTag(_xVector->selectedVector());
  VY = KST::vectorList.findTag(_yVector->selectedVector());
  EX = KST::vectorList.findTag(_xError->selectedVector());
  EY = KST::vectorList.findTag(_yError->selectedVector());
  if (VX == KST::vectorList.end() || VY == KST::vectorList.end()) {
    kdFatal() << "Bug in kst: the XVector field in plotDialog refers to "
              << "a non existant vector...." << endl;
  }

  // readlock the vectors, bercause when we update the curve, they get read
  KstReadLocker rl1(*VX), rl2(*VY);
  bool haveEx = (EX != KST::vectorList.end());
  bool haveEy = (EY != KST::vectorList.end());
  if (haveEx) {
    (*EX)->readLock();
  }
  if (haveEy) {
    (*EY)->readLock();
  }

  QString tag_name = _tagName->text();
  if (tag_name == defaultTag) {
    tag_name = KST::suggestCurveName((*VY)->tagName());
  }

  /* verify that the curve name is unique */
  if (KST::dataTagNameNotUnique(tag_name)) {
    _tagName->setFocus();
    KST::vectorList.lock().readUnlock();
    if (haveEx) {
      (*EX)->readUnlock();
    }
    if (haveEy) {
      (*EY)->readUnlock();
    }
    return false;
  }

  /* create the curve */
  KstVCurvePtr curve = new KstVCurve(tag_name, *VX, *VY,
                        haveEx ? *EX : KstVectorPtr(0L),
                        haveEy ? *EY : KstVectorPtr(0L),
                        _curveAppearance->color());
  KST::vectorList.lock().readUnlock();

  curve->setHasPoints(_curveAppearance->showPoints());
  curve->setHasLines(_curveAppearance->showLines());
  curve->setHasBars(_curveAppearance->showBars());
  curve->setLineWidth(_curveAppearance->lineWidth());
  curve->setLineStyle(_curveAppearance->lineStyle());
  curve->Point.setType(_curveAppearance->pointType());
  curve->setBarStyle(_curveAppearance->barStyle());
  if (_curvePlacement->existingPlot() || _curvePlacement->newPlot()) {

    KstViewWindow *w = dynamic_cast<KstViewWindow*>(KstApp::inst()->findWindow(_curvePlacement->_plotWindow->currentText()));
    if (!w) {
      QString n = KstApp::inst()->newWindow(KST::suggestWinName());
      w = static_cast<KstViewWindow*>(KstApp::inst()->findWindow(n));
    }
    if (w) {
      Kst2DPlotPtr plot;
      if (_curvePlacement->existingPlot()) {
        /* assign curve to plot */
        plot = kst_cast<Kst2DPlot>(w->view()->findChild(_curvePlacement->plotName()));
        if (plot) {
          plot->addCurve(curve.data());
          w->view()->paint(P_DATA);
        }
      }

      if (_curvePlacement->newPlot()) {
        /* assign curve to plot */
        QString name = w->createPlot<Kst2DPlot>(KST::suggestPlotName());
        plot = kst_cast<Kst2DPlot>(w->view()->findChild(name));
        if (_curvePlacement->reGrid()) {
          w->view()->cleanup(_curvePlacement->columns());
        }
        if (plot) {
          _curvePlacement->update();
          _curvePlacement->setCurrentPlot(plot->tagName());
          plot->addCurve(curve.data());
          plot->GenerateDefaultLabels();
          w->view()->paint(P_DATA);
        }
      }
    }
  }

  if (haveEx) {
    (*EX)->readUnlock();
  }
  if (haveEy) {
    (*EY)->readUnlock();
  }

  KST::dataObjectList.lock().writeLock();
  KST::dataObjectList.append(curve.data());
  KST::dataObjectList.lock().writeUnlock();

  curve = 0L; // drop the reference
  emit modified();
  return true;
}

bool KstCurveDialogI::edit_I() {
  bool rc = false;

  DP->writeLock();

  /* verify that the curve name is unique */
  if (_tagName->text() != DP->tagName() && KST::dataTagNameNotUnique(_tagName->text())) {
    _tagName->setFocus();
  } else {
    DP->setTagName(_tagName->text());

    { // leave this scope here to destroy the iterator
      KstReadLocker ml(&KST::vectorList.lock());
      KstVectorList::Iterator it = KST::vectorList.findTag(_xVector->selectedVector());
      if (it != KST::vectorList.end()) {
        DP->setXVector(*it);
      }

      it = KST::vectorList.findTag(_yVector->selectedVector());
      if (it != KST::vectorList.end()) {
        DP->setYVector(*it);
      }

      it = KST::vectorList.findTag(_xError->selectedVector());
      DP->setXError(*it);

      it = KST::vectorList.findTag(_yError->selectedVector());
      DP->setYError(*it);
    }

    DP->setColor(_curveAppearance->color());
    DP->setHasPoints(_curveAppearance->showPoints());
    DP->setHasLines(_curveAppearance->showLines());
    DP->setHasBars(_curveAppearance->showBars());
    DP->setLineWidth(_curveAppearance->lineWidth());
    DP->setLineStyle(_curveAppearance->lineStyle());
    DP->Point.setType(_curveAppearance->pointType());
    DP->setBarStyle(_curveAppearance->barStyle());
    DP->update(-1);

    rc = true;
  }
  
  DP->writeUnlock();

  if (rc) {
    emit modified();
  }

  return rc;
}


#include "kstcurvedialog_i.moc"
// vim: ts=2 sw=2 et
