gimp r26452 - in branches/soc-2008-tagging: . app/widgets
- From: aurisj svn gnome org
- To: svn-commits-list gnome org
- Subject: gimp r26452 - in branches/soc-2008-tagging: . app/widgets
- Date: Fri, 8 Aug 2008 19:51:37 +0000 (UTC)
Author: aurisj
Date: Fri Aug 8 19:51:37 2008
New Revision: 26452
URL: http://svn.gnome.org/viewvc/gimp?rev=26452&view=rev
Log:
2008-08-08 Aurimas JuÅka <aurisj svn gnome org>
* app/widgets/gimptagentry.[ch]: reorganized and rewritten jellybean
handling code.
Modified:
branches/soc-2008-tagging/ChangeLog
branches/soc-2008-tagging/app/widgets/gimptagentry.c
branches/soc-2008-tagging/app/widgets/gimptagentry.h
Modified: branches/soc-2008-tagging/app/widgets/gimptagentry.c
==============================================================================
--- branches/soc-2008-tagging/app/widgets/gimptagentry.c (original)
+++ branches/soc-2008-tagging/app/widgets/gimptagentry.c Fri Aug 8 19:51:37 2008
@@ -44,6 +44,13 @@
#define GIMP_TAG_ENTRY_MAX_RECENT_ITEMS 20
+typedef enum GimpTagSearchDir_
+{
+ TAG_SEARCH_NONE,
+ TAG_SEARCH_LEFT,
+ TAG_SEARCH_RIGHT,
+} GimpTagSearchDir;
+
enum
{
PROP_0,
@@ -70,6 +77,10 @@
gint text_length,
gint *position,
gpointer user_data);
+static void gimp_tag_entry_delete_text (GtkEditable *editable,
+ gint start_pos,
+ gint end_pos,
+ gpointer user_data);
static gboolean gimp_tag_entry_focus_in (GtkWidget *widget,
GdkEventFocus *event,
gpointer user_data);
@@ -81,10 +92,6 @@
GimpTagEntry *tag_entry);
static gboolean gimp_tag_entry_button_release (GtkWidget *widget,
GdkEventButton *event);
-static void gimp_tag_entry_backspace (GtkEntry *entry);
-static void gimp_tag_entry_delete_from_cursor (GtkEntry *entry,
- GtkDeleteType delete_type,
- gint count);
static gboolean gimp_tag_entry_key_press (GtkWidget *widget,
GdkEventKey *event,
gpointer user_data);
@@ -94,10 +101,6 @@
static void gimp_tag_entry_item_set_tags (GimpTagged *entry,
GList *tags);
-static gchar * gimp_tag_entry_get_current (GimpTagEntry *entry);
-static void gimp_tag_entry_set_current (GimpTagEntry *entry,
- const gchar *current);
-
static void gimp_tag_entry_load_selection (GimpTagEntry *tag_entry,
gboolean sort);
@@ -115,14 +118,23 @@
static gboolean gimp_tag_entry_expose (GtkWidget *widget,
GdkEventExpose *event,
gpointer user_data);
-
-static gboolean gimp_tag_entry_select_jellybean (GimpTagEntry *entry);
+static void gimp_tag_entry_commit_region (GString *tags,
+ GString *mask);
+static void gimp_tag_entry_commit_tags (GimpTagEntry *tag_entry);
+static gboolean gimp_tag_entry_commit_source_func (GimpTagEntry *tag_entry);
+static gboolean gimp_tag_entry_select_jellybean (GimpTagEntry *entry,
+ gint selection_start,
+ gint selection_end,
+ GimpTagSearchDir search_dir);
static gboolean gimp_tag_entry_try_select_jellybean (GimpTagEntry *tag_entry);
static gboolean gimp_tag_entry_add_to_recent (GimpTagEntry *tag_entry,
const gchar *tags_string,
gboolean to_front);
+static void gimp_tag_entry_next_tag (GimpTagEntry *tag_entry);
+static void gimp_tag_entry_previous_tag (GimpTagEntry *tag_entry);
+
GType
gimp_tag_entry_mode_get_type (void)
@@ -162,7 +174,6 @@
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- GtkEntryClass *entry_class = GTK_ENTRY_CLASS (klass);
object_class->dispose = gimp_tag_entry_dispose;
object_class->get_property = gimp_tag_entry_get_property;
@@ -170,9 +181,6 @@
widget_class->button_release_event = gimp_tag_entry_button_release;
- entry_class->backspace = gimp_tag_entry_backspace;
- entry_class->delete_from_cursor = gimp_tag_entry_delete_from_cursor;
-
g_object_class_install_property (object_class,
PROP_FILTERED_CONTAINER,
g_param_spec_object ("filtered-container",
@@ -202,6 +210,7 @@
entry->selected_items = NULL;
entry->mode = GIMP_TAG_ENTRY_MODE_QUERY;
entry->description_shown = FALSE;
+ entry->mask = g_string_new ("");
g_signal_connect (entry, "activate",
G_CALLBACK (gimp_tag_entry_activate),
@@ -212,6 +221,9 @@
g_signal_connect (entry, "insert-text",
G_CALLBACK (gimp_tag_entry_insert_text),
NULL);
+ g_signal_connect (entry, "delete-text",
+ G_CALLBACK (gimp_tag_entry_delete_text),
+ NULL);
g_signal_connect (entry, "key-press-event",
G_CALLBACK (gimp_tag_entry_key_press),
NULL);
@@ -252,6 +264,12 @@
tag_entry->filtered_container = NULL;
}
+ if (tag_entry->mask)
+ {
+ g_string_free (tag_entry->mask, TRUE);
+ tag_entry->mask = NULL;
+ }
+
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -394,17 +412,16 @@
{
g_return_if_fail (GIMP_IS_TAG_ENTRY (tag_entry));
- tag_entry->internal_change = TRUE;
+ tag_entry->internal_operation++;
gtk_entry_set_text (GTK_ENTRY (tag_entry), tag_string);
gtk_editable_set_position (GTK_EDITABLE (tag_entry), -1);
- tag_entry->internal_change = FALSE;
+ tag_entry->internal_operation--;
+ gimp_tag_entry_commit_tags (tag_entry);
if (tag_entry->mode == GIMP_TAG_ENTRY_MODE_ASSIGN)
{
gimp_tag_entry_assign_tags (tag_entry);
}
-
- tag_entry->tags_accepted = TRUE;
}
static void
@@ -440,7 +457,38 @@
gint *position,
gpointer user_data)
{
- if (! GIMP_TAG_ENTRY (editable)->internal_change)
+ GimpTagEntry *tag_entry = GIMP_TAG_ENTRY (editable);
+ const gchar *entry_text;
+ gboolean is_tag[2];
+ gint i;
+ gint insert_pos;
+
+ printf ("insert mask (b): '%s'\n", tag_entry->mask->str);
+
+ entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
+
+ is_tag[0] = FALSE;
+ if (*position > 0)
+ {
+ is_tag[0] = (tag_entry->mask->str[*position - 1] == 't' || tag_entry->mask->str[*position - 1] == 's');
+ }
+ is_tag[1] = (tag_entry->mask->str[*position] == 't' || tag_entry->mask->str[*position] == 's');
+ if (is_tag[0] && is_tag[1])
+ {
+ g_signal_stop_emission_by_name (editable, "insert_text");
+ }
+ else if (! tag_entry->suppress_mask_update)
+ {
+ insert_pos = *position;
+ for (i = 0; i < text_length; i++)
+ {
+ g_string_insert_c (tag_entry->mask, insert_pos + i, 'u');
+ }
+ }
+
+ printf ("insert mask (a): '%s'\n", tag_entry->mask->str);
+
+ if (! tag_entry->internal_operation)
{
g_idle_add ((GSourceFunc)gimp_tag_entry_auto_complete,
editable);
@@ -448,6 +496,59 @@
}
static void
+gimp_tag_entry_delete_text (GtkEditable *editable,
+ gint start_pos,
+ gint end_pos,
+ gpointer user_data)
+{
+ GimpTagEntry *tag_entry = GIMP_TAG_ENTRY (editable);
+
+ printf ("delete mask (b): '%s'\n", tag_entry->mask->str);
+
+ if (! tag_entry->internal_operation)
+ {
+ g_signal_handlers_block_by_func (editable,
+ gimp_tag_entry_delete_text, NULL);
+
+ if (end_pos > start_pos
+ && (tag_entry->mask->str[end_pos - 1] == 't'
+ || tag_entry->mask->str[end_pos - 1] == 's'))
+ {
+ while (end_pos <= tag_entry->mask->len
+ && (tag_entry->mask->str[end_pos] == 's'))
+ {
+ end_pos++;
+ }
+ while (end_pos <= tag_entry->mask->len
+ && (tag_entry->mask->str[end_pos] == 'w'))
+ {
+ end_pos++;
+ }
+ }
+
+ gtk_editable_delete_text (editable, start_pos, end_pos);
+ if (! tag_entry->suppress_mask_update)
+ {
+ g_string_erase (tag_entry->mask, start_pos, end_pos - start_pos);
+ }
+
+ g_signal_handlers_unblock_by_func (editable,
+ gimp_tag_entry_delete_text, NULL);
+
+ g_signal_stop_emission_by_name (editable, "delete_text");
+ }
+ else
+ {
+ if (! tag_entry->suppress_mask_update)
+ {
+ g_string_erase (tag_entry->mask, start_pos, end_pos - start_pos);
+ }
+ }
+
+ printf ("delete mask (a): '%s'\n", tag_entry->mask->str);
+}
+
+static void
gimp_tag_entry_query_tag (GimpTagEntry *entry)
{
gchar **parsed_tags;
@@ -538,10 +639,11 @@
gint i;
GimpTag *tag;
GList *tag_list = NULL;
- GList *iterator;
+#if 0
gchar *current_tag;
current_tag = gimp_tag_entry_get_current (tag_entry);
+#endif
parsed_tags = gimp_tag_entry_parse_tags (tag_entry);
count = g_strv_length (parsed_tags);
@@ -564,6 +666,7 @@
}
g_list_free (tag_list);
+#if 0
iterator = tag_entry->selected_items;
while (iterator)
{
@@ -593,6 +696,7 @@
}
g_free (current_tag);
+#endif
}
static void
@@ -685,75 +789,6 @@
return parsed_tags;
}
-static gchar *
-gimp_tag_entry_get_current (GimpTagEntry *entry)
-{
- GString *parsed_tag;
- const gchar *cursor;
- gunichar c;
- gint position;
- gint cursor_position = 0;
-
- position = gtk_editable_get_position (GTK_EDITABLE (entry));
-
- parsed_tag = g_string_new ("");
- cursor = gtk_entry_get_text (GTK_ENTRY (entry));
- do
- {
- c = g_utf8_get_char (cursor);
- cursor = g_utf8_next_char (cursor);
-
- if (! c || g_unichar_is_terminal_punctuation (c))
- {
- if (cursor_position >= position)
- {
- gchar *validated_tag = gimp_tag_string_make_valid (parsed_tag->str);
- g_string_free (parsed_tag, TRUE);
- return validated_tag;
- }
-
- g_string_set_size (parsed_tag, 0);
- }
- else
- {
- g_string_append_unichar (parsed_tag, c);
- }
-
- cursor_position++;
- } while (c);
- g_string_free (parsed_tag, TRUE);
-
- return NULL;
-}
-
-static void
-gimp_tag_entry_set_current (GimpTagEntry *entry,
- const gchar *current)
-{
- gint position = -1;
-
- if (current)
- {
- const gchar *entry_string;
- const gchar *current_in_entry;
- GString *current_string;
-
- entry_string = gtk_entry_get_text (GTK_ENTRY (entry));
- current_string = g_string_new (current);
- g_string_append (current_string, gimp_tag_entry_get_separator ());
- current_in_entry = strstr (entry_string, current_string->str);
- if (current_in_entry)
- {
- position = g_utf8_strlen (entry_string, current_in_entry - entry_string);
- }
- g_string_free (current_string, TRUE);
-
- position += g_utf8_strlen (current, -1);
- }
-
- gtk_editable_set_position (GTK_EDITABLE (entry), position);
-}
-
/**
* gimp_tag_entry_set_selected_items:
* @entry: a #GimpTagEntry widget.
@@ -792,18 +827,20 @@
iterator = g_list_next (iterator);
}
- if (entry->mode == GIMP_TAG_ENTRY_MODE_ASSIGN
- && iterator)
+ if (entry->mode == GIMP_TAG_ENTRY_MODE_ASSIGN)
{
- gimp_tag_entry_load_selection (entry, TRUE);
- gimp_tag_entry_toggle_desc (entry, FALSE);
- }
- else
- {
- entry->internal_change = TRUE;
- gtk_editable_delete_text (GTK_EDITABLE (entry), 0, -1);
- entry->internal_change = FALSE;
- gimp_tag_entry_toggle_desc (entry, TRUE);
+ if (iterator)
+ {
+ gimp_tag_entry_load_selection (entry, TRUE);
+ gimp_tag_entry_toggle_desc (entry, FALSE);
+ }
+ else
+ {
+ entry->internal_operation++;
+ gtk_editable_delete_text (GTK_EDITABLE (entry), 0, -1);
+ entry->internal_operation--;
+ gimp_tag_entry_toggle_desc (entry, TRUE);
+ }
}
}
@@ -818,9 +855,9 @@
GimpTag *tag;
gchar *text;
- tag_entry->internal_change = TRUE;
+ tag_entry->internal_operation++;
gtk_editable_delete_text (GTK_EDITABLE (tag_entry), 0, -1);
- tag_entry->internal_change = FALSE;
+ tag_entry->internal_operation--;
if (! tag_entry->selected_items)
{
@@ -840,15 +877,17 @@
{
tag = GIMP_TAG (tag_iterator->data);
text = g_strdup_printf ("%s%s", gimp_tag_get_name (tag), gimp_tag_entry_get_separator ());
- tag_entry->internal_change = TRUE;
+ tag_entry->internal_operation++;
gtk_editable_insert_text (GTK_EDITABLE (tag_entry), text, strlen (text),
&insert_pos);
- tag_entry->internal_change = FALSE;
+ tag_entry->internal_operation--;
g_free (text);
tag_iterator = g_list_next (tag_iterator);
}
g_list_free (tag_list);
+
+ gimp_tag_entry_commit_tags (tag_entry);
}
static gchar*
@@ -1035,10 +1074,10 @@
{
GimpTagEntry *tag_entry = GIMP_TAG_ENTRY (widget);
+ gimp_tag_entry_commit_tags (tag_entry);
gimp_tag_entry_add_to_recent (tag_entry,
gtk_entry_get_text (GTK_ENTRY (widget)),
TRUE);
- tag_entry->tags_accepted = TRUE;
gimp_tag_entry_toggle_desc (tag_entry, TRUE);
return FALSE;
@@ -1066,9 +1105,9 @@
}
if (! selected_iterator)
{
- tag_entry->internal_change = TRUE;
+ tag_entry->internal_operation++;
gtk_editable_delete_text (GTK_EDITABLE (tag_entry), 0, -1);
- tag_entry->internal_change = FALSE;
+ tag_entry->internal_operation--;
}
}
}
@@ -1191,47 +1230,20 @@
return FALSE;
}
-static void
-gimp_tag_entry_backspace (GtkEntry *entry)
-{
- GimpTagEntry *tag_entry = GIMP_TAG_ENTRY (entry);
- gint selection_start;
- gint selection_end;
-
- gtk_editable_get_selection_bounds (GTK_EDITABLE (entry),
- &selection_start, &selection_end);
- if (selection_start == selection_end
- && selection_start > 0
- && tag_entry->tags_accepted)
- {
- gtk_editable_set_position (GTK_EDITABLE (entry), selection_start - 1);
- }
-
- if (! gimp_tag_entry_select_jellybean (GIMP_TAG_ENTRY (entry)))
- {
- GTK_ENTRY_CLASS (parent_class)->backspace (entry);
- }
-}
-
-static void
-gimp_tag_entry_delete_from_cursor (GtkEntry *entry,
- GtkDeleteType delete_type,
- gint count)
-{
- if (count != 1
- || ! gimp_tag_entry_select_jellybean (GIMP_TAG_ENTRY (entry)))
- {
- GTK_ENTRY_CLASS (parent_class)->delete_from_cursor (entry, delete_type,
- count);
- }
-}
-
static gboolean
gimp_tag_entry_key_press (GtkWidget *widget,
GdkEventKey *event,
gpointer user_data)
{
GimpTagEntry *tag_entry = GIMP_TAG_ENTRY (widget);
+ guchar c;
+
+ c = gdk_keyval_to_unicode (event->keyval);
+ if (g_unichar_is_terminal_punctuation (c))
+ {
+ g_idle_add ((GSourceFunc) gimp_tag_entry_commit_source_func, tag_entry);
+ return FALSE;
+ }
switch (event->keyval)
{
@@ -1240,31 +1252,49 @@
gint selection_start;
gint selection_end;
- if (! tag_entry->internal_change)
- {
- g_idle_add ((GSourceFunc)gimp_tag_entry_auto_complete,
- tag_entry);
- }
- gtk_editable_get_selection_bounds (GTK_EDITABLE (tag_entry),
+ gtk_editable_get_selection_bounds (GTK_EDITABLE (widget),
&selection_start, &selection_end);
if (selection_start != selection_end)
{
- gtk_editable_select_region (GTK_EDITABLE (tag_entry),
+ gtk_editable_select_region (GTK_EDITABLE (widget),
selection_end, selection_end);
}
- tag_entry->tags_accepted = TRUE;
+ g_idle_add ((GSourceFunc)gimp_tag_entry_auto_complete,
+ tag_entry);
}
return TRUE;
case GDK_Return:
- case GDK_Escape:
- case GDK_comma:
- tag_entry->tags_accepted = TRUE;
+ gimp_tag_entry_commit_tags (tag_entry);
break;
+ case GDK_Left:
+ gimp_tag_entry_previous_tag (tag_entry);
+ return TRUE;
+
+ case GDK_Right:
+ gimp_tag_entry_next_tag (tag_entry);
+ return TRUE;
+
case GDK_BackSpace:
+ {
+ gint position = gtk_editable_get_position (GTK_EDITABLE (widget));
+ if (gimp_tag_entry_select_jellybean (tag_entry, position, position, TAG_SEARCH_LEFT))
+ {
+ return TRUE;
+ }
+ }
+ break;
+
case GDK_Delete:
+ {
+ gint position = gtk_editable_get_position (GTK_EDITABLE (widget));
+ if (gimp_tag_entry_select_jellybean (tag_entry, position, position, TAG_SEARCH_RIGHT))
+ {
+ return TRUE;
+ }
+ }
break;
case GDK_Up:
@@ -1292,17 +1322,14 @@
}
recent_item = (gchar *) g_list_first (tag_entry->recent_list)->data;
- tag_entry->internal_change = TRUE;
+ tag_entry->internal_operation++;
gtk_entry_set_text (GTK_ENTRY (tag_entry), recent_item);
gtk_editable_set_position (GTK_EDITABLE (tag_entry), -1);
- tag_entry->internal_change = FALSE;
-
- return TRUE;
+ tag_entry->internal_operation--;
}
- break;
+ return TRUE;
default:
- tag_entry->tags_accepted = FALSE;
break;
}
@@ -1313,20 +1340,20 @@
gimp_tag_entry_button_release (GtkWidget *widget,
GdkEventButton *event)
{
- GimpTagEntry *tag_entry = GIMP_TAG_ENTRY (widget);
-
if (event->button == 1)
{
- tag_entry->tags_accepted = TRUE;
g_idle_add ((GSourceFunc) gimp_tag_entry_try_select_jellybean,
widget);
}
+
return GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event);
}
static gboolean
gimp_tag_entry_try_select_jellybean (GimpTagEntry *tag_entry)
{
+ gint selection_start;
+ gint selection_end;
gint selection_pos = gtk_editable_get_position (GTK_EDITABLE (tag_entry));
gint char_count = g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (tag_entry)), -1);
if (selection_pos == char_count)
@@ -1334,110 +1361,106 @@
return FALSE;
}
- gimp_tag_entry_select_jellybean (tag_entry);
+ gtk_editable_get_selection_bounds (GTK_EDITABLE (tag_entry),
+ &selection_start, &selection_end);
+ gimp_tag_entry_select_jellybean (tag_entry, selection_start, selection_end, TAG_SEARCH_NONE);
return FALSE;
}
static gboolean
-gimp_tag_entry_jellybean_is_valid (const gchar *jellybean)
+gimp_tag_entry_select_jellybean (GimpTagEntry *tag_entry,
+ gint selection_start,
+ gint selection_end,
+ GimpTagSearchDir search_dir)
{
- gunichar c;
+ gint prev_selection_start;
+ gint prev_selection_end;
- do
+ if (! tag_entry->mask->len)
{
- c = g_utf8_get_char (jellybean);
- jellybean = g_utf8_next_char (jellybean);
- if (c
- && !g_unichar_is_terminal_punctuation (c)
- && !g_unichar_isspace (c))
- {
- return TRUE;
- }
- } while (c);
-
- return FALSE;
-}
-
-static gboolean
-gimp_tag_entry_select_jellybean (GimpTagEntry *entry)
-{
- gchar *original_string;
- gchar *jellybean_start;
- gchar *jellybean;
- gchar *cursor;
- gint position;
- gint i;
- gunichar c;
- gint selection_start;
- gint selection_end;
- gchar *previous_jellybean;
- gboolean jellybean_valid = FALSE;
+ return FALSE;
+ }
- if (!entry->tags_accepted)
+ if (selection_start >= tag_entry->mask->len)
{
- return FALSE;
+ selection_start = tag_entry->mask->len - 1;
}
- gtk_editable_get_selection_bounds (GTK_EDITABLE (entry),
- &selection_start, &selection_end);
- if (selection_start != selection_end)
+ if (tag_entry->mask->str[selection_start] == 'u')
{
return FALSE;
}
- original_string = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
- position = gtk_editable_get_position (GTK_EDITABLE (entry));
- cursor = original_string;
- jellybean_start = original_string;
- previous_jellybean = original_string;
- for (i = 0; i < position; i++)
+ switch (search_dir)
{
- c = g_utf8_get_char (cursor);
- if (! jellybean_valid
- && !g_unichar_is_terminal_punctuation (c)
- && !g_unichar_isspace (c))
- {
- jellybean_valid = TRUE;
- }
- cursor = g_utf8_next_char (cursor);
- if (g_unichar_is_terminal_punctuation (c)
- && jellybean_valid)
- {
- previous_jellybean = jellybean_start;
- jellybean_start = cursor;
- jellybean_valid = FALSE;
- }
+ case TAG_SEARCH_NONE:
+ {
+ if (selection_start > 0
+ && tag_entry->mask->str[selection_start] == 's')
+ {
+ selection_start--;
+ }
+ }
+ break;
+
+ case TAG_SEARCH_LEFT:
+ {
+ while (tag_entry->mask->str[selection_start] != 't'
+ && selection_start > 0)
+ {
+ selection_start--;
+ }
+ selection_end = selection_start + 1;
+ }
+ break;
+
+ case TAG_SEARCH_RIGHT:
+ {
+ while (tag_entry->mask->str[selection_start] != 't'
+ && selection_start < tag_entry->mask->len - 1)
+ {
+ selection_start++;
+ }
+ selection_end = selection_start + 1;
+ }
+ break;
}
- do
+
+ gtk_editable_get_selection_bounds (GTK_EDITABLE (tag_entry),
+ &prev_selection_start,
+ &prev_selection_end);
+
+ if (tag_entry->mask->str[selection_start] == 't')
{
- c = g_utf8_get_char (cursor);
- cursor = g_utf8_next_char (cursor);
- if (g_unichar_is_terminal_punctuation (c))
+ while (selection_start > 0
+ && (tag_entry->mask->str[selection_start - 1] == 't'))
{
- *cursor = '\0';
- break;
+ selection_start--;
}
- } while (c);
+ }
- jellybean = jellybean_start;
- if (! gimp_tag_entry_jellybean_is_valid (jellybean))
+ if (selection_end > selection_start
+ && (tag_entry->mask->str[selection_end - 1] == 't'))
{
- jellybean = previous_jellybean;
- if (! gimp_tag_entry_jellybean_is_valid (jellybean))
+ while (selection_end <= tag_entry->mask->len
+ && (tag_entry->mask->str[selection_end] == 't'))
{
- return FALSE;
+ selection_end++;
}
}
- selection_start = g_utf8_pointer_to_offset (original_string, jellybean);
- selection_end = g_utf8_pointer_to_offset (original_string,
- jellybean + strlen (jellybean));
- g_free (original_string);
-
- gtk_editable_select_region (GTK_EDITABLE (entry),
- selection_start, selection_end);
-
- return TRUE;
+ if ((selection_start != prev_selection_start
+ || selection_end != prev_selection_end)
+ && (tag_entry->mask->str[selection_start] == 't'))
+ {
+ gtk_editable_select_region (GTK_EDITABLE (tag_entry),
+ selection_start, selection_end);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
}
static gboolean
@@ -1509,3 +1532,279 @@
return _(", ");
}
+static void
+gimp_tag_entry_commit_region (GString *tags,
+ GString *mask)
+{
+ gint i = 0;
+ gint j;
+ gint stage = 0;
+ gunichar c;
+ gchar *cursor;
+ GString *out_tags;
+ GString *out_mask;
+ GString *tag_buffer;
+
+ out_tags = g_string_new ("");
+ out_mask = g_string_new ("");
+ tag_buffer = g_string_new ("");
+
+ cursor = tags->str;
+ for (i = 0; i <= mask->len; i++)
+ {
+ c = g_utf8_get_char (cursor);
+ cursor = g_utf8_next_char (cursor);
+
+ if (stage == 0)
+ {
+ /* whitespace before tag */
+ if (g_unichar_isspace (c))
+ {
+ g_string_append_unichar (out_tags, c);
+ g_string_append_c (out_mask, 'w');
+ }
+ else
+ {
+ stage++;
+ }
+ }
+
+ if (stage == 1)
+ {
+ /* tag */
+ if (c && ! g_unichar_is_terminal_punctuation (c))
+ {
+ g_string_append_unichar (tag_buffer, c);
+ }
+ else
+ {
+ gchar *valid_tag = gimp_tag_string_make_valid (tag_buffer->str);
+ gsize tag_length;
+
+ if (valid_tag)
+ {
+ tag_length = g_utf8_strlen (valid_tag, -1);
+ g_string_append (out_tags, valid_tag);
+ for (j = 0; j < tag_length; j++)
+ {
+ g_string_append_c (out_mask, 't');
+ }
+ g_free (valid_tag);
+
+ if (! c)
+ {
+ g_string_append (out_tags, gimp_tag_entry_get_separator ());
+ g_string_append_c (out_mask, 's');
+ g_string_append_c (out_mask, 'w');
+ }
+
+ stage++;
+ }
+ else
+ {
+ stage = 0;
+ }
+
+ g_string_set_size (tag_buffer, 0);
+
+ }
+ }
+
+ if (stage == 2)
+ {
+ if (g_unichar_is_terminal_punctuation (c))
+ {
+ g_string_append_unichar (out_tags, c);
+ g_string_append_c (out_mask, 's');
+ }
+ else
+ {
+ if (g_unichar_isspace (c))
+ {
+ g_string_append_unichar (out_tags, c);
+ g_string_append_c (out_mask, 'w');
+ }
+
+ stage = 0;
+ }
+ }
+ }
+
+ g_string_assign (tags, out_tags->str);
+ g_string_assign (mask, out_mask->str);
+
+ g_string_free (tag_buffer, TRUE);
+ g_string_free (out_tags, TRUE);
+ g_string_free (out_mask, TRUE);
+}
+
+static void
+gimp_tag_entry_commit_tags (GimpTagEntry *tag_entry)
+{
+ gint i;
+ gint region_start;
+ gint region_end;
+ gint position;
+ gboolean found_region;
+ gint cursor_position;
+
+ printf ("commiting tags ...\n");
+ printf ("commit mask (b): '%s'\n", tag_entry->mask->str);
+
+ cursor_position = gtk_editable_get_position (GTK_EDITABLE (tag_entry));
+
+ do
+ {
+ found_region = FALSE;
+
+ for (i = 0; i < tag_entry->mask->len; i++)
+ {
+ if (tag_entry->mask->str[i] == 'u')
+ {
+ found_region = TRUE;
+ region_start = i;
+ region_end = i + 1;
+ for (i++; i < tag_entry->mask->len; i++)
+ {
+ if (tag_entry->mask->str[i] == 'u')
+ {
+ region_end = i + 1;
+ }
+ else
+ {
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ if (found_region)
+ {
+ gchar *tags_string;
+ GString *tags;
+ GString *mask;
+ gboolean no_space = FALSE;
+
+ tags_string = gtk_editable_get_chars (GTK_EDITABLE (tag_entry), region_start, region_end);
+ tags = g_string_new (tags_string);
+ g_free (tags_string);
+
+ mask = g_string_new_len (tag_entry->mask->str + region_start, region_end - region_start);
+
+ gimp_tag_entry_commit_region (tags, mask);
+
+ if (region_start > 0)
+ {
+ gchar *last_c;
+ gunichar c;
+
+ last_c = g_utf8_offset_to_pointer (gtk_entry_get_text (GTK_ENTRY (tag_entry)),
+ region_start - 1);
+ c = g_utf8_get_char (last_c);
+ no_space = ! g_unichar_isspace (c);
+ }
+
+
+ if (no_space
+ && mask->len > 0
+ && mask->str[0] != 'w')
+ {
+ g_string_prepend_c (tags, ' ');
+ g_string_prepend_c (mask, 'w');
+ }
+
+ if (cursor_position <= region_end)
+ {
+ cursor_position += mask->len - (region_end - region_start);
+ }
+
+ tag_entry->internal_operation++;
+ tag_entry->suppress_mask_update++;
+ gtk_editable_delete_text (GTK_EDITABLE (tag_entry), region_start, region_end);
+ position = region_start;
+ gtk_editable_insert_text (GTK_EDITABLE (tag_entry), tags->str, mask->len, &position);
+ tag_entry->suppress_mask_update--;
+ tag_entry->internal_operation--;
+
+ g_string_erase (tag_entry->mask, region_start, region_end - region_start);
+ g_string_insert_len (tag_entry->mask, region_start, mask->str, mask->len);
+
+ g_string_free (mask, TRUE);
+ g_string_free (tags, TRUE);
+ }
+ } while (found_region);
+
+ gtk_editable_set_position (GTK_EDITABLE (tag_entry), cursor_position);
+
+
+ printf ("commit mask (a): '%s'\n", tag_entry->mask->str);
+}
+
+static gboolean
+gimp_tag_entry_commit_source_func (GimpTagEntry *tag_entry)
+{
+ gimp_tag_entry_commit_tags (GIMP_TAG_ENTRY (tag_entry));
+ return FALSE;
+}
+
+
+static void
+gimp_tag_entry_next_tag (GimpTagEntry *tag_entry)
+{
+ gint position = gtk_editable_get_position (GTK_EDITABLE (tag_entry));
+ if (tag_entry->mask->str[position] != 'u')
+ {
+ while (position < tag_entry->mask->len
+ && (tag_entry->mask->str[position] != 's'))
+ {
+ position++;
+ }
+
+ if (tag_entry->mask->str[position] == 's')
+ {
+ position++;
+ }
+ }
+ else if (position < tag_entry->mask->len)
+ {
+ position++;
+ }
+
+ gtk_editable_set_position (GTK_EDITABLE (tag_entry), position);
+}
+
+static void
+gimp_tag_entry_previous_tag (GimpTagEntry *tag_entry)
+{
+ gint position = gtk_editable_get_position (GTK_EDITABLE (tag_entry));
+ if (position >= 1
+ && tag_entry->mask->str[position - 1] == 's')
+ {
+ position--;
+ }
+ if (position < 1)
+ {
+ return;
+ }
+ if (tag_entry->mask->str[position - 1] != 'u')
+ {
+ while (position > 0
+ && (tag_entry->mask->str[position - 1] != 's'))
+ {
+ if (tag_entry->mask->str[position - 1] == 'u')
+ {
+ break;
+ }
+
+ position--;
+ }
+ }
+ else
+ {
+ position--;
+ }
+
+ gtk_editable_set_position (GTK_EDITABLE (tag_entry), position);
+}
+
Modified: branches/soc-2008-tagging/app/widgets/gimptagentry.h
==============================================================================
--- branches/soc-2008-tagging/app/widgets/gimptagentry.h (original)
+++ branches/soc-2008-tagging/app/widgets/gimptagentry.h Fri Aug 8 19:51:37 2008
@@ -47,12 +47,13 @@
GtkEntry parent_instance;
GimpFilteredContainer *filtered_container;
+ GString *mask;
GList *selected_items;
GList *recent_list;
GimpTagEntryMode mode;
+ gint internal_operation;
+ gint suppress_mask_update;
gboolean description_shown;
- gboolean internal_change;
- gboolean tags_accepted;
};
struct _GimpTagEntryClass
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]