commit bd545ea846e668112e5a54b702acc9c9f9231aea
parent d8a0d99da00d29ae50a0a8831d1d396769ed94f6
Author: TheJackiMonster <thejackimonster@gmail.com>
Date: Tue, 21 Dec 2021 18:59:39 +0100
Implemented preview for sending files and added ui for message content
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
Diffstat:
14 files changed, 512 insertions(+), 205 deletions(-)
diff --git a/resources/css/style.css b/resources/css/style.css
@@ -61,6 +61,10 @@
padding: 2px 4px;
}
+.timestamp-label {
+ font-size: x-small;
+}
+
.picker-switcher-box {
padding: 0px 8px;
}
diff --git a/resources/ui/message-sent.ui b/resources/ui/message-sent.ui
@@ -50,68 +50,13 @@ Author: Tobias Frisch
<property name="label-xalign">0</property>
<property name="shadow-type">none</property>
<child>
- <object class="GtkBox">
+ <object class="GtkBox" id="content_box">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
- <property name="spacing">4</property>
<child>
- <object class="GtkLabel" id="text_label">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="wrap">True</property>
- <property name="max-width-chars">64</property>
- <property name="xalign">0</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
+ <placeholder/>
</child>
- <child>
- <object class="GtkBox">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="spacing">4</property>
- <child>
- <object class="GtkImage" id="read_receipt_image">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="icon-name">emblem-default-symbolic</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack-type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="timestamp_label">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <attributes>
- <attribute name="weight" value="light"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack-type">end</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <style>
- <class name="message-content"/>
- </style>
</object>
</child>
<child type="label">
diff --git a/resources/ui/message-status.ui b/resources/ui/message-status.ui
@@ -39,15 +39,23 @@ Author: Tobias Frisch
<property name="can-focus">False</property>
<property name="spacing">8</property>
<child>
- <object class="GtkButton" id="deny_button">
- <property name="can-focus">True</property>
- <property name="receives-default">True</property>
- <property name="relief">none</property>
+ <object class="GtkRevealer" id="deny_revealer">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="transition-type">slide-left</property>
+ <property name="reveal-child">True</property>
<child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="icon-name">edit-delete-symbolic</property>
+ <object class="GtkButton" id="deny_button">
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="relief">none</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">edit-delete-symbolic</property>
+ </object>
+ </child>
</object>
</child>
</object>
@@ -58,65 +66,12 @@ Author: Tobias Frisch
</packing>
</child>
<child>
- <object class="GtkBox">
+ <object class="GtkBox" id="content_box">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
- <object class="GtkLabel" id="text_label">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="justify">center</property>
- <property name="wrap">True</property>
- <property name="xalign">0.5</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="spacing">4</property>
- <child>
- <object class="GtkImage" id="read_receipt_image">
- <property name="can-focus">False</property>
- <property name="xalign">1</property>
- <property name="icon-name">emblem-default-symbolic</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack-type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="timestamp_label">
- <property name="can-focus">False</property>
- <property name="justify">right</property>
- <property name="xalign">1</property>
- <attributes>
- <attribute name="weight" value="light"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack-type">end</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack-type">end</property>
- <property name="position">1</property>
- </packing>
+ <placeholder/>
</child>
</object>
<packing>
@@ -126,22 +81,29 @@ Author: Tobias Frisch
</packing>
</child>
<child>
- <object class="GtkButton" id="accept_button">
- <property name="can-focus">True</property>
- <property name="receives-default">True</property>
- <property name="relief">none</property>
+ <object class="GtkRevealer" id="accept_revealer">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="transition-type">slide-right</property>
+ <property name="reveal-child">True</property>
<child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="icon-name">emblem-ok-symbolic</property>
+ <object class="GtkButton" id="accept_button">
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="relief">none</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">emblem-ok-symbolic</property>
+ </object>
+ </child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="pack-type">end</property>
<property name="position">2</property>
</packing>
</child>
diff --git a/resources/ui/message.ui b/resources/ui/message.ui
@@ -49,67 +49,13 @@ Author: Tobias Frisch
<property name="label-xalign">0</property>
<property name="shadow-type">none</property>
<child>
- <object class="GtkBox">
+ <object class="GtkBox" id="content_box">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
- <property name="spacing">4</property>
<child>
- <object class="GtkLabel" id="text_label">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="wrap">True</property>
- <property name="max-width-chars">64</property>
- <property name="xalign">0</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
+ <placeholder/>
</child>
- <child>
- <object class="GtkBox">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="spacing">4</property>
- <child>
- <object class="GtkImage" id="read_receipt_image">
- <property name="can-focus">False</property>
- <property name="icon-name">emblem-default-symbolic</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack-type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="timestamp_label">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <attributes>
- <attribute name="weight" value="light"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack-type">end</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <style>
- <class name="message-content"/>
- </style>
</object>
</child>
<child type="label">
diff --git a/resources/ui/message_content.ui b/resources/ui/message_content.ui
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2
+
+Copyright (C) 2021 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
+by the Free Software Foundation, either version 3 of the License,
+or (at your option) any later version.
+
+GNUnet is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+SPDX-License-Identifier: AGPL3.0-or-later
+Author: Tobias Frisch
+
+-->
+<interface>
+ <requires lib="gtk+" version="3.24"/>
+ <object class="GtkBox" id="message_content_box">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkImage" id="read_receipt_image">
+ <property name="can-focus">False</property>
+ <property name="icon-name">emblem-default-symbolic</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="timestamp_label">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <attributes>
+ <attribute name="weight" value="ultralight"/>
+ </attributes>
+ <style>
+ <class name="timestamp-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkStack">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkLabel" id="text_label">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="wrap">True</property>
+ <property name="max-width-chars">64</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="name">text_page</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRevealer" id="file_revealer">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="transition-type">none</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="valign">center</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkLabel" id="filename_label">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkProgressBar">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="file_button">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="relief">none</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">folder-download-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">file_page</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkDrawingArea" id="preview_drawing_area">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ </object>
+ <packing>
+ <property name="name">preview_page</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <style>
+ <class name="message-content"/>
+ </style>
+ </object>
+</interface>
diff --git a/resources/ui/send_file.ui b/resources/ui/send_file.ui
@@ -78,6 +78,7 @@ Author: Tobias Frisch
<property name="spacing">4</property>
<child>
<object class="GtkDrawingArea" id="file_drawing_area">
+ <property name="width-request">250</property>
<property name="height-request">250</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
diff --git a/src/event.c b/src/event.c
@@ -190,7 +190,10 @@ event_joining_contact(MESSENGER_Application *app,
ui_chat_entry_update(handle, app, context);
- UI_MESSAGE_Handle *message = ui_message_new(UI_MESSAGE_STATUS);
+ UI_MESSAGE_Handle *message = ui_message_new(
+ UI_MESSAGE_STATUS,
+ UI_MESSAGE_CONTENT_TEXT
+ );
struct GNUNET_CHAT_Contact *contact = GNUNET_CHAT_message_get_sender(
msg
@@ -209,7 +212,7 @@ event_joining_contact(MESSENGER_Application *app,
message->message_box
);
- ui_message_delete(message);
+ handle->chat->messages = g_list_append(handle->chat->messages, message);
}
void
@@ -259,7 +262,10 @@ event_invitation(UNUSED MESSENGER_Application *app,
if (!invitation)
return;
- UI_MESSAGE_Handle *message = ui_message_new(UI_MESSAGE_STATUS);
+ UI_MESSAGE_Handle *message = ui_message_new(
+ UI_MESSAGE_STATUS,
+ UI_MESSAGE_CONTENT_TEXT
+ );
const struct GNUNET_CHAT_Contact *contact = GNUNET_CHAT_message_get_sender(
msg
@@ -285,7 +291,7 @@ event_invitation(UNUSED MESSENGER_Application *app,
message->message_box
);
- ui_message_delete(message);
+ handle->chat->messages = g_list_append(handle->chat->messages, message);
}
void
@@ -301,7 +307,8 @@ event_receive_message(UNUSED MESSENGER_Application *app,
const int sent = GNUNET_CHAT_message_is_sent(msg);
UI_MESSAGE_Handle *message = ui_message_new(
- GNUNET_YES == sent? UI_MESSAGE_SENT : UI_MESSAGE_DEFAULT
+ GNUNET_YES == sent? UI_MESSAGE_SENT : UI_MESSAGE_DEFAULT,
+ UI_MESSAGE_CONTENT_TEXT
);
const struct GNUNET_CHAT_Contact *contact = GNUNET_CHAT_message_get_sender(
@@ -329,7 +336,7 @@ event_receive_message(UNUSED MESSENGER_Application *app,
message->message_box
);
- ui_message_delete(message);
+ handle->chat->messages = g_list_append(handle->chat->messages, message);
gtk_label_set_text(handle->text_label, text? text : "");
gtk_label_set_text(handle->timestamp_label, time? time : "");
diff --git a/src/ui/chat.c b/src/ui/chat.c
@@ -26,6 +26,7 @@
#include <gdk/gdkkeysyms.h>
+#include "message.h"
#include "messenger.h"
#include "picker.h"
#include "profile_entry.h"
@@ -252,6 +253,8 @@ ui_chat_new(MESSENGER_Application *app)
UI_CHAT_Handle *handle = g_malloc(sizeof(UI_CHAT_Handle));
UI_MESSENGER_Handle *messenger = &(app->ui.messenger);
+ handle->messages = NULL;
+
handle->builder = gtk_builder_new_from_file(
"resources/ui/chat.ui"
);
@@ -552,5 +555,17 @@ ui_chat_delete(UI_CHAT_Handle *handle)
g_object_unref(handle->builder);
+ GList *list = handle->messages;
+
+ while (list) {
+ if (list->data)
+ ui_message_delete((UI_MESSAGE_Handle*) list->data);
+
+ list = list->next;
+ }
+
+ if (handle->messages)
+ g_list_free(handle->messages);
+
g_free(handle);
}
diff --git a/src/ui/chat.h b/src/ui/chat.h
@@ -36,6 +36,8 @@ typedef struct UI_PICKER_Handle UI_PICKER_Handle;
typedef struct UI_CHAT_Handle
{
+ GList *messages;
+
GtkBuilder *builder;
GtkWidget *chat_box;
diff --git a/src/ui/message.c b/src/ui/message.c
@@ -27,7 +27,8 @@
#include "../application.h"
UI_MESSAGE_Handle*
-ui_message_new(UI_MESSAGE_Type type)
+ui_message_new(UI_MESSAGE_Type type,
+ UI_MESSAGE_ContentType content_type)
{
UI_MESSAGE_Handle* handle = g_malloc(sizeof(UI_MESSAGE_Handle));
@@ -62,12 +63,16 @@ ui_message_new(UI_MESSAGE_Type type)
gtk_builder_get_object(handle->builder, "sender_label")
);
- handle->text_label = GTK_LABEL(
- gtk_builder_get_object(handle->builder, "text_label")
- );
-
if (UI_MESSAGE_STATUS == handle->type)
{
+ handle->deny_revealer = GTK_REVEALER(
+ gtk_builder_get_object(handle->builder, "deny_revealer")
+ );
+
+ handle->accept_revealer = GTK_REVEALER(
+ gtk_builder_get_object(handle->builder, "accept_revealer")
+ );
+
handle->deny_button = GTK_BUTTON(
gtk_builder_get_object(handle->builder, "deny_button")
);
@@ -78,18 +83,64 @@ ui_message_new(UI_MESSAGE_Type type)
}
else
{
+ handle->deny_revealer = NULL;
+ handle->accept_revealer = NULL;
+
handle->deny_button = NULL;
handle->accept_button = NULL;
}
+ GtkContainer *content_box = GTK_CONTAINER(
+ gtk_builder_get_object(handle->builder, "content_box")
+ );
+
+ GtkBuilder *builder = gtk_builder_new_from_file(
+ "resources/ui/message_content.ui"
+ );
+
handle->timestamp_label = GTK_LABEL(
- gtk_builder_get_object(handle->builder, "timestamp_label")
+ gtk_builder_get_object(builder, "timestamp_label")
);
handle->read_receipt_image = GTK_IMAGE(
- gtk_builder_get_object(handle->builder, "read_receipt_image")
+ gtk_builder_get_object(builder, "read_receipt_image")
+ );
+
+ handle->text_label = GTK_LABEL(
+ gtk_builder_get_object(builder, "text_label")
+ );
+
+ handle->file_revealer = GTK_REVEALER(
+ gtk_builder_get_object(builder, "file_revealer")
);
+ handle->preview_drawing_area = GTK_DRAWING_AREA(
+ gtk_builder_get_object(builder, "preview_drawing_area")
+ );
+
+ switch (handle->type)
+ {
+ case UI_MESSAGE_STATUS:
+ gtk_widget_set_visible(GTK_WIDGET(handle->timestamp_label), FALSE);
+ break;
+ default:
+ break;
+ }
+
+ switch (content_type)
+ {
+ case UI_MESSAGE_CONTENT_FILE:
+ gtk_revealer_set_reveal_child(handle->file_revealer, TRUE);
+ break;
+ default:
+ break;
+ }
+
+ gtk_container_add(content_box, GTK_WIDGET(
+ gtk_builder_get_object(builder, "message_content_box")
+ ));
+
+ g_object_unref(builder);
return handle;
}
diff --git a/src/ui/message.h b/src/ui/message.h
@@ -39,6 +39,13 @@ typedef enum UI_MESSAGE_Type
UI_MESSAGE_STATUS = 2
} UI_MESSAGE_Type;
+typedef enum UI_MESSAGE_ContentType
+{
+ UI_MESSAGE_CONTENT_TEXT = 0,
+ UI_MESSAGE_CONTENT_FILE = 1,
+ UI_MESSAGE_CONTENT_PREVIEW = 2
+} UI_MESSAGE_ContentType;
+
typedef struct UI_MESSAGE_Handle
{
UI_MESSAGE_Type type;
@@ -49,17 +56,23 @@ typedef struct UI_MESSAGE_Handle
HdyAvatar *sender_avatar;
GtkLabel *sender_label;
- GtkLabel *text_label;
+ GtkRevealer *deny_revealer;
+ GtkRevealer *accept_revealer;
GtkButton *deny_button;
GtkButton *accept_button;
GtkLabel *timestamp_label;
GtkImage *read_receipt_image;
+
+ GtkLabel *text_label;
+ GtkRevealer *file_revealer;
+ GtkDrawingArea *preview_drawing_area;
} UI_MESSAGE_Handle;
UI_MESSAGE_Handle*
-ui_message_new(UI_MESSAGE_Type type);
+ui_message_new(UI_MESSAGE_Type type,
+ UI_MESSAGE_ContentType content_type);
void
ui_message_delete(UI_MESSAGE_Handle *handle);
diff --git a/src/ui/new_contact.c b/src/ui/new_contact.c
@@ -69,7 +69,7 @@ handle_id_drawing_area_draw(GtkWidget* drawing_area,
GdkPixbuf *image = NULL;
if (!handle->image)
- goto render_image;
+ return FALSE;
uint w, h;
zbar_image_get_size(handle->image, &w, &h);
diff --git a/src/ui/send_file.c b/src/ui/send_file.c
@@ -71,6 +71,146 @@ handle_dialog_destroy(UNUSED GtkWidget *window,
ui_send_file_dialog_cleanup((UI_SEND_FILE_Handle*) user_data);
}
+static int
+handle_file_redraw_animation(gpointer user_data)
+{
+ UI_SEND_FILE_Handle *handle = (UI_SEND_FILE_Handle*) user_data;
+
+ handle->redraw_animation = 0;
+
+ if (handle->file_drawing_area)
+ gtk_widget_queue_draw(GTK_WIDGET(handle->file_drawing_area));
+
+ return FALSE;
+}
+
+static gboolean
+handle_file_drawing_area_draw(GtkWidget* drawing_area,
+ cairo_t* cairo,
+ gpointer user_data)
+{
+ UI_SEND_FILE_Handle *handle = (UI_SEND_FILE_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->image;
+
+ if (!handle->animation)
+ goto render_image;
+
+ if (handle->animation_iter)
+ gdk_pixbuf_animation_iter_advance(handle->animation_iter, NULL);
+ else
+ handle->animation_iter = gdk_pixbuf_animation_get_iter(
+ handle->animation, NULL
+ );
+
+ image = gdk_pixbuf_animation_iter_get_pixbuf(handle->animation_iter);
+
+ const int delay = gdk_pixbuf_animation_iter_get_delay_time(
+ handle->animation_iter
+ );
+
+ handle->redraw_animation = g_timeout_add(
+ delay, handle_file_redraw_animation, handle
+ );
+
+render_image:
+ if (!image)
+ return FALSE;
+
+ int dwidth = gdk_pixbuf_get_width(image);
+ int dheight = gdk_pixbuf_get_height(image);
+
+ 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_file_preview_data(UI_SEND_FILE_Handle *handle)
+{
+ if (handle->image)
+ {
+ g_object_unref(handle->image);
+ handle->image = NULL;
+ }
+
+ if (handle->redraw_animation)
+ {
+ g_source_remove(handle->redraw_animation);
+ handle->redraw_animation = 0;
+ }
+
+ if (handle->animation_iter)
+ {
+ g_object_unref(handle->animation_iter);
+ handle->animation_iter = NULL;
+ }
+
+ if (handle->animation)
+ {
+ g_object_unref(handle->animation);
+ handle->animation = NULL;
+ }
+}
+
+static void
+handle_file_chooser_button_file_set(GtkFileChooserButton *file_chooser_button,
+ gpointer user_data)
+{
+ UI_SEND_FILE_Handle *handle = (UI_SEND_FILE_Handle*) user_data;
+
+ _clear_file_preview_data(handle);
+
+ char *filename = gtk_file_chooser_get_filename(
+ GTK_FILE_CHOOSER(file_chooser_button)
+ );
+
+ if (filename)
+ {
+ handle->animation = gdk_pixbuf_animation_new_from_file(filename, NULL);
+
+ if (!handle->animation)
+ handle->image = gdk_pixbuf_new_from_file(filename, NULL);
+
+ g_free(filename);
+ }
+
+ gtk_widget_queue_draw(GTK_WIDGET(handle->file_drawing_area));
+}
+
void
ui_send_file_dialog_init(MESSENGER_Application *app,
UI_SEND_FILE_Handle *handle)
@@ -99,6 +239,20 @@ ui_send_file_dialog_init(MESSENGER_Application *app,
gtk_builder_get_object(handle->builder, "file_chooser_button")
);
+ g_signal_connect(
+ handle->file_drawing_area,
+ "draw",
+ G_CALLBACK(handle_file_drawing_area_draw),
+ handle
+ );
+
+ g_signal_connect(
+ handle->file_chooser_button,
+ "file-set",
+ G_CALLBACK(handle_file_chooser_button_file_set),
+ handle
+ );
+
handle->cancel_button = GTK_BUTTON(
gtk_builder_get_object(handle->builder, "cancel_button")
);
@@ -127,22 +281,36 @@ ui_send_file_dialog_init(MESSENGER_Application *app,
G_CALLBACK(handle_dialog_destroy),
handle
);
+
+ handle->image = NULL;
+ handle->animation = NULL;
+ handle->animation_iter = NULL;
+
+ handle->redraw_animation = 0;
}
void
ui_send_file_dialog_update(UI_SEND_FILE_Handle *handle,
const gchar *filename)
{
- if ((!filename) || (!gtk_file_chooser_set_filename(
- GTK_FILE_CHOOSER(handle->file_chooser_button),
- filename)))
+ if (!handle->file_chooser_button)
return;
- // TODO: update preview
+ gtk_file_chooser_set_filename(
+ GTK_FILE_CHOOSER(handle->file_chooser_button),
+ filename
+ );
+
+ handle_file_chooser_button_file_set(
+ handle->file_chooser_button,
+ handle
+ );
}
void
ui_send_file_dialog_cleanup(UI_SEND_FILE_Handle *handle)
{
+ _clear_file_preview_data(handle);
+
g_object_unref(handle->builder);
}
diff --git a/src/ui/send_file.h b/src/ui/send_file.h
@@ -39,6 +39,12 @@ typedef struct UI_SEND_FILE_Handle
GtkButton *cancel_button;
GtkButton *send_button;
+
+ GdkPixbuf *image;
+ GdkPixbufAnimation *animation;
+ GdkPixbufAnimationIter *animation_iter;
+
+ guint redraw_animation;
} UI_SEND_FILE_Handle;
void