summaryrefslogtreecommitdiff
path: root/src/ui/message.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/message.c')
-rw-r--r--src/ui/message.c217
1 files changed, 216 insertions, 1 deletions
diff --git a/src/ui/message.c b/src/ui/message.c
index da6bb97..4aa7a85 100644
--- a/src/ui/message.c
+++ b/src/ui/message.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2021 GNUnet e.V.
+ Copyright (C) 2021--2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -24,8 +24,143 @@
#include "message.h"
+#include <gnunet/gnunet_chat_lib.h>
+
#include "../application.h"
+static int
+handle_message_redraw_animation(gpointer user_data)
+{
+ UI_MESSAGE_Handle *handle = (UI_MESSAGE_Handle*) user_data;
+
+ handle->redraw_animation = 0;
+
+ if ((handle->preview_drawing_area) &&
+ ((handle->preview_image) ||
+ (handle->preview_animation) ||
+ (handle->preview_animation_iter)))
+ gtk_widget_queue_draw(GTK_WIDGET(handle->preview_drawing_area));
+
+ return FALSE;
+}
+
+static gboolean
+handle_preview_drawing_area_draw(GtkWidget* drawing_area,
+ cairo_t* cairo,
+ gpointer user_data)
+{
+ UI_MESSAGE_Handle *handle = (UI_MESSAGE_Handle*) user_data;
+
+ GtkStyleContext* context = gtk_widget_get_style_context(drawing_area);
+
+ const guint width = gtk_widget_get_allocated_width(drawing_area);
+ const guint height = gtk_widget_get_allocated_height(drawing_area);
+
+ gtk_render_background(context, cairo, 0, 0, width, height);
+
+ GdkPixbuf *image = handle->preview_image;
+
+ if (!(handle->preview_animation))
+ goto render_image;
+
+ if (handle->preview_animation_iter)
+ gdk_pixbuf_animation_iter_advance(handle->preview_animation_iter, NULL);
+ else
+ handle->preview_animation_iter = gdk_pixbuf_animation_get_iter(
+ handle->preview_animation, NULL
+ );
+
+ image = gdk_pixbuf_animation_iter_get_pixbuf(handle->preview_animation_iter);
+
+ const int delay = gdk_pixbuf_animation_iter_get_delay_time(
+ handle->preview_animation_iter
+ );
+
+ handle->redraw_animation = g_timeout_add(
+ delay, handle_message_redraw_animation, handle
+ );
+
+render_image:
+ if (!image)
+ return FALSE;
+
+ int dwidth = gdk_pixbuf_get_width(image);
+ int dheight = gdk_pixbuf_get_height(image);
+
+ gint optimal_height = width * dheight / dwidth;
+
+ gtk_widget_set_size_request(
+ GTK_WIDGET(drawing_area),
+ width,
+ optimal_height
+ );
+
+ double ratio_width = 1.0 * width / dwidth;
+ double ratio_height = 1.0 * height / dheight;
+
+ const double ratio = ratio_width < ratio_height? ratio_width : ratio_height;
+
+ dwidth = (int) (dwidth * ratio);
+ dheight = (int) (dheight * ratio);
+
+ double dx = (width - dwidth) * 0.5;
+ double dy = (height - dheight) * 0.5;
+
+ const int interp_type = (ratio >= 1.0?
+ GDK_INTERP_NEAREST :
+ GDK_INTERP_BILINEAR
+ );
+
+ GdkPixbuf* scaled = gdk_pixbuf_scale_simple(
+ image,
+ dwidth,
+ dheight,
+ interp_type
+ );
+
+ gtk_render_icon(context, cairo, scaled, dx, dy);
+
+ cairo_fill(cairo);
+
+ g_object_unref(scaled);
+ return FALSE;
+}
+
+static void
+_clear_message_preview_data(UI_MESSAGE_Handle *handle)
+{
+ if (handle->preview_image)
+ {
+ g_object_unref(handle->preview_image);
+ handle->preview_image = NULL;
+ }
+
+ if (handle->redraw_animation)
+ {
+ g_source_remove(handle->redraw_animation);
+ handle->redraw_animation = 0;
+ }
+
+ if (handle->preview_animation_iter)
+ {
+ g_object_unref(handle->preview_animation_iter);
+ handle->preview_animation_iter = NULL;
+ }
+
+ if (handle->preview_animation)
+ {
+ g_object_unref(handle->preview_animation);
+ handle->preview_animation = NULL;
+ }
+
+ if (handle->preview_drawing_area)
+ gtk_widget_set_size_request(
+ GTK_WIDGET(handle->preview_drawing_area),
+ -1,
+ -1
+ );
+}
+
UI_MESSAGE_Handle*
ui_message_new(MESSENGER_Application *app,
UI_MESSAGE_Type type)
@@ -120,10 +255,33 @@ ui_message_new(MESSENGER_Application *app,
gtk_builder_get_object(builder, "file_revealer")
);
+ handle->filename_label = GTK_LABEL(
+ gtk_builder_get_object(builder, "filename_label")
+ );
+
+ handle->file_progress_bar = GTK_PROGRESS_BAR(
+ gtk_builder_get_object(builder, "file_progress_bar")
+ );
+
+ handle->file_button = GTK_BUTTON(
+ gtk_builder_get_object(builder, "file_button")
+ );
+
+ handle->file_status_image = GTK_IMAGE(
+ gtk_builder_get_object(builder, "file_status_image")
+ );
+
handle->preview_drawing_area = GTK_DRAWING_AREA(
gtk_builder_get_object(builder, "preview_drawing_area")
);
+ handle->preview_draw_signal = g_signal_connect(
+ handle->preview_drawing_area,
+ "draw",
+ G_CALLBACK(handle_preview_drawing_area_draw),
+ handle
+ );
+
switch (handle->type)
{
case UI_MESSAGE_STATUS:
@@ -138,6 +296,13 @@ ui_message_new(MESSENGER_Application *app,
));
g_object_unref(builder);
+
+ handle->preview_image = NULL;
+ handle->preview_animation = NULL;
+ handle->preview_animation_iter = NULL;
+
+ handle->redraw_animation = 0;
+
return handle;
}
@@ -150,6 +315,49 @@ ui_message_update(UI_MESSAGE_Handle *handle,
if (!file)
return;
+ if (GNUNET_YES != GNUNET_CHAT_file_is_local(file))
+ goto file_content;
+
+ if (!(handle->preview_drawing_area))
+ goto file_progress;
+
+ const char *preview = GNUNET_CHAT_file_open_preview(file);
+
+ if (!preview)
+ goto file_progress;
+
+ handle->preview_animation = gdk_pixbuf_animation_new_from_file(
+ preview, NULL
+ );
+
+ if (!(handle->preview_animation))
+ handle->preview_image = gdk_pixbuf_new_from_file(preview, NULL);
+
+ if ((handle->preview_animation) || (handle->preview_animation))
+ {
+ gtk_widget_set_size_request(
+ GTK_WIDGET(handle->preview_drawing_area),
+ 250,
+ -1
+ );
+
+ gtk_stack_set_visible_child(
+ handle->content_stack,
+ GTK_WIDGET(handle->preview_drawing_area)
+ );
+
+ gtk_widget_queue_draw(GTK_WIDGET(handle->preview_drawing_area));
+ return;
+ }
+
+ GNUNET_CHAT_file_close_preview(file);
+
+file_progress:
+ gtk_progress_bar_set_fraction(handle->file_progress_bar, 1.0);
+
+file_content:
+ gtk_label_set_text(handle->filename_label, GNUNET_CHAT_file_get_name(file));
+
gtk_stack_set_visible_child(
handle->content_stack,
GTK_WIDGET(handle->file_revealer)
@@ -161,6 +369,13 @@ ui_message_update(UI_MESSAGE_Handle *handle,
void
ui_message_delete(UI_MESSAGE_Handle *handle)
{
+ _clear_message_preview_data(handle);
+
+ g_signal_handler_disconnect(
+ handle->preview_drawing_area,
+ handle->preview_draw_signal
+ );
+
g_object_unref(handle->builder);
g_free(handle);