[smuxi: 13/15] [Frontend-GNOME] Apply text size changes to emoji



commit 5c6e602391f576e29d5ef1978c254049d648e4e2
Author: Carlos Martín Nieto <cmn dwim me>
Date:   Mon Feb 2 17:38:51 2015 +0100

    [Frontend-GNOME] Apply text size changes to emoji
    
    When we resize the text, we must also take care to resize the pixbuf
    containing the emoji, as those do not automatically become scaled.
    
    To do this we must go through all emoji tags and replace their content
    with a new pixbuf of the appropriate size. We must take care to re-tag
    the new pixbuf with the tag so we can react to multiple size change
    requests.

 src/Frontend-GNOME/Frontend-GNOME.csproj    |    1 +
 src/Frontend-GNOME/Makefile.am              |    1 +
 src/Frontend-GNOME/Views/MessageTextView.cs |   78 ++++++++++++++++++++++----
 src/Frontend-GNOME/Views/Tags/EmojiTag.cs   |   48 ++++++++++++++++
 4 files changed, 116 insertions(+), 12 deletions(-)
---
diff --git a/src/Frontend-GNOME/Frontend-GNOME.csproj b/src/Frontend-GNOME/Frontend-GNOME.csproj
index 42fe744..afec9e0 100644
--- a/src/Frontend-GNOME/Frontend-GNOME.csproj
+++ b/src/Frontend-GNOME/Frontend-GNOME.csproj
@@ -163,6 +163,7 @@
     <Compile Include="Views\Tags\LinkTag.cs" />
     <Compile Include="Views\Tags\PersonTag.cs" />
     <Compile Include="Views\ChatTreeView.cs" />
+    <Compile Include="Views\Tags\EmojiTag.cs" />
   </ItemGroup>
   <ItemGroup>
     <Content Include="smuxi-frontend-gnome.exe.config">
diff --git a/src/Frontend-GNOME/Makefile.am b/src/Frontend-GNOME/Makefile.am
index aae285d..646e668 100644
--- a/src/Frontend-GNOME/Makefile.am
+++ b/src/Frontend-GNOME/Makefile.am
@@ -157,6 +157,7 @@ FILES = \
        Views/Assistants/Engine/EngineAssistantConnectionWidget.cs \
        Views/Assistants/Engine/EngineAssistantIntroWidget.cs \
        Views/Assistants/Engine/EngineAssistant.cs \
+       Views/Tags/EmojiTag.cs \
        Views/Tags/LinkTag.cs \
        Views/Tags/PersonTag.cs \
        QuickConnectDialog.cs \
diff --git a/src/Frontend-GNOME/Views/MessageTextView.cs b/src/Frontend-GNOME/Views/MessageTextView.cs
index 87015ae..2d0073e 100644
--- a/src/Frontend-GNOME/Views/MessageTextView.cs
+++ b/src/Frontend-GNOME/Views/MessageTextView.cs
@@ -52,8 +52,8 @@ namespace Smuxi.Frontend.Gnome
         private Gdk.Color    _MarkerlineColor = new Gdk.Color(255, 0, 0);
         private int          _MarkerlineBufferPosition;
         private int          _BufferLines = -1;
-        private IconCache    _EmojiCache = new IconCache("emoji");
 
+        IconCache EmojiCache { get; set; }
         Gtk.TextTag BoldTag { get; set; }
         Gtk.TextTag ItalicTag { get; set; }
         Gtk.TextTag UnderlineTag { get; set; }
@@ -160,7 +160,8 @@ namespace Smuxi.Frontend.Gnome
 
             _MessageTextTagTable = BuildTagTable();
             _ThemeSettings = new ThemeSettings();
-            
+
+            EmojiCache = new IconCache("emoji");
             Buffer = new Gtk.TextBuffer(_MessageTextTagTable);
             MotionNotifyEvent += OnMotionNotifyEvent;
             PopulatePopup += OnPopulatePopup;
@@ -205,6 +206,49 @@ namespace Smuxi.Frontend.Gnome
             }
 
             _BufferLines = (int) config["Interface/Notebook/BufferLines"];
+
+#if LOG4NET
+            DateTime start = DateTime.UtcNow;
+#endif
+
+            ResizeEmoji();
+
+#if LOG4NET
+            DateTime stop = DateTime.UtcNow;
+            double duration = stop.Subtract(start).TotalMilliseconds;
+            _Logger.Debug("ApplyConfig(): ResizeEmoji()" +
+                " done, took: " + Math.Round(duration) + " ms");
+#endif
+        }
+
+        void ResizeEmoji()
+        {
+            var buffer = Buffer;
+
+            int width, height;
+            using (var layout = CreatePangoLayout(null)) {
+                layout.GetPixelSize(out width, out height);
+            }
+
+            _MessageTextTagTable.Foreach((tag) => {
+                if (!(tag is EmojiTag)) {
+                    return;
+                }
+
+                var emojiTag = tag as EmojiTag;
+                var pix = new Gdk.Pixbuf(emojiTag.Path, -1, height);
+
+                var beforeIter = buffer.GetIterAtMark(emojiTag.Mark);
+                var afterIter = beforeIter;
+                afterIter.ForwardToTagToggle(tag);
+                buffer.RemoveTag(tag, beforeIter, afterIter);
+                buffer.Delete(ref beforeIter, ref afterIter);
+                buffer.InsertPixbuf(ref beforeIter, pix);
+                // after all that, we need to re-apply the tag to the buffer
+                afterIter = beforeIter;
+                beforeIter = Buffer.GetIterAtMark(emojiTag.Mark);
+                buffer.ApplyTag(tag, beforeIter, afterIter);
+            });
         }
 
         void CheckStyle()
@@ -263,13 +307,23 @@ namespace Smuxi.Frontend.Gnome
                 layout.GetPixelSize(out width, out height);
             }
 
+            // A mark here serves two pusposes. One is to allow us to apply the
+            // tag across the pixbuf. It also lets us know later where to put
+            // the pixbuf if we need to load it from the network
+            var mark = new Gtk.TextMark(null, true);
+            buffer.AddMark(mark, iter);
+
             var emojiName = unicode + ".png";
             string emojiPath;
-            if (_EmojiCache.TryGetIcon("emojione", emojiName, out emojiPath)) {
+            if (EmojiCache.TryGetIcon("emojione", emojiName, out emojiPath)) {
                 var emojiFile = new FileInfo(emojiPath);
                 if (emojiFile.Exists && emojiFile.Length > 0) {
                     var pix = new Gdk.Pixbuf(emojiPath, -1, height);
                     buffer.InsertPixbuf(ref iter, pix);
+                    var beforeIter = buffer.GetIterAtMark(mark);
+                    var imgTag = new EmojiTag(mark, emojiFile.FullName);
+                    _MessageTextTagTable.Add(imgTag);
+                    buffer.ApplyTag(imgTag, beforeIter, iter);
                 } else {
                     AddAlternativeText(buffer, ref iter, imgPart);
                 }
@@ -277,23 +331,23 @@ namespace Smuxi.Frontend.Gnome
                 return;
             }
 
-            // add a mark here so we know where to insert the pixbuf
-            // once we've downloaded the file; in case of error we
-            // insert the name instead
-            var mark = new Gtk.TextMark(null, true);
-            buffer.AddMark(mark, iter);
             var emojiUrl = Emojione.UnicodeToUrl(unicode);
-            _EmojiCache.BeginDownloadFile("emojione", emojiName, emojiUrl,
+            EmojiCache.BeginDownloadFile("emojione", emojiName, emojiUrl,
                 (path) => {
                     GLib.Idle.Add(delegate {
-                        var markIter = buffer.GetIterAtMark(mark);
-                        buffer.InsertPixbuf(ref markIter, new Gdk.Pixbuf(path, -1, height));
+                        var afterIter = buffer.GetIterAtMark(mark);
+                        buffer.InsertPixbuf(ref afterIter, new Gdk.Pixbuf(path, -1, height));
+                        var beforeIter = buffer.GetIterAtMark(mark);
+                        var emojiTag = new EmojiTag(mark, path);
+                        _MessageTextTagTable.Add(emojiTag);
+                        buffer.ApplyTag(emojiTag, beforeIter, afterIter);
                         return false;
                     });
                 },
                 (ex) => {
                     GLib.Idle.Add(delegate {
                         var markIter = buffer.GetIterAtMark(mark);
+                        buffer.DeleteMark(mark);
                         AddAlternativeText(buffer, ref markIter, imgPart);
                         return false;
                     });
@@ -870,7 +924,7 @@ namespace Smuxi.Frontend.Gnome
                          tagName.StartsWith("bg_color:"))) {
                         continue;
                     }
-                    if (tag.IndentSet || tag is LinkTag || tag is PersonTag) {
+                    if (tag.IndentSet || tag is LinkTag || tag is PersonTag || tag is EmojiTag) {
                         buffer.RemoveTag(tag, start_iter, end_iter);
                         _MessageTextTagTable.Remove(tag);
                         tag.Dispose();
diff --git a/src/Frontend-GNOME/Views/Tags/EmojiTag.cs b/src/Frontend-GNOME/Views/Tags/EmojiTag.cs
new file mode 100644
index 0000000..4ce2f46
--- /dev/null
+++ b/src/Frontend-GNOME/Views/Tags/EmojiTag.cs
@@ -0,0 +1,48 @@
+// Smuxi - Smart MUltipleXed Irc
+//
+// Copyright (c) 2015 Carlos Martín Nieto
+//
+// Full GPL License: <http://www.gnu.org/licenses/gpl.txt>
+//
+// 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;
+
+namespace Smuxi.Frontend.Gnome
+{
+    public class EmojiTag : Gtk.TextTag
+    {
+        public string Path { get; private set; }
+        public Gtk.TextMark Mark { get; private set; }
+
+        public EmojiTag(Gtk.TextMark mark, string path) : base(null)
+        {
+            if (mark == null) {
+                throw new ArgumentNullException("mark");
+            }
+
+            if (path == null) {
+                throw new ArgumentNullException("path");
+            }
+
+            Mark = mark;
+            Path = path;
+        }
+
+        protected EmojiTag(IntPtr handle) : base(handle)
+        {
+        }
+    }
+}
+


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