1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
#include "statusindicator.hpp"
#include "../abaddon.hpp"
static const constexpr int Diameter = 8;
static const auto OnlineColor = Gdk::RGBA("#43B581");
static const auto IdleColor = Gdk::RGBA("#FAA61A");
static const auto DNDColor = Gdk::RGBA("#982929");
static const auto OfflineColor = Gdk::RGBA("#808080");
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();
}
StatusIndicator::~StatusIndicator() {
}
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, height / 2, width / 3, 0.0, 2 * (4 * std::atan(1)));
cr->close_path();
cr->fill_preserve();
cr->stroke();
return true;
}
|