static void gimp_combo_tag_entry_icon_press (GtkWidget *widget, GtkEntryIconPosition icon_pos, GdkEvent *event, gpointer user_data) { GimpComboTagEntry *entry = GIMP_COMBO_TAG_ENTRY (widget); if (! entry->popup) { GimpTaggedContainer *container = GIMP_TAG_ENTRY (entry)->container; gint tag_count; tag_count = gimp_tagged_container_get_tag_count (container); if (tag_count > 0 && ! GIMP_TAG_ENTRY (entry)->has_invalid_tags) { entry->popup = gimp_tag_popup_new (entry); g_signal_connect (entry->popup, "destroy", G_CALLBACK (gimp_combo_tag_entry_popup_destroy), entry); gimp_tag_popup_show (GIMP_TAG_POPUP (entry->popup)); } } else { gtk_widget_destroy (entry->popup); } }
static void gimp_combo_tag_entry_constructed (GObject *object) { GimpComboTagEntry *entry = GIMP_COMBO_TAG_ENTRY (object); G_OBJECT_CLASS (parent_class)->constructed (object); g_signal_connect_object (GIMP_TAG_ENTRY (entry)->container, "tag-count-changed", G_CALLBACK (gimp_combo_tag_entry_tag_count_changed), entry, 0); }
static void gimp_combo_tag_entry_tag_count_changed (GimpTaggedContainer *container, gint tag_count, GimpComboTagEntry *entry) { gboolean sensitive; sensitive = tag_count > 0 && ! GIMP_TAG_ENTRY (entry)->has_invalid_tags; gtk_entry_set_icon_sensitive (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, sensitive); }
static void gimp_tag_popup_toggle_tag (GimpTagPopup *popup, PopupTagData *tag_data) { gchar **current_tags; GString *tag_str; gint length; gint i; gboolean tag_toggled_off = FALSE; if (tag_data->state == GTK_STATE_NORMAL) { tag_data->state = GTK_STATE_SELECTED; } else if (tag_data->state == GTK_STATE_SELECTED) { tag_data->state = GTK_STATE_NORMAL; } else { return; } current_tags = gimp_tag_entry_parse_tags (GIMP_TAG_ENTRY (popup->combo_entry)); tag_str = g_string_new (""); length = g_strv_length (current_tags); for (i = 0; i < length; i++) { if (! gimp_tag_compare_with_string (tag_data->tag, current_tags[i])) { tag_toggled_off = TRUE; } else { if (tag_str->len) { g_string_append (tag_str, gimp_tag_entry_get_separator ()); g_string_append_c (tag_str, ' '); } g_string_append (tag_str, current_tags[i]); } } if (! tag_toggled_off) { /* this tag was not selected yet, so it needs to be toggled on */ if (tag_str->len) { g_string_append (tag_str, gimp_tag_entry_get_separator ()); g_string_append_c (tag_str, ' '); } g_string_append (tag_str, gimp_tag_get_name (tag_data->tag)); } gimp_tag_entry_set_tag_string (GIMP_TAG_ENTRY (popup->combo_entry), tag_str->str); g_string_free (tag_str, TRUE); g_strfreev (current_tags); if (GIMP_TAG_ENTRY (popup->combo_entry)->mode == GIMP_TAG_ENTRY_MODE_QUERY) { GimpTaggedContainer *container; container = GIMP_TAG_ENTRY (popup->combo_entry)->container; for (i = 0; i < popup->tag_count; i++) { if (popup->tag_data[i].state != GTK_STATE_SELECTED) { popup->tag_data[i].state = GTK_STATE_INSENSITIVE; } } gimp_container_foreach (GIMP_CONTAINER (container), (GFunc) gimp_tag_popup_check_can_toggle, popup); } }
static void gimp_tag_popup_constructed (GObject *object) { GimpTagPopup *popup = GIMP_TAG_POPUP (object); GimpTaggedContainer *container; GtkWidget *entry; GtkAllocation entry_allocation; GtkStyle *frame_style; gint x; gint y; gint width; gint height; gint popup_height; GHashTable *tag_hash; GList *tag_list; GList *tag_iterator; gint i; gint max_height; gint screen_height; gchar **current_tags; gint current_count; GdkRectangle popup_rects[2]; /* variants of popup placement */ GdkRectangle popup_rect; /* best popup rect in screen coordinates */ if (G_OBJECT_CLASS (parent_class)->constructed) G_OBJECT_CLASS (parent_class)->constructed (object); entry = GTK_WIDGET (popup->combo_entry); gtk_window_set_screen (GTK_WINDOW (popup), gtk_widget_get_screen (entry)); popup->context = gtk_widget_create_pango_context (GTK_WIDGET (popup)); popup->layout = pango_layout_new (popup->context); gtk_widget_get_allocation (entry, &entry_allocation); gtk_widget_style_get (GTK_WIDGET (popup), "scroll-arrow-vlength", &popup->scroll_arrow_height, NULL); pango_layout_set_attributes (popup->layout, popup->combo_entry->normal_item_attr); current_tags = gimp_tag_entry_parse_tags (GIMP_TAG_ENTRY (popup->combo_entry)); current_count = g_strv_length (current_tags); container = GIMP_TAG_ENTRY (popup->combo_entry)->container; tag_hash = container->tag_ref_counts; tag_list = g_hash_table_get_keys (tag_hash); tag_list = g_list_sort (tag_list, gimp_tag_compare_func); popup->tag_count = g_list_length (tag_list); popup->tag_data = g_new0 (PopupTagData, popup->tag_count); for (i = 0, tag_iterator = tag_list; i < popup->tag_count; i++, tag_iterator = g_list_next (tag_iterator)) { PopupTagData *tag_data = &popup->tag_data[i]; gint j; tag_data->tag = tag_iterator->data; tag_data->state = GTK_STATE_NORMAL; for (j = 0; j < current_count; j++) { if (! gimp_tag_compare_with_string (tag_data->tag, current_tags[j])) { tag_data->state = GTK_STATE_SELECTED; break; } } } g_list_free (tag_list); g_strfreev (current_tags); if (GIMP_TAG_ENTRY (popup->combo_entry)->mode == GIMP_TAG_ENTRY_MODE_QUERY) { for (i = 0; i < popup->tag_count; i++) { if (popup->tag_data[i].state != GTK_STATE_SELECTED) { popup->tag_data[i].state = GTK_STATE_INSENSITIVE; } } gimp_container_foreach (GIMP_CONTAINER (container), (GFunc) gimp_tag_popup_check_can_toggle, popup); } frame_style = gtk_widget_get_style (popup->frame); width = (entry_allocation.width - 2 * frame_style->xthickness); height = (gimp_tag_popup_layout_tags (popup, width) + 2 * frame_style->ythickness); gdk_window_get_origin (gtk_widget_get_window (entry), &x, &y); max_height = entry_allocation.height * 10; screen_height = gdk_screen_get_height (gtk_widget_get_screen (entry)); popup_height = MIN (height, max_height); popup_rects[0].x = x; popup_rects[0].y = 0; popup_rects[0].width = entry_allocation.width; popup_rects[0].height = y + entry_allocation.height; popup_rects[1].x = x; popup_rects[1].y = y; popup_rects[1].width = popup_rects[0].width; popup_rects[1].height = screen_height - popup_rects[0].height; if (popup_rects[0].height >= popup_height) { popup_rect = popup_rects[0]; popup_rect.y += popup_rects[0].height - popup_height; popup_rect.height = popup_height; } else if (popup_rects[1].height >= popup_height) { popup_rect = popup_rects[1]; popup_rect.height = popup_height; } else { if (popup_rects[0].height >= popup_rects[1].height) { popup_rect = popup_rects[0]; popup_rect.y += popup->scroll_arrow_height + frame_style->ythickness; } else { popup_rect = popup_rects[1]; popup_rect.y -= popup->scroll_arrow_height + frame_style->ythickness; } popup_height = popup_rect.height; } if (popup_height < height) { popup->arrows_visible = TRUE; popup->upper_arrow_state = GTK_STATE_INSENSITIVE; gtk_alignment_set_padding (GTK_ALIGNMENT (popup->alignment), popup->scroll_arrow_height + 2, popup->scroll_arrow_height + 2, 0, 0); popup_height -= 2 * popup->scroll_arrow_height + 4; popup->scroll_height = height - popup_rect.height; popup->scroll_y = 0; popup->scroll_step = 0; } gtk_widget_set_size_request (popup->tag_area, width, popup_height); gtk_window_move (GTK_WINDOW (popup), popup_rect.x, popup_rect.y); gtk_window_resize (GTK_WINDOW (popup), popup_rect.width, popup_rect.height); }