#ifdef CGAL_USE_QT

#include <list>
#include <qapplication.h>
#include <qmainwindow.h>
#include <CGAL/Cartesian.h>
#include <CGAL/Gmpq.h>
#include <CGAL/Point_2.h>
#include <CGAL/IO/Qt_widget.h>
#include <CGAL/IO/Qt_widget_layer.h>
#include <CGAL/IO/Qt_widget_standard_toolbar.h>

using namespace CGAL;
using std::list;

typedef Gmpq number;
typedef Cartesian<number> K;
typedef Point_2<K> Point;

/******************************************************************************
 * slow convex hull algorithm
 *
 * input:  pt -- list of Points
 * output: hullpt -- list of Points
 *                   traversing the convex hull of pt in positive direction
 ******************************************************************************/

void SlowConvexHull (const list<Point> & pt, list<Point> & hullpt)
{
   hullpt.clear();
   for (list<Point>::const_iterator p = pt.begin(); p != pt.end(); ++p)
      hullpt.push_back (*p);
}

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

/***** one layer *****/

class ConvexHullLayer : public Qt_widget_layer
{
      void draw();
   public:
      list<Point> points;
      list<Point> hull;
};

/***** what we want to draw *****/

void ConvexHullLayer::draw()
{
   widget->lock();
   // draw points in blue
   *widget << BLUE;
   for (list<Point>::const_iterator p = points.begin(); p != points.end(); ++p)
      *widget << *p;
   // and if there's a convex hull draw it in green
   if (!hull.empty())
   {
      *widget << GREEN;
      list<Point>::const_iterator q = hull.begin();
      ++q;
      for (list<Point>::const_iterator p = hull.begin(); q != hull.end(); ++p, ++q)
	 *widget << Segment_2<K>(*p,*q);
      *widget << Segment_2<K>(hull.back(), hull.front());
   }
   widget->unlock();
}

/***** main window *****/

class ConvexHullWindow : public QMainWindow
{
      Q_OBJECT

      Qt_widget *cgal_widget;
      Qt_widget_standard_toolbar *cgal_toolbar;
      ConvexHullLayer onlylayer;
      
   public:
      ConvexHullWindow(int width=600, int height=600, int xleft=-1, int xright=1, int ylower=-1, int yupper=1);

   private slots:
      void mouse_pressed (QMouseEvent* e);
      void key_pressed (QKeyEvent* e);
};

ConvexHullWindow::ConvexHullWindow (int x, int y, int xleft, int xright, int ylower, int yupper)
{
   cgal_widget = new Qt_widget(this);
   cgal_widget->resize(x,y);
   cgal_widget->set_window (xleft, xright, ylower, yupper);
   cgal_toolbar = new CGAL::Qt_widget_standard_toolbar (cgal_widget, this, "Plain Window Toolbar");
   cgal_widget->attach(&onlylayer);
   connect (cgal_widget, SIGNAL(s_keyPressEvent(QKeyEvent*)), this, SLOT(key_pressed(QKeyEvent*)));
   connect (cgal_widget, SIGNAL(s_mousePressEvent(QMouseEvent*)), this, SLOT(mouse_pressed(QMouseEvent*)));
   setCentralWidget (cgal_widget);
   cgal_widget->grabKeyboard();
}

void ConvexHullWindow::key_pressed (QKeyEvent* e)
{
   cgal_widget->clear();
   switch (e->key())
   {
      case Qt::Key_Q:
	 close();
	 break;
      case Qt::Key_C:
	 onlylayer.points.clear();
	 onlylayer.hull.clear();
   }
   cgal_widget->redraw();
}

void ConvexHullWindow::mouse_pressed (QMouseEvent* e)
{
   onlylayer.points.push_back (Point (cgal_widget->x_real(e->x()), cgal_widget->y_real(e->y())));
   SlowConvexHull (onlylayer.points, onlylayer.hull);
   cgal_widget->redraw();
}

//moc_source_file : convex-hull.C
#include "convex-hull.moc"

/***** main() *****/

int main (int argc, char** argv)
{
   QApplication app(argc,argv);
   ConvexHullWindow mainwindow;
   app.setMainWidget (&mainwindow);
   mainwindow.show();

   return app.exec();
}

#else

#include <iostream>

int main ()
{
   std::cout << "Sorry, this program needs QT...";
   std::cout << std::endl;
   return 0;
}

#endif // CGAL_USE_QT

