tomboy r2313 - in trunk: . Tomboy/Addins/PrintNotes po



Author: sharm
Date: Mon Feb  2 06:14:24 2009
New Revision: 2313
URL: http://svn.gnome.org/viewvc/tomboy?rev=2313&view=rev

Log:
* po/POTFILES.in:
* Tomboy/Addins/PrintNotes/Makefile.am:
* Tomboy/Addins/PrintNotes/gedit-print.h:
* Tomboy/Addins/PrintNotes/gedit-print.c:
* Tomboy/Addins/PrintNotes/gtksourceprintjob.h:
* Tomboy/Addins/PrintNotes/gtksourceprintjob.c: Delete old
  libgnomeprint-dependent print code. Add Mono.Cairo reference.

* Tomboy/Addins/PrintNotes/PrintNotes.addin.xml: Bump to version 0.2.

* Tomboy/Addins/PrintNotes/PrintNotesNoteAddin.cs: New printing
  implementation using Gtk.Print. Partial fix for bug #512369. There
  are known wacky margin/header/footer problems on Linux. Many thanks
  to Benjamin Podszun for doing this in record time.

Removed:
   trunk/Tomboy/Addins/PrintNotes/gedit-print.c
   trunk/Tomboy/Addins/PrintNotes/gedit-print.h
   trunk/Tomboy/Addins/PrintNotes/gtksourceprintjob.c
   trunk/Tomboy/Addins/PrintNotes/gtksourceprintjob.h
Modified:
   trunk/ChangeLog
   trunk/Tomboy/Addins/PrintNotes/Makefile.am
   trunk/Tomboy/Addins/PrintNotes/PrintNotes.addin.xml
   trunk/Tomboy/Addins/PrintNotes/PrintNotesNoteAddin.cs
   trunk/po/POTFILES.in

Modified: trunk/Tomboy/Addins/PrintNotes/Makefile.am
==============================================================================
--- trunk/Tomboy/Addins/PrintNotes/Makefile.am	(original)
+++ trunk/Tomboy/Addins/PrintNotes/Makefile.am	Mon Feb  2 06:14:24 2009
@@ -9,7 +9,8 @@
 	$(LINK_TOMBOY_EXE)			\
 	$(GTKSHARP_LIBS) 				\
 	$(LINK_MONO_ADDINS)			\
-	-r:Mono.Posix
+	-r:Mono.Posix				\
+	-r:Mono.Cairo
 
 ADDIN_NAME = PrintNotes
 TARGET = $(ADDIN_NAME).dll
@@ -35,29 +36,5 @@
 	$(TARGET).mdb \
 	$(TARGET)
 
-##
-## Build libprintnotes for gedit print capability
-##
-
-INCLUDES =								\
-	-I$(top_srcdir)						\
-	-DG_LOG_DOMAIN=\"libprintnotes\"	\
-	-DGTK_DISABLE_DEPRECATED			\
-	-DGDK_DISABLE_DEPRECATED			\
-	-DG_DISABLE_DEPRECATED				\
-	$(LIBTOMBOY_CFLAGS)
-
-printnoteslibdir = $(pkglibdir)
-printnoteslib_LTLIBRARIES = libprintnotes.la
-
-libprintnotes_la_SOURCES =				\
-	gedit-print.h						\
-	gedit-print.c						\
-	gtksourceprintjob.h					\
-	gtksourceprintjob.c
-
-libprintnotes_la_LDFLAGS = -export-dynamic -module -avoid-version
-libprintnotes_la_LIBADD = $(LIBTOMBOY_LIBS)
-
 maintainer-clean-local:
 	rm -f Makefile.in

Modified: trunk/Tomboy/Addins/PrintNotes/PrintNotes.addin.xml
==============================================================================
--- trunk/Tomboy/Addins/PrintNotes/PrintNotes.addin.xml	(original)
+++ trunk/Tomboy/Addins/PrintNotes/PrintNotes.addin.xml	Mon Feb  2 06:14:24 2009
@@ -5,7 +5,7 @@
 	description="Allows you to print a note."
 	category="Desktop Integration"
 	defaultEnabled="true"
-	version="0.1">
+	version="0.2">
 
 	<Runtime>
 		<Import assembly="PrintNotes.dll" />

Modified: trunk/Tomboy/Addins/PrintNotes/PrintNotesNoteAddin.cs
==============================================================================
--- trunk/Tomboy/Addins/PrintNotes/PrintNotesNoteAddin.cs	(original)
+++ trunk/Tomboy/Addins/PrintNotes/PrintNotesNoteAddin.cs	Mon Feb  2 06:14:24 2009
@@ -1,26 +1,53 @@
-
 using System;
-using System.Runtime.InteropServices;
+using System.Collections.Generic;
 using Mono.Unix;
 
-using Gtk;
-
-using Tomboy;
-
 namespace Tomboy.PrintNotes
 {
+	// TODO:
+	// COMMENT! A lot!
+	// Remove magic numbers (margins), turn them into constants or preferences
+	// Localize the footer?
+	// Replace bullet point chars with an image?
+	// Split the file if it grows any further
+
+	struct PrintMargins
+	{
+		public int Top;
+		public int Left;
+		public int Right;
+		public int Bottom;
+
+		public int VerticalMargins ()
+		{
+			return Top + Bottom;
+		}
+
+		public int HorizontalMargins ()
+		{
+			return Left + Right;
+		}
+	}
+
 	public class PrintNotesNoteAddin : NoteAddin
 	{
-		Gtk.ImageMenuItem item;
+		private Gtk.ImageMenuItem item;
+		private Gtk.PrintOperation print_op;
+		private PrintMargins page_margins;
+		private Pango.Layout date_time_footer;
+		private List<int> page_breaks;
 
 		public override void Initialize ()
 		{
+			page_margins = new PrintMargins ();
+			page_margins.Top = 400;
+			page_margins.Left = 200;
+			page_margins.Right = 100;
+			page_margins.Bottom = 0;
 		}
 
 		public override void Shutdown ()
 		{
-			// Disconnect the event handlers so
-			// there aren't any memory leaks.
 			if (item != null)
 				item.Activated -= PrintButtonClicked;
 		}
@@ -30,20 +57,322 @@
 			item = new Gtk.ImageMenuItem (Catalog.GetString ("Print"));
 			item.Image = new Gtk.Image (Gtk.Stock.Print, Gtk.IconSize.Menu);
 			item.Activated += PrintButtonClicked;
+			item.AddAccelerator ("activate", Window.AccelGroup,
+				(uint) Gdk.Key.p, Gdk.ModifierType.ControlMask,
+				Gtk.AccelFlags.Visible);
 			item.Show ();
 			AddPluginMenuItem (item);
 		}
 
-		[DllImport("libprintnotes")]
-		static extern void gedit_print (IntPtr text_view_handle);
+		private void PrintButtonClicked (object sender, EventArgs args)
+		{
+			print_op = new Gtk.PrintOperation ();
+			print_op.JobName = Note.Title;
+
+			print_op.BeginPrint += OnBeginPrint;
+			print_op.DrawPage += OnDrawPage;
+			print_op.EndPrint += OnEndPrint;
+
+			print_op.Run (Gtk.PrintOperationAction.PrintDialog, Window);
+		}
+
+		private static IEnumerable<Pango.Attribute> GetParagraphAttributes (
+			Pango.Layout layout, ref PrintMargins margins,
+			ref Gtk.TextIter position, Gtk.TextIter limit)
+		{
+			IList<Pango.Attribute> attributes = new List<Pango.Attribute> ();
+
+			Gtk.TextTag [] tags = position.Tags;
+			position.ForwardToTagToggle (null);
+			if (position.Compare (limit) > 0) position = limit;
+
+			foreach (Gtk.TextTag tag in tags) {
+				if (tag.BackgroundSet) {
+					Gdk.Color color = tag.BackgroundGdk;
+					attributes.Add (new Pango.AttrBackground (
+						color.Red, color.Green, color.Blue));
+				}
+				if (tag.ForegroundSet) {
+					Gdk.Color color = tag.ForegroundGdk;
+					attributes.Add (new Pango.AttrForeground (
+						color.Red, color.Green, color.Blue));
+				}
+				if (tag.IndentSet) {
+					layout.Indent = tag.Indent;
+				}
+				if (tag.LeftMarginSet) {
+					margins.Left = Math.Max (tag.LeftMargin * 2, margins.Left);
+				}
+				if (tag.RightMarginSet) {
+					margins.Right = Math.Max (tag.RightMargin * 2, margins.Right);
+				}
+				if (tag.FontDesc != null) {
+					attributes.Add (new Pango.AttrFontDesc (tag.FontDesc));
+				}
+				if (tag.FamilySet) {
+					attributes.Add (new Pango.AttrFamily (tag.Family));
+				}
+				if (tag.SizeSet) {
+					attributes.Add (new Pango.AttrSize (tag.Size));
+				}
+				if (tag.StyleSet) {
+					attributes.Add (new Pango.AttrStyle (tag.Style));
+				}
+				if (tag.UnderlineSet && tag.Underline != Pango.Underline.Error) {
+					attributes.Add (new Pango.AttrUnderline (tag.Underline));
+				}
+				if (tag.WeightSet) {
+					attributes.Add (new Pango.AttrWeight (tag.Weight));
+				}
+				if (tag.StrikethroughSet) {
+					attributes.Add (new Pango.AttrStrikethrough (tag.Strikethrough));
+				}
+				if (tag.RiseSet) {
+					attributes.Add (new Pango.AttrRise (tag.Rise));
+				}
+				if (tag.ScaleSet) {
+					attributes.Add (new Pango.AttrScale (tag.Scale));
+				}
+				if (tag.StretchSet) {
+					attributes.Add (new Pango.AttrStretch (tag.Stretch));
+				}
+			}
+
+			return attributes;
+		}
+
+		private Pango.Layout CreateLayoutForParagraph (Gtk.PrintContext context,
+							       Gtk.TextIter p_start,
+							       Gtk.TextIter p_end,
+							       out PrintMargins margins)
+		{
+			Pango.Layout layout = context.CreatePangoLayout ();
+			layout.FontDescription = Window.Editor.Style.FontDesc;
+			int start_index = p_start.LineIndex;
+
+			margins = new PrintMargins ();
+
+			using (Pango.AttrList attr_list = new Pango.AttrList ()) {
+				Gtk.TextIter segm_start = p_start;
+				Gtk.TextIter segm_end;
+
+				while (segm_start.Compare (p_end) < 0) {
+					segm_end = segm_start;
+					IEnumerable<Pango.Attribute> attrs =
+						GetParagraphAttributes (
+							layout, ref margins,
+							ref segm_end, p_end);
+
+					uint si = (uint) (segm_start.LineIndex - start_index);
+					uint ei = (uint) (segm_end.LineIndex - start_index);
+
+					foreach (Pango.Attribute a in attrs) {
+						a.StartIndex = si;
+						a.EndIndex = ei;
+						attr_list.Insert (a);
+					}
+					segm_start = segm_end;
+				}
+
+				layout.Attributes = attr_list;
+			}
+
+			layout.Width = Pango.Units.FromPixels ((int)context.Width) -
+				Pango.Units.FromPixels (margins.HorizontalMargins ()) -
+				Pango.Units.FromPixels (page_margins.HorizontalMargins ());
+			layout.SetText (Buffer.GetSlice (p_start, p_end, false));
+			return layout;
+		}
+
+		private Pango.Layout CreateLayoutForPagenumbers (Gtk.PrintContext context, int page_number, int total_pages)
+		{
+			Pango.Layout layout = context.CreatePangoLayout ();
+			layout.FontDescription = Window.Editor.Style.FontDesc;
+			layout.Width = Pango.Units.FromPixels ((int) context.Width);
+			layout.FontDescription.Style = Pango.Style.Normal;
+			layout.FontDescription.Weight = Pango.Weight.Light;
+
+			string footer_left = string.Format (Catalog.GetString ("Page {0} of {1}"),
+			                                    page_number, total_pages);
+			layout.Alignment = Pango.Alignment.Left;
+			layout.SetText (footer_left);
+
+			return layout;
+		}
+
+		private Pango.Layout CreateLayoutForTimestamp (Gtk.PrintContext context)
+		{
+			Pango.Layout layout = context.CreatePangoLayout ();
+			layout.FontDescription = Window.Editor.Style.FontDesc;
+			layout.Width = Pango.Units.FromPixels ((int) context.Width);
+			layout.FontDescription.Style = Pango.Style.Normal;
+			layout.FontDescription.Weight = Pango.Weight.Light;
+
+			string footer_right = DateTime.Now.ToString (
+				Catalog.GetString ("dddd MM/dd/yyyy, hh:mm:ss tt"));
+			Logger.Debug (footer_right);
+			layout.Alignment = Pango.Alignment.Right;
+			layout.SetText (footer_right);
+
+			return layout;
+		}
+
+		private void OnBeginPrint (object sender, Gtk.BeginPrintArgs args)
+		{
+			Gtk.PrintContext context = args.Context;
+
+			date_time_footer = CreateLayoutForTimestamp (context);
+			Pango.Rectangle footer_ink_rect;
+			Pango.Rectangle footer_logical_rect;
+			date_time_footer.GetExtents (out footer_ink_rect,
+			                             out footer_logical_rect);
+			page_margins.Bottom += Pango.Units.ToPixels (footer_logical_rect.Height) +
+					       100;
+
+			double height = Pango.Units.FromPixels ((int) context.Height) - Pango.Units.FromPixels (page_margins.VerticalMargins ());
+			double page_height = 0;
+
+			page_breaks = new List<int> ();
+
+			Gtk.TextIter position;
+			Gtk.TextIter end_iter;
+			Buffer.GetBounds (out position, out end_iter);
+
+			bool done = position.Compare (end_iter) >= 0;
+			while (!done) {
+				int line_number = position.Line;
+
+				Gtk.TextIter line_end = position;
+				if (!line_end.EndsLine ())
+					line_end.ForwardToLineEnd ();
+
+				PrintMargins margins;
+				using (Pango.Layout layout = CreateLayoutForParagraph (
+					context, position, line_end, out margins)) {
+
+					Pango.Rectangle ink_rect;
+					Pango.Rectangle logical_rect;
+					layout.GetExtents (out ink_rect, out logical_rect);
+
+					if (page_height + logical_rect.Height > height) {
+						page_breaks.Add (line_number);
+						page_height = 0;
+					}
+
+					page_height += logical_rect.Height;
+				}
+
+				position.ForwardLine ();
+				done = position.Compare (end_iter) >= 0;
+			}
+
+			Gtk.PrintOperation op = (Gtk.PrintOperation) sender;
+			op.NPages = page_breaks.Count + 1;
+		}
+
+		private void PrintFooter (Gtk.DrawPageArgs args)
+		{
+			int total_height = Pango.Units.FromPixels ((int) args.Context.Height);
+			int total_width = Pango.Units.FromPixels ((int) args.Context.Width);
+
+			Cairo.Context cr = args.Context.CairoContext;
+
+			cr.MoveTo (50, Pango.Units.ToPixels (total_height - page_margins.Bottom));
+			cr.LineWidth = 4;
+			cr.LineTo (Pango.Units.ToPixels (total_width) - 100, Pango.Units.ToPixels (total_height - page_margins.Bottom));
+			cr.Stroke ();
+
+			Cairo.PointD footer_anchor = new Cairo.PointD (
+				50, Pango.Units.ToPixels (total_height - page_margins.Bottom) + 100);
+
+			cr.MoveTo (footer_anchor);
+			using (Pango.Layout pages_footer = CreateLayoutForPagenumbers (
+				args.Context, args.PageNr + 1, page_breaks.Count + 1)) {
+				Pango.CairoHelper.ShowLayoutLine (cr, pages_footer.Lines [0]);
+			}
+
+
+			Pango.Rectangle ink_rect;
+			Pango.Rectangle logical_rect;
+			date_time_footer.GetExtents (out ink_rect, out logical_rect);
+
+			cr.MoveTo (Pango.Units.ToPixels (total_width - logical_rect.Width) - 100, footer_anchor.Y);
+
+			Pango.CairoHelper.ShowLayoutLine (cr, date_time_footer.Lines [0]);
+		}
+
+		public void OnDrawPage (object sender, Gtk.DrawPageArgs args)
+		{
+			Cairo.Context cr = args.Context.CairoContext;
+			cr.MoveTo (page_margins.Left, page_margins.Top);
+
+			int start_line = 0;
+			if (args.PageNr != 0)
+				start_line = page_breaks [args.PageNr - 1] + 1;
+
+			int last_line = -1;
+			if (page_breaks.Count > args.PageNr)
+				last_line = page_breaks [args.PageNr];
+
+			Gtk.TextIter position;
+			Gtk.TextIter end_iter;
+			Buffer.GetBounds (out position, out end_iter);
 
-		//
-		// Handle Print menu item Click
-		//
+			bool done = position.Compare (end_iter) >= 0;
+			int line_number = position.Line;
+
+			// Fast-forward to the starting line
+			while (!done && line_number < start_line) {
+				Gtk.TextIter line_end = position;
+				if (!line_end.EndsLine ())
+					line_end.ForwardToLineEnd ();
+
+				position.ForwardLine ();
+				done = position.Compare (end_iter) >= 0;
+				line_number = position.Line;
+			}
+
+			// Print the current page's content
+			while (!done && ((last_line == -1) || (line_number < last_line))) {
+				line_number = position.Line;
+
+				Gtk.TextIter line_end = position;
+				if (!line_end.EndsLine ())
+					line_end.ForwardToLineEnd ();
+
+				PrintMargins margins;
+				using (Pango.Layout layout =
+					CreateLayoutForParagraph (args.Context,
+						position, line_end, out margins)) {
+
+					foreach (Pango.LayoutLine line in layout.Lines) {
+						Pango.Rectangle ink_rect = Pango.Rectangle.Zero;
+						Pango.Rectangle logical_rect = Pango.Rectangle.Zero;
+						line.GetExtents (ref ink_rect, ref logical_rect);
+
+						int line_height = (int) (logical_rect.Height /
+									 Pango.Scale.PangoScale);
+						Cairo.PointD new_line_point = new Cairo.PointD (
+							page_margins.Left + margins.Left,
+							cr.CurrentPoint.Y + line_height);
+						Pango.CairoHelper.ShowLayoutLine (cr, line);
+						cr.MoveTo (new_line_point);
+					}
+				}
+
+				position.ForwardLine ();
+				done = position.Compare (end_iter) >= 0;
+			}
+
+			// Print the footer
+			PrintFooter (args);
+		}
 
-		void PrintButtonClicked (object sender, EventArgs args)
+		private void OnEndPrint (object sender, Gtk.EndPrintArgs args)
 		{
-			gedit_print (Note.Window.Editor.Handle);
+			date_time_footer.Dispose ();
+			page_breaks.Clear ();
+			print_op.Dispose ();
 		}
 	}
 }

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Mon Feb  2 06:14:24 2009
@@ -30,8 +30,6 @@
 Tomboy/Addins/NoteOfTheDay/NoteOfTheDay.addin.xml
 Tomboy/Addins/PrintNotes/PrintNotesNoteAddin.cs
 Tomboy/Addins/PrintNotes/PrintNotes.addin.xml
-Tomboy/Addins/PrintNotes/gedit-print.c
-Tomboy/Addins/PrintNotes/gtksourceprintjob.c
 Tomboy/Addins/Sketching/SketchingNoteAddin.cs
 Tomboy/Addins/SshSyncService/SshSyncServiceAddin.cs
 Tomboy/Addins/SshSyncService/SshSyncService.addin.xml



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