/// <summary> /// Remove the task tag on the line specified by the TextIter. This /// will not remove the "todo:" text (i.e., it will not modify the /// actual characters of the TextBuffer. /// <param name="iter">The TextIter specifying the line where the /// TaskTag should be removed.</param> /// <returns>True if a TaskTag was removed, otherwise False.</returns> /// </summary> bool RemoveTaskTagFromLine(Gtk.TextIter iter) { Gtk.TextIter start = iter; Gtk.TextIter end = iter; TaskTag task_tag = GetTaskTagFromLineIter(ref start); if (task_tag == null) { return(false); } while (start.StartsLine() == false) { start.BackwardChar(); } while (end.EndsLine() == false) { end.ForwardChar(); } // end.ForwardToLineEnd (); last_removed_tag = null; Buffer.RemoveTag(task_tag, start, end); return(true); }
/// <summary> /// Remove the task from the line specified by the TextIter. This /// will remove the TextTag and also the "todo:" portion of the line /// so it will no longer be a task. The task summary text will be /// left on the line. /// <param name="iter">The TextIter specifying the line where the /// task should be removed.</param> /// <returns>True if a task was removed, otherwise False.</returns> /// </summary> bool RemoveTaskFromLine(ref Gtk.TextIter iter) { if (RemoveTaskTagFromLine(iter) == false) { return(false); } while (iter.StartsLine() == false) { iter.BackwardChar(); } Gtk.TextIter line_end = iter; while (line_end.EndsLine() == false) { line_end.ForwardChar(); } // line_end.ForwardToLineEnd (); string text = iter.GetText(line_end); Buffer.Delete(ref iter, ref line_end); text = GetTaskSummaryFromLine(text); if (text.Length > 0) { Buffer.Insert(ref iter, text); } return(true); }
private void OnBeginPrint(object sender, Gtk.BeginPrintArgs args) { Gtk.PrintOperation op = (Gtk.PrintOperation)sender; Gtk.PrintContext context = args.Context; timestamp_footer = CreateTimestampLayout(context); // FIXME: These should be configurable settings later (UI Change) margin_top = CmToPixel(1.5, context.DpiY); margin_left = CmToPixel(1, context.DpiX); margin_right = CmToPixel(1, context.DpiX); margin_bottom = 0; double max_height = Pango.Units.FromPixels((int)context.Height - margin_top - margin_bottom - ComputeFooterHeight(context)); Gtk.TextIter position; Gtk.TextIter end_iter; Buffer.GetBounds(out position, out end_iter); double page_height = 0; bool done = position.Compare(end_iter) >= 0; while (!done) { Gtk.TextIter line_end = position; if (!line_end.EndsLine()) { line_end.ForwardToLineEnd(); } int paragraph_number = position.Line; int indentation; using (Pango.Layout layout = CreateParagraphLayout( context, position, line_end, out indentation)) { Pango.Rectangle ink_rect = Pango.Rectangle.Zero; Pango.Rectangle logical_rect = Pango.Rectangle.Zero; for (int line_in_paragraph = 0; line_in_paragraph < layout.LineCount; line_in_paragraph++) { Pango.LayoutLine line = layout.GetLine(line_in_paragraph); line.GetExtents(ref ink_rect, ref logical_rect); if (page_height + logical_rect.Height >= max_height) { PageBreak page_break = new PageBreak( paragraph_number, line_in_paragraph); page_breaks.Add(page_break); page_height = 0; } page_height += logical_rect.Height; } position.ForwardLine(); done = position.Compare(end_iter) >= 0; } } op.NPages = page_breaks.Count + 1; }
/// <summary> /// If the renamed task is included inside this note, this /// handler will update the task summary in the note buffer. /// </summary> private void OnTaskRenamed(Task task, string old_title) { if (task.OriginNoteUri == null || task.OriginNoteUri != Note.Uri) { return; } // Search through the note looking for the TaskTag so that it can // be renamed if (!ContainsText(old_title)) { return; } // Iterate through the lines looking for tasks Gtk.TextIter iter = Buffer.StartIter; iter.ForwardLine(); // Move past the note's title do { TaskTag task_tag = (TaskTag) Buffer.GetDynamicTag("task", iter); if (task_tag != null) { if (task_tag.Uri != task.Uri) { continue; } Gtk.TextIter line_start = iter; while (line_start.StartsLine() == false) { line_start.BackwardChar(); } Gtk.TextIter line_end = iter; while (line_end.EndsLine() == false) { line_end.ForwardChar(); } // line_end.ForwardToLineEnd (); Buffer.Delete(ref line_start, ref line_end); last_removed_tag = task_tag; Buffer.Insert(ref line_start, string.Format("{0}: {1}", Catalog.GetString("todo"), task.Summary)); task_tag.fillByData(task.Data); break; } } while (iter.ForwardLine()); }
public void OnDrawPage(object sender, Gtk.DrawPageArgs args) { using (Cairo.Context cr = args.Context.CairoContext) { cr.MoveTo(margin_left, margin_top); PageBreak start; if (args.PageNr == 0) { start = new PageBreak(0, 0); } else { start = page_breaks [args.PageNr - 1]; } PageBreak end; if (args.PageNr < page_breaks.Count) { end = page_breaks [args.PageNr]; } else { end = new PageBreak(-1, -1); } Gtk.PrintContext context = args.Context; Gtk.TextIter position; Gtk.TextIter end_iter; Buffer.GetBounds(out position, out end_iter); // Fast-forward to the right starting paragraph while (position.Line < start.Paragraph) { position.ForwardLine(); } bool done = position.Compare(end_iter) >= 0; while (!done) { Gtk.TextIter line_end = position; if (!line_end.EndsLine()) { line_end.ForwardToLineEnd(); } int paragraph_number = position.Line; int indentation; using (Pango.Layout layout = CreateParagraphLayout( context, position, line_end, out indentation)) { for (int line_number = 0; line_number < layout.LineCount && !done; line_number++) { // Skip the lines up to the starting line in the // first paragraph on this page if ((paragraph_number == start.Paragraph) && (line_number < start.Line)) { continue; } // Break as soon as we hit the end line if ((paragraph_number == end.Paragraph) && (line_number == end.Line)) { done = true; break; } Pango.LayoutLine line = layout.Lines [line_number]; Pango.Rectangle ink_rect = Pango.Rectangle.Zero; Pango.Rectangle logical_rect = Pango.Rectangle.Zero; line.GetExtents(ref ink_rect, ref logical_rect); cr.MoveTo(margin_left + indentation, cr.CurrentPoint.Y); int line_height = Pango.Units.ToPixels(logical_rect.Height); Cairo.PointD new_line_point = new Cairo.PointD( margin_left + indentation, cr.CurrentPoint.Y + line_height); Pango.CairoHelper.ShowLayoutLine(cr, line); cr.MoveTo(new_line_point); } } position.ForwardLine(); done = done || position.Compare(end_iter) >= 0; } int total_height = (int)args.Context.Height; int total_width = (int)args.Context.Width; int footer_height = 0; Cairo.PointD footer_anchor; using (Pango.Layout pages_footer = CreatePagenumbersLayout( args.Context, args.PageNr + 1, page_breaks.Count + 1)) { Pango.Rectangle ink_footer_rect; Pango.Rectangle logical_footer_rect; pages_footer.GetExtents(out ink_footer_rect, out logical_footer_rect); footer_anchor = new Cairo.PointD( CmToPixel(0.5, args.Context.DpiX), total_height - margin_bottom); footer_height = Pango.Units.ToPixels(logical_footer_rect.Height); cr.MoveTo( total_width - Pango.Units.ToPixels(logical_footer_rect.Width) - CmToPixel(0.5, args.Context.DpiX), footer_anchor.Y); Pango.CairoHelper.ShowLayoutLine(cr, pages_footer.Lines [0]); } cr.MoveTo(footer_anchor); Pango.CairoHelper.ShowLayoutLine(cr, timestamp_footer.Lines [0]); cr.MoveTo(CmToPixel(0.5, args.Context.DpiX), total_height - margin_bottom - footer_height); cr.LineTo(total_width - CmToPixel(0.5, args.Context.DpiX), total_height - margin_bottom - footer_height); cr.Stroke(); } }
void OnInsertText(object sender, Gtk.InsertTextArgs args) { Gtk.TextIter start = args.Pos; //Logger.Debug ("TaskNoteAddin.OnInsertText:\n" + // "\tLength: {0}\n" + // "\tText: {1}\n" + // "\tLine: {2}", // args.Length, // args.Text, // args.Pos.Line); if (args.Length == 1 && args.Text == "\n") { Gtk.TextIter curr_line = args.Pos; TaskTag task_tag = GetTaskTagFromLineIter(ref curr_line); Gtk.TextIter prev_line = args.Pos; prev_line.BackwardLine(); /*TaskTag*/ task_tag = GetTaskTagFromLineIter(ref prev_line); if (task_tag != null) { // If the user just entered a newline and the previous // line was a task, do some special processing...but // we have to do it on idle since there are other // Buffer.InsertText handlers that we'll screw up if // we modify anything here. args.RetVal = ProcessNewline(); } else { // Check to see if the previous line is a todo: line while (prev_line.StartsLine() == false) { prev_line.BackwardChar(); } Gtk.TextIter prev_line_end = prev_line; while (prev_line_end.EndsLine() == false) { prev_line_end.ForwardChar(); } string prev_line_text = prev_line.GetText(prev_line_end); Match match = regex.Match(prev_line_text); if (match.Success && last_removed_tag != null) { TaskManager task_mgr = TasksApplicationAddin.DefaultTaskManager; Task task; task = task_mgr.FindByUri(last_removed_tag.Uri); if (task != null) { // Update the task's summary and make sure that // the previous line is appropriately tagged. string summary = GetTaskSummaryFromLine(prev_line_text); task.Summary = summary; Buffer.ApplyTag(last_removed_tag, prev_line, prev_line_end); } else { Logger.Debug("Shouldn't ever hit this code (hopefully)"); } } last_removed_tag = null; } } else { ApplyTaskTagToBlock(ref start, args.Pos); } }
void ApplyTaskTagToBlock(ref Gtk.TextIter start, Gtk.TextIter end) { Gtk.TextIter line_end = start; while (line_end.EndsLine() == false) { line_end.ForwardChar(); } // For some reason, the above code behaves like it should (i.e., // without advancing to the next line). The line below that's // commented out doesn't work. It ends up advancing the iter to // the end of the next line. Very strange! // line_end.ForwardToLineEnd (); TaskTag task_tag = GetTaskTagFromLineIter(ref start); if (task_tag != null) { Buffer.RemoveTag(task_tag, start, line_end); } else { task_tag = last_removed_tag; } string text = start.GetText(line_end); // Logger.Debug ("Evaluating with regex: {0}", text); TaskManager task_mgr = TasksApplicationAddin.DefaultTaskManager; Task task; Match match = regex.Match(text); if (match.Success) { string summary = GetTaskSummaryFromLine(text); if (task_tag == null) { task = task_mgr.Create(summary); task.QueueSave(true); task.OriginNoteUri = Note.Uri; task_tag = (TaskTag) Note.TagTable.CreateDynamicTag("task"); task_tag.Uri = task.Uri; } else { task = task_mgr.FindByUri(task_tag.Uri); if (task != null) { task.Summary = summary; } else { Logger.Debug("FIXME: Add code to remove the task tag if this case is hit"); } } Buffer.ApplyTag(task_tag, start, line_end); last_removed_tag = null; } else if (task_tag != null) { // This task should be deleted task = task_mgr.FindByUri(task_tag.Uri); if (task != null) { task_mgr.Delete(task); } last_removed_tag = null; } }