static void gimp_tag_popup_dispose (GObject *object) { GimpTagPopup *popup = GIMP_TAG_POPUP (object); gimp_tag_popup_remove_scroll_timeout (popup); if (popup->combo_entry) { g_object_unref (popup->combo_entry); popup->combo_entry = NULL; } if (popup->layout) { g_object_unref (popup->layout); popup->layout = NULL; } if (popup->context) { g_object_unref (popup->context); popup->context = NULL; } if (popup->tag_data) { g_free (popup->tag_data); popup->tag_data = NULL; } G_OBJECT_CLASS (parent_class)->dispose (object); }
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_tag_popup_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GimpTagPopup *popup = GIMP_TAG_POPUP (object); switch (property_id) { case PROP_OWNER: g_value_set_object (value, popup->combo_entry); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } }
static gboolean gimp_tag_popup_border_event (GtkWidget *widget, GdkEvent *event) { GimpTagPopup *popup = GIMP_TAG_POPUP (widget); if (event->type == GDK_BUTTON_PRESS) { GdkEventButton *button_event = (GdkEventButton *) event; GtkAllocation allocation; gint x; gint y; if (button_event->window == gtk_widget_get_window (widget) && gimp_tag_popup_button_scroll (popup, button_event)) { return TRUE; } gtk_widget_get_allocation (widget, &allocation); gdk_window_get_pointer (gtk_widget_get_window (widget), &x, &y, NULL); if (button_event->window != gtk_widget_get_window (popup->tag_area) && (x < allocation.y || y < allocation.x || x > allocation.x + allocation.width || y > allocation.y + allocation.height)) { /* user has clicked outside the popup area, * which means it should be hidden. */ gtk_grab_remove (widget); gdk_display_pointer_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME); gtk_widget_destroy (widget); } } else if (event->type == GDK_MOTION_NOTIFY) { GdkEventMotion *motion_event = (GdkEventMotion *) event; gint x, y; gdk_window_get_pointer (gtk_widget_get_window (widget), &x, &y, NULL); gimp_tag_popup_handle_scrolling (popup, x, y, motion_event->window == gtk_widget_get_window (widget), TRUE); } else if (event->type == GDK_BUTTON_RELEASE) { GdkEventButton *button_event = (GdkEventButton *) event; popup->single_select_disabled = TRUE; if (button_event->window == gtk_widget_get_window (widget) && gimp_tag_popup_button_scroll (popup, button_event)) { return TRUE; } } else if (event->type == GDK_GRAB_BROKEN) { gtk_grab_remove (widget); gdk_display_pointer_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME); gtk_widget_destroy (widget); } else if (event->type == GDK_KEY_PRESS) { gtk_grab_remove (widget); gdk_display_pointer_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME); gtk_widget_destroy (widget); } else if (event->type == GDK_SCROLL) { GdkEventScroll *scroll_event = (GdkEventScroll *) event; switch (scroll_event->direction) { case GDK_SCROLL_RIGHT: case GDK_SCROLL_DOWN: gimp_tag_popup_scroll_by (popup, MENU_SCROLL_STEP2); return TRUE; case GDK_SCROLL_LEFT: case GDK_SCROLL_UP: gimp_tag_popup_scroll_by (popup, - MENU_SCROLL_STEP2); return TRUE; } } return FALSE; }
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); }