[gnome-subtitles] Show margin with character counts in subtitle edit (bug #625485)
- From: Pedro Daniel da Rocha Melo e Castro <pcastro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-subtitles] Show margin with character counts in subtitle edit (bug #625485)
- Date: Sat, 16 Jul 2011 21:35:55 +0000 (UTC)
commit b0cc60bf22d944c0c4247302f34bb786fc79cf7e
Author: Pedro Castro <pedro gnomesubtitles org>
Date: Sat Jul 16 19:05:43 2011 +0100
Show margin with character counts in subtitle edit (bug #625485)
gnome-subtitles.mdp | 3 +
src/Glade/MainWindow.glade | 24 ++-
src/GnomeSubtitles/Ui/Edit/SubtitleEditTextView.cs | 37 ++--
.../Ui/Edit/SubtitleEditTextViewMargin.cs | 222 ++++++++++++++++++++
4 files changed, 263 insertions(+), 23 deletions(-)
---
diff --git a/gnome-subtitles.mdp b/gnome-subtitles.mdp
index 7081637..710d0a8 100644
--- a/gnome-subtitles.mdp
+++ b/gnome-subtitles.mdp
@@ -260,6 +260,7 @@
<File subtype="Code" buildaction="Compile" name="src/SubLib/Core/Timing/MergeOperator.cs" />
<File subtype="Code" buildaction="Compile" name="src/GnomeSubtitles/Core/Command/MergeSubtitlesCommand.cs" />
<File subtype="Code" buildaction="Compile" name="src/SubLib/Exceptions/FileTooLargeException.cs" />
+ <File subtype="Code" buildaction="Compile" name="src/GnomeSubtitles/Ui/Edit/SubtitleEditTextViewMargin.cs" />
</Contents>
<References>
<ProjectReference type="Gac" localcopy="True" refto="Mono.Posix, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" />
@@ -271,6 +272,8 @@
<ProjectReference type="Gac" localcopy="True" refto="gconf-sharp, Version=2.24.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<ProjectReference type="Gac" localcopy="True" refto="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<ProjectReference type="Gac" localcopy="True" refto="System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <ProjectReference type="Gac" localcopy="True" refto="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+ <ProjectReference type="Gac" localcopy="True" refto="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
</References>
<LanguageParameters StartupObject="GnomeSubtitles.Execution.Executable" ApplicationIcon="." ctype="CSharpProjectParameters" />
<DeploymentInformation strategy="File" />
diff --git a/src/Glade/MainWindow.glade b/src/Glade/MainWindow.glade
index 437d91a..a8cfc86 100644
--- a/src/Glade/MainWindow.glade
+++ b/src/Glade/MainWindow.glade
@@ -247,8 +247,8 @@
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<signal name="activate" handler="OnEditRedo"/>
- <accelerator key="Z" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
<accelerator key="Y" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+ <accelerator key="Z" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@@ -586,8 +586,8 @@
<property name="label" translatable="yes">Find Ne_xt</property>
<property name="use_underline">True</property>
<signal name="activate" handler="OnSearchFindNext"/>
- <accelerator key="g" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<accelerator key="F3" signal="activate"/>
+ <accelerator key="g" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@@ -597,8 +597,8 @@
<property name="label" translatable="yes">Find Pre_vious</property>
<property name="use_underline">True</property>
<signal name="activate" handler="OnSearchFindPrevious"/>
- <accelerator key="g" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
<accelerator key="F3" signal="activate" modifiers="GDK_SHIFT_MASK"/>
+ <accelerator key="g" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@@ -842,8 +842,8 @@
<property name="use_underline">True</property>
<property name="use_stock">False</property>
<signal name="activate" handler="OnVideoPlayPause"/>
- <accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<accelerator key="F5" signal="activate"/>
+ <accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<child internal-child="image">
<widget class="GtkImage" id="videoPlayPauseImage">
<property name="visible">True</property>
@@ -870,8 +870,8 @@
<property name="use_underline">True</property>
<property name="use_stock">False</property>
<signal name="activate" handler="OnVideoRewind"/>
- <accelerator key="k" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<accelerator key="F6" signal="activate"/>
+ <accelerator key="k" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<child internal-child="image">
<widget class="GtkImage" id="videoRewindImage">
<property name="visible">True</property>
@@ -889,8 +889,8 @@
<property name="use_underline">True</property>
<property name="use_stock">False</property>
<signal name="activate" handler="OnVideoForward"/>
- <accelerator key="l" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<accelerator key="F7" signal="activate"/>
+ <accelerator key="l" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<child internal-child="image">
<widget class="GtkImage" id="videoForwardImage">
<property name="visible">True</property>
@@ -930,8 +930,8 @@
<property name="label" translatable="yes">Seek _to Selection</property>
<property name="use_underline">True</property>
<signal name="activate" handler="OnVideoSeekToSelection"/>
- <accelerator key="r" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
<accelerator key="F4" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
+ <accelerator key="r" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@@ -941,8 +941,8 @@
<property name="label" translatable="yes">Select Nearest Subtitle</property>
<property name="use_underline">True</property>
<signal name="activate" handler="OnVideoSelectNearestSubtitle"/>
- <accelerator key="F4" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<accelerator key="r" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+ <accelerator key="F4" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@@ -1919,8 +1919,10 @@ Shift+Plus/Minus (on the numpad) shifts timings.</property>
<widget class="GtkTextView" id="subtitleEditText">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="pixels_above_lines">10</property>
+ <property name="pixels_above_lines">5</property>
<property name="justification">center</property>
+ <property name="left_margin">15</property>
+ <property name="right_margin">15</property>
<property name="accepts_tab">False</property>
</widget>
</child>
@@ -1939,8 +1941,10 @@ Shift+Plus/Minus (on the numpad) shifts timings.</property>
<widget class="GtkTextView" id="subtitleEditTranslation">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="pixels_above_lines">10</property>
+ <property name="pixels_above_lines">5</property>
<property name="justification">center</property>
+ <property name="left_margin">15</property>
+ <property name="right_margin">15</property>
<property name="accepts_tab">False</property>
</widget>
</child>
diff --git a/src/GnomeSubtitles/Ui/Edit/SubtitleEditTextView.cs b/src/GnomeSubtitles/Ui/Edit/SubtitleEditTextView.cs
index dfee5e4..9a74ce9 100644
--- a/src/GnomeSubtitles/Ui/Edit/SubtitleEditTextView.cs
+++ b/src/GnomeSubtitles/Ui/Edit/SubtitleEditTextView.cs
@@ -1,6 +1,6 @@
/*
* This file is part of Gnome Subtitles.
- * Copyright (C) 2006-2009 Pedro Castro
+ * Copyright (C) 2006-2009,2011 Pedro Castro
*
* Gnome Subtitles is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,15 +26,16 @@ using System.Runtime.InteropServices;
namespace GnomeSubtitles.Ui.Edit {
+//FIXME italics, bolds, underlines, change style insted of applying tags
public abstract class SubtitleEditTextView {
private TextView textView = null;
+
private bool isBufferChangeSilent = false; //used to indicate whether a buffer change should set the subtitle text in the subtitle list
private bool isBufferInsertManual = false; //used to indicate whether there were manual (not by the user) inserts to the buffer
private bool isBufferDeleteManual = false; //used to indicate whether there were manual (not by the user) inserts to the buffer
private bool isToggleOverwriteSilent = false; //used to indicate whether an overwrite toggle was manual
/* Text tags */
- private TextTag scaleTag = new TextTag("scale");
private TextTag boldTag = new TextTag("bold");
private TextTag italicTag = new TextTag("italic");
private TextTag underlineTag = new TextTag("underline");
@@ -44,21 +45,22 @@ public abstract class SubtitleEditTextView {
private Subtitle subtitle = null;
private IntPtr spellTextView = IntPtr.Zero;
-
public SubtitleEditTextView (TextView textView) {
this.textView = textView;
/* Init tags */
- scaleTag.Scale = Pango.Scale.XLarge;
boldTag.Weight = Pango.Weight.Bold;
italicTag.Style = Pango.Style.Italic;
underlineTag.Underline = Pango.Underline.Single;
/* Init text view */
- textView.Buffer.TagTable.Add(scaleTag);
- textView.Buffer.TagTable.Add(boldTag);
- textView.Buffer.TagTable.Add(italicTag);
- textView.Buffer.TagTable.Add(underlineTag);
+ this.textView.Buffer.TagTable.Add(boldTag);
+ this.textView.Buffer.TagTable.Add(italicTag);
+ this.textView.Buffer.TagTable.Add(underlineTag);
+ this.textView.ModifyFont(Pango.FontDescription.FromString("sans 14"));
+
+ /* Init margin */
+ new SubtitleEditTextViewMargin(this.textView);
Base.InitFinished += OnBaseInitFinished;
}
@@ -249,11 +251,21 @@ public abstract class SubtitleEditTextView {
private void LoadTags (SubLib.Core.Domain.Style style) {
subtitleTags.Clear();
- if (style.Bold)
+ /*if (style.Bold)
subtitleTags.Add(boldTag);
if (style.Italic)
subtitleTags.Add(italicTag);
if (style.Underline)
+ subtitleTags.Add(underlineTag);*/
+
+ if (style.Bold)
+ subtitleTags.Add(boldTag);
+ if (style.Italic) {
+ Pango.FontDescription fd = textView.PangoContext.FontDescription.Copy();
+ fd.Style = Pango.Style.Italic;
+ textView.ModifyFont(fd);
+ }
+ if (style.Underline)
subtitleTags.Add(underlineTag);
}
@@ -261,7 +273,6 @@ public abstract class SubtitleEditTextView {
TextBuffer buffer = textView.Buffer;
TextIter start = buffer.StartIter;
TextIter end = buffer.EndIter;
- buffer.ApplyTag(scaleTag, start, end);
foreach (TextTag tag in subtitleTags)
SetTag(tag, start, end, true);
}
@@ -416,8 +427,9 @@ public abstract class SubtitleEditTextView {
}
}
}
-
+
private void OnBaseInitFinished () {
+
/* Buffer signals */
textView.Buffer.Changed += OnBufferChanged;
textView.Buffer.MarkSet += OnBufferMarkSet;
@@ -431,11 +443,11 @@ public abstract class SubtitleEditTextView {
textView.ToggleOverwrite += OnToggleOverwrite;
textView.Destroyed += OnDestroyed;
-
/* Spell signals */
Base.SpellLanguages.ToggleEnabled += OnSpellToggleEnabled;
ConnectLanguageChangedSignal();
+ /* Selection signals */
Base.Ui.View.Selection.Changed += OnSubtitleSelectionChanged;
}
@@ -468,7 +480,6 @@ public abstract class SubtitleEditTextView {
SetText(String.Empty);
}
-
}
}
diff --git a/src/GnomeSubtitles/Ui/Edit/SubtitleEditTextViewMargin.cs b/src/GnomeSubtitles/Ui/Edit/SubtitleEditTextViewMargin.cs
new file mode 100644
index 0000000..9deab9a
--- /dev/null
+++ b/src/GnomeSubtitles/Ui/Edit/SubtitleEditTextViewMargin.cs
@@ -0,0 +1,222 @@
+/*
+ * This file is part of Gnome Subtitles.
+ * Copyright (C) 2011 Pedro Castro
+ *
+ * Gnome Subtitles 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.
+ *
+ * Gnome Subtitles 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+using GnomeSubtitles.Core;
+using Gtk;
+using System;
+
+namespace GnomeSubtitles.Ui.Edit {
+
+public class SubtitleEditTextViewMargin {
+ private int marginCharWidth = -1; //pixels
+ private int marginSpace = 4; //pixels
+ private int marginMinDigits = 2; //the minimum number of digits for margin width (1 would make the margin adjust with more than 9 chars, so it's better to keep a minimum of 2 to avoid constant adjustment
+ private int marginDigitCount = 2;
+
+ /* Cached GCs and Pango Layout */
+ private Gdk.GC bgGC = null;
+ private Gdk.GC lineGC = null;
+ private Gdk.GC textGC = null;
+ private Pango.Layout textLayout = null;
+
+ /* Widgets */
+ private TextView textView = null;
+
+ public SubtitleEditTextViewMargin (TextView textView) {
+ this.textView = textView;
+
+ Base.InitFinished += OnBaseInitFinished;
+ }
+
+ /* Private methods */
+
+ public void DrawMargin (TextView textView, Gdk.Window window) {
+ /* Get char count info */
+ int[,] info;
+ int maxCharCount;
+ GetCharCountDrawInfo(textView, out info, out maxCharCount);
+
+ /* Do some calculations */
+ int marginNumbersWidth = marginDigitCount * this.marginCharWidth;
+ int marginNumbersX = textView.Allocation.Width - this.marginSpace - marginNumbersWidth;
+
+ /* Draw line */
+ int marginWidth = (this.marginSpace * 2) + marginNumbersWidth;
+ int marginLineX = textView.Allocation.Width - marginWidth;
+ window.DrawLine(this.lineGC, marginLineX, 0, marginLineX, textView.Allocation.Height);
+
+ /* Draw background area */
+ window.DrawRectangle(this.bgGC, true, marginLineX+1, 0, marginWidth-1, textView.Allocation.Height);
+
+ /* Draw text */
+ int infoCount = info.GetLength(0);
+ for (int i = 0 ; i < infoCount ; i++) {
+ int charCount = info[i, 0];
+ int y = info[i, 1];
+
+ this.textLayout.SetText(charCount.ToString());
+ Pango.Rectangle layoutRect = GetPangoLayoutRect(this.textLayout);
+ window.DrawLayout(this.textGC, marginNumbersX, y - layoutRect.Height/2, this.textLayout);
+ }
+ }
+
+ private void GetCharCountDrawInfo (TextView textView, out int[,] info, out int maxCharCount) {
+ if (textView.Buffer.LineCount == 0) {
+ info = null;
+ maxCharCount = 0;
+ return; //shouldn't happen, but just to make sure
+ }
+
+ /* Get visible coordinates */
+ int minVisibleY = textView.VisibleRect.Top;
+ int maxVisibleY = textView.VisibleRect.Bottom;
+
+ /* Get visible start and end iters */
+ TextIter startIter, endIter;
+ int lineTop;
+ textView.GetLineAtY(out startIter, minVisibleY, out lineTop);
+ textView.GetLineAtY(out endIter, maxVisibleY, out lineTop);
+ int lineCount = endIter.Line - startIter.Line + 1;
+ int startLine = startIter.Line;
+ int endLine = endIter.Line;
+
+ /* Initializations */
+ info = new int[lineCount, 2];
+ maxCharCount = -1;
+
+ /* Process start iter */
+ int startLineCharCount = startIter.CharsInLine - (lineCount > 1 ? 1 : 0); //subtract 1 for newline if there are >1 lines
+ info[0, 0] = startLineCharCount; //Char Count
+ Gdk.Rectangle startIterLocation = textView.GetIterLocation(startIter);
+ info[0, 1] = startIterLocation.Bottom - (startIterLocation.Height/2) - minVisibleY; //Y
+ if (startLineCharCount > maxCharCount) {
+ maxCharCount = startLineCharCount;
+ }
+
+ /* If only 1 line, return */
+ if (lineCount == 1) {
+ return;
+ }
+
+ /* Process middle iters */
+ for (int i = 1, line = startLine + 1 ; line < endLine ; i++, line++) {
+ TextIter iter = textView.Buffer.GetIterAtLine(line);
+ int charCount = iter.CharsInLine - 1; //subtract 1 for newline
+ info[i, 0] = charCount;
+ Gdk.Rectangle iterLocation = textView.GetIterLocation(iter);
+ info[i, 1] = iterLocation.Bottom - (iterLocation.Height/2) - minVisibleY; //Y
+ if (charCount > maxCharCount) {
+ maxCharCount = charCount;
+ }
+ }
+
+ /* Process end iter */
+ int endLineCharCount = endIter.CharsInLine; //don't subtract newline because it's the last line
+ info[lineCount-1, 0] = endLineCharCount;
+ Gdk.Rectangle endIterLocation = textView.GetIterLocation(endIter);
+ info[lineCount-1, 1] = endIterLocation.Bottom - (endIterLocation.Height/2) - minVisibleY; //Y
+ if (endLineCharCount > maxCharCount) {
+ maxCharCount = endLineCharCount;
+ }
+ }
+
+ private Pango.Rectangle GetPangoLayoutRect (Pango.Layout layout) {
+ Pango.Rectangle inkRect, logicalRect;
+ layout.GetPixelExtents(out inkRect, out logicalRect);
+ return logicalRect;
+ }
+
+
+ private int CalcDigitCount (TextBuffer buffer, int marginMinDigits) {
+ int maxChars = -1;
+ int lineCount = buffer.LineCount;
+ for (int line = 0 ; line < lineCount; line++) {
+ TextIter iter = buffer.GetIterAtLine(line);
+ int chars = iter.CharsInLine - (line == lineCount - 1 ? 0 : 1); //Subtract 1 for newline (except for the last line)
+ if (chars > maxChars) {
+ maxChars = chars;
+ }
+ }
+
+ int digitCount = CountDigitsInNumber(maxChars);
+ return Math.Max(digitCount, this.marginMinDigits);
+ }
+
+ private int CountDigitsInNumber (int number) {
+ return (number == 0 ? 1 : (int)Math.Floor(Math.Log10(number)) + 1); //assuming the number is positive, otherwise would need to use abs() too
+ }
+
+ private void SetGCs () {
+ this.bgGC = Base.Ui.Window.Style.BackgroundGC(StateType.Normal);
+ this.lineGC = Base.Ui.Window.Style.BackgroundGC(StateType.Active);
+ this.textGC = Base.Ui.Window.Style.TextGC(StateType.Active);
+ }
+
+ private void Refresh () {
+ textView.QueueDraw();
+ }
+
+
+ /* Event members */
+
+ private void OnBaseInitFinished () {
+
+ /* GCs */
+ SetGCs();
+
+ /* Layouts */
+ this.textLayout = new Pango.Layout(textView.PangoContext);
+ this.textLayout.FontDescription = Pango.FontDescription.FromString("sans 10");
+
+ /* Margin char width */
+ this.textLayout.SetText("0");
+ Pango.Rectangle layoutRect = GetPangoLayoutRect(this.textLayout);
+ this.marginCharWidth = layoutRect.Width;
+
+ /* Events */
+ textView.ExposeEvent += OnExposeEvent;
+ textView.Buffer.Changed += OnBufferChanged; //To calculate margin digit count (based on the largest line char count)
+ textView.StyleSet += OnStyleSet; //To update colors if the style is changed
+ textView.Parent.ExposeEvent += OnScrolledWindowExposeEvent;
+ }
+
+ private void OnExposeEvent (object o, ExposeEventArgs args) {
+ TextView textView = o as TextView;
+ if (textView.State != StateType.Insensitive) {
+ DrawMargin(textView, args.Event.Window);
+ }
+ }
+
+ private void OnScrolledWindowExposeEvent (object o, ExposeEventArgs args) {
+ Refresh(); //Necessary for artifacts not to appear when scrolling
+ }
+
+ private void OnBufferChanged (object o, EventArgs args) {
+ this.marginDigitCount = CalcDigitCount(o as TextBuffer, this.marginMinDigits);
+ }
+
+ private void OnStyleSet (object o, StyleSetArgs args) {
+ SetGCs();
+ }
+
+
+}
+
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]