messenger-gtk

Gtk+3 graphical user interfaces for GNUnet Messenger
Log | Files | Refs | Submodules | README | LICENSE

commit 9b67d565baf5ce0f555cb38abdda22696cbfe778
parent 5df934d452aaedf319028740987de0e0dcac52d5
Author: TheJackiMonster <thejackimonster@gmail.com>
Date:   Thu, 25 Nov 2021 22:45:04 +0100

Added emoji picker

Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>

Diffstat:
A.gitmodules | 3+++
MMakefile | 5++++-
Mresources/css/style.css | 8++++++++
Mresources/ui/chat.ui | 19++++++++++++++++++-
Aresources/ui/picker.ui | 508+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/application.c | 2--
Msrc/ui/chat.c | 35+++++++++++++++++++++++++++++++++--
Msrc/ui/chat.h | 5+++++
Msrc/ui/messenger.c | 2++
Asrc/ui/picker.c | 251+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ui/picker.h | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asubmodules/gnome-characters | 1+
12 files changed, 898 insertions(+), 6 deletions(-)

diff --git a/.gitmodules b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "submodules/gnome-characters"] + path = submodules/gnome-characters + url = https://gitlab.gnome.org/GNOME/gnome-characters.git diff --git a/Makefile b/Makefile @@ -15,6 +15,7 @@ SOURCES = messenger_gtk.c\ ui/messenger.c\ ui/new_contact.c\ ui/new_platform.c\ + ui/picker.c\ ui/profile_entry.c\ ui/settings.c @@ -22,6 +23,7 @@ HEADERS = LIBRARIES = gnunetchat PACKAGES = gnunetutil libhandy-1 gtk+-3.0 libnotify zbar libqrencode +INCLUDES = submodules/gnome-characters/lib GNU_CC ?= gcc GNU_LD ?= gcc @@ -38,6 +40,7 @@ OBJECT_FILES = $(SOURCE_FILES:%.c=%.o) HEADER_FILES = $(addprefix $(SOURCE_DIR), $(HEADERS)) LIBRARY_FLAGS = $(addprefix -l, $(LIBRARIES)) PACKAGE_FLAGS = $(shell pkg-config --cflags --libs $(PACKAGES)) +INCLUDE_FLAGS = $(addprefix -I, $(INCLUDES)) all: $(BINARY) @@ -48,7 +51,7 @@ release: CFLAGS += $(RELEASEFLAGS) release: $(BINARY) %.o: %.c - $(GNU_CC) $(CFLAGS) -c $< -o $@ $(LIBRARY_FLAGS) $(PACKAGE_FLAGS) + $(GNU_CC) $(CFLAGS) -c $< -o $@ $(LIBRARY_FLAGS) $(PACKAGE_FLAGS) $(INCLUDE_FLAGS) $(BINARY): $(OBJECT_FILES) $(GNU_LD) $(LDFLAGS) $^ -o $@ $(LIBRARY_FLAGS) $(PACKAGE_FLAGS) diff --git a/resources/css/style.css b/resources/css/style.css @@ -61,6 +61,14 @@ padding: 2px 4px; } +.picker-switcher-box { + padding: 0px 8px; +} + +.emoji-flow-box { + font-size: large; +} + .settings-entry { margin: 8px; } diff --git a/resources/ui/chat.ui b/resources/ui/chat.ui @@ -169,6 +169,22 @@ Author: Tobias Frisch </packing> </child> <child> + <object class="GtkRevealer" id="picker_revealer"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="transition-type">slide-up</property> + <child> + <placeholder/> + </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> + <child> <object class="GtkBox"> <property name="visible">True</property> <property name="can-focus">False</property> @@ -263,7 +279,8 @@ Author: Tobias Frisch <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">2</property> + <property name="pack-type">end</property> + <property name="position">3</property> </packing> </child> </object> diff --git a/resources/ui/picker.ui b/resources/ui/picker.ui @@ -0,0 +1,508 @@ +<?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"/> + <requires lib="libhandy" version="1.2"/> + <object class="GtkBox" id="picker_box"> + <property name="height-request">250</property> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkStack" id="picker_stack"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="vscrollbar-policy">never</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="HdyViewSwitcherBar" id="emoji_switcher_bar"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="stack">emoji_stack</property> + <property name="reveal">True</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkStack" id="emoji_stack"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkFlowBox" id="recent_flow_box"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="border-width">8</property> + <property name="homogeneous">True</property> + <property name="max-children-per-line">8</property> + <property name="selection-mode">none</property> + <style> + <class name="emoji-flow-box"/> + </style> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="name">recent</property> + <property name="icon-name">emoji-recent-symbolic</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkFlowBox" id="people_flow_box"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="border-width">8</property> + <property name="homogeneous">True</property> + <property name="max-children-per-line">8</property> + <property name="selection-mode">none</property> + <style> + <class name="emoji-flow-box"/> + </style> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="name">people</property> + <property name="icon-name">emoji-people-symbolic</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkFlowBox" id="nature_flow_box"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="border-width">8</property> + <property name="homogeneous">True</property> + <property name="max-children-per-line">8</property> + <property name="selection-mode">none</property> + <style> + <class name="emoji-flow-box"/> + </style> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="name">nature</property> + <property name="icon-name">emoji-nature-symbolic</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkFlowBox" id="food_flow_box"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="border-width">8</property> + <property name="homogeneous">True</property> + <property name="max-children-per-line">8</property> + <property name="selection-mode">none</property> + <style> + <class name="emoji-flow-box"/> + </style> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="name">food</property> + <property name="icon-name">emoji-food-symbolic</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkFlowBox" id="activities_flow_box"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="border-width">8</property> + <property name="homogeneous">True</property> + <property name="max-children-per-line">8</property> + <property name="selection-mode">none</property> + <style> + <class name="emoji-flow-box"/> + </style> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="name">activities</property> + <property name="icon-name">emoji-activities-symbolic</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkFlowBox" id="travel_flow_box"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="border-width">8</property> + <property name="homogeneous">True</property> + <property name="max-children-per-line">8</property> + <property name="selection-mode">none</property> + <style> + <class name="emoji-flow-box"/> + </style> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="name">travel</property> + <property name="icon-name">emoji-travel-symbolic</property> + <property name="position">5</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkFlowBox" id="objects_flow_box"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="border-width">8</property> + <property name="homogeneous">True</property> + <property name="max-children-per-line">8</property> + <property name="selection-mode">none</property> + <style> + <class name="emoji-flow-box"/> + </style> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="name">objects</property> + <property name="icon-name">emoji-objects-symbolic</property> + <property name="position">6</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkFlowBox" id="symbols_flow_box"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="border-width">8</property> + <property name="homogeneous">True</property> + <property name="max-children-per-line">8</property> + <property name="selection-mode">none</property> + <style> + <class name="emoji-flow-box"/> + </style> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="name">symbols</property> + <property name="icon-name">emoji-symbols-symbolic</property> + <property name="position">7</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkFlowBox" id="flags_flow_box"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="border-width">8</property> + <property name="homogeneous">True</property> + <property name="max-children-per-line">8</property> + <property name="selection-mode">none</property> + <style> + <class name="emoji-flow-box"/> + </style> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="name">flags</property> + <property name="icon-name">emoji-flags-symbolic</property> + <property name="position">8</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="pack-type">end</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="HdySearchBar" id="emoji_search_bar"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="show-close-button">True</property> + <child> + <object class="GtkSearchEntry" id="emoji_search_entry"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="primary-icon-name">edit-find-symbolic</property> + <property name="primary-icon-activatable">False</property> + <property name="primary-icon-sensitive">False</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="name">emoji</property> + <property name="title" translatable="yes">Emoji</property> + <property name="icon-name">face-smile-symbolic</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="name">gif</property> + <property name="title" translatable="yes">GIF</property> + <property name="icon-name">video-x-generic-symbolic</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="name">stickers</property> + <property name="title" translatable="yes">Stickers</property> + <property name="icon-name">image-x-generic-symbolic</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> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkButton" id="search_button"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</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">system-search-symbolic</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="HdyViewSwitcherBar" id="picker_switcher_bar"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="policy">auto</property> + <property name="stack">picker_stack</property> + <property name="reveal">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="settings_button"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</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">preferences-other-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">2</property> + </packing> + </child> + <style> + <class name="picker-switcher-box"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + </object> +</interface> diff --git a/src/application.c b/src/application.c @@ -157,8 +157,6 @@ application_run(MESSENGER_Application *app) pthread_join(app->chat.tid, NULL); - ui_messenger_cleanup(&(app->ui.messenger)); - g_hash_table_destroy(app->ui.bindings); notify_uninit(); diff --git a/src/ui/chat.c b/src/ui/chat.c @@ -25,6 +25,7 @@ #include "chat.h" #include "messenger.h" +#include "picker.h" #include "../application.h" static void @@ -67,7 +68,7 @@ handle_send_text_buffer_changed(GtkTextBuffer *buffer, gtk_image_set_from_icon_name( symbol, - 0 < g_utf8_strlen(text, 1)? + 0 < strlen(text)? "mail-send-symbolic" : "audio-input-microphone-symbolic", GTK_ICON_SIZE_BUTTON @@ -86,7 +87,7 @@ _send_text_from_view(MESSENGER_Application *app, const gchar *text = gtk_text_buffer_get_text(buffer, &start, &end, TRUE); - if (0 == g_utf8_strlen(text, 1)) + if (0 == strlen(text)) return FALSE; struct GNUNET_CHAT_Context *context = g_hash_table_lookup( @@ -132,6 +133,16 @@ handle_send_text_key_press (GtkWidget *widget, return _send_text_from_view(app, GTK_TEXT_VIEW(widget)); } +static void +handle_picker_button_click(UNUSED GtkButton *button, + gpointer user_data) +{ + GtkRevealer *revealer = GTK_REVEALER(user_data); + gboolean reveal = !gtk_revealer_get_child_revealed(revealer); + + gtk_revealer_set_reveal_child(revealer, reveal); +} + UI_CHAT_Handle* ui_chat_new(MESSENGER_Application *app) { @@ -239,12 +250,32 @@ ui_chat_new(MESSENGER_Application *app) handle->send_text_view ); + handle->picker_revealer = GTK_REVEALER( + gtk_builder_get_object(handle->builder, "picker_revealer") + ); + + handle->picker = ui_picker_new(app, handle); + + gtk_container_add( + GTK_CONTAINER(handle->picker_revealer), + handle->picker->picker_box + ); + + g_signal_connect( + handle->emoji_button, + "clicked", + G_CALLBACK(handle_picker_button_click), + handle->picker_revealer + ); + return handle; } void ui_chat_delete(UI_CHAT_Handle *handle) { + ui_picker_delete(handle->picker); + g_object_unref(handle->builder); g_free(handle); diff --git a/src/ui/chat.h b/src/ui/chat.h @@ -30,6 +30,7 @@ #include <libnotify/notify.h> typedef struct MESSENGER_Application MESSENGER_Application; +typedef struct UI_PICKER_Handle UI_PICKER_Handle; typedef struct UI_CHAT_Handle { @@ -49,6 +50,10 @@ typedef struct UI_CHAT_Handle GtkButton *emoji_button; GtkButton *send_record_button; GtkImage *send_record_symbol; + + GtkRevealer *picker_revealer; + + UI_PICKER_Handle *picker; } UI_CHAT_Handle; UI_CHAT_Handle* diff --git a/src/ui/messenger.c b/src/ui/messenger.c @@ -150,6 +150,8 @@ handle_main_window_destroy(UNUSED GtkWidget *window, { MESSENGER_Application *app = (MESSENGER_Application*) user_data; + ui_messenger_cleanup(&(app->ui.messenger)); + application_exit(app, MESSENGER_QUIT); } diff --git a/src/ui/picker.c b/src/ui/picker.c @@ -0,0 +1,251 @@ +/* + This file is part of GNUnet. + 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 + * @file ui/picker.c + */ + +#include "picker.h" + +#include "../application.h" + +#include <emoji.h> + +static void +handle_emoji_button_click(GtkButton *button, + gpointer user_data) +{ + GtkTextView *text_view = GTK_TEXT_VIEW(user_data); + GtkTextBuffer *text_buffer = gtk_text_view_get_buffer(text_view); + + const gchar *label = gtk_button_get_label(button); + + if (label) + gtk_text_buffer_insert_at_cursor(text_buffer, label, strlen(label)); +} + +static void +_add_emoji_buttons(GtkFlowBox *flow_box, + GtkTextView *text_view, + size_t characters_count, + const uint32_t *characters) +{ + for (size_t i = 0; i < characters_count; i++) { + GString *string = g_string_new(""); + g_string_append_unichar(string, (gunichar) characters[i]); + + GtkButton *emoji_button = GTK_BUTTON( + gtk_button_new_with_label(string->str) + ); + + gtk_button_set_relief(emoji_button, GTK_RELIEF_NONE); + + g_signal_connect( + emoji_button, + "clicked", + G_CALLBACK(handle_emoji_button_click), + text_view + ); + + gtk_flow_box_insert(flow_box, GTK_WIDGET(emoji_button), -1); + gtk_widget_show(GTK_WIDGET(emoji_button)); + + g_string_free(string, TRUE); + } +} + +static void +handle_search_button_click(UNUSED GtkButton *button, + gpointer user_data) +{ + UI_PICKER_Handle *handle = (UI_PICKER_Handle*) user_data; + + const gchar* picked = gtk_stack_get_visible_child_name(handle->picker_stack); + + HdySearchBar *search_bar = NULL; + + if (0 == g_strcmp0(picked, "emoji")) + search_bar = handle->emoji_search_bar; + + if (search_bar) + hdy_search_bar_set_search_mode( + search_bar, + !hdy_search_bar_get_search_mode(search_bar) + ); +} + +UI_PICKER_Handle* +ui_picker_new(UNUSED MESSENGER_Application *app, + UI_CHAT_Handle *chat) +{ + UI_PICKER_Handle *handle = g_malloc(sizeof(UI_PICKER_Handle)); + + handle->builder = gtk_builder_new_from_file( + "resources/ui/picker.ui" + ); + + handle->picker_box = GTK_WIDGET( + gtk_builder_get_object(handle->builder, "picker_box") + ); + + handle->picker_stack = GTK_STACK( + gtk_builder_get_object(handle->builder, "picker_stack") + ); + + handle->emoji_stack = GTK_STACK( + gtk_builder_get_object(handle->builder, "emoji_stack") + ); + + handle->picker_switcher_bar = HDY_VIEW_SWITCHER_BAR( + gtk_builder_get_object(handle->builder, "picker_switcher_bar") + ); + + handle->emoji_switcher_bar = HDY_VIEW_SWITCHER_BAR( + gtk_builder_get_object(handle->builder, "emoji_switcher_bar") + ); + + handle->recent_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "recent_flow_box") + ); + + handle->people_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "people_flow_box") + ); + + _add_emoji_buttons( + handle->people_flow_box, + chat->send_text_view, + EMOJI_SMILEYS_CHARACTER_COUNT, + emoji_smileys_characters + ); + + handle->nature_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "nature_flow_box") + ); + + _add_emoji_buttons( + handle->nature_flow_box, + chat->send_text_view, + EMOJI_ANIMALS_CHARACTER_COUNT, + emoji_animals_characters + ); + + handle->food_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "food_flow_box") + ); + + _add_emoji_buttons( + handle->food_flow_box, + chat->send_text_view, + EMOJI_FOOD_CHARACTER_COUNT, + emoji_food_characters + ); + + handle->activities_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "activities_flow_box") + ); + + _add_emoji_buttons( + handle->activities_flow_box, + chat->send_text_view, + EMOJI_ACTIVITIES_CHARACTER_COUNT, + emoji_activities_characters + ); + + handle->travel_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "travel_flow_box") + ); + + _add_emoji_buttons( + handle->travel_flow_box, + chat->send_text_view, + EMOJI_TRAVEL_CHARACTER_COUNT, + emoji_travel_characters + ); + + handle->objects_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "objects_flow_box") + ); + + _add_emoji_buttons( + handle->objects_flow_box, + chat->send_text_view, + EMOJI_OBJECTS_CHARACTER_COUNT, + emoji_objects_characters + ); + + handle->symbols_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "symbols_flow_box") + ); + + _add_emoji_buttons( + handle->symbols_flow_box, + chat->send_text_view, + EMOJI_SYMBOLS_CHARACTER_COUNT, + emoji_symbols_characters + ); + + handle->flags_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "flags_flow_box") + ); + + _add_emoji_buttons( + handle->flags_flow_box, + chat->send_text_view, + EMOJI_FLAGS_CHARACTER_COUNT, + emoji_flags_characters + ); + + handle->emoji_search_bar = HDY_SEARCH_BAR( + gtk_builder_get_object(handle->builder, "emoji_search_bar") + ); + + handle->emoji_search_entry = GTK_SEARCH_ENTRY( + gtk_builder_get_object(handle->builder, "emoji_search_entry") + ); + + handle->search_button = GTK_BUTTON( + gtk_builder_get_object(handle->builder, "search_button") + ); + + g_signal_connect( + handle->search_button, + "clicked", + G_CALLBACK(handle_search_button_click), + handle + ); + + handle->settings_button = GTK_BUTTON( + gtk_builder_get_object(handle->builder, "settings_button") + ); + + return handle; +} + +void +ui_picker_delete(UI_PICKER_Handle *handle) +{ + hdy_view_switcher_bar_set_stack(handle->picker_switcher_bar, NULL); + hdy_view_switcher_bar_set_stack(handle->emoji_switcher_bar, NULL); + + g_object_unref(handle->builder); + + g_free(handle); +} diff --git a/src/ui/picker.h b/src/ui/picker.h @@ -0,0 +1,65 @@ +/* + This file is part of GNUnet. + 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 + * @file ui/picker.h + */ + +#ifndef UI_PICKER_H_ +#define UI_PICKER_H_ + +#include "chat.h" + +typedef struct UI_PICKER_Handle +{ + GtkBuilder *builder; + GtkWidget *picker_box; + + GtkStack *picker_stack; + GtkStack *emoji_stack; + + HdyViewSwitcherBar *picker_switcher_bar; + HdyViewSwitcherBar *emoji_switcher_bar; + + GtkFlowBox *recent_flow_box; + GtkFlowBox *people_flow_box; + GtkFlowBox *nature_flow_box; + GtkFlowBox *food_flow_box; + GtkFlowBox *activities_flow_box; + GtkFlowBox *travel_flow_box; + GtkFlowBox *objects_flow_box; + GtkFlowBox *symbols_flow_box; + GtkFlowBox *flags_flow_box; + + HdySearchBar *emoji_search_bar; + GtkSearchEntry *emoji_search_entry; + + GtkButton *search_button; + GtkButton *settings_button; +} UI_PICKER_Handle; + +UI_PICKER_Handle* +ui_picker_new(MESSENGER_Application *app, + UI_CHAT_Handle *chat); + +void +ui_picker_delete(UI_PICKER_Handle *handle); + +#endif /* UI_PICKER_H_ */ diff --git a/submodules/gnome-characters b/submodules/gnome-characters @@ -0,0 +1 @@ +Subproject commit f732b513cd5b8882d4176ed6ada1a78aba61a636