aboutsummaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2022-01-10 21:56:48 +0100
committerTheJackiMonster <thejackimonster@gmail.com>2022-01-10 21:56:48 +0100
commit1049e99951c69db162f66eb6288450c2eacbbe15 (patch)
tree0e148d2f179a0889cc83385ee60a4eaac595cccd /src/ui
parent69e3d367f8e0d1168d5c6d6daebed1d2722b265c (diff)
downloadmessenger-gtk-1049e99951c69db162f66eb6288450c2eacbbe15.tar.gz
messenger-gtk-1049e99951c69db162f66eb6288450c2eacbbe15.zip
Added visual previews of files
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/message.c217
-rw-r--r--src/ui/message.h16
-rw-r--r--src/ui/send_file.c12
3 files changed, 239 insertions, 6 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);
diff --git a/src/ui/message.h b/src/ui/message.h
index f5883de..0463732 100644
--- a/src/ui/message.h
+++ b/src/ui/message.h
@@ -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
@@ -63,8 +63,22 @@ typedef struct UI_MESSAGE_Handle
63 GtkStack *content_stack; 63 GtkStack *content_stack;
64 64
65 GtkLabel *text_label; 65 GtkLabel *text_label;
66
66 GtkRevealer *file_revealer; 67 GtkRevealer *file_revealer;
68 GtkLabel *filename_label;
69 GtkProgressBar *file_progress_bar;
70 GtkButton *file_button;
71 GtkImage *file_status_image;
72
67 GtkDrawingArea *preview_drawing_area; 73 GtkDrawingArea *preview_drawing_area;
74
75 gulong preview_draw_signal;
76
77 GdkPixbuf *preview_image;
78 GdkPixbufAnimation *preview_animation;
79 GdkPixbufAnimationIter *preview_animation_iter;
80
81 guint redraw_animation;
68} UI_MESSAGE_Handle; 82} UI_MESSAGE_Handle;
69 83
70UI_MESSAGE_Handle* 84UI_MESSAGE_Handle*
diff --git a/src/ui/send_file.c b/src/ui/send_file.c
index d998e24..42c5584 100644
--- a/src/ui/send_file.c
+++ b/src/ui/send_file.c
@@ -85,17 +85,16 @@ handle_send_button_click(GtkButton *button,
85 UI_CHAT_ENTRY_Handle *entry = GNUNET_CHAT_context_get_user_pointer(context); 85 UI_CHAT_ENTRY_Handle *entry = GNUNET_CHAT_context_get_user_pointer(context);
86 UI_CHAT_Handle *handle = entry? entry->chat : NULL; 86 UI_CHAT_Handle *handle = entry? entry->chat : NULL;
87 87
88 UI_FILE_LOAD_ENTRY_Handle *file_load = NULL;
88 struct GNUNET_CHAT_File *file = NULL; 89 struct GNUNET_CHAT_File *file = NULL;
89 90
90 if ((context) && (handle)) 91 if ((context) && (handle))
91 { 92 {
92 UI_FILE_LOAD_ENTRY_Handle *file_load = ui_file_load_entry_new(app); 93 file_load = ui_file_load_entry_new(app);
93 94
94 gtk_label_set_text(file_load->file_label, filename); 95 gtk_label_set_text(file_load->file_label, filename);
95 gtk_progress_bar_set_fraction(file_load->load_progress_bar, 0.0); 96 gtk_progress_bar_set_fraction(file_load->load_progress_bar, 0.0);
96 97
97 ui_chat_add_file_load(handle, file_load);
98
99 file = GNUNET_CHAT_context_send_file( 98 file = GNUNET_CHAT_context_send_file(
100 context, 99 context,
101 filename, 100 filename,
@@ -109,11 +108,16 @@ handle_send_button_click(GtkButton *button,
109 gtk_window_close(GTK_WINDOW(app->ui.send_file.dialog)); 108 gtk_window_close(GTK_WINDOW(app->ui.send_file.dialog));
110 109
111 if (!file) 110 if (!file)
111 {
112 if (file_load)
113 ui_file_load_entry_delete(file_load);
114
112 return; 115 return;
116 }
113 117
114 file_create_info(file); 118 file_create_info(file);
115 119
116 // TODO: create UI component? 120 ui_chat_add_file_load(handle, file_load);
117} 121}
118 122
119static void 123static void