comparison pidgin/gtkimhtml.c @ 32472:2f014dbda8a6

Make some gtkimhtml functions private
author Mark Doliner <mark@kingant.net>
date Thu, 01 Sep 2011 07:27:16 +0000
parents 4676bbc64e36
children 3340d322c8f8
comparison
equal deleted inserted replaced
32471:c66910c13433 32472:2f014dbda8a6
3591 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, 3591 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x,
3592 rect.y + rect.height); 3592 rect.y + rect.height);
3593 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); 3593 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0);
3594 } 3594 }
3595 3595
3596 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ 3596 /**
3597 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id) 3597 * Destroys and frees a GTK+ IM/HTML scalable image.
3598 { 3598 *
3599 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); 3599 * @param scale The GTK+ IM/HTML scalable.
3600 3600 */
3601 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; 3601 static void gtk_imhtml_image_free(GtkIMHtmlScalable *scale)
3602 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; 3602 {
3603 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; 3603 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale;
3604 3604
3605 im_image->pixbuf = img; 3605 g_object_unref(image->pixbuf);
3606 im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf)); 3606 g_free(image->filename);
3607 im_image->width = gdk_pixbuf_get_width(img); 3607 if (image->filesel)
3608 im_image->height = gdk_pixbuf_get_height(img); 3608 gtk_widget_destroy(image->filesel);
3609 im_image->mark = NULL; 3609 g_free(scale);
3610 im_image->filename = g_strdup(filename); 3610 }
3611 im_image->id = id; 3611
3612 im_image->filesel = NULL; 3612 /**
3613 3613 * Destroys and frees a GTK+ IM/HTML scalable animation.
3614 g_object_ref(img); 3614 *
3615 return GTK_IMHTML_SCALABLE(im_image); 3615 * @param scale The GTK+ IM/HTML scalable.
3616 } 3616 */
3617 3617 static void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale)
3618 static gboolean 3618 {
3619 animate_image_cb(gpointer data) 3619 GtkIMHtmlAnimation *animation = (GtkIMHtmlAnimation *)scale;
3620 { 3620
3621 GtkIMHtmlImage *im_image; 3621 if (animation->timer > 0)
3622 int width, height; 3622 g_source_remove(animation->timer);
3623 int delay; 3623 if (animation->iter != NULL)
3624 3624 g_object_unref(animation->iter);
3625 im_image = data; 3625 g_object_unref(animation->anim);
3626 3626
3627 /* Update the pointer to this GdkPixbuf frame of the animation */ 3627 gtk_imhtml_image_free(scale);
3628 if (gdk_pixbuf_animation_iter_advance(GTK_IMHTML_ANIMATION(im_image)->iter, NULL)) {
3629 GdkPixbuf *pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
3630 g_object_unref(G_OBJECT(im_image->pixbuf));
3631 im_image->pixbuf = gdk_pixbuf_copy(pb);
3632
3633 /* Update the displayed GtkImage */
3634 width = gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image));
3635 height = gdk_pixbuf_get_height(gtk_image_get_pixbuf(im_image->image));
3636 if (width > 0 && height > 0)
3637 {
3638 /* Need to scale the new frame to the same size as the old frame */
3639 GdkPixbuf *tmp;
3640 tmp = gdk_pixbuf_scale_simple(im_image->pixbuf, width, height, GDK_INTERP_BILINEAR);
3641 gtk_image_set_from_pixbuf(im_image->image, tmp);
3642 g_object_unref(G_OBJECT(tmp));
3643 } else {
3644 /* Display at full-size */
3645 gtk_image_set_from_pixbuf(im_image->image, im_image->pixbuf);
3646 }
3647 }
3648
3649 delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
3650 GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image);
3651
3652 return FALSE;
3653 }
3654
3655 GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *anim, const gchar *filename, int id)
3656 {
3657 GtkIMHtmlImage *im_image = (GtkIMHtmlImage *) g_new0(GtkIMHtmlAnimation, 1);
3658
3659 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale;
3660 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to;
3661 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_animation_free;
3662
3663 GTK_IMHTML_ANIMATION(im_image)->anim = anim;
3664 if (gdk_pixbuf_animation_is_static_image(anim)) {
3665 im_image->pixbuf = gdk_pixbuf_animation_get_static_image(anim);
3666 g_object_ref(im_image->pixbuf);
3667 } else {
3668 int delay;
3669 GdkPixbuf *pb;
3670 GTK_IMHTML_ANIMATION(im_image)->iter = gdk_pixbuf_animation_get_iter(anim, NULL);
3671 pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
3672 im_image->pixbuf = gdk_pixbuf_copy(pb);
3673 delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
3674 GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image);
3675 }
3676 im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf));
3677 im_image->width = gdk_pixbuf_animation_get_width(anim);
3678 im_image->height = gdk_pixbuf_animation_get_height(anim);
3679 im_image->filename = g_strdup(filename);
3680 im_image->id = id;
3681
3682 g_object_ref(anim);
3683
3684 return GTK_IMHTML_SCALABLE(im_image);
3685 }
3686
3687 void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height)
3688 {
3689 GtkIMHtmlImage *im_image = (GtkIMHtmlImage *)scale;
3690
3691 if (im_image->width > width || im_image->height > height) {
3692 double ratio_w, ratio_h, ratio;
3693 int new_h, new_w;
3694 GdkPixbuf *new_image = NULL;
3695
3696 ratio_w = ((double)width - 2) / im_image->width;
3697 ratio_h = ((double)height - 2) / im_image->height;
3698
3699 ratio = (ratio_w < ratio_h) ? ratio_w : ratio_h;
3700
3701 new_w = (int)(im_image->width * ratio);
3702 new_h = (int)(im_image->height * ratio);
3703
3704 new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, new_w, new_h, GDK_INTERP_BILINEAR);
3705 gtk_image_set_from_pixbuf(im_image->image, new_image);
3706 g_object_unref(G_OBJECT(new_image));
3707 } else if (gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image)) != im_image->width) {
3708 /* Enough space to show the full-size of the image. */
3709 GdkPixbuf *new_image;
3710
3711 new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, im_image->width, im_image->height, GDK_INTERP_BILINEAR);
3712 gtk_image_set_from_pixbuf(im_image->image, new_image);
3713 g_object_unref(G_OBJECT(new_image));
3714 }
3715 } 3628 }
3716 3629
3717 static void 3630 static void
3718 image_save_yes_cb(GtkIMHtmlImageSave *save, const char *filename) 3631 image_save_yes_cb(GtkIMHtmlImageSave *save, const char *filename)
3719 { 3632 {
3916 else 3829 else
3917 return FALSE; /* Let clicks go through if we didn't catch anything */ 3830 return FALSE; /* Let clicks go through if we didn't catch anything */
3918 3831
3919 } 3832 }
3920 3833
3921 static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley) 3834 /**
3922 { 3835 * Rescales a GTK+ IM/HTML scalable image to a given size.
3923 GdkPixbufAnimation *anim = NULL; 3836 *
3924 GtkIMHtmlImageSave *save = NULL; 3837 * @param scale The GTK+ IM/HTML scalable.
3925 gboolean ret; 3838 * @param width The new width.
3926 3839 * @param height The new height.
3927 if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3) 3840 */
3928 return FALSE; 3841 static void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height)
3929 3842 {
3930 anim = gtk_smiley_get_image(smiley); 3843 GtkIMHtmlImage *im_image = (GtkIMHtmlImage *)scale;
3931 if (!anim) 3844
3932 return FALSE; 3845 if (im_image->width > width || im_image->height > height) {
3933 3846 double ratio_w, ratio_h, ratio;
3934 save = g_new0(GtkIMHtmlImageSave, 1); 3847 int new_h, new_w;
3935 save->image = (GtkIMHtmlScalable *)gtk_imhtml_animation_new(anim, smiley->smile, 0); 3848 GdkPixbuf *new_image = NULL;
3936 save->data = smiley->data; /* Do not need to memdup here, since the smiley is not 3849
3937 destroyed before this GtkIMHtmlImageSave */ 3850 ratio_w = ((double)width - 2) / im_image->width;
3938 save->datasize = smiley->datasize; 3851 ratio_h = ((double)height - 2) / im_image->height;
3939 ret = gtk_imhtml_image_clicked(w, event, save); 3852
3940 g_object_set_data_full(G_OBJECT(w), "image-data", save->image, (GDestroyNotify)gtk_imhtml_animation_free); 3853 ratio = (ratio_w < ratio_h) ? ratio_w : ratio_h;
3941 g_object_set_data_full(G_OBJECT(w), "image-save-data", save, (GDestroyNotify)g_free); 3854
3942 return ret; 3855 new_w = (int)(im_image->width * ratio);
3943 } 3856 new_h = (int)(im_image->height * ratio);
3944 3857
3945 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) 3858 new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, new_w, new_h, GDK_INTERP_BILINEAR);
3946 { 3859 gtk_image_set_from_pixbuf(im_image->image, new_image);
3947 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; 3860 g_object_unref(G_OBJECT(new_image));
3948 3861 } else if (gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image)) != im_image->width) {
3949 g_object_unref(image->pixbuf); 3862 /* Enough space to show the full-size of the image. */
3950 g_free(image->filename); 3863 GdkPixbuf *new_image;
3951 if (image->filesel) 3864
3952 gtk_widget_destroy(image->filesel); 3865 new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, im_image->width, im_image->height, GDK_INTERP_BILINEAR);
3953 g_free(scale); 3866 gtk_image_set_from_pixbuf(im_image->image, new_image);
3954 } 3867 g_object_unref(G_OBJECT(new_image));
3955 3868 }
3956 void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale) 3869 }
3957 { 3870
3958 GtkIMHtmlAnimation *animation = (GtkIMHtmlAnimation *)scale; 3871 /**
3959 3872 * Adds a GTK+ IM/HTML scalable image to a given GTK+ IM/HTML at a given iter.
3960 if (animation->timer > 0) 3873 *
3961 g_source_remove(animation->timer); 3874 * @param scale The GTK+ IM/HTML scalable.
3962 if (animation->iter != NULL) 3875 * @param imhtml The GTK+ IM/HTML.
3963 g_object_unref(animation->iter); 3876 * @param iter The GtkTextIter at which to add the scalable.
3964 g_object_unref(animation->anim); 3877 */
3965 3878 static void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter)
3966 gtk_imhtml_image_free(scale);
3967 }
3968
3969 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter)
3970 { 3879 {
3971 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; 3880 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale;
3972 GtkWidget *box = gtk_event_box_new(); 3881 GtkWidget *box = gtk_event_box_new();
3973 char *tag; 3882 char *tag;
3974 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); 3883 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter);
3990 3899
3991 save = g_new0(GtkIMHtmlImageSave, 1); 3900 save = g_new0(GtkIMHtmlImageSave, 1);
3992 save->image = scale; 3901 save->image = scale;
3993 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), save); 3902 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), save);
3994 g_object_set_data_full(G_OBJECT(box), "image-save-data", save, (GDestroyNotify)g_free); 3903 g_object_set_data_full(G_OBJECT(box), "image-save-data", save, (GDestroyNotify)g_free);
3904 }
3905
3906 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */
3907 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id)
3908 {
3909 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage));
3910
3911 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale;
3912 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to;
3913 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free;
3914
3915 im_image->pixbuf = img;
3916 im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf));
3917 im_image->width = gdk_pixbuf_get_width(img);
3918 im_image->height = gdk_pixbuf_get_height(img);
3919 im_image->mark = NULL;
3920 im_image->filename = g_strdup(filename);
3921 im_image->id = id;
3922 im_image->filesel = NULL;
3923
3924 g_object_ref(img);
3925 return GTK_IMHTML_SCALABLE(im_image);
3926 }
3927
3928 static gboolean
3929 animate_image_cb(gpointer data)
3930 {
3931 GtkIMHtmlImage *im_image;
3932 int width, height;
3933 int delay;
3934
3935 im_image = data;
3936
3937 /* Update the pointer to this GdkPixbuf frame of the animation */
3938 if (gdk_pixbuf_animation_iter_advance(GTK_IMHTML_ANIMATION(im_image)->iter, NULL)) {
3939 GdkPixbuf *pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
3940 g_object_unref(G_OBJECT(im_image->pixbuf));
3941 im_image->pixbuf = gdk_pixbuf_copy(pb);
3942
3943 /* Update the displayed GtkImage */
3944 width = gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image));
3945 height = gdk_pixbuf_get_height(gtk_image_get_pixbuf(im_image->image));
3946 if (width > 0 && height > 0)
3947 {
3948 /* Need to scale the new frame to the same size as the old frame */
3949 GdkPixbuf *tmp;
3950 tmp = gdk_pixbuf_scale_simple(im_image->pixbuf, width, height, GDK_INTERP_BILINEAR);
3951 gtk_image_set_from_pixbuf(im_image->image, tmp);
3952 g_object_unref(G_OBJECT(tmp));
3953 } else {
3954 /* Display at full-size */
3955 gtk_image_set_from_pixbuf(im_image->image, im_image->pixbuf);
3956 }
3957 }
3958
3959 delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
3960 GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image);
3961
3962 return FALSE;
3963 }
3964
3965 /**
3966 * Creates and returns a new GTK+ IM/HTML scalable object with an
3967 * animated image.
3968 *
3969 * @param img A GdkPixbufAnimation of the image to add.
3970 * @param filename The filename to associate with the image.
3971 * @param id The id to associate with the image.
3972 *
3973 * @return A new IM/HTML Scalable object with an image.
3974 *
3975 * @since 2.1.0
3976 */
3977 /*
3978 * TODO: All this animation code could be combined much better with
3979 * the image code. It couldn't be done when it was written
3980 * because it requires breaking backward compatibility. It
3981 * would be good to do it for 3.0.0.
3982 */
3983 static GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *anim, const gchar *filename, int id)
3984 {
3985 GtkIMHtmlImage *im_image = (GtkIMHtmlImage *) g_new0(GtkIMHtmlAnimation, 1);
3986
3987 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale;
3988 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to;
3989 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_animation_free;
3990
3991 GTK_IMHTML_ANIMATION(im_image)->anim = anim;
3992 if (gdk_pixbuf_animation_is_static_image(anim)) {
3993 im_image->pixbuf = gdk_pixbuf_animation_get_static_image(anim);
3994 g_object_ref(im_image->pixbuf);
3995 } else {
3996 int delay;
3997 GdkPixbuf *pb;
3998 GTK_IMHTML_ANIMATION(im_image)->iter = gdk_pixbuf_animation_get_iter(anim, NULL);
3999 pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
4000 im_image->pixbuf = gdk_pixbuf_copy(pb);
4001 delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
4002 GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image);
4003 }
4004 im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf));
4005 im_image->width = gdk_pixbuf_animation_get_width(anim);
4006 im_image->height = gdk_pixbuf_animation_get_height(anim);
4007 im_image->filename = g_strdup(filename);
4008 im_image->id = id;
4009
4010 g_object_ref(anim);
4011
4012 return GTK_IMHTML_SCALABLE(im_image);
3995 } 4013 }
3996 4014
3997 GtkIMHtmlScalable *gtk_imhtml_hr_new() 4015 GtkIMHtmlScalable *gtk_imhtml_hr_new()
3998 { 4016 {
3999 GtkIMHtmlHr *hr = g_malloc(sizeof(GtkIMHtmlHr)); 4017 GtkIMHtmlHr *hr = g_malloc(sizeof(GtkIMHtmlHr));
4914 imhtml->animations->head = g_list_delete_link(imhtml->animations->head, l); 4932 imhtml->animations->head = g_list_delete_link(imhtml->animations->head, l);
4915 imhtml->num_animations--; 4933 imhtml->num_animations--;
4916 } 4934 }
4917 l = next; 4935 l = next;
4918 } 4936 }
4937 }
4938
4939 static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley)
4940 {
4941 GdkPixbufAnimation *anim = NULL;
4942 GtkIMHtmlImageSave *save = NULL;
4943 gboolean ret;
4944
4945 if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3)
4946 return FALSE;
4947
4948 anim = gtk_smiley_get_image(smiley);
4949 if (!anim)
4950 return FALSE;
4951
4952 save = g_new0(GtkIMHtmlImageSave, 1);
4953 save->image = (GtkIMHtmlScalable *)gtk_imhtml_animation_new(anim, smiley->smile, 0);
4954 save->data = smiley->data; /* Do not need to memdup here, since the smiley is not
4955 destroyed before this GtkIMHtmlImageSave */
4956 save->datasize = smiley->datasize;
4957 ret = gtk_imhtml_image_clicked(w, event, save);
4958 g_object_set_data_full(G_OBJECT(w), "image-data", save->image, (GDestroyNotify)gtk_imhtml_animation_free);
4959 g_object_set_data_full(G_OBJECT(w), "image-save-data", save, (GDestroyNotify)g_free);
4960 return ret;
4919 } 4961 }
4920 4962
4921 void gtk_imhtml_insert_smiley_at_iter(GtkIMHtml *imhtml, const char *sml, char *smiley, GtkTextIter *iter) 4963 void gtk_imhtml_insert_smiley_at_iter(GtkIMHtml *imhtml, const char *sml, char *smiley, GtkTextIter *iter)
4922 { 4964 {
4923 GdkPixbuf *pixbuf = NULL; 4965 GdkPixbuf *pixbuf = NULL;