aboutsummaryrefslogtreecommitdiff
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 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V. 3 Copyright (C) 2021--2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -24,8 +24,143 @@
24 24
25#include "message.h" 25#include "message.h"
26 26
27#include <gnunet/gnunet_chat_lib.h>
28
27#include "../application.h" 29#include "../application.h"
28 30
31static int
32handle_message_redraw_animation(gpointer user_data)
33{
34 UI_MESSAGE_Handle *handle = (UI_MESSAGE_Handle*) user_data;
35
36 handle->redraw_animation = 0;
37
38 if ((handle->preview_drawing_area) &&
39 ((handle->preview_image) ||
40 (handle->preview_animation) ||
41 (handle->preview_animation_iter)))
42 gtk_widget_queue_draw(GTK_WIDGET(handle->preview_drawing_area));
43
44 return FALSE;
45}
46
47static gboolean
48handle_preview_drawing_area_draw(GtkWidget* drawing_area,
49 cairo_t* cairo,
50 gpointer user_data)
51{
52 UI_MESSAGE_Handle *handle = (UI_MESSAGE_Handle*) user_data;
53
54 GtkStyleContext* context = gtk_widget_get_style_context(drawing_area);
55
56 const guint width = gtk_widget_get_allocated_width(drawing_area);
57 const guint height = gtk_widget_get_allocated_height(drawing_area);
58
59 gtk_render_background(context, cairo, 0, 0, width, height);
60
61 GdkPixbuf *image = handle->preview_image;
62
63 if (!(handle->preview_animation))
64 goto render_image;
65
66 if (handle->preview_animation_iter)
67 gdk_pixbuf_animation_iter_advance(handle->preview_animation_iter, NULL);
68 else
69 handle->preview_animation_iter = gdk_pixbuf_animation_get_iter(
70 handle->preview_animation, NULL
71 );
72
73 image = gdk_pixbuf_animation_iter_get_pixbuf(handle->preview_animation_iter);
74
75 const int delay = gdk_pixbuf_animation_iter_get_delay_time(
76 handle->preview_animation_iter
77 );
78
79 handle->redraw_animation = g_timeout_add(
80 delay, handle_message_redraw_animation, handle
81 );
82
83render_image:
84 if (!image)
85 return FALSE;
86
87 int dwidth = gdk_pixbuf_get_width(image);
88 int dheight = gdk_pixbuf_get_height(image);
89
90 gint optimal_height = width * dheight / dwidth;
91
92 gtk_widget_set_size_request(
93 GTK_WIDGET(drawing_area),
94 width,
95 optimal_height
96 );
97
98 double ratio_width = 1.0 * width / dwidth;
99 double ratio_height = 1.0 * height / dheight;
100
101 const double ratio = ratio_width < ratio_height? ratio_width : ratio_height;
102
103 dwidth = (int) (dwidth * ratio);
104 dheight = (int) (dheight * ratio);
105
106 double dx = (width - dwidth) * 0.5;
107 double dy = (height - dheight) * 0.5;
108
109 const int interp_type = (ratio >= 1.0?
110 GDK_INTERP_NEAREST :
111 GDK_INTERP_BILINEAR
112 );
113
114 GdkPixbuf* scaled = gdk_pixbuf_scale_simple(
115 image,
116 dwidth,
117 dheight,
118 interp_type
119 );
120
121 gtk_render_icon(context, cairo, scaled, dx, dy);
122
123 cairo_fill(cairo);
124
125 g_object_unref(scaled);
126 return FALSE;
127}
128
129static void
130_clear_message_preview_data(UI_MESSAGE_Handle *handle)
131{
132 if (handle->preview_image)
133 {
134 g_object_unref(handle->preview_image);
135 handle->preview_image = NULL;
136 }
137
138 if (handle->redraw_animation)
139 {
140 g_source_remove(handle->redraw_animation);
141 handle->redraw_animation = 0;
142 }
143
144 if (handle->preview_animation_iter)
145 {
146 g_object_unref(handle->preview_animation_iter);
147 handle->preview_animation_iter = NULL;
148 }
149
150 if (handle->preview_animation)
151 {
152 g_object_unref(handle->preview_animation);
153 handle->preview_animation = NULL;
154 }
155
156 if (handle->preview_drawing_area)
157 gtk_widget_set_size_request(
158 GTK_WIDGET(handle->preview_drawing_area),
159 -1,
160 -1
161 );
162}
163
29UI_MESSAGE_Handle* 164UI_MESSAGE_Handle*
30ui_message_new(MESSENGER_Application *app, 165ui_message_new(MESSENGER_Application *app,
31 UI_MESSAGE_Type type) 166 UI_MESSAGE_Type type)
@@ -120,10 +255,33 @@ ui_message_new(MESSENGER_Application *app,
120 gtk_builder_get_object(builder, "file_revealer") 255 gtk_builder_get_object(builder, "file_revealer")
121 ); 256 );
122 257
258 handle->filename_label = GTK_LABEL(
259 gtk_builder_get_object(builder, "filename_label")
260 );
261
262 handle->file_progress_bar = GTK_PROGRESS_BAR(
263 gtk_builder_get_object(builder, "file_progress_bar")
264 );
265
266 handle->file_button = GTK_BUTTON(
267 gtk_builder_get_object(builder, "file_button")
268 );
269
270 handle->file_status_image = GTK_IMAGE(
271 gtk_builder_get_object(builder, "file_status_image")
272 );
273
123 handle->preview_drawing_area = GTK_DRAWING_AREA( 274 handle->preview_drawing_area = GTK_DRAWING_AREA(
124 gtk_builder_get_object(builder, "preview_drawing_area") 275 gtk_builder_get_object(builder, "preview_drawing_area")
125 ); 276 );
126 277
278 handle->preview_draw_signal = g_signal_connect(
279 handle->preview_drawing_area,
280 "draw",
281 G_CALLBACK(handle_preview_drawing_area_draw),
282 handle
283 );
284
127 switch (handle->type) 285 switch (handle->type)
128 { 286 {
129 case UI_MESSAGE_STATUS: 287 case UI_MESSAGE_STATUS:
@@ -138,6 +296,13 @@ ui_message_new(MESSENGER_Application *app,
138 )); 296 ));
139 297
140 g_object_unref(builder); 298 g_object_unref(builder);
299
300 handle->preview_image = NULL;
301 handle->preview_animation = NULL;
302 handle->preview_animation_iter = NULL;
303
304 handle->redraw_animation = 0;
305
141 return handle; 306 return handle;
142} 307}
143 308
@@ -150,6 +315,49 @@ ui_message_update(UI_MESSAGE_Handle *handle,
150 if (!file) 315 if (!file)
151 return; 316 return;
152 317
318 if (GNUNET_YES != GNUNET_CHAT_file_is_local(file))
319 goto file_content;
320
321 if (!(handle->preview_drawing_area))
322 goto file_progress;
323
324 const char *preview = GNUNET_CHAT_file_open_preview(file);
325
326 if (!preview)
327 goto file_progress;
328
329 handle->preview_animation = gdk_pixbuf_animation_new_from_file(
330 preview, NULL
331 );
332
333 if (!(handle->preview_animation))
334 handle->preview_image = gdk_pixbuf_new_from_file(preview, NULL);
335
336 if ((handle->preview_animation) || (handle->preview_animation))
337 {
338 gtk_widget_set_size_request(
339 GTK_WIDGET(handle->preview_drawing_area),
340 250,
341 -1
342 );
343
344 gtk_stack_set_visible_child(
345 handle->content_stack,
346 GTK_WIDGET(handle->preview_drawing_area)
347 );
348
349 gtk_widget_queue_draw(GTK_WIDGET(handle->preview_drawing_area));
350 return;
351 }
352
353 GNUNET_CHAT_file_close_preview(file);
354
355file_progress:
356 gtk_progress_bar_set_fraction(handle->file_progress_bar, 1.0);
357
358file_content:
359 gtk_label_set_text(handle->filename_label, GNUNET_CHAT_file_get_name(file));
360
153 gtk_stack_set_visible_child( 361 gtk_stack_set_visible_child(
154 handle->content_stack, 362 handle->content_stack,
155 GTK_WIDGET(handle->file_revealer) 363 GTK_WIDGET(handle->file_revealer)
@@ -161,6 +369,13 @@ ui_message_update(UI_MESSAGE_Handle *handle,
161void 369void
162ui_message_delete(UI_MESSAGE_Handle *handle) 370ui_message_delete(UI_MESSAGE_Handle *handle)
163{ 371{
372 _clear_message_preview_data(handle);
373
374 g_signal_handler_disconnect(
375 handle->preview_drawing_area,
376 handle->preview_draw_signal
377 );
378
164 g_object_unref(handle->builder); 379 g_object_unref(handle->builder);
165 380
166 g_free(handle); 381 g_free(handle);