[gimp] app: allow to select fonts on text spans



commit bea0c7f3d440619697e537e0cd34015a1c02af8d
Author: Michael Natterer <mitch gimp org>
Date:   Tue Mar 2 11:11:06 2010 +0100

    app: allow to select fonts on text spans
    
    A bit hackish, will cleanup...

 app/widgets/gimptextbuffer.c      |  169 ++++++++++++++++++++++++++++++++-----
 app/widgets/gimptextbuffer.h      |   16 ++++
 app/widgets/gimptextstyleeditor.c |  135 +++++++++++++++++++++++++++---
 3 files changed, 289 insertions(+), 31 deletions(-)
---
diff --git a/app/widgets/gimptextbuffer.c b/app/widgets/gimptextbuffer.c
index 4bf1a15..ae40126 100644
--- a/app/widgets/gimptextbuffer.c
+++ b/app/widgets/gimptextbuffer.c
@@ -162,6 +162,12 @@ gimp_text_buffer_finalize (GObject *object)
       buffer->spacing_tags = NULL;
     }
 
+  if (buffer->font_tags)
+    {
+      g_list_free (buffer->font_tags);
+      buffer->font_tags = NULL;
+    }
+
   gimp_text_buffer_clear_insert_tags (buffer);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -297,10 +303,10 @@ gimp_text_buffer_get_markup (GimpTextBuffer *buffer)
   return markup;
 }
 
-static gint
-get_baseline_at_iter (GimpTextBuffer     *buffer,
-                      const GtkTextIter  *iter,
-                      GtkTextTag        **baseline_tag)
+gint
+gimp_text_buffer_get_baseline (GimpTextBuffer     *buffer,
+                               const GtkTextIter  *iter,
+                               GtkTextTag        **baseline_tag)
 {
   GList *list;
 
@@ -328,8 +334,8 @@ get_baseline_at_iter (GimpTextBuffer     *buffer,
 }
 
 static GtkTextTag *
-get_baseline_tag (GimpTextBuffer *buffer,
-                  gint            baseline)
+gimp_text_buffer_get_baseline_tag (GimpTextBuffer *buffer,
+                                   gint            baseline)
 {
   GList      *list;
   GtkTextTag *tag;
@@ -382,7 +388,7 @@ gimp_text_buffer_change_baseline (GimpTextBuffer    *buffer,
 
   iter          = *start;
   span_start    = *start;
-  span_baseline = get_baseline_at_iter (buffer, &iter, &span_tag);
+  span_baseline = gimp_text_buffer_get_baseline (buffer, &iter, &span_tag);
 
   gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer));
 
@@ -393,7 +399,7 @@ gimp_text_buffer_change_baseline (GimpTextBuffer    *buffer,
 
       gtk_text_iter_forward_char (&iter);
 
-      iter_baseline = get_baseline_at_iter (buffer, &iter, &iter_tag);
+      iter_baseline = gimp_text_buffer_get_baseline (buffer, &iter, &iter_tag);
 
       span_end = iter;
 
@@ -408,7 +414,8 @@ gimp_text_buffer_change_baseline (GimpTextBuffer    *buffer,
 
           if (span_baseline + count != 0)
             {
-              span_tag = get_baseline_tag (buffer, span_baseline + count);
+              span_tag = gimp_text_buffer_get_baseline_tag (buffer,
+                                                            span_baseline + count);
 
               gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (buffer), span_tag,
                                          &span_start, &span_end);
@@ -428,10 +435,10 @@ gimp_text_buffer_change_baseline (GimpTextBuffer    *buffer,
   gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer));
 }
 
-static gint
-get_spacing_at_iter (GimpTextBuffer     *buffer,
-                     const GtkTextIter  *iter,
-                     GtkTextTag        **spacing_tag)
+gint
+gimp_text_buffer_get_spacing (GimpTextBuffer     *buffer,
+                              const GtkTextIter  *iter,
+                              GtkTextTag        **spacing_tag)
 {
   GList *list;
 
@@ -459,8 +466,8 @@ get_spacing_at_iter (GimpTextBuffer     *buffer,
 }
 
 static GtkTextTag *
-get_spacing_tag (GimpTextBuffer *buffer,
-                 gint            spacing)
+gimp_text_buffer_get_spacing_tag (GimpTextBuffer *buffer,
+                                  gint            spacing)
 {
   GList      *list;
   GtkTextTag *tag;
@@ -513,7 +520,7 @@ gimp_text_buffer_change_spacing (GimpTextBuffer    *buffer,
 
   iter         = *start;
   span_start   = *start;
-  span_spacing = get_spacing_at_iter (buffer, &iter, &span_tag);
+  span_spacing = gimp_text_buffer_get_spacing (buffer, &iter, &span_tag);
 
   gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer));
 
@@ -524,7 +531,7 @@ gimp_text_buffer_change_spacing (GimpTextBuffer    *buffer,
 
       gtk_text_iter_forward_char (&iter);
 
-      iter_spacing = get_spacing_at_iter (buffer, &iter, &iter_tag);
+      iter_spacing = gimp_text_buffer_get_spacing (buffer, &iter, &iter_tag);
 
       span_end = iter;
 
@@ -539,7 +546,8 @@ gimp_text_buffer_change_spacing (GimpTextBuffer    *buffer,
 
           if (span_spacing + count != 0)
             {
-              span_tag = get_spacing_tag (buffer, span_spacing + count);
+              span_tag = gimp_text_buffer_get_spacing_tag (buffer,
+                                                           span_spacing + count);
 
               gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (buffer), span_tag,
                                          &span_start, &span_end);
@@ -559,6 +567,109 @@ gimp_text_buffer_change_spacing (GimpTextBuffer    *buffer,
   gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer));
 }
 
+gchar *
+gimp_text_buffer_get_font (GimpTextBuffer     *buffer,
+                           const GtkTextIter  *iter,
+                           GtkTextTag        **font_tag)
+{
+  GList *list;
+
+  for (list = buffer->font_tags; list; list = g_list_next (list))
+    {
+      GtkTextTag *tag = list->data;
+
+      if (gtk_text_iter_has_tag (iter, tag))
+        {
+          gchar *font;
+
+          *font_tag = tag;
+
+          g_object_get (tag,
+                        "font", &font,
+                        NULL);
+
+          return font;
+        }
+    }
+
+  *font_tag = NULL;
+
+  return NULL;
+}
+
+static GtkTextTag *
+gimp_text_buffer_get_font_tag (GimpTextBuffer *buffer,
+                               const gchar    *font)
+{
+  GList      *list;
+  GtkTextTag *tag;
+  gchar       name[256];
+
+  for (list = buffer->font_tags; list; list = g_list_next (list))
+    {
+      gchar *tag_font;
+
+      tag = list->data;
+
+      g_object_get (tag,
+                    "font", &tag_font,
+                    NULL);
+
+      if (! strcmp (font, tag_font))
+        {
+          g_free (tag_font);
+          return tag;
+        }
+
+      g_free (tag_font);
+    }
+
+  g_snprintf (name, sizeof (name), "font-%s", font);
+
+  tag = gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (buffer),
+                                    name,
+                                    "font", font,
+                                    NULL);
+
+  buffer->font_tags = g_list_prepend (buffer->font_tags, tag);
+
+  return tag;
+}
+
+void
+gimp_text_buffer_set_font (GimpTextBuffer    *buffer,
+                           const GtkTextIter *start,
+                           const GtkTextIter *end,
+                           const gchar       *font)
+{
+  GList *list;
+
+  g_return_if_fail (GIMP_IS_TEXT_BUFFER (buffer));
+  g_return_if_fail (start != NULL);
+  g_return_if_fail (end != NULL);
+
+  if (gtk_text_iter_equal (start, end))
+    return;
+
+  gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer));
+
+  for (list = buffer->font_tags; list; list = g_list_next (list))
+    {
+      gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (buffer), list->data,
+                                  start, end);
+    }
+
+  if (font)
+    {
+      GtkTextTag *tag = gimp_text_buffer_get_font_tag (buffer, font);
+
+      gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (buffer), tag,
+                                 start, end);
+    }
+
+  gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer));
+}
+
 const gchar *
 gimp_text_buffer_tag_to_name (GimpTextBuffer  *buffer,
                               GtkTextTag      *tag,
@@ -626,6 +737,20 @@ gimp_text_buffer_tag_to_name (GimpTextBuffer  *buffer,
 
       return "span";
     }
+  else if (g_list_find (buffer->font_tags, tag))
+    {
+      if (attribute)
+        *attribute = "font";
+
+      if (value)
+        {
+          g_object_get (tag,
+                        "font", value,
+                        NULL);
+        }
+
+      return "span";
+    }
 
   return NULL;
 }
@@ -661,11 +786,15 @@ gimp_text_buffer_name_to_tag (GimpTextBuffer *buffer,
     {
       if (! strcmp (attribute, "rise"))
         {
-          return get_baseline_tag (buffer, atoi (value));
+          return gimp_text_buffer_get_baseline_tag (buffer, atoi (value));
         }
       else if (! strcmp (attribute, "letter_spacing"))
         {
-          return get_spacing_tag (buffer, atoi (value));
+          return gimp_text_buffer_get_spacing_tag (buffer, atoi (value));
+        }
+      else if (! strcmp (attribute, "font"))
+        {
+          return gimp_text_buffer_get_font_tag (buffer, value);
         }
     }
 
diff --git a/app/widgets/gimptextbuffer.h b/app/widgets/gimptextbuffer.h
index ab695ff..cb982c0 100644
--- a/app/widgets/gimptextbuffer.h
+++ b/app/widgets/gimptextbuffer.h
@@ -42,6 +42,7 @@ struct _GimpTextBuffer
 
   GList         *baseline_tags;
   GList         *spacing_tags;
+  GList         *font_tags;
 
   gboolean       insert_tags_set;
   GList         *insert_tags;
@@ -68,15 +69,30 @@ void             gimp_text_buffer_set_markup        (GimpTextBuffer    *buffer,
                                                      const gchar       *markup);
 gchar          * gimp_text_buffer_get_markup        (GimpTextBuffer    *buffer);
 
+gint             gimp_text_buffer_get_baseline      (GimpTextBuffer    *buffer,
+                                                     const GtkTextIter *iter,
+                                                     GtkTextTag       **baseline_tag);
 void             gimp_text_buffer_change_baseline   (GimpTextBuffer    *buffer,
                                                      const GtkTextIter *start,
                                                      const GtkTextIter *end,
                                                      gint               count);
+
+gint             gimp_text_buffer_get_spacing       (GimpTextBuffer    *buffer,
+                                                     const GtkTextIter *iter,
+                                                     GtkTextTag       **spacing_tag);
 void             gimp_text_buffer_change_spacing    (GimpTextBuffer    *buffer,
                                                      const GtkTextIter *start,
                                                      const GtkTextIter *end,
                                                      gint               count);
 
+gchar          * gimp_text_buffer_get_font          (GimpTextBuffer    *buffer,
+                                                     const GtkTextIter *iter,
+                                                     GtkTextTag       **font_tag);
+void             gimp_text_buffer_set_font          (GimpTextBuffer    *buffer,
+                                                     const GtkTextIter *start,
+                                                     const GtkTextIter *end,
+                                                     const gchar       *font);
+
 const gchar    * gimp_text_buffer_tag_to_name       (GimpTextBuffer    *buffer,
                                                      GtkTextTag        *tag,
                                                      const gchar      **attribute,
diff --git a/app/widgets/gimptextstyleeditor.c b/app/widgets/gimptextstyleeditor.c
index 27c046c..cccd42c 100644
--- a/app/widgets/gimptextstyleeditor.c
+++ b/app/widgets/gimptextstyleeditor.c
@@ -73,6 +73,9 @@ static GtkWidget *
 
 static void      gimp_text_style_editor_clear_tags   (GtkButton           *button,
                                                       GimpTextStyleEditor *editor);
+static void      gimp_text_style_editor_font_changed (GimpContext         *context,
+                                                      GimpFont            *font,
+                                                      GimpTextStyleEditor *editor);
 static void      gimp_text_style_editor_tag_toggled  (GtkToggleButton     *toggle,
                                                       GimpTextStyleEditor *editor);
 
@@ -194,6 +197,10 @@ gimp_text_style_editor_constructor (GType                  type,
 
   editor->context = gimp_context_new (editor->gimp, "text style editor", NULL);
 
+  g_signal_connect (editor->context, "font-changed",
+                    G_CALLBACK (gimp_text_style_editor_font_changed),
+                    editor);
+
   gimp_container_view_set_container (GIMP_CONTAINER_VIEW (editor->font_entry),
                                      editor->fonts);
   gimp_container_view_set_context (GIMP_CONTAINER_VIEW (editor->font_entry),
@@ -439,6 +446,28 @@ gimp_text_style_editor_clear_tags (GtkButton           *button,
 }
 
 static void
+gimp_text_style_editor_font_changed (GimpContext         *context,
+                                     GimpFont            *font,
+                                     GimpTextStyleEditor *editor)
+{
+  GtkTextBuffer *buffer = GTK_TEXT_BUFFER (editor->buffer);
+  const gchar   *name   = gimp_context_get_font_name (context);
+
+  if (gtk_text_buffer_get_has_selection (buffer))
+    {
+      GtkTextIter start, end;
+
+      gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
+
+      gtk_text_buffer_begin_user_action (buffer);
+
+      gimp_text_buffer_set_font (editor->buffer, &start, &end, name);
+
+      gtk_text_buffer_end_user_action (buffer);
+    }
+}
+
+static void
 gimp_text_style_editor_tag_toggled (GtkToggleButton     *toggle,
                                     GimpTextStyleEditor *editor)
 {
@@ -488,6 +517,30 @@ gimp_text_style_editor_set_toggle (GimpTextStyleEditor *editor,
 }
 
 static void
+gimp_text_style_editor_set_font (GimpTextStyleEditor *editor,
+                                 GtkTextTag          *font_tag)
+{
+  gchar *font = NULL;
+
+  if (font_tag)
+    g_object_get (font_tag,
+                  "font", &font,
+                  NULL);
+
+  g_signal_handlers_block_by_func (editor->context,
+                                   gimp_text_style_editor_font_changed,
+                                   editor);
+
+  gimp_context_set_font_name (editor->context, font);
+
+  g_signal_handlers_unblock_by_func (editor->context,
+                                     gimp_text_style_editor_font_changed,
+                                     editor);
+
+  g_free (font);
+}
+
+static void
 gimp_text_style_editor_update (GimpTextStyleEditor *editor)
 {
   GtkTextBuffer *buffer = GTK_TEXT_BUFFER (editor->buffer);
@@ -497,6 +550,9 @@ gimp_text_style_editor_update (GimpTextStyleEditor *editor)
       GtkTextIter  start, end;
       GtkTextIter  iter;
       GList       *list;
+      gboolean     any_toggle_active = TRUE;
+      gboolean     font_differs      = FALSE;
+      GtkTextTag  *font_tag          = NULL;
 
       gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
       gtk_text_iter_order (&start, &end);
@@ -509,32 +565,73 @@ gimp_text_style_editor_update (GimpTextStyleEditor *editor)
           gimp_text_style_editor_set_toggle (editor, toggle, TRUE);
         }
 
+      /*  and get the initial font tag  */
+      for (list = editor->buffer->font_tags; list; list = g_list_next (list))
+        {
+          GtkTextTag *tag = list->data;
+
+          if (gtk_text_iter_has_tag (&start, tag))
+            {
+              font_tag = tag;
+              break;
+            }
+        }
+
       for (iter = start;
            gtk_text_iter_in_range (&iter, &start, &end);
            gtk_text_iter_forward_cursor_position (&iter))
         {
-          gboolean any_active = FALSE;
-
-          for (list = editor->toggles; list; list = g_list_next (list))
+          if (any_toggle_active)
             {
-              GtkToggleButton *toggle = list->data;
-              GtkTextTag      *tag    = g_object_get_data (G_OBJECT (toggle),
-                                                           "tag");
+              any_toggle_active = FALSE;
 
-              if (! gtk_text_iter_has_tag (&iter, tag))
+              for (list = editor->toggles; list; list = g_list_next (list))
                 {
-                  gimp_text_style_editor_set_toggle (editor, toggle, FALSE);
+                  GtkToggleButton *toggle = list->data;
+                  GtkTextTag      *tag    = g_object_get_data (G_OBJECT (toggle),
+                                                               "tag");
+
+                  if (! gtk_text_iter_has_tag (&iter, tag))
+                    {
+                      gimp_text_style_editor_set_toggle (editor, toggle, FALSE);
+                    }
+                  else
+                    {
+                      any_toggle_active = TRUE;
+                    }
                 }
-              else
+            }
+
+          if (! font_differs)
+            {
+              for (list = editor->buffer->font_tags;
+                   list;
+                   list = g_list_next (list))
                 {
-                  any_active = TRUE;
+                  GtkTextTag *tag = list->data;
+
+                  if (gtk_text_iter_has_tag (&iter, tag))
+                    {
+                      if (tag != font_tag)
+                        font_differs = TRUE;
+
+                      break;
+                    }
                 }
+
+              if (! list && font_tag)
+                font_differs = TRUE;
             }
 
-          if (! any_active)
+          if (! any_toggle_active || font_differs)
             break;
        }
 
+      if (font_differs)
+        font_tag = NULL;
+
+      gimp_text_style_editor_set_font (editor, font_tag);
+
       gtk_label_set_text (GTK_LABEL (editor->size_label), "---");
     }
   else
@@ -553,6 +650,22 @@ gimp_text_style_editor_update (GimpTextStyleEditor *editor)
       tags_on  = gtk_text_iter_get_toggled_tags (&cursor, TRUE);
       tags_off = gtk_text_iter_get_toggled_tags (&cursor, FALSE);
 
+      for (list = editor->buffer->font_tags; list; list = g_list_next (list))
+        {
+          GtkTextTag *tag = list->data;
+
+          if ((g_slist_find (tags, tag) &&
+               ! g_slist_find (tags_on, tag)) ||
+              g_slist_find (tags_off, tag))
+            {
+              gimp_text_style_editor_set_font (editor, tag);
+              break;
+            }
+        }
+
+      if (! list)
+        gimp_text_style_editor_set_font (editor, NULL);
+
       for (list = editor->toggles; list; list = g_list_next (list))
         {
           GtkToggleButton *toggle = list->data;



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