[gbrainy] Initial mouse & full RTL support



commit 36f845c0e95dfd394b8dac683d35e80afc13efbd
Author: Jordi Mas <jmas softcatala org>
Date:   Sun Jan 24 22:56:26 2010 +0100

    Initial mouse & full RTL support

 src/Clients/Classical/gbrainy.cs     |   74 +++++++++++++++---
 src/Core/Libraries/CairoContextEx.cs |    2 +-
 src/Core/Main/Game.cs                |   46 +++++++++++-
 src/Core/Main/GameSession.cs         |    7 ++-
 src/Core/Main/IMouseEvent.cs         |   51 +++++++++++++
 src/Core/Makefile.am                 |    4 +
 src/Core/Toolkit/Container.cs        |  132 +++++++++++++++++++++++++++++++++
 src/Core/Toolkit/DrawableArea.cs     |   82 +++++++++++++++++++++
 src/Core/Toolkit/Widget.cs           |  112 ++++++++++++++++++++++++++++
 src/Core/Views/WelcomeView.cs        |  129 +++++++++++++++++++++++++-------
 src/Games/Logic/PuzzlePencil.cs      |  134 ++++++++++++++++++++--------------
 11 files changed, 674 insertions(+), 99 deletions(-)
---
diff --git a/src/Clients/Classical/gbrainy.cs b/src/Clients/Classical/gbrainy.cs
index 9fe4695..32acaa2 100644
--- a/src/Clients/Classical/gbrainy.cs
+++ b/src/Clients/Classical/gbrainy.cs
@@ -23,6 +23,7 @@ using Gtk;
 using Gnome;
 using Mono.Unix;
 using System.Diagnostics;
+using Gdk;
 
 using gbrainy.Core.Main;
 using gbrainy.Core.Libraries;
@@ -62,6 +63,8 @@ namespace gbrainy.Clients.Classical
 		SimpleLabel question_label;
 		SimpleLabel solution_label;
 		bool margins = false;
+		double offset_x, offset_y;
+		int drawing_square;
 
 		public GtkClient (string [] args, params object [] props)
 		: base ("gbrainy", Defines.VERSION, Modules.UI,  args, props)
@@ -100,8 +103,17 @@ namespace gbrainy.Clients.Classical
 			solution_label = new SimpleLabel ();
 			solution_label.HeightMargin = 2;
 			solution_vbox.Add (solution_label);
+
+			EventBox eb = new EventBox (); // Provides a window for drawing area windowless widget
+			
+			eb.Events = Gdk.EventMask.PointerMotionMask;
+			drawing_vbox.Add (eb);
 	
-			drawing_vbox.Add (drawing_area);
+			eb.Add (drawing_area);
+
+			eb.MotionNotifyEvent += OnMouseMotionEvent;
+			eb.ButtonPressEvent += OnHandleButtonPress;
+
 			app_window.IconName = "gbrainy";
 			app_window.ShowAll ();
 
@@ -114,7 +126,6 @@ namespace gbrainy.Clients.Classical
 		#else
 			extensions_menu.Visible = false;
 		#endif
-
 			ActiveInputControls (false);
 		}
 
@@ -130,7 +141,7 @@ namespace gbrainy.Clients.Classical
 				UpdateStatusBar ();
 				break;
 			default:
-				throw new InvalidOperationException ("Unknow value");
+				throw new InvalidOperationException ("Unknown value");
 			}
 		}
 
@@ -144,8 +155,7 @@ namespace gbrainy.Clients.Classical
 		{
 			Gdk.EventExpose args = ar.Event;
 
-			int w, h, nw, nh;
-			double x = 0, y = 0;
+			int w, h;
 			args.Window.GetSize (out w, out h);
 
 			Cairo.Context cc = Gdk.CairoHelper.Create (args.Window);
@@ -153,25 +163,54 @@ namespace gbrainy.Clients.Classical
 
 			// We want a square drawing area for the puzzles then the figures are shown as designed. 
 			// For example, squares are squares. This also makes sure that proportions are kept when resizing
-			nh = nw = Math.Min (w, h);	
+			drawing_square = Math.Min (w, h);	
 
-			if (nw < w)
-				x = (w - nw) / 2;
+			if (drawing_square < w)
+				offset_x = (w - drawing_square) / 2;
 
-			if (nh < h)
-				y = (h - nh) / 2;
+			if (drawing_square < h)
+				offset_y = (h - drawing_square) / 2;
 
 			if (margins)
-				SetMargin ((int) x);
+				SetMargin ((int) offset_x);
 			else
 				SetMargin (2);
 
-			cr.Translate (x, y);
-			session.Draw (cr, nw, nh, drawing_area.Direction == Gtk.TextDirection.Rtl);
+			cr.Translate (offset_x, offset_y);
+			session.Draw (cr, drawing_square, drawing_square, drawing_area.Direction == Gtk.TextDirection.Rtl);
 
 			((IDisposable)cc).Dispose();
 			((IDisposable)cr).Dispose();
 		}
+		
+		void OnMouseMotionEvent (object o, MotionNotifyEventArgs ev_args)
+		{
+			SendMouseEvent (ev_args.Event.X, ev_args.Event.Y, MouseEventType.Move);
+		}
+
+		void OnHandleButtonPress (object o, ButtonPressEventArgs ev_args)
+		{
+			if (ev_args.Event.Type != EventType.TwoButtonPress)
+				return;
+
+			SendMouseEvent (ev_args.Event.X, ev_args.Event.Y, MouseEventType.DoubleClick);
+		}
+
+		void SendMouseEvent (double ev_x, double ev_y, MouseEventType type)
+		{
+			double x, y;
+
+			x = ev_x - offset_x;
+			y = ev_y - offset_y;
+
+			if (x < 0 || y < 0 || x > drawing_square || y > drawing_square) 
+				return;
+
+			x =  x / drawing_square;
+			y =  y / drawing_square;
+
+			session.MouseEvent (this, new MouseEventArgs (x, y, type));
+		}
 
 		public void UpdateStatusBar ()
 		{
@@ -313,6 +352,7 @@ namespace gbrainy.Clients.Classical
 			UpdateSolution (String.Empty);
 			UpdateQuestion (String.Empty);
 			session.NextGame ();
+			session.CurrentGame.AnswerEvent += OnAnswerFromGame;
 
 			ActiveInputControls (session.CurrentGame.ButtonsActive);
 			next_button.Sensitive = true;
@@ -322,6 +362,14 @@ namespace gbrainy.Clients.Classical
 			session.CurrentGame.DrawAnswer = false;
 			drawing_area.QueueDraw ();
 		}
+
+		// The user has clicked with the mouse in an answer and generated this event
+		void OnAnswerFromGame (object obj, Game.AnswerEventArgs args)
+		{
+			answer_entry.Text = args.Answer;
+			OnAnswerButtonClicked (this, EventArgs.Empty);
+			session.CurrentGame.AnswerEvent -= OnAnswerFromGame; // User can only answer once
+		}
 	
 		void OnMenuAbout (object sender, EventArgs args)
 		{
diff --git a/src/Core/Libraries/CairoContextEx.cs b/src/Core/Libraries/CairoContextEx.cs
index c2135c3..94a6db0 100644
--- a/src/Core/Libraries/CairoContextEx.cs
+++ b/src/Core/Libraries/CairoContextEx.cs
@@ -172,7 +172,7 @@ namespace gbrainy.Core.Libraries
 			layout.SingleParagraphMode = true;
 			layout.Width = -1;
 			layout.GetPixelSize (out w, out h);
-			MoveTo ((old.X0 + x * old.Xx) - w / 2, (y - font_size / 2) * old.Xx);
+			MoveTo ((old.X0 + x * old.Xx) - w / 2, (old.Y0 + y * old.Yy) - font_size / 2);
 			Pango.CairoHelper.ShowLayout (this, layout);
 			Matrix = old;
 		}
diff --git a/src/Core/Main/Game.cs b/src/Core/Main/Game.cs
index bd38124..5f4b192 100644
--- a/src/Core/Main/Game.cs
+++ b/src/Core/Main/Game.cs
@@ -19,14 +19,16 @@
 
 using System;
 using System.ComponentModel;
+using System.Collections.Generic;
 using Mono.Unix;
 
 using gbrainy.Core.Views;
 using gbrainy.Core.Libraries;
+using gbrainy.Core.Toolkit;
 
 namespace gbrainy.Core.Main
 {
-	abstract public class Game : IDrawable, IDrawRequest
+	abstract public class Game : IDrawable, IDrawRequest, IMouseEvent
 	{
 		// See: GetGameTypeDescription
 		public enum Types
@@ -46,6 +48,16 @@ namespace gbrainy.Core.Main
 			Master			= 8,
 		}
 
+		public class AnswerEventArgs : EventArgs
+		{
+			public AnswerEventArgs (string answer)
+			{
+				Answer = answer;
+			}
+
+			public string Answer { get; set; }
+		}
+
 		private bool draw_answer;
 		private Cairo.Color default_color;
 		protected string right_answer;
@@ -54,9 +66,11 @@ namespace gbrainy.Core.Main
 		private bool tip_used;
 		private Difficulty difficulty;
 		private ISynchronizeInvoke synchronize;
+		private List <Toolkit.Container> containers;
 
 		public event EventHandler DrawRequest;
 		public event EventHandler <UpdateUIStateEventArgs> UpdateUIElement;
+		public event EventHandler <AnswerEventArgs> AnswerEvent;
 
 		protected Game ()
 		{
@@ -65,6 +79,7 @@ namespace gbrainy.Core.Main
 			default_color = new Cairo.Color (0, 0, 0);
 			tip_used = false;
 			difficulty = Difficulty.Medium;
+			containers = new List <Toolkit.Container> ();
 		}
 
 		// Used by games to request a redraw of the view
@@ -248,6 +263,26 @@ namespace gbrainy.Core.Main
 
 			return (int) score;
 		}
+
+		public void AddWidget (Toolkit.Container container)
+		{
+			if (containers.Contains (container))
+				throw new InvalidOperationException ("Child already exists in container");
+
+			container.DrawRequest += delegate (object sender, EventArgs e)
+			{
+				OnDrawRequest ();
+			};
+
+			// If the user has selected an item we should propage an answer
+			container.SelectedEvent += delegate (object sender, Widget.SeletectedEventArgs e)
+			{
+				if (AnswerEvent != null)
+					AnswerEvent (this, new AnswerEventArgs ((string) e.DataEx));
+			};
+
+			containers.Add (container);
+		}
 	
 		public abstract void Initialize ();
 		public virtual void Finish () {}
@@ -293,6 +328,9 @@ namespace gbrainy.Core.Main
 			gr.DrawBackground ();
 			gr.Color = new Cairo.Color (0, 0, 0);
 			gr.LineWidth = LineWidth;
+	
+			foreach (Toolkit.Container container in containers)
+				container.Draw (gr, width, height, rtl);
 		}
 
 		public virtual void DrawPreview (CairoContextEx gr, int width, int height, bool rtl)
@@ -346,5 +384,11 @@ namespace gbrainy.Core.Main
 			}
 			return str;
 		}
+
+		public void MouseEvent (object obj, MouseEventArgs args)
+		{
+			foreach (Toolkit.Container container in containers)
+				container.MouseEvent (obj, args);
+		}
 	}
 }
diff --git a/src/Core/Main/GameSession.cs b/src/Core/Main/GameSession.cs
index 4dc3131..1a131b8 100644
--- a/src/Core/Main/GameSession.cs
+++ b/src/Core/Main/GameSession.cs
@@ -27,7 +27,7 @@ using gbrainy.Core.Libraries;
 
 namespace gbrainy.Core.Main
 {
-	public class GameSession : IDrawable, IDrawRequest
+	public class GameSession : IDrawable, IDrawRequest, IMouseEvent
 	{
 		[Flags]
 		public enum Types
@@ -478,5 +478,10 @@ namespace gbrainy.Core.Main
 			controler.CurrentView.Draw (gr, width, height, rtl);
 		}
 
+		public void MouseEvent (object obj, MouseEventArgs args)
+		{
+			if (controler.CurrentView as IMouseEvent != null)
+				(controler.CurrentView as IMouseEvent).MouseEvent (this, args);
+		}
 	}
 }
diff --git a/src/Core/Main/IMouseEvent.cs b/src/Core/Main/IMouseEvent.cs
new file mode 100644
index 0000000..1e72965
--- /dev/null
+++ b/src/Core/Main/IMouseEvent.cs
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 Jordi Mas i Hernàndez <jmas softcatala org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+using System;
+using System.ComponentModel;
+
+using gbrainy.Core.Libraries;
+
+namespace gbrainy.Core.Main
+{
+	public enum MouseEventType
+	{
+		Move,
+		DoubleClick,
+	};
+
+	public struct MouseEventArgs
+	{
+		public double X { get; set; }
+		public double Y { get; set; }
+		public MouseEventType EventType { get; set; }
+
+		public MouseEventArgs (double x, double y, MouseEventType event_type)
+		{
+			X = x;
+			Y = y;
+			EventType = event_type;
+		}
+	}
+
+	public interface IMouseEvent
+	{
+		void MouseEvent (object obj, MouseEventArgs args);
+	}
+}
diff --git a/src/Core/Makefile.am b/src/Core/Makefile.am
index ae24e3c..c170e48 100644
--- a/src/Core/Makefile.am
+++ b/src/Core/Makefile.am
@@ -8,6 +8,7 @@ CSFILES =  \
 		Main/ArrayListIndicesRandom.cs	\
 		Main/ColorPalette.cs		\
 		Main/Defines.cs			\
+		Main/IMouseEvent.cs		\
 		Main/Game.cs			\
 		Main/GameManager.cs		\
 		Main/GameSession.cs		\
@@ -27,6 +28,9 @@ CSFILES =  \
 		Views/FinishView.cs		\
 		Main/IDrawable.cs		\
 		Main/IDrawRequest.cs		\
+		Toolkit/Container.cs		\
+		Toolkit/DrawableArea.cs		\
+		Toolkit/Widget.cs		\
 		Views/PlayerHistoryView.cs	\
 		Views/ViewsControler.cs		\
 		Views/WelcomeView.cs		\
diff --git a/src/Core/Toolkit/Container.cs b/src/Core/Toolkit/Container.cs
new file mode 100644
index 0000000..3206f90
--- /dev/null
+++ b/src/Core/Toolkit/Container.cs
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2010 Jordi Mas i Hernàndez <jmas softcatala org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+using System;
+using System.Collections.Generic;
+
+using gbrainy.Core.Libraries;
+using gbrainy.Core.Main;
+
+namespace gbrainy.Core.Toolkit
+{
+	// Horizontal Container
+	public class Container : Widget
+	{
+		List <Widget> children;
+		bool rtl;
+
+		public Container (double x, double y, double width, double height) : base (width, height)
+		{
+			X = x;
+			Y = y;
+			children = new List <Widget> ();
+		}
+
+		public double X { get; set; }
+		public double Y { get; set; }
+
+		public Widget [] Children {
+			get { return children.ToArray (); }
+		}
+
+		public void AddChild (Widget widget)
+		{
+			if (children.Contains (widget))
+				throw new InvalidOperationException ("Child already exists in container");
+
+			//
+			// Propagate events from child controls to this container (parent)
+			//
+			widget.DrawRequest += delegate (object sender, EventArgs e)
+			{
+				OnDrawRequest ();
+			};
+
+			widget.SelectedEvent += delegate (object sender, Widget.SeletectedEventArgs e)
+			{
+				OnSelected (e);
+			};
+
+			children.Add (widget);
+		}
+
+		public override void Draw (CairoContextEx gr, int area_width, int area_height, bool rtl)
+		{
+			double x = X, y = Y;
+	
+			this.rtl = rtl;
+
+			/*gr.Save ();
+			gr.Color = new Cairo.Color (0, 0, 1);
+			gr.Rectangle (X, Y, Width, Height);
+			gr.Stroke ();
+			gr.Restore ();*/
+
+			//
+			// Coordinates are stored right to left
+			//
+			if (rtl == false) {
+				for (int i = 0; i < children.Count; i++)
+				{
+					gr.Save ();						
+					gr.Translate (x, y);
+
+					children[i].Draw (gr, area_width, area_height, rtl);
+					gr.Restore ();
+					x += children[i].Width;
+				}
+			} else {
+				x += Width;
+				for (int i = 0; i < children.Count; i++)
+				{
+					x -= children[i].Width;
+					gr.Save ();
+					gr.Translate (x, y);
+					children[i].Draw (gr, area_width, area_height, rtl);
+					gr.Restore ();
+				}
+			}
+		}
+
+		public override void MouseEvent (object obj, MouseEventArgs args)
+		{
+			double x = X, y = Y;
+
+			if (rtl == true)
+				x += Width;
+
+			foreach (Widget child in Children)
+			{
+				if (rtl == true)
+					x -= child.Width;
+
+				if ((args.X >= x) && (args.X < x + child.Width) && 
+					(args.Y >= y) && (args.Y < y + child.Height))
+				{
+					child.MouseEvent (this, args);
+				} else {
+					child.MouseEvent (this, new MouseEventArgs (-1, -1, args.EventType));
+				}
+
+				if (rtl == false)
+					x += child.Width;
+			}
+		}
+	}
+}
diff --git a/src/Core/Toolkit/DrawableArea.cs b/src/Core/Toolkit/DrawableArea.cs
new file mode 100644
index 0000000..92cf89f
--- /dev/null
+++ b/src/Core/Toolkit/DrawableArea.cs
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010 Jordi Mas i Hernàndez <jmas softcatala org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+using System;
+
+using gbrainy.Core.Libraries;
+using gbrainy.Core.Main;
+
+namespace gbrainy.Core.Toolkit
+{
+	public class DrawableArea : Widget
+	{
+		public virtual event WidgetDrawEventHandler DrawEventHandler;
+		public virtual event WidgetSelectedEventHandler SelectedRequestEvent;
+		bool hoover;
+
+	    	public DrawableArea (double width, double height) : base (width, height)
+		{
+
+		}
+
+		public override void Draw (CairoContextEx gr, int area_width, int area_height, bool rtl) 
+		{
+			if (hoover == true)
+  			{
+				double lw = gr.LineWidth;
+				double [] dashes = {0.01,  /* ink */
+						   0.01,  /* skip */
+				};
+
+				gr.Save ();
+
+				gr.Color = new Cairo.Color (0.5, 0.5, 0.5, 1);
+				gr.SetDash (dashes, 0);
+				gr.Rectangle (-lw, -lw, Width + lw * 2, Height + lw * 2);
+				gr.Stroke ();
+				gr.Restore ();
+			}
+
+			if (DrawEventHandler == null)
+				return;
+	
+			DrawEventHandler (this, new DrawEventArgs (gr, Width, Height, rtl, Data));
+		}
+
+		public override void MouseEvent (object obj, MouseEventArgs args)
+		{
+			if (args.X == -1 || args.Y == -1) {
+				if (hoover == true) {
+					hoover = false;
+					OnDrawRequest ();
+				}
+			} else {
+
+				if (args.EventType == MouseEventType.DoubleClick) {
+					OnSelected (new SeletectedEventArgs (Data, DataEx));
+				} else {
+					if (hoover == false) {
+						hoover = true;
+						OnDrawRequest ();
+					}
+				}
+			}
+		}		
+	}
+}
diff --git a/src/Core/Toolkit/Widget.cs b/src/Core/Toolkit/Widget.cs
new file mode 100644
index 0000000..1b3e4f5
--- /dev/null
+++ b/src/Core/Toolkit/Widget.cs
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2010 Jordi Mas i Hernàndez <jmas softcatala org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+using System;
+using System.ComponentModel;
+
+using gbrainy.Core.Main;
+using gbrainy.Core.Libraries;
+
+namespace gbrainy.Core.Toolkit
+{
+	public abstract class Widget : IDrawable, IDrawRequest, IMouseEvent
+	{
+		public delegate void WidgetDrawEventHandler (object sender, DrawEventArgs e);
+		public delegate void WidgetSelectedEventHandler (object sender, SeletectedEventArgs e);
+
+		public event EventHandler DrawRequest;
+		public event WidgetSelectedEventHandler SelectedEvent;
+		ISynchronizeInvoke synchronize;
+
+		public class DrawEventArgs: EventArgs
+		{
+			public DrawEventArgs (CairoContextEx gr, double width, double height, bool rtl, object data)
+			{
+				Context = gr;
+				Width = width;
+				Height = height;
+				Rtl = rtl;
+				Data = data;
+			}
+
+			public CairoContextEx Context { get; set; }
+			public double Width { get; set; }
+			public double Height { get; set; }
+			public bool Rtl { get; set; }
+			public object Data { get; set; }
+		}
+
+		public class SeletectedEventArgs: EventArgs
+		{
+			public SeletectedEventArgs (object data, object data_ex)
+			{
+				Data = data;
+				DataEx = data_ex;
+			}
+
+			public object Data { get; set; }
+			public object DataEx { get; set; }
+		}
+
+	    	public Widget (double width, double height)
+		{
+			Width = width;
+			Height = height;
+		}
+
+		public bool Visible { get; set; }
+		public bool Sensitive { get; set; }
+		public object Data { get; set; }
+		public object DataEx { get; set; }
+
+		public double Width { get; set; }
+		public double Height { get; set; }
+
+		public ISynchronizeInvoke SynchronizingObject { 
+			set { synchronize = value; }
+			get { return synchronize; }
+		}
+
+		protected void OnDrawRequest ()
+		{
+			if (DrawRequest == null)
+				return;
+
+			DrawRequest (this, EventArgs.Empty);
+		}
+
+		protected void OnSelected (SeletectedEventArgs e)
+		{
+			if (SelectedEvent == null)
+				return;
+
+			SelectedEvent (this, e);
+		}
+
+		public virtual void Draw (CairoContextEx gr, int area_width, int area_height, bool rtl) 
+		{
+			throw new InvalidOperationException ();
+		}
+
+		public virtual void MouseEvent (object obj, MouseEventArgs args)
+		{
+			throw new InvalidOperationException ();
+		}
+	}
+}
diff --git a/src/Core/Views/WelcomeView.cs b/src/Core/Views/WelcomeView.cs
index d037c15..a1aa395 100644
--- a/src/Core/Views/WelcomeView.cs
+++ b/src/Core/Views/WelcomeView.cs
@@ -21,28 +21,120 @@
 using System;
 using Cairo;
 using Mono.Unix;
+using System.Collections.Generic;
 
 using gbrainy.Core.Main;
 using gbrainy.Core.Libraries;
+using gbrainy.Core.Toolkit;
 
 namespace gbrainy.Core.Views
 {
 	public class WelcomeView : IDrawable
 	{
+		List <Toolkit.Container> containers;
+		const double space = 0.17;
+		const double image_size = 0.14;
+
 		public WelcomeView ()
 		{
+			Container container;
+			DrawableArea drawable_area;
+			double y = 0.22;
+
+			containers = new List <Toolkit.Container> ();
+	
+			/* Logic */
+			container = new Container (0.05, y, 0.95, space);
+			containers.Add (container);
+
+			drawable_area = new DrawableArea (0.17, image_size);
+			container.AddChild (drawable_area);
+			drawable_area.DrawEventHandler += delegate (object sender, Widget.DrawEventArgs e)
+			{
+				e.Context.DrawImageFromAssembly ("logic-games.svg", 0, 0, image_size, image_size);
+			};
+
+			drawable_area = new DrawableArea (0.75, 0.25);
+			container.AddChild (drawable_area);
+			drawable_area.DrawEventHandler += delegate (object sender, Widget.DrawEventArgs e)
+			{
+				e.Context.DrawStringWithWrapping (0, 0,
+					Catalog.GetString ("Logic puzzles. Challenge your reasoning and thinking skills."), 
+					e.Width);
+			};
+
+			/* Math */
+			y += space;
+			container = new Container (0.05, y, 0.95, space);
+			containers.Add (container);
+
+			drawable_area = new DrawableArea (0.17, image_size);
+			container.AddChild (drawable_area);
+			drawable_area.DrawEventHandler += delegate (object sender, Widget.DrawEventArgs e)
+			{
+				e.Context.DrawImageFromAssembly ("math-games.svg", 0, 0, image_size, image_size);
+			};
+
+			drawable_area = new DrawableArea (0.75, 0.25);
+			container.AddChild (drawable_area);
+			drawable_area.DrawEventHandler += delegate (object sender, Widget.DrawEventArgs e)
+			{
+				e.Context.DrawStringWithWrapping (0, 0,
+					Catalog.GetString ("Mental calculation. Arithmetical operations that test your mental calculation abilities."),
+					e.Width);
+			};
+
+			/* Memory */
+			y += space;
+			container = new Container (0.05, y, 0.95, space);
+			containers.Add (container);
+
+			drawable_area = new DrawableArea (0.17, image_size);
+			container.AddChild (drawable_area);
+			drawable_area.DrawEventHandler += delegate (object sender, Widget.DrawEventArgs e)
+			{
+				e.Context.DrawImageFromAssembly ("memory-games.svg", 0, 0, image_size, image_size);
+			};
+
+			drawable_area = new DrawableArea (0.75, 0.25);
+			container.AddChild (drawable_area);
+			drawable_area.DrawEventHandler += delegate (object sender, Widget.DrawEventArgs e)
+			{
+				e.Context.DrawStringWithWrapping (0, 0,
+					Catalog.GetString ("Memory trainers. To prove your short term memory."),
+					e.Width);
+			};
 
+			/* Verbal */
+			y += space;
+			container = new Container (0.05, y, 0.95, space);
+			containers.Add (container);
+
+			drawable_area = new DrawableArea (0.17, image_size);
+			container.AddChild (drawable_area);
+			drawable_area.DrawEventHandler += delegate (object sender, Widget.DrawEventArgs e)
+			{
+				e.Context.DrawImageFromAssembly ("verbal-games.svg", 0, 0, image_size, image_size);
+			};
+
+			drawable_area = new DrawableArea (0.75, 0.25);
+			container.AddChild (drawable_area);
+			drawable_area.DrawEventHandler += delegate (object sender, Widget.DrawEventArgs e)
+			{
+				e.Context.DrawStringWithWrapping (0, 0,
+					Catalog.GetString ("Verbal analogies. Challenge your verbal aptitude."),
+					e.Width);
+			};
 		}
 
 		public void Draw (CairoContextEx gr, int area_width, int area_height, bool rtl)
 		{
 			double y = 0.03;
-			const double space = 0.17;
-			const double image_size = 0.14;
 
 			gr.Scale (area_width, area_height);
 			gr.DrawBackground ();
-			//gr.SetPangoNormalFontSize ();
+			gr.LineWidth = 0.005;
+
 			gr.Color = new Cairo.Color (0, 0, 0, 1);
 
 			gr.MoveTo (0.05, y);
@@ -50,34 +142,15 @@ namespace gbrainy.Core.Views
 			gr.ShowPangoText (String.Format (Catalog.GetString ("Welcome to gbrainy {0}"), Defines.VERSION), true, -1, 0);
 			gr.Stroke ();
 
-			gr.DrawStringWithWrapping (0.05, y + 0.07, Catalog.GetString ("gbrainy is a brain teaser game and trainer to have fun and to keep your brain trained. It includes:"));
-
-			y = 0.22;
-			gr.DrawImageFromAssembly ("logic-games.svg", rtl ? 0.75 : 0.05, y, image_size, image_size);
-			gr.DrawStringWithWrapping (rtl ? 0.05 : 0.23, y + 0.01, 
-				Catalog.GetString ("Logic puzzles. Challenge your reasoning and thinking skills."), 
-				rtl ? 0.65 : -1);
-
-			y += space;
-			gr.DrawImageFromAssembly ("math-games.svg", rtl ? 0.75 : 0.05, y, image_size, image_size);
-			gr.DrawStringWithWrapping (rtl ? 0.05 : 0.23, y + 0.01, 
-				Catalog.GetString ("Mental calculation. Arithmetical operations that test your mental calculation abilities."),
-				rtl ? 0.65 : -1);
-
-			y += space;
-			gr.DrawImageFromAssembly ("memory-games.svg", rtl ? 0.75 : 0.05, y, image_size, image_size);
-			gr.DrawStringWithWrapping (rtl ? 0.05 : 0.23, y + 0.01, 
-				Catalog.GetString ("Memory trainers. To prove your short term memory."),
-				rtl ? 0.65 : -1);
-
-			y += space;
-			gr.DrawImageFromAssembly ("verbal-games.svg", rtl ? 0.75 : 0.05, y, image_size, image_size);
-			gr.DrawStringWithWrapping (rtl ? 0.05 : 0.23, y + 0.01, 
-				Catalog.GetString ("Verbal analogies. Challenge your verbal aptitude."),
-				rtl ? 0.65 : -1);
+			gr.DrawStringWithWrapping (0.05, y + 0.07, 
+				Catalog.GetString ("gbrainy is a brain teaser game and trainer to have fun and to keep your brain trained. It includes:"));
 
+			y = 0.22 + space * 3;
 			gr.DrawStringWithWrapping (0.05, y + 0.17,  Catalog.GetString ("Use the Settings to adjust the difficulty level of the game."));
 			gr.Stroke ();
+
+			foreach (Toolkit.Container container in containers)
+				container.Draw (gr, area_width, area_height, rtl);
 		}
 	}
 }
diff --git a/src/Games/Logic/PuzzlePencil.cs b/src/Games/Logic/PuzzlePencil.cs
index be16cb8..7987723 100644
--- a/src/Games/Logic/PuzzlePencil.cs
+++ b/src/Games/Logic/PuzzlePencil.cs
@@ -23,6 +23,7 @@ using Mono.Unix;
 
 using gbrainy.Core.Main;
 using gbrainy.Core.Libraries;
+using gbrainy.Core.Toolkit;
 
 namespace gbrainy.Games.Logic
 {
@@ -56,7 +57,83 @@ namespace gbrainy.Games.Logic
 			
 				right_answer = GetPossibleAnswer (i);
 				break;
-			}	
+			}
+
+			double x = DrawAreaX, y = DrawAreaY + 0.1, box_size = (1 - (DrawAreaX * 2)) / 3;
+			Container container1, container2, container = null;
+			DrawableArea drawable_area;
+
+			for (int figure = 0; figure < figures; figure++)
+			{
+				switch (figure) {
+				case 0:
+					x = DrawAreaX;
+					container1 = new Container (x, y, 0.8, figure_size);
+					container = container1;
+					AddWidget (container);
+					break;
+				case 3:
+					x = DrawAreaX;
+					y += 0.4;
+					container2 = new Container (x, y, 0.8, figure_size);
+					container = container2;
+					AddWidget (container);
+					break;
+				default:
+					break;
+				}
+
+				drawable_area = new DrawableArea (box_size, figure_size);
+				drawable_area.Data = figure;
+				drawable_area.DataEx = GetPossibleAnswer (figure);
+
+				switch (random_indices[figure]) {
+				case 0:
+					drawable_area.DrawEventHandler += delegate (object sender, Widget.DrawEventArgs e)
+					{
+						DrawTriangle (e.Context, (e.Width - figure_size) / 2, 0);
+						e.Context.DrawTextCentered (e.Width / 2, figure_size + 0.02, 
+							GetPossibleFigureAnswer ((int) e.Data));
+					};
+					break;
+				case 1:
+					drawable_area.DrawEventHandler += delegate (object sender, Widget.DrawEventArgs e)
+					{
+						DrawDiamon (e.Context, (e.Width - figure_size) / 2, 0);
+						e.Context.DrawTextCentered (e.Width / 2, figure_size + 0.02,
+							GetPossibleFigureAnswer ((int) e.Data));
+					};
+					break;
+				case 2:
+					drawable_area.DrawEventHandler += delegate (object sender, Widget.DrawEventArgs e)
+					{
+						DrawRectangleWithTriangles (e.Context, (e.Width - figure_size) / 2, 0);
+						e.Context.DrawTextCentered (e.Width / 2, figure_size + + 0.02,
+							GetPossibleFigureAnswer ((int) e.Data));
+					};
+					break;
+				case 3:
+					drawable_area.DrawEventHandler += delegate (object sender, Widget.DrawEventArgs e)
+					{
+						DrawThreeTriangles (e.Context, (e.Width - figure_size) / 2, 0);
+						e.Context.DrawTextCentered (e.Width / 2, figure_size + + 0.02,
+							GetPossibleFigureAnswer ((int) e.Data));
+					};
+					break;
+				case answer_index:
+					drawable_area.DrawEventHandler += delegate (object sender, Widget.DrawEventArgs e)
+					{
+						DrawRectangleWithCross (e.Context, (e.Width - figure_size) / 2, 0);
+						e.Context.DrawTextCentered (e.Width / 2, figure_size + 0.02,
+							GetPossibleFigureAnswer ((int) e.Data));
+					};
+					break;
+				}			
+
+				container.AddChild (drawable_area);
+				x += box_size;
+			}
+			
 		}
 
 		static private void DrawTriangle (CairoContextEx gr, double x, double y)
@@ -71,6 +148,7 @@ namespace gbrainy.Games.Logic
 
 		static private void DrawDiamon (CairoContextEx gr, double x, double y)
 		{
+			x += 0.1;
 			gr.MoveTo (x, y);
 			gr.LineTo (x - (figure_size / 2), y + (figure_size / 2));
 			gr.LineTo (x, y + figure_size);
@@ -111,20 +189,6 @@ namespace gbrainy.Games.Logic
 		
 		}
 
-	/*	private void DrawHouse (CairoContextEx gr, double x, double y)
-		{
-			gr.MoveTo (x, y + figure_size);
-			gr.LineTo (x, y + figure_size / 2);
-			gr.LineTo (x + figure_size / 2, y);
-			gr.LineTo (x + figure_size, y + figure_size / 2);
-			gr.LineTo (x, y + figure_size / 2);
-			gr.LineTo (x + figure_size, y + figure_size);
-			gr.LineTo (x + figure_size, y + figure_size / 2);
-			gr.LineTo (x, y + figure_size);
-			gr.LineTo (x + figure_size, y + figure_size);
-			gr.Stroke ();		
-		}*/
-
 		static private void DrawRectangleWithCross (CairoContextEx gr, double x, double y)
 		{
 			gr.Rectangle (x, y, figure_size, figure_size);
@@ -140,47 +204,7 @@ namespace gbrainy.Games.Logic
 
 		public override void Draw (CairoContextEx gr, int area_width, int area_height, bool rtl)
 		{
-			double x = DrawAreaX, y = DrawAreaY;
-
 			base.Draw (gr, area_width, area_height, rtl);
-
-			for (int figure = 0; figure < figures; figure++)
-			{
-				switch (random_indices[figure]) {
-				case 0:
-					DrawTriangle (gr, x, y);
-					break;
-				case 1:
-					DrawDiamon (gr, x + 0.1, y);
-					break;
-				//case 2:
-				//	DrawHouse (gr, x, y);				
-				//	break;
-				case 2:
-					DrawRectangleWithTriangles (gr, x, y);
-					break;
-				case 3:
-					DrawThreeTriangles (gr, x, y);
-					break;
-				case answer_index:
-					DrawRectangleWithCross (gr, x, y);
-					break;
-			
-				}			
-						
-				gr.MoveTo (x, y + figure_size + 0.05);
-				gr.ShowPangoText (GetPossibleFigureAnswer (figure));
-
-				if (figure == 2) {
-					x = DrawAreaX;
-					y += figure_size + space_height;
-
-				} else {						
-					x += figure_size + space_width;		
-				}
-			}
-
 		}
-
 	}
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]