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 --- src/ChatMessage.cpp | 29 ++++++----------------------- src/DynamicImage.cpp | 28 ++++++++++++++++++++++++++++ src/GtkGif.cpp | 29 +++++++++++++++++++++++------ src/Window.cpp | 7 +++++-- 4 files changed, 62 insertions(+), 31 deletions(-) create mode 100644 src/DynamicImage.cpp (limited to 'src') 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