mirror of
https://github.com/uowuo/abaddon.git
synced 2024-11-10 06:00:10 +00:00
Merge branch 'master' into theming
This commit is contained in:
commit
d68afa0fd4
@ -199,11 +199,6 @@ spam filter's wrath:
|
||||
| `.embed-field-value` | The value of an embed field |
|
||||
| `.embed-footer` | The footer of an embed |
|
||||
| `.member-list` | Container of the member list |
|
||||
| `.status-indicator` | The status indicator |
|
||||
| `.online` | Applied to status indicators when the associated user is online |
|
||||
| `.idle` | Applied to status indicators when the associated user is away |
|
||||
| `.dnd` | Applied to status indicators when the associated user is on do not disturb |
|
||||
| `.offline` | Applied to status indicators when the associated user is offline |
|
||||
| `.typing-indicator` | The typing indicator (also used for replies) |
|
||||
|
||||
Used in reorderable list implementation:
|
||||
|
@ -50,7 +50,7 @@
|
||||
/bin/libpng16-16.dll
|
||||
/bin/libpsl-5.dll
|
||||
/bin/libsigc-2.0-0.dll
|
||||
/bin/libsodium-23.dll
|
||||
/bin/libsodium-26.dll
|
||||
/bin/libspdlog.dll
|
||||
/bin/libsqlite3-0.dll
|
||||
/bin/libssh2-1.dll
|
||||
|
@ -6,7 +6,8 @@ CellRendererMemberList::CellRendererMemberList()
|
||||
, m_property_id(*this, "id")
|
||||
, m_property_name(*this, "name")
|
||||
, m_property_pixbuf(*this, "pixbuf")
|
||||
, m_property_color(*this, "color") {
|
||||
, m_property_color(*this, "color")
|
||||
, m_property_status(*this, "status") {
|
||||
property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE;
|
||||
property_xpad() = 2;
|
||||
property_ypad() = 2;
|
||||
@ -35,6 +36,10 @@ Glib::PropertyProxy<Gdk::RGBA> CellRendererMemberList::property_color() {
|
||||
return m_property_color.get_proxy();
|
||||
}
|
||||
|
||||
Glib::PropertyProxy<PresenceStatus> CellRendererMemberList::property_status() {
|
||||
return m_property_status.get_proxy();
|
||||
}
|
||||
|
||||
void CellRendererMemberList::get_preferred_width_vfunc(Gtk::Widget &widget, int &minimum_width, int &natural_width) const {
|
||||
switch (m_property_type.get_value()) {
|
||||
case MemberListRenderType::Role:
|
||||
@ -117,8 +122,9 @@ void CellRendererMemberList::get_preferred_height_for_width_vfunc_member(Gtk::Wi
|
||||
}
|
||||
|
||||
void CellRendererMemberList::render_vfunc_member(const Cairo::RefPtr<Cairo::Context> &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area, Gtk::CellRendererState flags) {
|
||||
// Text
|
||||
Gdk::Rectangle text_cell_area = cell_area;
|
||||
text_cell_area.set_x(22);
|
||||
text_cell_area.set_x(31);
|
||||
const auto color = m_property_color.get_value();
|
||||
if (color.get_alpha_u() > 0) {
|
||||
m_renderer_text.property_foreground_rgba().set_value(color);
|
||||
@ -126,6 +132,30 @@ void CellRendererMemberList::render_vfunc_member(const Cairo::RefPtr<Cairo::Cont
|
||||
m_renderer_text.render(cr, widget, background_area, text_cell_area, flags);
|
||||
m_renderer_text.property_foreground_set().set_value(false);
|
||||
|
||||
// Status indicator
|
||||
// TODO: reintroduce custom status colors... somehow
|
||||
cr->begin_new_path();
|
||||
switch (m_property_status.get_value()) {
|
||||
case PresenceStatus::Online:
|
||||
cr->set_source_rgb(33.0 / 255.0, 157.0 / 255.0, 86.0 / 255.0);
|
||||
break;
|
||||
case PresenceStatus::Idle:
|
||||
cr->set_source_rgb(230.0 / 255.0, 170.0 / 255.0, 48.0 / 255.0);
|
||||
break;
|
||||
case PresenceStatus::DND:
|
||||
cr->set_source_rgb(233.0 / 255.0, 61.0 / 255.0, 65.0 / 255.0);
|
||||
break;
|
||||
case PresenceStatus::Offline:
|
||||
cr->set_source_rgb(122.0 / 255.0, 126.0 / 255.0, 135.0 / 255.0);
|
||||
break;
|
||||
}
|
||||
|
||||
cr->arc(background_area.get_x() + 6.0 + 16.0 + 6.0, background_area.get_y() + background_area.get_height() / 2.0, 2.0, 0.0, 2 * (4 * std::atan(1)));
|
||||
cr->close_path();
|
||||
cr->fill_preserve();
|
||||
cr->stroke();
|
||||
|
||||
// Icon
|
||||
const double icon_x = background_area.get_x() + 6.0;
|
||||
const double icon_y = background_area.get_y() + background_area.get_height() / 2.0 - 8.0;
|
||||
Gdk::Cairo::set_source_pixbuf(cr, m_property_pixbuf.get_value(), icon_x, icon_y);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <gtkmm/cellrenderer.h>
|
||||
#include "discord/activity.hpp"
|
||||
|
||||
enum class MemberListRenderType : uint8_t {
|
||||
Role,
|
||||
@ -16,6 +17,7 @@ public:
|
||||
Glib::PropertyProxy<Glib::ustring> property_name();
|
||||
Glib::PropertyProxy<Glib::RefPtr<Gdk::Pixbuf>> property_pixbuf();
|
||||
Glib::PropertyProxy<Gdk::RGBA> property_color();
|
||||
Glib::PropertyProxy<PresenceStatus> property_status();
|
||||
|
||||
protected:
|
||||
void get_preferred_width_vfunc(Gtk::Widget &widget, int &minimum_width, int &natural_width) const override;
|
||||
@ -56,6 +58,7 @@ private:
|
||||
Glib::Property<Glib::ustring> m_property_name;
|
||||
Glib::Property<Glib::RefPtr<Gdk::Pixbuf>> m_property_pixbuf;
|
||||
Glib::Property<Gdk::RGBA> m_property_color;
|
||||
Glib::Property<PresenceStatus> m_property_status;
|
||||
|
||||
using type_signal_render = sigc::signal<void(uint64_t)>;
|
||||
type_signal_render m_signal_render;
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "channels.hpp"
|
||||
#include "imgmanager.hpp"
|
||||
#include "statusindicator.hpp"
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
@ -28,6 +28,7 @@ MemberList::MemberList()
|
||||
column->add_attribute(renderer->property_name(), m_columns.m_name);
|
||||
column->add_attribute(renderer->property_pixbuf(), m_columns.m_pixbuf);
|
||||
column->add_attribute(renderer->property_color(), m_columns.m_color);
|
||||
column->add_attribute(renderer->property_status(), m_columns.m_status);
|
||||
m_view.append_column(*column);
|
||||
|
||||
m_model->set_sort_column(m_columns.m_sort, Gtk::SORT_ASCENDING);
|
||||
@ -44,6 +45,8 @@ MemberList::MemberList()
|
||||
m_menu_role_copy_id.signal_activate().connect([this]() {
|
||||
Gtk::Clipboard::get()->set_text(std::to_string((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]));
|
||||
});
|
||||
|
||||
Abaddon::Get().GetDiscordClient().signal_presence_update().connect(sigc::mem_fun(*this, &MemberList::OnPresenceUpdate));
|
||||
}
|
||||
|
||||
Gtk::Widget *MemberList::GetRoot() {
|
||||
@ -73,6 +76,7 @@ void MemberList::UpdateMemberList() {
|
||||
row[m_columns.m_color] = color_transparent;
|
||||
row[m_columns.m_av_requested] = false;
|
||||
row[m_columns.m_pixbuf] = Abaddon::Get().GetImageManager().GetPlaceholder(16);
|
||||
row[m_columns.m_status] = Abaddon::Get().GetDiscordClient().GetUserStatus(user.ID);
|
||||
m_pending_avatars[user.ID] = row_iter;
|
||||
}
|
||||
}
|
||||
@ -126,6 +130,7 @@ void MemberList::UpdateMemberList() {
|
||||
row[m_columns.m_id] = user.ID;
|
||||
row[m_columns.m_name] = user.GetDisplayNameEscaped();
|
||||
row[m_columns.m_pixbuf] = Abaddon::Get().GetImageManager().GetPlaceholder(16);
|
||||
row[m_columns.m_status] = Abaddon::Get().GetDiscordClient().GetUserStatus(user.ID);
|
||||
row[m_columns.m_av_requested] = false;
|
||||
if (const auto iter = user_to_color.find(user.ID); iter != user_to_color.end()) {
|
||||
row[m_columns.m_color] = IntToRGBA(iter->second);
|
||||
@ -241,12 +246,24 @@ int MemberList::SortFunc(const Gtk::TreeModel::iterator &a, const Gtk::TreeModel
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MemberList::OnPresenceUpdate(const UserData &user, PresenceStatus status) {
|
||||
for (auto &role : m_model->children()) {
|
||||
for (auto &member : role.children()) {
|
||||
if ((*member)[m_columns.m_id] == user.ID) {
|
||||
(*member)[m_columns.m_status] = status;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MemberList::ModelColumns::ModelColumns() {
|
||||
add(m_type);
|
||||
add(m_id);
|
||||
add(m_name);
|
||||
add(m_pixbuf);
|
||||
add(m_av_requested);
|
||||
add(m_color);
|
||||
add(m_status);
|
||||
add(m_sort);
|
||||
add(m_av_requested);
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ private:
|
||||
|
||||
int SortFunc(const Gtk::TreeModel::iterator &a, const Gtk::TreeModel::iterator &b);
|
||||
|
||||
void OnPresenceUpdate(const UserData &user, PresenceStatus status);
|
||||
|
||||
class ModelColumns : public Gtk::TreeModel::ColumnRecord {
|
||||
public:
|
||||
ModelColumns();
|
||||
@ -35,6 +37,7 @@ private:
|
||||
Gtk::TreeModelColumn<Glib::ustring> m_name;
|
||||
Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf>> m_pixbuf;
|
||||
Gtk::TreeModelColumn<Gdk::RGBA> m_color;
|
||||
Gtk::TreeModelColumn<PresenceStatus> m_status;
|
||||
Gtk::TreeModelColumn<int> m_sort;
|
||||
|
||||
Gtk::TreeModelColumn<bool> m_av_requested;
|
||||
|
@ -1,122 +0,0 @@
|
||||
#include "statusindicator.hpp"
|
||||
|
||||
static const constexpr int Diameter = 8;
|
||||
|
||||
StatusIndicator::StatusIndicator(Snowflake user_id)
|
||||
: Glib::ObjectBase("statusindicator")
|
||||
, Gtk::Widget()
|
||||
, m_id(user_id)
|
||||
, m_status(static_cast<PresenceStatus>(-1)) {
|
||||
set_has_window(true);
|
||||
set_name("status-indicator");
|
||||
|
||||
get_style_context()->add_class("status-indicator");
|
||||
|
||||
Abaddon::Get().GetDiscordClient().signal_guild_member_list_update().connect(sigc::hide(sigc::mem_fun(*this, &StatusIndicator::CheckStatus)));
|
||||
auto cb = [this](const UserData &user, PresenceStatus status) {
|
||||
if (user.ID == m_id) CheckStatus();
|
||||
};
|
||||
Abaddon::Get().GetDiscordClient().signal_presence_update().connect(sigc::track_obj(cb, *this));
|
||||
|
||||
CheckStatus();
|
||||
}
|
||||
|
||||
void StatusIndicator::CheckStatus() {
|
||||
const auto status = Abaddon::Get().GetDiscordClient().GetUserStatus(m_id);
|
||||
const auto last_status = m_status;
|
||||
get_style_context()->remove_class("online");
|
||||
get_style_context()->remove_class("dnd");
|
||||
get_style_context()->remove_class("idle");
|
||||
get_style_context()->remove_class("offline");
|
||||
get_style_context()->add_class(GetPresenceString(status));
|
||||
m_status = status;
|
||||
|
||||
if (last_status != m_status)
|
||||
queue_draw();
|
||||
}
|
||||
|
||||
Gtk::SizeRequestMode StatusIndicator::get_request_mode_vfunc() const {
|
||||
return Gtk::Widget::get_request_mode_vfunc();
|
||||
}
|
||||
|
||||
void StatusIndicator::get_preferred_width_vfunc(int &minimum_width, int &natural_width) const {
|
||||
minimum_width = 0;
|
||||
natural_width = Diameter;
|
||||
}
|
||||
|
||||
void StatusIndicator::get_preferred_height_for_width_vfunc(int width, int &minimum_height, int &natural_height) const {
|
||||
minimum_height = 0;
|
||||
natural_height = Diameter;
|
||||
}
|
||||
|
||||
void StatusIndicator::get_preferred_height_vfunc(int &minimum_height, int &natural_height) const {
|
||||
minimum_height = 0;
|
||||
natural_height = Diameter;
|
||||
}
|
||||
|
||||
void StatusIndicator::get_preferred_width_for_height_vfunc(int height, int &minimum_width, int &natural_width) const {
|
||||
minimum_width = 0;
|
||||
natural_width = Diameter;
|
||||
}
|
||||
|
||||
void StatusIndicator::on_size_allocate(Gtk::Allocation &allocation) {
|
||||
set_allocation(allocation);
|
||||
|
||||
if (m_window)
|
||||
m_window->move_resize(allocation.get_x(), allocation.get_y(), allocation.get_width(), allocation.get_height());
|
||||
}
|
||||
|
||||
void StatusIndicator::on_map() {
|
||||
Gtk::Widget::on_map();
|
||||
}
|
||||
|
||||
void StatusIndicator::on_unmap() {
|
||||
Gtk::Widget::on_unmap();
|
||||
}
|
||||
|
||||
void StatusIndicator::on_realize() {
|
||||
set_realized(true);
|
||||
|
||||
if (!m_window) {
|
||||
GdkWindowAttr attributes;
|
||||
std::memset(&attributes, 0, sizeof(attributes));
|
||||
|
||||
auto allocation = get_allocation();
|
||||
|
||||
attributes.x = allocation.get_x();
|
||||
attributes.y = allocation.get_y();
|
||||
attributes.width = allocation.get_width();
|
||||
attributes.height = allocation.get_height();
|
||||
|
||||
attributes.event_mask = get_events() | Gdk::EXPOSURE_MASK;
|
||||
attributes.window_type = GDK_WINDOW_CHILD;
|
||||
attributes.wclass = GDK_INPUT_OUTPUT;
|
||||
|
||||
m_window = Gdk::Window::create(get_parent_window(), &attributes, GDK_WA_X | GDK_WA_Y);
|
||||
set_window(m_window);
|
||||
|
||||
m_window->set_user_data(gobj());
|
||||
}
|
||||
}
|
||||
|
||||
void StatusIndicator::on_unrealize() {
|
||||
m_window.reset();
|
||||
|
||||
Gtk::Widget::on_unrealize();
|
||||
}
|
||||
|
||||
bool StatusIndicator::on_draw(const Cairo::RefPtr<Cairo::Context> &cr) {
|
||||
const auto allocation = get_allocation();
|
||||
const auto width = allocation.get_width();
|
||||
const auto height = allocation.get_height();
|
||||
|
||||
const auto color = get_style_context()->get_color(Gtk::STATE_FLAG_NORMAL);
|
||||
|
||||
cr->set_source_rgb(color.get_red(), color.get_green(), color.get_blue());
|
||||
cr->arc(width / 2.0, height / 2.0, width / 3.0, 0.0, 2 * (4 * std::atan(1)));
|
||||
cr->close_path();
|
||||
cr->fill_preserve();
|
||||
cr->stroke();
|
||||
|
||||
return true;
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
#include "discord/snowflake.hpp"
|
||||
#include "discord/activity.hpp"
|
||||
|
||||
class StatusIndicator : public Gtk::Widget {
|
||||
public:
|
||||
StatusIndicator(Snowflake user_id);
|
||||
~StatusIndicator() override = default;
|
||||
|
||||
protected:
|
||||
Gtk::SizeRequestMode get_request_mode_vfunc() const override;
|
||||
void get_preferred_width_vfunc(int &minimum_width, int &natural_width) const override;
|
||||
void get_preferred_width_for_height_vfunc(int height, int &minimum_width, int &natural_width) const override;
|
||||
void get_preferred_height_vfunc(int &minimum_height, int &natural_height) const override;
|
||||
void get_preferred_height_for_width_vfunc(int width, int &minimum_height, int &natural_height) const override;
|
||||
void on_size_allocate(Gtk::Allocation &allocation) override;
|
||||
void on_map() override;
|
||||
void on_unmap() override;
|
||||
void on_realize() override;
|
||||
void on_unrealize() override;
|
||||
bool on_draw(const Cairo::RefPtr<Cairo::Context> &cr) override;
|
||||
|
||||
Glib::RefPtr<Gdk::Window> m_window;
|
||||
|
||||
void CheckStatus();
|
||||
|
||||
Snowflake m_id;
|
||||
PresenceStatus m_status;
|
||||
};
|
Loading…
Reference in New Issue
Block a user