tomboy r1756 - in trunk: . Tomboy/Addins Tomboy/Addins/Sketching



Author: jtickle
Date: Thu Jan 10 01:45:30 2008
New Revision: 1756
URL: http://svn.gnome.org/viewvc/tomboy?rev=1756&view=rev

Log:
Sketching ApplicationAddin aka Virtual Paper

Added:
   trunk/Tomboy/Addins/Sketching/
   trunk/Tomboy/Addins/Sketching/Handwriting.cs
   trunk/Tomboy/Addins/Sketching/Makefile.am
   trunk/Tomboy/Addins/Sketching/Paper.cs
   trunk/Tomboy/Addins/Sketching/Pen.cs
   trunk/Tomboy/Addins/Sketching/Sketching.addin.xml
   trunk/Tomboy/Addins/Sketching/SketchingNoteAddin.cs
   trunk/Tomboy/Addins/Sketching/SketchingTextTag.cs
   trunk/Tomboy/Addins/Sketching/Stroke.cs
Modified:
   trunk/ChangeLog
   trunk/Tomboy/Addins/Makefile.am
   trunk/configure.in

Modified: trunk/Tomboy/Addins/Makefile.am
==============================================================================
--- trunk/Tomboy/Addins/Makefile.am	(original)
+++ trunk/Tomboy/Addins/Makefile.am	Thu Jan 10 01:45:30 2008
@@ -5,6 +5,7 @@
 	Evolution		\
 	FixedWidth			\
 	GalagoPresence		\
+	Sketching			\
 	InsertTimestamp		\
 	NoteOfTheDay		\
 	PrintNotes			\

Added: trunk/Tomboy/Addins/Sketching/Handwriting.cs
==============================================================================
--- (empty file)
+++ trunk/Tomboy/Addins/Sketching/Handwriting.cs	Thu Jan 10 01:45:30 2008
@@ -0,0 +1,257 @@
+using System;
+using System.Xml;
+using Cairo;
+using Gtk;
+using Gdk;
+
+namespace VirtualPaper
+{
+    public class Handwriting : DrawingArea
+    {
+        public event EventHandler Changed;
+
+        private Paper paper;
+
+        public Paper Paper {
+            get {
+                return paper;
+            }
+            protected set {
+                paper = value;
+            }
+        }
+                
+        public Handwriting(Paper p) : base()
+        {
+            AppPaintable = true;
+            Events = EventMask.ExposureMask | EventMask.ButtonPressMask |
+                     EventMask.ButtonReleaseMask | EventMask.PointerMotionMask;
+            ExtensionEvents = ExtensionMode.Cursor;
+
+            Paper = p;
+
+            // TODO: How do you shut the mouse cursor up?  If they're using a
+            // tablet, there should be no cursor at all.  At worst, a little
+            // black dot representing the pen size and color, but I'd prefer
+            // no cursor at all.  If they're using a mouse, then the little
+            // dot can stay.
+//            GdkWindow.Cursor = Cursor.NewFromName(Display.Default, "Clock");
+        }
+
+        public void DrawToSurface(Cairo.Surface surface, Gdk.Rectangle size)
+        {
+            Cairo.Context cr = new Cairo.Context(surface);
+
+            Paper.Draw(cr, size);
+
+            ((IDisposable)cr).Dispose();
+        }
+
+        public void Serialize(XmlTextWriter xml)
+        {
+/*            xml.WriteStartDocument();
+            xml.WriteStartElement(null, "handwriting-data", null);
+            xml.WriteAttributeString("version", "0.1");
+
+            // Paper Configuration
+            xml.WriteStartElement(null, "paper", null);
+
+            paper.Serialize(xml);
+
+            xml.WriteEndElement();
+
+            // Strokes
+            xml.WriteStartElement(null, "strokes", null);
+
+            foreach(Stroke s in strokes) {
+                s.WriteXml(xml);
+            }
+
+            xml.WriteEndElement();*/
+        }
+
+        public void Deserialize(XmlTextReader xml)
+        {
+            Clear();
+
+/*            while(xml.Read()) {
+                switch(xml.NodeType) {
+                case XmlNodeType.Element:
+                    if(xml.Name == "handwriting-data") {
+                        break;
+                    } else if(xml.Name == "paper") {
+                        paper = Paper.Deserialize(xml);
+                    } else if(xml.Name == "strokes") {
+                        while(xml.Read()) {
+                            if(xml.NodeType == XmlNodeType.Element &&
+                                xml.Name == "stroke") {
+                                CairoStroke stroke = new CairoStroke(xml);
+                                countPoints += stroke.Count;
+                                strokes.Add(stroke);
+                            } else if(xml.NodeType == XmlNodeType.EndElement) {
+                                break;
+                            }
+                        }
+                    } else {
+                        Console.WriteLine("Ignoring Unknown XML Element: {0}",
+                            xml.Name);
+                    }
+                    break;
+                }
+            }*/
+        }
+
+        public void Undo()
+        {
+            Stroke undoneStroke = Paper.Undo();
+            if(undoneStroke != null) {
+                QueueDrawArea(undoneStroke);
+            }
+        }
+
+        public void Redo()
+        {
+            Stroke redoneStroke = Paper.Redo();
+            if(redoneStroke != null) {
+                QueueDrawArea(redoneStroke);
+            }
+        }
+
+        public void Clear()
+        {
+            Paper.Clear();
+            QueueDraw();
+        }
+
+        protected override bool OnConfigureEvent(EventConfigure ev)
+        {
+            foreach(Device d in GdkWindow.Display.ListDevices()) {
+                if(d.Source == InputSource.Pen ||
+                   d.Source == InputSource.Eraser ||
+                   d.Source == InputSource.Mouse) {
+                    d.SetMode(InputMode.Screen);
+                }
+            }
+
+            return true;
+        }
+
+        protected override bool OnExposeEvent(EventExpose ev)
+        {
+            if(!IsRealized) {
+                return false;
+            }
+
+            Cairo.Context cr = CairoHelper.Create(GdkWindow);
+
+            Gdk.Rectangle rect = ev.Area;
+            cr.Rectangle(rect.X, rect.Y, rect.Width, rect.Height);
+            cr.Clip();
+
+            Paper.Draw(cr, rect);
+
+            // Uncomment this to see the clipping region
+/*            cr.Color = new Cairo.Color(0.0,1.0,0.0,0.5);
+            cr.Rectangle(rect.X, rect.Y, rect.Width, rect.Height);
+            cr.Stroke();*/
+
+            ((IDisposable)cr).Dispose();
+
+            return true;
+        }
+
+        protected override bool OnButtonPressEvent(EventButton ev)
+        {
+            if(ev.Device.Source == InputSource.Pen ||
+               ev.Device.Source == InputSource.Mouse) {
+                if(ev.Device.NumAxes > 2 || ev.Button == 1) {
+                    Paper.BeginStroke(Paper.Pen);
+                } else if(ev.Button == 3) {
+                        Paper.BeginStroke(Paper.Eraser);
+                }
+                // We don't care about any other buttons
+            } else if(ev.Device.Source == InputSource.Eraser ||
+                ev.Button == 3) {
+                Paper.BeginStroke(Paper.Eraser);
+            }
+            // Any other combinations?  They go here.
+
+            return true;
+        }
+
+        protected override bool OnButtonReleaseEvent(EventButton ev)
+        {
+            Paper.EndStroke();
+
+            return true;
+        }
+
+        protected override bool OnMotionNotifyEvent(EventMotion ev)
+        {
+            if(!Paper.AwaitingStrokeData) {
+                return true;
+            }
+            double[] axes;
+            ModifierType mask;
+
+            if(ev.IsHint) {
+                ev.Device.GetState(GdkWindow, out axes, out mask);
+            } else {
+                axes = ev.Axes;
+                mask = ev.State;
+            }
+
+            Gdk.Rectangle changed = Gdk.Rectangle.Zero;
+
+            if(ev.Device.Source == InputSource.Pen) {
+                if(ev.Device.NumAxes > 2) {
+                    Console.WriteLine("X: {0}, Y: {1}", axes[0], axes[1]);
+                    changed = Paper.ContinueStroke(axes[0], axes[1], axes[2],
+                        0d, 0d);
+                } else {
+                    changed = Paper.ContinueStroke(axes[0], axes[1], 1d,
+                        0d, 0d);
+                }
+            } else if(ev.Device.Source == InputSource.Eraser) {
+                changed = Paper.ContinueStroke(axes[0], axes[1], 1d, 0d, 0d);
+            } else if(ev.Device.Source == InputSource.Mouse) {
+                changed = Paper.ContinueStroke(ev.X, ev.Y, 1d, 0d, 0d);
+            } else {
+                // Unknown Button
+            }
+
+            if(changed != Gdk.Rectangle.Zero) {
+                QueueDrawArea(changed);
+            }
+
+            return true;
+        }
+
+        private void QueueDrawArea(Stroke s)
+        {
+            QueueDrawArea((int)s.X, (int)s.Y, (int)s.Width, (int)s.Height);
+        }
+
+        private void QueueDrawArea(Gdk.Rectangle r)
+        {
+            QueueDrawArea(r.X, r.Y, r.Width, r.Height);
+        }
+
+/*        private void QueuePaddedDrawArea(Stroke s)
+        {
+            QueuePaddedDrawArea((int)s.X,(int)s.Y,(int)s.Width,(int)s.Height);
+        }
+
+        private void QueuePaddedDrawArea(Gdk.Rectangle r)
+        {
+            QueuePaddedDrawArea(r.X, r.Y, r.Width, r.Height);
+        }
+
+        private void QueuePaddedDrawArea(int X, int Y, int Width, int Height) {
+            int lineWidth = Convert.ToInt32(penStyle.Size);
+            QueueDrawArea(X     -   lineWidth, Y      -   lineWidth,
+                          Width + 2*lineWidth, Height + 2*lineWidth);
+        }*/
+
+    }
+}

Added: trunk/Tomboy/Addins/Sketching/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/Tomboy/Addins/Sketching/Makefile.am	Thu Jan 10 01:45:30 2008
@@ -0,0 +1,44 @@
+include $(top_srcdir)/Makefile.include
+
+CSFLAGS = 		\
+	-debug 		\
+	-define:DEBUG 	\
+	-target:library
+
+ASSEMBLIES = 					\
+	$(LINK_TOMBOY_EXE)			\
+	$(TOMBOY_LIBS) 				\
+	$(LINK_MONO_ADDINS)			\
+	-r:Mono.Posix               \
+	-r:Mono.Cairo
+
+ADDIN_NAME = Sketching
+CSFILES = \
+	$(srcdir)/SketchingNoteAddin.cs	\
+	$(srcdir)/SketchingTextTag.cs   \
+	$(srcdir)/Handwriting.cs        \
+	$(srcdir)/Paper.cs              \
+	$(srcdir)/Pen.cs                \
+	$(srcdir)/Stroke.cs
+
+if ENABLE_SKETCHING
+TARGET = $(ADDIN_NAME).dll
+RESOURCES = \
+	-resource:$(srcdir)/$(ADDIN_NAME).addin.xml
+
+$(TARGET): $(CSFILES) $(top_builddir)/Tomboy/Tomboy.exe
+	$(CSC) -out:$@ $(CSFLAGS) $(ASSEMBLIES) $(CSFILES) $(RESOURCES)
+endif
+
+addinsdir = $(pkglibdir)/addins
+addins_DATA = 			\
+	$(TARGET)
+
+EXTRA_DIST =            	\
+	$(CSFILES) \
+	$(srcdir)/$(ADDIN_NAME).addin.xml
+
+CLEANFILES =				\
+	$(TARGET).mdb \
+	$(TARGET)
+

Added: trunk/Tomboy/Addins/Sketching/Paper.cs
==============================================================================
--- (empty file)
+++ trunk/Tomboy/Addins/Sketching/Paper.cs	Thu Jan 10 01:45:30 2008
@@ -0,0 +1,226 @@
+using System;
+using System.Xml;
+using System.Collections.Generic;
+using Cairo;
+
+namespace VirtualPaper
+{
+    public class Paper
+    {
+        private Color        backgroundColor;
+        private Stroke       activeStroke;
+        private List<Stroke> strokes;
+        private Pen          pen;
+        private Pen          eraser;
+
+        private int undo;
+
+        public Color BackgroundColor {
+            get {
+                return backgroundColor;
+            }
+            protected set {
+                backgroundColor = value;
+            }
+        }
+
+        public List<Stroke> Strokes {
+            get {
+                return strokes;
+            }
+            protected set {
+                strokes = value;
+            }
+        }
+
+        public Pen Pen {
+            get {
+                return pen;
+            }
+            protected set {
+                pen = value;
+            }
+        }
+
+        public Pen Eraser {
+            get {
+                return eraser;
+            }
+            protected set {
+                eraser = value;
+            }
+        }
+
+        public virtual bool CanUndo {
+            get {
+                return undo > Strokes.Count;
+            }
+        }
+
+        public virtual bool CanRedo {
+            get {
+                return undo > 0;
+            }
+        }
+
+        public virtual Gdk.Rectangle Bounds {
+            get {
+                Gdk.Rectangle bounds = new Gdk.Rectangle();
+                foreach(Stroke stroke in Strokes) {
+                    if(stroke.Bounds.X + stroke.Bounds.Width > bounds.Width)
+                        bounds.Width = stroke.Bounds.X + stroke.Bounds.Width;
+                    if(stroke.Bounds.Y + stroke.Bounds.Height > bounds.Height)
+                        bounds.Height = stroke.Bounds.Y + stroke.Bounds.Height;
+                }
+                return bounds;
+            }
+        }
+
+        public bool AwaitingStrokeData {
+            get {
+                return activeStroke != null;
+            }
+        }
+
+        public Paper(Color background)
+        {
+            BackgroundColor = background;
+
+            Strokes = new List<Stroke>();
+
+            Pen = new Pen();
+            Pen.Color = new Cairo.Color(0.0,0.0,0.0,1.0);
+            Pen.Size  = 3.0;
+
+            Eraser = new Pen();
+            Eraser.Color = background;
+            Eraser.Size  = 10.0;
+        }
+
+        public Paper(XmlTextReader xml)
+        {
+/*            while(xml.Read()) {
+                if(xml.NodeType == XmlNodeType.Element) {
+                    if(xml.Name == "background-color") {
+                        BackgroundColor.R = Convert.ToDouble(xml.GetAttribute("r"));
+                        BackgroundColor.G = Convert.ToDouble(xml.GetAttribute("g"));
+                        BackgroundColor.B = Convert.ToDouble(xml.GetAttribute("b"));
+                        BackgroundColor.A = Convert.ToDouble(xml.GetAttribute("a"));
+                    } else {
+                        Console.WriteLine("Ignoring Unknown XML Element: {0}",
+                            xml.Name);
+                    }
+                }
+            }*/
+        }
+
+        public virtual void Draw(Context cr, Gdk.Rectangle clip)
+        {
+            cr.Rectangle(clip.X, clip.Y, clip.Width, clip.Height);
+            cr.Color = BackgroundColor;
+            cr.Fill();
+            cr.Stroke();
+
+            DrawStrokes(cr, clip);
+        }
+
+        protected virtual void DrawStrokes(Context cr, Gdk.Rectangle clip)
+        {
+            int strokeCount = Strokes.Count;
+
+            foreach(Stroke stroke in Strokes) {
+                strokeCount--;
+                if(strokeCount < undo) break;
+
+                if(stroke.Bounds.IntersectsWith(clip)) {
+                    stroke.Draw(cr, clip);
+                }
+            }
+        }
+
+        public virtual Stroke Undo()
+        {
+            if(CanUndo) {
+                undo++;
+                return Strokes[Strokes.Count - undo];
+            }
+
+            return null;
+        }
+
+        public virtual Stroke Redo()
+        {
+            if(CanRedo) {
+                Stroke redoneStroke = Strokes[Strokes.Count - undo];
+                undo--;
+                return redoneStroke;
+            }
+
+            return null;
+        }
+
+        public virtual void Clear()
+        {
+            Strokes.Clear();
+            undo = 0;
+        }
+
+        public virtual void BeginStroke(Pen style)
+        {
+            activeStroke = new Stroke(style);
+
+            Strokes.RemoveRange(Strokes.Count - undo, undo);
+            undo = 0;
+
+            Strokes.Add(activeStroke);
+        }
+
+        public virtual Gdk.Rectangle ContinueStroke(double x, double y,
+            double p, double tx, double ty)
+        {
+            if(activeStroke == null)
+                return new Gdk.Rectangle(0,0,0,0);
+
+            Gdk.Rectangle changed =
+                activeStroke.AddPoint(x, y, p);
+            if(changed.Width  < 1) changed.Width  = 1;
+            if(changed.Height < 1) changed.Height = 1;
+
+            return changed;
+        }
+
+        public virtual void EndStroke()
+        {
+            activeStroke = null;
+        }
+
+        public virtual void Serialize(XmlTextWriter xml)
+        {
+            xml.WriteStartElement(null, "background-color", null);
+            xml.WriteAttributeString("r", BackgroundColor.R.ToString());
+            xml.WriteAttributeString("g", BackgroundColor.G.ToString());
+            xml.WriteAttributeString("b", BackgroundColor.B.ToString());
+            xml.WriteAttributeString("a", BackgroundColor.A.ToString());
+            xml.WriteEndElement();
+        }
+
+        public static Paper Deserialize(XmlTextReader xml)
+        {
+            // TODO: The following is a poor example of how we do object-
+            // oriented programming.  I should be shot for this.  However,
+            // much like the Undo code, I just want to see it work and clean
+            // it up later.  Enjoy and laugh :-D
+/*            string type = xml.GetAttribute("type");
+            if(type == "NotebookPaper") {
+                return new NotebookPaper(xml);
+            } else if(type == "Paper") {
+                return new Paper(xml);
+            } else {
+                Console.WriteLine("Unknown Paper Type: {0}", type);
+                Console.WriteLine("Defaulting to Plain Paper");
+                return new Paper(xml);
+            }*/
+            return null;
+        }
+    }
+}

Added: trunk/Tomboy/Addins/Sketching/Pen.cs
==============================================================================
--- (empty file)
+++ trunk/Tomboy/Addins/Sketching/Pen.cs	Thu Jan 10 01:45:30 2008
@@ -0,0 +1,36 @@
+using Cairo;
+
+namespace VirtualPaper
+{
+    public class Pen
+    {
+        private Color color;
+        private double size;
+
+        public Color Color {
+            get { return color; }
+            set { color = value; }
+        }
+
+        public double Size {
+            get { return size; }
+            set { size = value; }
+        }
+
+        public Pen()
+        {
+            color = new Color(0.0,0.0,0.0,1.0);
+            size = 3.0;
+        }
+
+        public Pen Clone()
+        {
+            Pen p = new Pen();
+
+            p.Color = new Color(color.R, Color.G, Color.B, Color.A);
+            p.Size  = size;
+
+            return p;
+        }
+    }
+}

Added: trunk/Tomboy/Addins/Sketching/Sketching.addin.xml
==============================================================================
--- (empty file)
+++ trunk/Tomboy/Addins/Sketching/Sketching.addin.xml	Thu Jan 10 01:45:30 2008
@@ -0,0 +1,21 @@
+<Addin id="SketchingAddin"
+	namespace="Tomboy"
+	name="Sketching"
+	author="Tomboy Project"
+	description="Sketch a drawing directly inside of a note."
+	category="Tools"
+	defaultEnabled="true"
+	version="0.1">
+
+	<Runtime>
+		<Import assembly="Sketching.dll" />
+	</Runtime>
+
+	<Dependencies>
+		<Addin id="Tomboy" version="0.7" />
+	</Dependencies>
+
+	<Extension path="/Tomboy/NoteAddins">
+		<NoteAddin type="Tomboy.Sketching.SketchingNoteAddin" />
+	</Extension>
+</Addin>

Added: trunk/Tomboy/Addins/Sketching/SketchingNoteAddin.cs
==============================================================================
--- (empty file)
+++ trunk/Tomboy/Addins/Sketching/SketchingNoteAddin.cs	Thu Jan 10 01:45:30 2008
@@ -0,0 +1,59 @@
+using System;
+using System.Collections;
+using VirtualPaper;
+
+using Mono.Unix;
+
+using Tomboy;
+
+namespace Tomboy.Sketching
+{
+	public class SketchingNoteAddin : NoteAddin
+	{
+		Gtk.ImageMenuItem menu_item;
+		
+		public override void Initialize ()
+		{
+			menu_item = new Gtk.ImageMenuItem (
+					Catalog.GetString ("Add a sketch"));
+			// FIXME: Use a real Sketching icon instead of the Edit icon
+			menu_item.Image = new Gtk.Image (Gtk.Stock.Edit, Gtk.IconSize.Menu);
+			menu_item.Activated += OnMenuItemActivated;
+			menu_item.Show ();
+			AddPluginMenuItem (menu_item);
+
+			if (!Note.TagTable.IsDynamicTagRegistered ("sketch"))
+				Note.TagTable.RegisterDynamicTag ("sketch", typeof (SketchingTextTag));
+		}
+
+		public override void Shutdown ()
+		{
+			// The following two lines are required to prevent the plugin
+			// from leaking references when the plugin is disabled.
+			menu_item.Activated -= OnMenuItemActivated;
+		}
+
+		public override void OnNoteOpened ()
+		{
+		}
+		
+		void OnMenuItemActivated (object sender, EventArgs args)
+		{
+			// Insert a new Sketching Widget at the current cursor position
+			SketchingTextTag tag = (SketchingTextTag)
+				Note.TagTable.CreateDynamicTag ("sketch");
+
+			// FIXME: Create a dynamic name for a sketch file that will
+			// be stored in the note's attachments directory.
+			tag.Uri = "test";
+            Handwriting h = new Handwriting(new Paper(new Cairo.Color(1.0,1.0,1.0,1.0)));
+            h.SetSizeRequest(500,500);
+            tag.Widget = h;
+
+			// Insert the sketch tag at the current cursor position
+			Gtk.TextIter cursor = Buffer.GetIterAtMark (Buffer.InsertMark);
+			Gtk.TextTag[] tags = {tag};
+			Buffer.InsertWithTags (ref cursor, String.Empty, tags);
+		}
+	}
+}

Added: trunk/Tomboy/Addins/Sketching/SketchingTextTag.cs
==============================================================================
--- (empty file)
+++ trunk/Tomboy/Addins/Sketching/SketchingTextTag.cs	Thu Jan 10 01:45:30 2008
@@ -0,0 +1,32 @@
+using System;
+using Tomboy;
+
+namespace Tomboy.Sketching
+{
+	public class SketchingTextTag : DynamicNoteTag
+	{
+		Gdk.Pixbuf Icon;
+
+		public SketchingTextTag ()
+			: base ()
+		{
+		}
+
+		public override void Initialize (string element_name)
+		{
+			base.Initialize (element_name);
+
+			Foreground = "black";
+			CanActivate = true;
+			CanGrow = true;
+			CanSpellCheck = false;
+			CanSplit = false;
+		}
+
+		public string Uri
+		{
+			get { return (string) Attributes ["uri"]; }
+			set { Attributes ["uri"] = value; }
+		}
+	}
+}

Added: trunk/Tomboy/Addins/Sketching/Stroke.cs
==============================================================================
--- (empty file)
+++ trunk/Tomboy/Addins/Sketching/Stroke.cs	Thu Jan 10 01:45:30 2008
@@ -0,0 +1,180 @@
+using System;
+using System.Xml;
+using System.Collections.Generic;
+using Cairo;
+
+namespace VirtualPaper
+{
+    public class Stroke
+    {
+        protected List<double> x, y;
+        protected List<Color> color;
+        protected Pen style;
+        protected int count;
+        protected double minX;
+        protected double minY;
+        protected double maxX;
+        protected double maxY;
+        protected bool firstStroke;
+
+        public virtual double X {
+            get {
+                return minX;
+            }
+        }
+
+        public virtual double Y {
+            get {
+                return minY;
+            }
+        }
+
+        public virtual double Height {
+            get {
+                return maxY - minY;
+            }
+        }
+
+        public virtual double Width {
+            get {
+                return maxX - minX;
+            }
+        }
+
+        public Gdk.Rectangle Bounds {
+            get {
+                int w = (int)Math.Ceiling(style.Size);
+                int w2 = w*2;
+
+                Gdk.Rectangle rect = new Gdk.Rectangle();
+                rect.X = (int)minX - w;
+                rect.Y = (int)minY - w;
+                rect.Width = (int)(maxX - minX) + w2;
+                rect.Height = (int)(maxY - minY) + w2;
+                return rect;
+            }
+        }
+        
+        public virtual int Count {
+            get {
+                return count;
+            }
+        }
+
+        public Stroke(Pen penStyle)
+        {
+            x = new List<double>();
+            y = new List<double>();
+            color = new List<Cairo.Color>();
+            style = penStyle.Clone();
+            count = 0;
+            minX = 0;
+            minY = 0;
+            maxX = 0;
+            maxY = 0;
+            firstStroke = false;
+        }
+
+        public virtual void AddPoint(double x, double y)
+        {
+            AddPoint(x, y, 1.0);
+        }
+
+        public virtual Gdk.Rectangle AddPoint(double x, double y, double pressure)
+        {
+            Cairo.Color c = new Cairo.Color(
+                style.Color.R,
+                style.Color.G,
+                style.Color.B,
+                pressure);
+            this.x.Add(x);
+            this.y.Add(y);
+            this.color.Add(c);
+            count++;
+
+            if(firstStroke) {
+                if(x < minX) minX = x;
+                else if(x > maxX) maxX = x;
+                if(y < minY) minY = y;
+                else if(y > maxY) maxY = y;
+            } else {
+                minX = x;
+                maxX = x;
+                minY = y;
+                maxY = y;
+                firstStroke = true;
+            }
+
+            int w = (int)Math.Ceiling(style.Size);
+            int w2 = w*2;
+
+            if(this.x.Count > 1 && this.y.Count > 1) {
+                double oldX = this.x[this.x.Count - 2];
+                double oldY = this.y[this.y.Count - 2];
+                if(x < oldX) {
+                    double temp = oldX;
+                    oldX = x;
+                    x = temp;
+                }
+                if(y < oldY) {
+                    double temp = oldY;
+                    oldY = y;
+                    y = temp;
+                }
+
+                return new Gdk.Rectangle((int)oldX - w, (int)oldY - w,
+                    (int)(x - oldX) + w2, (int)(y - oldY) + w2);
+            }
+            return new Gdk.Rectangle((int)x - w, (int)y - w, w2, w2);
+        }
+
+        public void Draw(Context cr, Gdk.Rectangle clip)
+        {
+            cr.LineWidth = style.Size;
+
+            for(int i = 1; i < count; i++) {
+                Gdk.Rectangle rect = new Gdk.Rectangle();
+                rect.X = (int)((x[i] < x[i-1]) ? x[i] : x[i-1]);
+                rect.Y = (int)((y[i] < y[i-1]) ? y[i] : y[i-1]);
+                rect.Width  = (int)((x[i] < x[i-1]) ? x[i-1]-x[i] : x[i]-x[i-1]);
+                rect.Height = (int)((y[i] < y[i-1]) ? y[i-1]-y[i] : y[i]-y[i-1]);
+
+                if(clip.IntersectsWith(rect)) {
+                    cr.MoveTo(x[i-1], y[i-1]);
+                    cr.LineTo(x[i], y[i]);
+
+                    LinearGradient g = new LinearGradient(x[i-1], y[i-1], x[i], y[i]);
+                    g.AddColorStop(0.0, color[i-1]);
+                    g.AddColorStop(1.0, color[i]);
+
+                    cr.Pattern = g;
+                    cr.Stroke();
+                }
+            }
+        }
+
+        public virtual void WriteXml(XmlTextWriter xml)
+        {
+            xml.WriteStartElement(null, "stroke", null);
+
+            xml.WriteAttributeString("left", minX.ToString());
+            xml.WriteAttributeString("top", minY.ToString());
+            xml.WriteAttributeString("right", maxX.ToString());
+            xml.WriteAttributeString("bottom", maxY.ToString());
+
+            WriteXmlPoints(xml);
+
+            xml.WriteEndElement();
+        }
+
+        protected virtual void WriteXmlPoints(XmlTextWriter xml)
+        {
+            for(int i = 0; i < count; i++) {
+                xml.WriteStartElement(null, "point", null);
+                xml.WriteAttributeString("x", x[i].ToString());
+                xml.WriteAttributeString("y", y[i].ToString());
+                xml.WriteEndElement();
+            }
+        }
+    }
+}

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Thu Jan 10 01:45:30 2008
@@ -159,6 +159,17 @@
 AC_SUBST(EVOLUTION_LIBS)
 
 #
+# Sketching.dll is very sketchy; for now disable by default
+#
+PKG_CHECK_MODULES(CAIRO, mono-cairo, [
+          AC_ARG_ENABLE(sketching,
+              [  --enable-sketching[[=no/yes]]  compile sketching addin [[default: disabled]]],
+              ENABLE_SKETCHING="$enableval") ],
+          ENABLE_SKETCHING="no")
+AM_CONDITIONAL(ENABLE_SKETCHING, test "$ENABLE_SKETCHING" = "yes")
+AC_SUBST(SKETCHING_LIBS)
+
+#
 # GalagoPresence.dll needs Galago#
 #
 PKG_CHECK_MODULES(GALAGO, galago-sharp >= 0.5.0, ENABLE_GALAGO="yes", ENABLE_GALAGO="no")
@@ -228,6 +239,7 @@
 Tomboy/Addins/Evolution/Makefile
 Tomboy/Addins/FixedWidth/Makefile
 Tomboy/Addins/GalagoPresence/Makefile
+Tomboy/Addins/Sketching/Makefile
 Tomboy/Addins/InsertTimestamp/Makefile
 Tomboy/Addins/NoteOfTheDay/Makefile
 Tomboy/Addins/PrintNotes/Makefile



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