add ugly little mention indicator to classic guild listing

This commit is contained in:
ouwou 2024-05-21 02:06:20 -04:00
parent a4856a5378
commit 057dd2a1f8
9 changed files with 122 additions and 19 deletions

View File

@ -1,13 +1,15 @@
#include "cellrendererchannels.hpp" #include "cellrendererchannels.hpp"
#include <gdkmm/general.h> #include <gdkmm/general.h>
#include "misc/cairo.hpp"
#include "abaddon.hpp" #include "abaddon.hpp"
constexpr static int MentionsRightPad = 7; constexpr static int MentionsRightPad = 7;
#ifndef M_PI #ifndef M_PI
constexpr static double M_PI = 3.14159265358979; constexpr static double M_PI = 3.14159265358979;
#endif #endif
constexpr static double M_PI_H = M_PI / 2.0;
constexpr static double M_PI_3_2 = M_PI * 3.0 / 2.0;
void AddUnreadIndicator(const Cairo::RefPtr<Cairo::Context> &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area) { void AddUnreadIndicator(const Cairo::RefPtr<Cairo::Context> &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area) {
static const auto color_setting = Gdk::RGBA(Abaddon::Get().GetSettings().UnreadIndicatorColor); static const auto color_setting = Gdk::RGBA(Abaddon::Get().GetSettings().UnreadIndicatorColor);
@ -832,17 +834,6 @@ void CellRendererChannels::render_vfunc_dm(const Cairo::RefPtr<Cairo::Context> &
} }
} }
void CellRendererChannels::cairo_path_rounded_rect(const Cairo::RefPtr<Cairo::Context> &cr, double x, double y, double w, double h, double r) {
const double degrees = M_PI / 180.0;
cr->begin_new_sub_path();
cr->arc(x + w - r, y + r, r, -M_PI_H, 0);
cr->arc(x + w - r, y + h - r, r, 0, M_PI_H);
cr->arc(x + r, y + h - r, r, M_PI_H, M_PI);
cr->arc(x + r, y + r, r, M_PI, M_PI_3_2);
cr->close_path();
}
void CellRendererChannels::unread_render_mentions(const Cairo::RefPtr<Cairo::Context> &cr, Gtk::Widget &widget, int mentions, int edge, const Gdk::Rectangle &cell_area) { void CellRendererChannels::unread_render_mentions(const Cairo::RefPtr<Cairo::Context> &cr, Gtk::Widget &widget, int mentions, int edge, const Gdk::Rectangle &cell_area) {
Pango::FontDescription font; Pango::FontDescription font;
font.set_family("sans 14"); font.set_family("sans 14");
@ -863,7 +854,7 @@ void CellRendererChannels::unread_render_mentions(const Cairo::RefPtr<Cairo::Con
const auto x = cell_area.get_x() + edge - width - MentionsRightPad; const auto x = cell_area.get_x() + edge - width - MentionsRightPad;
const auto y = cell_area.get_y() + cell_area.get_height() / 2.0 - height / 2.0 - 1; const auto y = cell_area.get_y() + cell_area.get_height() / 2.0 - height / 2.0 - 1;
cairo_path_rounded_rect(cr, x - 4, y + 2, width + 8, height, 5); CairoUtil::PathRoundedRect(cr, x - 4, y + 2, width + 8, height, 5);
cr->set_source_rgb(bg.get_red(), bg.get_green(), bg.get_blue()); cr->set_source_rgb(bg.get_red(), bg.get_green(), bg.get_blue());
cr->fill(); cr->fill();
cr->set_source_rgb(text.get_red(), text.get_green(), text.get_blue()); cr->set_source_rgb(text.get_red(), text.get_green(), text.get_blue());

View File

@ -153,7 +153,6 @@ protected:
const Gdk::Rectangle &cell_area, const Gdk::Rectangle &cell_area,
Gtk::CellRendererState flags); Gtk::CellRendererState flags);
static void cairo_path_rounded_rect(const Cairo::RefPtr<Cairo::Context> &cr, double x, double y, double w, double h, double r);
static void unread_render_mentions(const Cairo::RefPtr<Cairo::Context> &cr, Gtk::Widget &widget, int mentions, int edge, const Gdk::Rectangle &cell_area); static void unread_render_mentions(const Cairo::RefPtr<Cairo::Context> &cr, Gtk::Widget &widget, int mentions, int edge, const Gdk::Rectangle &cell_area);
private: private:

View File

@ -3,6 +3,7 @@
#include "abaddon.hpp" #include "abaddon.hpp"
#include "util.hpp" #include "util.hpp"
#include "guildlistfolderitem.hpp" #include "guildlistfolderitem.hpp"
#include "mentionoverlay.hpp"
class GuildListDMsButton : public Gtk::EventBox { class GuildListDMsButton : public Gtk::EventBox {
public: public:
@ -93,10 +94,19 @@ void GuildList::UpdateListing() {
} }
} }
static Gtk::Widget *AddMentionOverlay(Gtk::Widget *widget, Snowflake guild_id) {
auto *overlay = Gtk::make_managed<Gtk::Overlay>();
overlay->add(*widget);
auto *mention_overlay = Gtk::make_managed<MentionOverlay>(guild_id);
overlay->add_overlay(*mention_overlay);
overlay->show_all();
return overlay;
}
void GuildList::AddGuild(Snowflake id) { void GuildList::AddGuild(Snowflake id) {
if (auto item = CreateGuildWidget(id)) { if (auto item = CreateGuildWidget(id)) {
item->show(); item->show();
add(*item); add(*AddMentionOverlay(item, id));
} }
} }
@ -132,7 +142,7 @@ void GuildList::AddFolder(const UserSettingsGuildFoldersEntry &folder) {
for (const auto guild_id : folder.GuildIDs) { for (const auto guild_id : folder.GuildIDs) {
if (auto *guild_widget = CreateGuildWidget(guild_id)) { if (auto *guild_widget = CreateGuildWidget(guild_id)) {
guild_widget->show(); guild_widget->show();
folder_widget->AddGuildWidget(guild_widget); folder_widget->AddGuildWidget(AddMentionOverlay(guild_widget, guild_id));
} }
} }

View File

@ -95,7 +95,7 @@ GuildListFolderItem::GuildListFolderItem(const UserSettingsGuildFoldersEntry &fo
CheckUnreadStatus(); CheckUnreadStatus();
} }
void GuildListFolderItem::AddGuildWidget(GuildListGuildItem *widget) { void GuildListFolderItem::AddGuildWidget(Gtk::Widget *widget) {
m_box.add(*widget); m_box.add(*widget);
} }

View File

@ -24,7 +24,7 @@ class GuildListFolderItem : public Gtk::VBox {
public: public:
GuildListFolderItem(const UserSettingsGuildFoldersEntry &folder); GuildListFolderItem(const UserSettingsGuildFoldersEntry &folder);
void AddGuildWidget(GuildListGuildItem *widget); void AddGuildWidget(Gtk::Widget *widget);
private: private:
void OnMessageCreate(const Message &msg); void OnMessageCreate(const Message &msg);

View File

@ -0,0 +1,62 @@
#include "mentionoverlay.hpp"
#include "misc/cairo.hpp"
#include "abaddon.hpp"
MentionOverlay::MentionOverlay(Snowflake guild_id)
: m_guild_id(guild_id) {
m_font.set_family("sans 14");
m_layout = create_pango_layout("12");
m_layout->set_font_description(m_font);
m_layout->set_alignment(Pango::ALIGN_RIGHT);
get_style_context()->add_class("classic-mention-overlay"); // fuck you
set_hexpand(false);
set_vexpand(false);
signal_draw().connect(sigc::mem_fun(*this, &MentionOverlay::OnDraw));
Abaddon::Get().GetDiscordClient().signal_message_ack().connect([this](const MessageAckData &data) {
// fetching and checking guild id is probably more expensive than just forcing a redraw anyways
queue_draw();
});
Abaddon::Get().GetDiscordClient().signal_message_create().connect([this](const Message &msg) {
if (msg.GuildID.has_value() && *msg.GuildID != m_guild_id) return;
if (!msg.DoesMentionEveryone && msg.Mentions.empty() && msg.MentionRoles.empty()) return;
queue_draw();
});
}
bool MentionOverlay::OnDraw(const Cairo::RefPtr<Cairo::Context> &cr) {
int mentions;
Abaddon::Get().GetDiscordClient().GetUnreadStateForGuild(m_guild_id, mentions);
if (mentions == 0) return true;
m_layout->set_text(std::to_string(mentions));
const int width = get_allocated_width();
const int height = get_allocated_height();
int lw, lh;
m_layout->get_pixel_size(lw, lh);
{
static const auto badge_setting = Gdk::RGBA(Abaddon::Get().GetSettings().MentionBadgeColor);
static const auto text_setting = Gdk::RGBA(Abaddon::Get().GetSettings().MentionBadgeTextColor);
auto bg = badge_setting.get_alpha_u() > 0 ? badge_setting : get_style_context()->get_background_color(Gtk::STATE_FLAG_SELECTED);
auto text = text_setting.get_alpha_u() > 0 ? text_setting : get_style_context()->get_color(Gtk::STATE_FLAG_SELECTED);
const auto x = width - lw - 5;
const auto y = height - lh - 1;
CairoUtil::PathRoundedRect(cr, x - 4, y + 2, lw + 8, lh, 5);
cr->set_source_rgb(bg.get_red(), bg.get_green(), bg.get_blue());
cr->fill();
cr->set_source_rgb(text.get_red(), text.get_green(), text.get_blue());
cr->move_to(x, y);
m_layout->show_in_cairo_context(cr);
}
return true;
}

View File

@ -0,0 +1,19 @@
#pragma once
#include <gtkmm/drawingarea.h>
#include <pangomm/fontdescription.h>
#include "discord/snowflake.hpp"
class MentionOverlay : public Gtk::DrawingArea {
public:
MentionOverlay(Snowflake guild_id);
private:
bool OnDraw(const Cairo::RefPtr<Cairo::Context> &cr);
Snowflake m_guild_id;
Pango::FontDescription m_font;
Glib::RefPtr<Pango::Layout> m_layout;
};

17
src/misc/cairo.cpp Normal file
View File

@ -0,0 +1,17 @@
#include "cairo.hpp"
#include <cairomm/context.h>
constexpr static double M_PI_H = M_PI / 2.0;
constexpr static double M_PI_3_2 = M_PI * 3.0 / 2.0;
void CairoUtil::PathRoundedRect(const Cairo::RefPtr<Cairo::Context> &cr, double x, double y, double w, double h, double r) {
const double degrees = M_PI / 180.0;
cr->begin_new_sub_path();
cr->arc(x + w - r, y + r, r, -M_PI_H, 0);
cr->arc(x + w - r, y + h - r, r, 0, M_PI_H);
cr->arc(x + r, y + h - r, r, M_PI_H, M_PI);
cr->arc(x + r, y + r, r, M_PI, M_PI_3_2);
cr->close_path();
}

5
src/misc/cairo.hpp Normal file
View File

@ -0,0 +1,5 @@
#pragma once
namespace CairoUtil {
void PathRoundedRect(const Cairo::RefPtr<Cairo::Context> &cr, double x, double y, double w, double h, double r);
} // namespace CairoUtil