// scribblewindow.cs - Qt# scribblewindow
//
// Author: Adam Treat <manyoso@yahoo.com>
// (c) 2002 Adam Treat
// Licensed under the terms of the GNU GPL

namespace QtSamples {

	using Qt;
	using System;

	[DeclareQtSignal ("colorChanged(QColor)")]
	[DeclareQtSignal ("load(QString)")]
	[DeclareQtSignal ("save(QString)")]
	public class ScribbleWindow : QMainWindow {

		private QMenuBar menubar;
		private QPopupMenu filemenu;
		private QPopupMenu aboutmenu;
		private QScrollView scrollview;
		public ScribbleArea scribblearea;

		enum Color {Black, Red, Blue, Green, Yellow};

		public static int Main (String[] args)
		{
			QApplication app = new QApplication (args);
			ScribbleWindow demo = new ScribbleWindow ();
			demo.SetGeometry (50, 500, 400, 400);
			app.SetMainWidget (demo);
			demo.SetCaption ("Qt# 0.7!");
			demo.Show ();
			return app.Exec ();
		}

		ScribbleWindow () : base (null, null)
		{
			filemenu = new QPopupMenu (null, "filemenu");
			filemenu.InsertItem ("&Load", this, SLOT ("SlotLoad()") );
			filemenu.InsertItem ("&Save", this, SLOT ("SlotSave()") );
			filemenu.InsertSeparator ();
			filemenu.InsertItem ("&Quit", qApp, SLOT ("quit()"));

			aboutmenu = new QPopupMenu (null, "helpmenu");
			aboutmenu.InsertItem ("&About Qt-Sharp", this, SLOT ("SlotAboutQtSharp()"));
			aboutmenu.InsertItem ("&About Qt", this, SLOT ("SlotAboutQt()"));

			menubar = new QMenuBar (this, "");
			menubar.InsertItem ("&File", filemenu);
			menubar.InsertItem ("&Color", this, SLOT("SlotColorChooser()"));
			menubar.InsertItem ("&About", aboutmenu);

			scrollview = new QScrollView (this);
			scrollview.SetGeometry (0, menubar.Height (), Width (), Height () - menubar.Height ());
			scribblearea = new ScribbleArea (this);
			scribblearea.SetGeometry (0, 0, 1000, 1000);
			scrollview.AddChild (scribblearea);
			this.SetCentralWidget (scrollview);
			SetMaximumSize (Width (), Height () - menubar.Height ());

			QObject.Connect (this, SIGNAL ("colorChanged(QColor)"),
				scribblearea, SLOT ("SlotSetColor(QColor)") );
			QObject.Connect (this, SIGNAL ("load(QString)"),
				scribblearea, SLOT ("PerformLoad(QString)") );
			QObject.Connect (this, SIGNAL ("save(QString)"),
				scribblearea, SLOT ("PerformSave(QString)") );
		}

		public void SlotLoad ()
		{
			string filename = QFileDialog.GetOpenFileName (".", "*.bmp", this,
				null, "Load File", QString.Null, true);
			
			if ( filename != null )
				Emit ("load(QString)", (QString) filename);
		}

		public void SlotSave ()
		{
			string filename = QFileDialog.GetSaveFileName (".", "*.bmp", this,
				null, "Save File", QString.Null, true);

			if ( filename != null )
			{
				if ( ! filename.ToLower().EndsWith(".bmp") )
					filename += ".bmp";
				Emit ("save(QString)", (QString) filename);
			}
		}

		public void SlotAboutQtSharp ()
		{
			QMessageBox.Information (this, "About Qt# 0.7",
											"A Qt (http://www.trolltech.com) to C# language binding. \n" +
											"Qt# is compatible with Mono (http://go-mono.org) and\n" +
											"Portable.NET (http://www.southern-storm.com.au/portable_net.html)\n" +
											"(c) 2002 Adam Treat. Licensed under the terms of the GNU GPL.\n"
											);
		}

		public void SlotAboutQt ()
		{
			QMessageBox.AboutQt (this, "About Qt");
		}

		public void SlotColorChooser ()
		{
			QColor chosenColor = QColorDialog.GetColor();
			if (chosenColor.IsValid())
				Emit ("colorChanged(QColor)", chosenColor);
		}

		public class ScribbleArea : QFrame {
			private QPoint last;
			private QPixmap buffer;
			private QColor currentcolor = new QColor("Black");
			private QPopupMenu popupmenu;

			public ScribbleArea (QWidget parent) : base (parent)
			{
				buffer = new QPixmap ();
				last = new QPoint ();
				SetBackgroundMode (Qt.BackgroundMode.NoBackground);

				popupmenu = new QPopupMenu();
				popupmenu.InsertItem ("&Clear", this, SLOT ("SlotClearArea()") );

				mouseMoveEvent += new MouseMoveEvent (MouseMoved);
				mousePressEvent += new MousePressEvent (MousePressed);
				paintEvent += new PaintEvent (PerformPaint);
				resizeEvent += new ResizeEvent (PerformResize);
			}

			public void PerformLoad (QString filename)
			{
 				if ( ! buffer.Load(filename)  )
 					QMessageBox.Warning (null, "Load error", "Could not load file");
 				Repaint();
			}

			public void PerformSave (QString filename)
			{
				if ( ! buffer.Save (filename, "BMP") )
					QMessageBox.Warning( null, "Save error", "Could not save file");
			}

			public void SlotClearArea ()
			{
				buffer.Fill( new QColor ("white") );
				BitBlt (this, 0, 0, buffer, 0, 0, -1, -1, Qt.RasterOp.CopyROP, false);
			}


			public void SlotSetColor (QColor color)
			{
				currentcolor = color;
			}

			// Note, Dispose() is called on QPoints here to increase performance
			// of the UI. Otherwise, the GC would let dead QPoint instances pile
			// up and delete them all at once, causing the UI to pause while it frees
			// memory. (This happens because the GC runs in the same thread as the
			// application.)

			protected void MousePressed (QMouseEvent e)
			{
				if (e.Button() == ButtonState.RightButton )
					popupmenu.Exec (QCursor.Pos ());
				else {
					last.Dispose ();
					last = e.Pos();
				}
			}

			protected void MouseMoved (QMouseEvent e)
			{
				QPainter windowPainter = new QPainter ();
				QPainter bufferPainter = new QPainter ();

				windowPainter.Begin (this);
				bufferPainter.Begin (buffer);

				windowPainter.SetPen (currentcolor);
				bufferPainter.SetPen (currentcolor);

				windowPainter.DrawLine (last, e.Pos());
				bufferPainter.DrawLine (last, e.Pos());

				windowPainter.End ();
				bufferPainter.End ();

				last.Dispose ();
 				last = e.Pos ();
			}

			protected void PerformPaint (QPaintEvent e)
			{
				BitBlt(this, 0, 0, buffer,
					0, 0, -1, -1, RasterOp.CopyROP, false);
			}

			protected void PerformResize (QResizeEvent e)
			{
				QPixmap save = new QPixmap (buffer);
				buffer.Resize (e.Size());
				buffer.Fill (new QColor("white"));
				BitBlt (buffer, 0, 0, save,
					0, 0, -1, -1, RasterOp.CopyROP, false);
			}
		}
	}
}
