summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorouwou <26526779+ouwou@users.noreply.github.com>2021-03-17 23:55:41 -0400
committerouwou <26526779+ouwou@users.noreply.github.com>2021-03-17 23:55:41 -0400
commit60404783bd4ce9be26233fe66fc3a74475d9eaa3 (patch)
tree7fd851858e9bdf25ad36c0e1542f5b28fb1c1e64 /components
parent65943b4bd74ae52e6f6ffbff0e9ba619053172d6 (diff)
downloadabaddon-portaudio-60404783bd4ce9be26233fe66fc3a74475d9eaa3.tar.gz
abaddon-portaudio-60404783bd4ce9be26233fe66fc3a74475d9eaa3.zip
manage emojis
Diffstat (limited to 'components')
-rw-r--r--components/cellrendererpixbufanimation.cpp95
-rw-r--r--components/cellrendererpixbufanimation.hpp41
2 files changed, 136 insertions, 0 deletions
diff --git a/components/cellrendererpixbufanimation.cpp b/components/cellrendererpixbufanimation.cpp
new file mode 100644
index 0000000..1f49402
--- /dev/null
+++ b/components/cellrendererpixbufanimation.cpp
@@ -0,0 +1,95 @@
+#include "cellrendererpixbufanimation.hpp"
+
+CellRendererPixbufAnimation::CellRendererPixbufAnimation()
+ : Glib::ObjectBase(typeid(CellRendererPixbufAnimation))
+ , Gtk::CellRenderer()
+ , m_property_pixbuf(*this, "pixbuf")
+ , m_property_pixbuf_animation(*this, "pixbuf-animation") {
+ property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE;
+ property_xpad() = 2;
+ property_ypad() = 2;
+}
+
+CellRendererPixbufAnimation::~CellRendererPixbufAnimation() {}
+
+Glib::PropertyProxy<Glib::RefPtr<Gdk::Pixbuf>> CellRendererPixbufAnimation::property_pixbuf() {
+ return m_property_pixbuf.get_proxy();
+}
+
+Glib::PropertyProxy<Glib::RefPtr<Gdk::PixbufAnimation>> CellRendererPixbufAnimation::property_pixbuf_animation() {
+ return m_property_pixbuf_animation.get_proxy();
+}
+
+void CellRendererPixbufAnimation::get_preferred_width_vfunc(Gtk::Widget &widget, int &minimum_width, int &natural_width) const {
+ int width = 0;
+
+ if (auto pixbuf = m_property_pixbuf_animation.get_value())
+ width = pixbuf->get_width();
+ else if (auto pixbuf = m_property_pixbuf.get_value())
+ width = pixbuf->get_width();
+
+ int xpad, ypad;
+ get_padding(xpad, ypad);
+ minimum_width = natural_width = xpad * 2 + width;
+}
+
+void CellRendererPixbufAnimation::get_preferred_width_for_height_vfunc(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const {
+ get_preferred_width_vfunc(widget, minimum_width, natural_width);
+}
+
+void CellRendererPixbufAnimation::get_preferred_height_vfunc(Gtk::Widget &widget, int &minimum_height, int &natural_height) const {
+ int height = 0;
+
+ if (auto pixbuf = m_property_pixbuf_animation.get_value())
+ height = pixbuf->get_height();
+ else if (auto pixbuf = m_property_pixbuf.get_value())
+ height = pixbuf->get_height();
+
+ int xpad, ypad;
+ get_padding(xpad, ypad);
+ minimum_height = natural_height = ypad * 2 + height;
+}
+
+void CellRendererPixbufAnimation::get_preferred_height_for_width_vfunc(Gtk::Widget &widget, int width, int &minimum_height, int &natural_height) const {
+ get_preferred_height_vfunc(widget, minimum_height, natural_height);
+}
+
+void CellRendererPixbufAnimation::render_vfunc(const Cairo::RefPtr<Cairo::Context> &cr,
+ Gtk::Widget &widget,
+ const Gdk::Rectangle &background_area,
+ const Gdk::Rectangle &cell_area,
+ Gtk::CellRendererState flags) {
+ Gtk::Requisition minimum, natural;
+ get_preferred_size(widget, minimum, natural);
+ auto alloc = widget.get_allocation();
+ int xpad, ypad;
+ get_padding(xpad, ypad);
+ int pix_x = cell_area.get_x() + xpad;
+ int pix_y = cell_area.get_y() + ypad;
+ natural.width -= xpad * 2;
+ natural.height -= ypad * 2;
+
+ Gdk::Rectangle pix_rect(pix_x, pix_y, natural.width, natural.height);
+ if (!cell_area.intersects(pix_rect))
+ return;
+
+ if (auto anim = m_property_pixbuf_animation.get_value()) {
+ auto map_iter = m_pixbuf_animation_iters.find(anim);
+ if (map_iter == m_pixbuf_animation_iters.end())
+ m_pixbuf_animation_iters[anim] = anim->get_iter(nullptr);
+ auto pb_iter = m_pixbuf_animation_iters.at(anim);
+
+ const auto cb = [this, &widget, anim] {
+ if (m_pixbuf_animation_iters.at(anim)->advance())
+ widget.queue_draw();
+ };
+ Glib::signal_timeout().connect_once(sigc::track_obj(cb, widget), pb_iter->get_delay_time());
+ Gdk::Cairo::set_source_pixbuf(cr, pb_iter->get_pixbuf(), pix_x, pix_y);
+ cr->rectangle(pix_x, pix_y, natural.width, natural.height);
+ cr->fill();
+ } else if (auto pixbuf = m_property_pixbuf.get_value()) {
+ Gdk::Cairo::set_source_pixbuf(cr, pixbuf, pix_x, pix_y);
+ cr->rectangle(pix_x, pix_y, natural.width, natural.height);
+ cr->fill();
+ }
+}
diff --git a/components/cellrendererpixbufanimation.hpp b/components/cellrendererpixbufanimation.hpp
new file mode 100644
index 0000000..f47e928
--- /dev/null
+++ b/components/cellrendererpixbufanimation.hpp
@@ -0,0 +1,41 @@
+#pragma once
+#include <gtkmm.h>
+#include <unordered_map>
+
+// handles both static and animated
+class CellRendererPixbufAnimation : public Gtk::CellRenderer {
+public:
+ CellRendererPixbufAnimation();
+ virtual ~CellRendererPixbufAnimation();
+
+ Glib::PropertyProxy<Glib::RefPtr<Gdk::Pixbuf>> property_pixbuf();
+ Glib::PropertyProxy<Glib::RefPtr<Gdk::PixbufAnimation>> property_pixbuf_animation();
+
+protected:
+ void get_preferred_width_vfunc(Gtk::Widget &widget, int &minimum_width, int &natural_width) const override;
+
+ void get_preferred_width_for_height_vfunc(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const override;
+
+ void get_preferred_height_vfunc(Gtk::Widget &widget, int &minimum_height, int &natural_height) const override;
+
+ void get_preferred_height_for_width_vfunc(Gtk::Widget &widget, int width, int &minimum_height, int &natural_height) const override;
+
+ void render_vfunc(const Cairo::RefPtr<Cairo::Context> &cr,
+ Gtk::Widget &widget,
+ const Gdk::Rectangle &background_area,
+ const Gdk::Rectangle &cell_area,
+ Gtk::CellRendererState flag) override;
+
+private:
+ Glib::Property<Glib::RefPtr<Gdk::Pixbuf>> m_property_pixbuf;
+ Glib::Property<Glib::RefPtr<Gdk::PixbufAnimation>> m_property_pixbuf_animation;
+ /* one cellrenderer is used for every animation and i dont know how to
+ store data per-pixbuf (in this case the iter) so this little map thing will have to do
+ i would try set_data on the pixbuf but i dont know if that will cause memory leaks
+ this would mean if a row's pixbuf animation is changed more than once then it wont be released immediately
+ but thats not a problem for me in this case
+
+ unordered_map doesnt compile cuz theres no hash overload, i guess
+ */
+ std::map<Glib::RefPtr<Gdk::PixbufAnimation>, Glib::RefPtr<Gdk::PixbufAnimationIter>> m_pixbuf_animation_iters;
+};