From c7138bca7ea7d007198c544b2d8bc27ae414d2e2 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 3 Nov 2018 22:49:29 +0100 Subject: Start with gif/image widget --- .gitignore | 1 + depends/dchat_core | 2 +- include/ChatMessage.hpp | 5 ++--- include/DynamicImage.hpp | 18 ++++++++++++++++++ include/GtkGif.hpp | 10 +++++----- src/ChatMessage.cpp | 29 ++++++----------------------- src/DynamicImage.cpp | 28 ++++++++++++++++++++++++++++ src/GtkGif.cpp | 29 +++++++++++++++++++++++------ src/Window.cpp | 7 +++++-- 9 files changed, 89 insertions(+), 40 deletions(-) create mode 100644 include/DynamicImage.hpp create mode 100644 src/DynamicImage.cpp diff --git a/.gitignore b/.gitignore index 0dee329..b583353 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ compile_commands.json tests/sibs-build/ tests/compile_commands.json .vscode/ +.gdb_history diff --git a/depends/dchat_core b/depends/dchat_core index c5b9161..38d987b 160000 --- a/depends/dchat_core +++ b/depends/dchat_core @@ -1 +1 @@ -Subproject commit c5b916157ae111da514481899d53f3e2bf5be982 +Subproject commit 38d987b7583cda88c0485acf0fecc65cd15edcc1 diff --git a/include/ChatMessage.hpp b/include/ChatMessage.hpp index c1ef459..5259a9c 100644 --- a/include/ChatMessage.hpp +++ b/include/ChatMessage.hpp @@ -1,5 +1,6 @@ #pragma once +#include "DynamicImage.hpp" #include #include #include @@ -12,11 +13,9 @@ namespace dchat public: ChatMessage(const Glib::ustring &username, const Glib::ustring &text, uint32_t timestampSeconds); - Gtk::Grid avatar; + DynamicImage avatar; Gtk::Label username; Gtk::Label text; uint32_t timestampSeconds; - private: - bool updateContent(const Cairo::RefPtr &cairo); }; } \ No newline at end of file diff --git a/include/DynamicImage.hpp b/include/DynamicImage.hpp new file mode 100644 index 0000000..578b91a --- /dev/null +++ b/include/DynamicImage.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +namespace dchat +{ + class DynamicImage : public Gtk::DrawingArea + { + public: + DynamicImage(int downloadLimitBytes = 12582912); + + std::string url; + int downloadLimitBytes; + private: + bool updateContent(const Cairo::RefPtr &cairo); + }; +} \ No newline at end of file diff --git a/include/GtkGif.hpp b/include/GtkGif.hpp index 91b3a12..a4a28d7 100644 --- a/include/GtkGif.hpp +++ b/include/GtkGif.hpp @@ -1,23 +1,23 @@ #pragma once #include -#include -#include +#include +#include namespace dchat { - class GtkGif : public Gif, public Gtk::DrawingArea + class GtkGif : public Gif { public: GtkGif(StringView fileContent); virtual ~GtkGif(){} + + void draw(const Cairo::RefPtr &cairo, int width, int height); protected: // Return false if texture creation failed bool createTexture(int width, int height) override; // Size of texture data is same as the size that the texture was created with (also same size returned by @getSize function) void updateTexture(void *textureData) override; - private: - bool on_draw(const Cairo::RefPtr &cairo) override; private: Cairo::RefPtr surface; }; diff --git a/src/ChatMessage.cpp b/src/ChatMessage.cpp index d48a6a9..fe3afdc 100644 --- a/src/ChatMessage.cpp +++ b/src/ChatMessage.cpp @@ -1,6 +1,4 @@ #include "../include/ChatMessage.hpp" -#include "../include/GlobalCache.hpp" -#include "../include/GtkGif.hpp" namespace dchat { @@ -11,6 +9,8 @@ namespace dchat { avatar.set_halign(Gtk::ALIGN_START); avatar.set_valign(Gtk::ALIGN_START); + avatar.set_size_request(50, 50); + avatar.url = "https://discordemoji.com/assets/emoji/7752_PepePOOGERSFAST.gif"; username.set_selectable(true); username.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_START); @@ -20,6 +20,7 @@ namespace dchat text.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_START); text.set_line_wrap(true); text.set_line_wrap_mode(Pango::WRAP_WORD_CHAR); + text.set_vexpand(true); text.get_style_context()->add_class("chat-message-text"); attach(avatar, 0, 0, 1, 2); @@ -27,26 +28,8 @@ namespace dchat attach_next_to(text, username, Gtk::POS_BOTTOM, 1, 1); get_style_context()->add_class("chat-message"); - signal_draw().connect(sigc::mem_fun(*this, &ChatMessage::updateContent)); - } - - bool ChatMessage::updateContent(const Cairo::RefPtr &cairo) - { - #if 0 - auto result = getGlobalCache().getContentByUrl("https://discordemoji.com/assets/emoji/3644_epicKirby.gif"); - printf("result type: %d\n", result.type); - if(result.type == ContentByUrlResult::Type::CACHED && result.gif) - { - Gtk::Widget *child = avatar.get_child_at(0, 0); - if(!child) - { - printf("add gif!\n"); - //GtkGif *gif = new GtkGif(GtkGif*)result.gif; - //gif->copy - //avatar.attach(*(GtkGif*)result.gif, 0, 0, 1, 1); - } - } - #endif - return true; + set_column_spacing(10); + set_row_spacing(0); + set_vexpand(false); } } \ No newline at end of file diff --git a/src/DynamicImage.cpp b/src/DynamicImage.cpp new file mode 100644 index 0000000..8759497 --- /dev/null +++ b/src/DynamicImage.cpp @@ -0,0 +1,28 @@ +#include "../include/DynamicImage.hpp" +#include "../include/GlobalCache.hpp" +#include "../include/GtkGif.hpp" + +namespace dchat +{ + DynamicImage::DynamicImage(int _downloadLimitBytes) : + downloadLimitBytes(_downloadLimitBytes) + { + signal_draw().connect(sigc::mem_fun(*this, &DynamicImage::updateContent)); + } + + bool DynamicImage::updateContent(const Cairo::RefPtr &cairo) + { + if(!url.empty()) + { + Gtk::Allocation alloc = get_allocation(); + auto result = getGlobalCache().getContentByUrl(url, downloadLimitBytes); + if(result.type == ContentByUrlResult::Type::CACHED && result.gif) + { + GtkGif *gif = (GtkGif*)result.gif; + gif->draw(cairo, alloc.get_width(), alloc.get_height()); + } + } + queue_draw(); + return true; + } +} \ No newline at end of file diff --git a/src/GtkGif.cpp b/src/GtkGif.cpp index 1da48a8..92aae88 100644 --- a/src/GtkGif.cpp +++ b/src/GtkGif.cpp @@ -5,8 +5,7 @@ namespace dchat GtkGif::GtkGif(StringView fileContent) : Gif(fileContent) { - //signal_draw().connect(sigc::mem_fun(*this, &GtkGif::updateContent)); - set_app_paintable(true); + } bool GtkGif::createTexture(int width, int height) @@ -18,14 +17,32 @@ namespace dchat void GtkGif::updateTexture(void *textureData) { unsigned char *pixels = surface->get_data(); - memcpy(pixels, textureData, surface->get_stride() * surface->get_height()); + surface->flush(); + char *p = (char*)textureData; + // TODO: Optimize this + for(int i = 0; i < surface->get_stride() * surface->get_height(); i += 4) + { + pixels[i + 0] = p[i + 2]; + pixels[i + 1] = p[i + 1]; + pixels[i + 2] = p[i + 0]; + pixels[i + 3] = p[i + 3]; + } + //memcpy(pixels, textureData, surface->get_stride() * surface->get_height()); + surface->mark_dirty(); } - bool GtkGif::on_draw(const Cairo::RefPtr &cairo) + void GtkGif::draw(const Cairo::RefPtr &cairo, int width, int height) { update(); + + int minSize = std::min(width/2, height/2); + cairo->arc(width/2, height/2, minSize, 0.0, 2.0 * M_PI); + cairo->clip(); + + double scaleX = (double)width / (double)surface->get_width(); + double scaleY = (double)height / (double)surface->get_height(); + cairo->scale(scaleX, scaleY); cairo->set_source(surface, 0.0, 0.0); - cairo->fill(); - return true; + cairo->paint(); } } \ No newline at end of file diff --git a/src/Window.cpp b/src/Window.cpp index 8b23aa9..b5a9f26 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -43,7 +43,7 @@ namespace dchat { fprintf(stderr, "Trying to login with username %s\n", username.raw().c_str()); rooms->loginUser(username.raw(), password.raw()); - windowNotification->show(Glib::ustring("Successfully logged in as ") + username); + //windowNotification->show(Glib::ustring("Successfully logged in as ") + username); drawBackgroundConnection.disconnect(); chatWindow.show_all(); stack.set_visible_child(chatWindow); @@ -260,7 +260,10 @@ namespace dchat //cairo->paint(); */ - overlay.draw(cairo); + Gtk::Allocation alloc = overlay.get_allocation(); + // For some reason gtk sometimes needs time to allocate the overlay, and it freezes the application if you do not wait for it + if(!alloc.has_zero_area()) + overlay.draw(cairo); queue_draw(); return true; } -- cgit v1.2.3