From 00fe6642a9395eb231faeb1c2437f5097eec69f2 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Sun, 11 Sep 2022 02:46:22 -0400 Subject: [PATCH] basic functionality --- src/components/memberlist.cpp | 251 ++++++++-------------- src/components/memberlist.hpp | 51 ++--- src/components/memberlistcellrenderer.cpp | 177 +++++++++++++++ src/components/memberlistcellrenderer.hpp | 60 ++++++ src/windows/mainwindow.cpp | 13 +- src/windows/mainwindow.hpp | 2 +- 6 files changed, 356 insertions(+), 198 deletions(-) create mode 100644 src/components/memberlistcellrenderer.cpp create mode 100644 src/components/memberlistcellrenderer.hpp diff --git a/src/components/memberlist.cpp b/src/components/memberlist.cpp index 85ccd05..5e809cf 100644 --- a/src/components/memberlist.cpp +++ b/src/components/memberlist.cpp @@ -1,85 +1,32 @@ #include "memberlist.hpp" #include "abaddon.hpp" -#include "util.hpp" -#include "lazyimage.hpp" -#include "statusindicator.hpp" -constexpr static const int MaxMemberListRows = 200; +MemberList::MemberList() + : m_model(Gtk::TreeStore::create(m_columns)) { + add(m_view); + show_all_children(); -MemberListUserRow::MemberListUserRow(const std::optional &guild, const UserData &data) { - ID = data.ID; - m_ev = Gtk::manage(new Gtk::EventBox); - m_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL)); - m_label = Gtk::manage(new Gtk::Label); - m_avatar = Gtk::manage(new LazyImage(16, 16)); - m_status_indicator = Gtk::manage(new StatusIndicator(ID)); + m_view.set_activate_on_single_click(true); + m_view.set_hexpand(true); + m_view.set_vexpand(true); - if (Abaddon::Get().GetSettings().ShowOwnerCrown && guild.has_value() && guild->OwnerID == data.ID) { - try { - const static auto crown_path = Abaddon::GetResPath("/crown.png"); - auto pixbuf = Gdk::Pixbuf::create_from_file(crown_path, 12, 12); - m_crown = Gtk::manage(new Gtk::Image(pixbuf)); - m_crown->set_valign(Gtk::ALIGN_CENTER); - m_crown->set_margin_end(8); - } catch (...) {} - } + m_view.set_show_expanders(false); + m_view.set_enable_search(false); + m_view.set_headers_visible(false); + m_view.set_model(m_model); - m_status_indicator->set_margin_start(3); + m_model->set_sort_column(m_columns.m_sort, Gtk::SORT_DESCENDING); - if (guild.has_value()) - m_avatar->SetURL(data.GetAvatarURL(guild->ID, "png")); - else - m_avatar->SetURL(data.GetAvatarURL("png")); + auto *column = Gtk::make_managed("display"); + auto *renderer = Gtk::make_managed(); + column->pack_start(*renderer); + column->add_attribute(renderer->property_type(), m_columns.m_type); + column->add_attribute(renderer->property_id(), m_columns.m_id); + column->add_attribute(renderer->property_markup(), m_columns.m_markup); + column->add_attribute(renderer->property_icon(), m_columns.m_icon); + m_view.append_column(*column); - get_style_context()->add_class("members-row"); - get_style_context()->add_class("members-row-member"); - m_label->get_style_context()->add_class("members-row-label"); - m_avatar->get_style_context()->add_class("members-row-avatar"); - - m_label->set_single_line_mode(true); - m_label->set_ellipsize(Pango::ELLIPSIZE_END); - - std::string display = data.Username; - if (Abaddon::Get().GetSettings().ShowMemberListDiscriminators) - display += "#" + data.Discriminator; - if (guild.has_value()) { - if (const auto col_id = data.GetHoistedRole(guild->ID, true); col_id.IsValid()) { - auto color = Abaddon::Get().GetDiscordClient().GetRole(col_id)->Color; - m_label->set_use_markup(true); - m_label->set_markup("" + Glib::Markup::escape_text(display) + ""); - } else { - m_label->set_text(display); - } - } else { - m_label->set_text(display); - } - - m_label->set_halign(Gtk::ALIGN_START); - m_box->add(*m_avatar); - m_box->add(*m_status_indicator); - m_box->add(*m_label); - if (m_crown != nullptr) - m_box->add(*m_crown); - m_ev->add(*m_box); - add(*m_ev); - show_all(); -} - -MemberList::MemberList() { - m_main = Gtk::manage(new Gtk::ScrolledWindow); - m_listbox = Gtk::manage(new Gtk::ListBox); - - m_listbox->get_style_context()->add_class("members"); - - m_listbox->set_selection_mode(Gtk::SELECTION_NONE); - - m_main->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); - m_main->add(*m_listbox); - m_main->show_all(); -} - -Gtk::Widget *MemberList::GetRoot() const { - return m_main; + m_view.expand_all(); } void MemberList::Clear() { @@ -97,45 +44,43 @@ void MemberList::SetActiveChannel(Snowflake id) { } void MemberList::UpdateMemberList() { - m_id_to_row.clear(); - - auto children = m_listbox->get_children(); - auto it = children.begin(); - while (it != children.end()) { - delete *it; - it++; - } - - if (!Abaddon::Get().GetDiscordClient().IsStarted()) return; - if (!m_chan_id.IsValid()) return; - + m_model->clear(); auto &discord = Abaddon::Get().GetDiscordClient(); - const auto chan = discord.GetChannel(m_chan_id); - if (!chan.has_value()) return; - if (chan->Type == ChannelType::DM || chan->Type == ChannelType::GROUP_DM) { - int num_rows = 0; - for (const auto &user : chan->GetDMRecipients()) { - if (num_rows++ > MaxMemberListRows) break; - auto *row = Gtk::manage(new MemberListUserRow(std::nullopt, user)); - m_id_to_row[user.ID] = row; - AttachUserMenuHandler(row, user.ID); - m_listbox->add(*row); + if (!discord.IsStarted()) return; + + const auto channel = discord.GetChannel(m_chan_id); + if (!channel.has_value()) return; + + // dm + if (channel->IsDM()) { + // todo eliminate for dm + auto everyone_row = *m_model->append(); + everyone_row[m_columns.m_type] = MemberListRenderType::Role; + everyone_row[m_columns.m_id] = Snowflake::Invalid; + everyone_row[m_columns.m_markup] = "Users"; + + for (const auto &user : channel->GetDMRecipients()) { + auto row = *m_model->append(everyone_row.children()); + row[m_columns.m_type] = MemberListRenderType::Member; + row[m_columns.m_id] = user.ID; + row[m_columns.m_markup] = Glib::Markup::escape_text(user.Username + "#" + user.Discriminator); + row[m_columns.m_icon] = Abaddon::Get().GetImageManager().GetPlaceholder(16); } return; } std::set ids; - if (chan->IsThread()) { - const auto x = discord.GetUsersInThread(m_chan_id); + if (channel->IsThread()) { + auto x = discord.GetUsersInThread(m_chan_id); ids = { x.begin(), x.end() }; - } else + } else { ids = discord.GetUsersInGuild(m_guild_id); + } - // process all the shit first so its in proper order std::map pos_to_role; std::map> pos_to_users; - std::unordered_map user_to_color; + // std::unordered_map user_to_color; std::vector roleless_users; for (const auto &id : ids) { @@ -143,10 +88,10 @@ void MemberList::UpdateMemberList() { if (!user.has_value() || user->IsDeleted()) continue; - auto pos_role_id = discord.GetMemberHoistedRole(m_guild_id, id); // role for positioning - auto col_role_id = discord.GetMemberHoistedRole(m_guild_id, id, true); // role for color + auto pos_role_id = discord.GetMemberHoistedRole(m_guild_id, id); // role for positioning + // auto col_role_id = discord.GetMemberHoistedRole(m_guild_id, id, true); // role for color auto pos_role = discord.GetRole(pos_role_id); - auto col_role = discord.GetRole(col_role_id); + // auto col_role = discord.GetRole(col_role_id); if (!pos_role.has_value()) { roleless_users.push_back(id); @@ -155,73 +100,55 @@ void MemberList::UpdateMemberList() { pos_to_role[pos_role->Position] = *pos_role; pos_to_users[pos_role->Position].push_back(std::move(*user)); - if (col_role.has_value()) - user_to_color[id] = col_role->Color; + // if (col_role.has_value()) + // user_to_color[id] = col_role->Color; } - int num_rows = 0; const auto guild = discord.GetGuild(m_guild_id); if (!guild.has_value()) return; - auto add_user = [this, &num_rows, guild](const UserData &data) -> bool { - if (num_rows++ > MaxMemberListRows) return false; - auto *row = Gtk::manage(new MemberListUserRow(*guild, data)); - m_id_to_row[data.ID] = row; - AttachUserMenuHandler(row, data.ID); - m_listbox->add(*row); + auto add_user = [this](const UserData &user, const Gtk::TreeNodeChildren &node) -> bool { + auto row = *m_model->append(node); + row[m_columns.m_type] = MemberListRenderType::Member; + row[m_columns.m_id] = user.ID; + row[m_columns.m_markup] = user.GetEscapedName() + "#" + user.Discriminator; + row[m_columns.m_sort] = static_cast(user.ID); + row[m_columns.m_icon] = Abaddon::Get().GetImageManager().GetPlaceholder(16); + // come on + Gtk::TreeRowReference ref(m_model, m_model->get_path(row)); + Abaddon::Get().GetImageManager().LoadFromURL(user.GetAvatarURL(), [this, ref = std::move(ref)](const Glib::RefPtr &pb) { + if (ref.is_valid()) { + auto row = *m_model->get_iter(ref.get_path()); + row[m_columns.m_icon] = pb->scale_simple(16, 16, Gdk::INTERP_BILINEAR); + } + }); return true; }; - auto add_role = [this](const std::string &name) { - auto *role_row = Gtk::manage(new Gtk::ListBoxRow); - auto *role_lbl = Gtk::manage(new Gtk::Label); - - role_row->get_style_context()->add_class("members-row"); - role_row->get_style_context()->add_class("members-row-role"); - role_lbl->get_style_context()->add_class("members-row-label"); - - role_lbl->set_single_line_mode(true); - role_lbl->set_ellipsize(Pango::ELLIPSIZE_END); - role_lbl->set_use_markup(true); - role_lbl->set_markup("" + Glib::Markup::escape_text(name) + ""); - role_lbl->set_halign(Gtk::ALIGN_START); - role_row->add(*role_lbl); - role_row->show_all(); - m_listbox->add(*role_row); + auto add_role = [this](const RoleData &role) -> Gtk::TreeRow { + auto row = *m_model->append(); + row[m_columns.m_type] = MemberListRenderType::Role; + row[m_columns.m_id] = role.ID; + row[m_columns.m_markup] = "" + role.GetEscapedName() + ""; + row[m_columns.m_sort] = role.Position; + return row; }; - for (auto it = pos_to_role.crbegin(); it != pos_to_role.crend(); it++) { - auto pos = it->first; - const auto &role = it->second; - - add_role(role.Name); - - if (pos_to_users.find(pos) == pos_to_users.end()) continue; - - auto &users = pos_to_users.at(pos); - AlphabeticalSort(users.begin(), users.end(), [](const auto &e) { return e.Username; }); - - for (const auto &data : users) - if (!add_user(data)) return; - } - - if (chan->Type == ChannelType::DM || chan->Type == ChannelType::GROUP_DM) - add_role("Users"); - else - add_role("@everyone"); - for (const auto &id : roleless_users) { - const auto user = discord.GetUser(id); - if (user.has_value()) - if (!add_user(*user)) return; - } -} - -void MemberList::AttachUserMenuHandler(Gtk::ListBoxRow *row, Snowflake id) { - row->signal_button_press_event().connect([this, id](GdkEventButton *e) -> bool { - if (e->type == GDK_BUTTON_PRESS && e->button == GDK_BUTTON_SECONDARY) { - Abaddon::Get().ShowUserMenu(reinterpret_cast(e), id, m_guild_id); - return true; + for (auto &[pos, role] : pos_to_role) { + auto role_children = add_role(role).children(); + if (auto it = pos_to_users.find(pos); it != pos_to_users.end()) { + for (const auto &user : it->second) { + if (!add_user(user, role_children)) break; + } } + } - return false; - }); + m_view.expand_all(); +} + +MemberList::ModelColumns::ModelColumns() { + add(m_type); + add(m_id); + add(m_markup); + add(m_icon); + add(m_sort); } diff --git a/src/components/memberlist.hpp b/src/components/memberlist.hpp index 60a25bc..ecd19a6 100644 --- a/src/components/memberlist.hpp +++ b/src/components/memberlist.hpp @@ -1,44 +1,37 @@ #pragma once -#include -#include -#include -#include -#include "discord/discord.hpp" +#include +#include +#include +#include +#include +#include "discord/snowflake.hpp" +#include "memberlistcellrenderer.hpp" -class LazyImage; -class StatusIndicator; -class MemberListUserRow : public Gtk::ListBoxRow { -public: - MemberListUserRow(const std::optional &guild, const UserData &data); - - Snowflake ID; - -private: - Gtk::EventBox *m_ev; - Gtk::Box *m_box; - LazyImage *m_avatar; - StatusIndicator *m_status_indicator; - Gtk::Label *m_label; - Gtk::Image *m_crown = nullptr; -}; - -class MemberList { +class MemberList : public Gtk::ScrolledWindow { public: MemberList(); - Gtk::Widget *GetRoot() const; void UpdateMemberList(); void Clear(); void SetActiveChannel(Snowflake id); private: - void AttachUserMenuHandler(Gtk::ListBoxRow *row, Snowflake id); + class ModelColumns : public Gtk::TreeModel::ColumnRecord { + public: + ModelColumns(); - Gtk::ScrolledWindow *m_main; - Gtk::ListBox *m_listbox; + Gtk::TreeModelColumn m_type; + Gtk::TreeModelColumn m_id; + Gtk::TreeModelColumn m_markup; + Gtk::TreeModelColumn> m_icon; + + Gtk::TreeModelColumn m_sort; + }; + + ModelColumns m_columns; + Glib::RefPtr m_model; + Gtk::TreeView m_view; Snowflake m_guild_id; Snowflake m_chan_id; - - std::unordered_map m_id_to_row; }; diff --git a/src/components/memberlistcellrenderer.cpp b/src/components/memberlistcellrenderer.cpp new file mode 100644 index 0000000..6c9ff28 --- /dev/null +++ b/src/components/memberlistcellrenderer.cpp @@ -0,0 +1,177 @@ +#include "memberlistcellrenderer.hpp" +#include + +CellRendererMemberList::CellRendererMemberList() + : Glib::ObjectBase(typeid(CellRendererMemberList)) + , m_property_type(*this, "render-type") + , m_property_id(*this, "id") + , m_property_markup(*this, "markup") + , m_property_icon(*this, "pixbuf") { + m_renderer_text.property_ellipsize() = Pango::ELLIPSIZE_END; + m_property_markup.get_proxy().signal_changed().connect([this]() { + m_renderer_text.property_markup() = m_property_markup; + }); +} + +Glib::PropertyProxy CellRendererMemberList::property_type() { + return m_property_type.get_proxy(); +} + +Glib::PropertyProxy CellRendererMemberList::property_id() { + return m_property_id.get_proxy(); +} + +Glib::PropertyProxy CellRendererMemberList::property_markup() { + return m_property_markup.get_proxy(); +} + +Glib::PropertyProxy> CellRendererMemberList::property_icon() { + return m_property_icon.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::Member: + return get_preferred_width_vfunc_member(widget, minimum_width, natural_width); + case MemberListRenderType::Role: + return get_preferred_width_vfunc_role(widget, minimum_width, natural_width); + } +} + +void CellRendererMemberList::get_preferred_width_for_height_vfunc(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const { + switch (m_property_type.get_value()) { + case MemberListRenderType::Member: + return get_preferred_width_for_height_vfunc_member(widget, height, minimum_width, natural_width); + case MemberListRenderType::Role: + return get_preferred_width_for_height_vfunc_role(widget, height, minimum_width, natural_width); + } +} + +void CellRendererMemberList::get_preferred_height_vfunc(Gtk::Widget &widget, int &minimum_height, int &natural_height) const { + switch (m_property_type.get_value()) { + case MemberListRenderType::Member: + return get_preferred_height_vfunc_member(widget, minimum_height, natural_height); + case MemberListRenderType::Role: + return get_preferred_height_vfunc_role(widget, minimum_height, natural_height); + } +} + +void CellRendererMemberList::get_preferred_height_for_width_vfunc(Gtk::Widget &widget, int width, int &minimum_height, int &natural_height) const { + switch (m_property_type.get_value()) { + case MemberListRenderType::Member: + return get_preferred_height_for_width_vfunc_member(widget, width, minimum_height, natural_height); + case MemberListRenderType::Role: + return get_preferred_height_for_width_vfunc_role(widget, width, minimum_height, natural_height); + } +} + +void CellRendererMemberList::render_vfunc(const Cairo::RefPtr &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area, Gtk::CellRendererState flags) { + switch (m_property_type.get_value()) { + case MemberListRenderType::Member: + return render_vfunc_member(cr, widget, background_area, cell_area, flags); + case MemberListRenderType::Role: + return render_vfunc_role(cr, widget, background_area, cell_area, flags); + } +} + +void CellRendererMemberList::get_preferred_width_vfunc_role(Gtk::Widget &widget, int &minimum_width, int &natural_width) const { + int text_min, text_nat; + m_renderer_text.get_preferred_width(widget, text_min, text_nat); + int xpad, ypad; + get_padding(xpad, ypad); + minimum_width = text_min + xpad * 2; + natural_width = text_nat + xpad * 2; +} + +void CellRendererMemberList::get_preferred_width_for_height_vfunc_role(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const { + get_preferred_width_vfunc_role(widget, minimum_width, natural_width); +} + +void CellRendererMemberList::get_preferred_height_vfunc_role(Gtk::Widget &widget, int &minimum_height, int &natural_height) const { + int text_min, text_nat; + m_renderer_text.get_preferred_height(widget, text_min, text_nat); + int xpad, ypad; + get_padding(xpad, ypad); + minimum_height = text_min + ypad * 2; + natural_height = text_nat + ypad * 2; +} + +void CellRendererMemberList::get_preferred_height_for_width_vfunc_role(Gtk::Widget &widget, int width, int &minimum_height, int &natural_height) const { + get_preferred_height_vfunc_role(widget, minimum_height, natural_height); +} + +void CellRendererMemberList::render_vfunc_role(const Cairo::RefPtr &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area, Gtk::CellRendererState flags) { + Gtk::Requisition text_min, text_nat, min, nat; + m_renderer_text.get_preferred_size(widget, text_min, text_nat); + get_preferred_size(widget, min, nat); + + int x = background_area.get_x() + 5; + int y = background_area.get_y() + background_area.get_height() / 2.0 - text_nat.height / 2.0; + int w = text_nat.width; + int h = text_nat.height; + + Gdk::Rectangle text_cell_area(x, y, w, h); + m_renderer_text.render(cr, widget, background_area, text_cell_area, flags); +} + +void CellRendererMemberList::get_preferred_width_vfunc_member(Gtk::Widget &widget, int &minimum_width, int &natural_width) const { + int text_min, text_nat; + m_renderer_text.get_preferred_width(widget, text_min, text_nat); + int xpad, ypad; + get_padding(xpad, ypad); + minimum_width = text_min + xpad * 2; + natural_width = text_nat + xpad * 2; +} + +void CellRendererMemberList::get_preferred_width_for_height_vfunc_member(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const { + get_preferred_width_vfunc_role(widget, minimum_width, natural_width); +} + +void CellRendererMemberList::get_preferred_height_vfunc_member(Gtk::Widget &widget, int &minimum_height, int &natural_height) const { + int text_min, text_nat; + m_renderer_text.get_preferred_height(widget, text_min, text_nat); + int xpad, ypad; + get_padding(xpad, ypad); + minimum_height = text_min + ypad * 2; + natural_height = text_nat + ypad * 2; +} + +void CellRendererMemberList::get_preferred_height_for_width_vfunc_member(Gtk::Widget &widget, int width, int &minimum_height, int &natural_height) const { + get_preferred_height_vfunc_role(widget, minimum_height, natural_height); +} + +void CellRendererMemberList::render_vfunc_member(const Cairo::RefPtr &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area, Gtk::CellRendererState flags) { + Gtk::Requisition text_min, text_nat, min, nat; + m_renderer_text.get_preferred_size(widget, text_min, text_nat); + get_preferred_size(widget, min, nat); + + int pixbuf_w = 0, pixbuf_h = 0; + if (auto pixbuf = m_property_icon.get_value()) { + pixbuf_w = pixbuf->get_width(); + pixbuf_h = pixbuf->get_height(); + } + + const double icon_w = pixbuf_w; + const double icon_h = pixbuf_h; + const double icon_x = background_area.get_x() + 3.0; + const double icon_y = background_area.get_y() + background_area.get_height() / 2.0 - icon_h / 2.0; + + const double x = icon_x + icon_w + 5; + const double y = background_area.get_y() + background_area.get_height() / 2.0 - text_nat.height / 2.0; + const double w = text_nat.width; + const double h = text_nat.height; + + if (auto pixbuf = m_property_icon.get_value()) { + Gdk::Cairo::set_source_pixbuf(cr, pixbuf, icon_x, icon_y); + cr->rectangle(icon_x, icon_y, icon_w, icon_h); + cr->fill(); + } + + Gdk::Rectangle text_cell_area( + static_cast(x), + static_cast(y), + static_cast(w), + static_cast(h)); + + m_renderer_text.render(cr, widget, background_area, text_cell_area, flags); +} diff --git a/src/components/memberlistcellrenderer.hpp b/src/components/memberlistcellrenderer.hpp new file mode 100644 index 0000000..25d1cc7 --- /dev/null +++ b/src/components/memberlistcellrenderer.hpp @@ -0,0 +1,60 @@ +#pragma once +#include +#include +#include + +enum class MemberListRenderType { + Role, + Member, +}; + +class CellRendererMemberList : public Gtk::CellRenderer { +public: + CellRendererMemberList(); + ~CellRendererMemberList() = default; + + Glib::PropertyProxy property_type(); + Glib::PropertyProxy property_id(); + Glib::PropertyProxy property_markup(); + Glib::PropertyProxy> property_icon(); + +private: + 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 &cr, + Gtk::Widget &widget, + const Gdk::Rectangle &background_area, + const Gdk::Rectangle &cell_area, + Gtk::CellRendererState flags) override; + + // role + void get_preferred_width_vfunc_role(Gtk::Widget &widget, int &minimum_width, int &natural_width) const; + void get_preferred_width_for_height_vfunc_role(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const; + void get_preferred_height_vfunc_role(Gtk::Widget &widget, int &minimum_height, int &natural_height) const; + void get_preferred_height_for_width_vfunc_role(Gtk::Widget &widget, int width, int &minimum_height, int &natural_height) const; + void render_vfunc_role(const Cairo::RefPtr &cr, + Gtk::Widget &widget, + const Gdk::Rectangle &background_area, + const Gdk::Rectangle &cell_area, + Gtk::CellRendererState flags); + + // member + void get_preferred_width_vfunc_member(Gtk::Widget &widget, int &minimum_width, int &natural_width) const; + void get_preferred_width_for_height_vfunc_member(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const; + void get_preferred_height_vfunc_member(Gtk::Widget &widget, int &minimum_height, int &natural_height) const; + void get_preferred_height_for_width_vfunc_member(Gtk::Widget &widget, int width, int &minimum_height, int &natural_height) const; + void render_vfunc_member(const Cairo::RefPtr &cr, + Gtk::Widget &widget, + const Gdk::Rectangle &background_area, + const Gdk::Rectangle &cell_area, + Gtk::CellRendererState flags); + + Gtk::CellRendererText m_renderer_text; + + Glib::Property m_property_type; + Glib::Property m_property_id; + Glib::Property m_property_markup; + Glib::Property> m_property_icon; +}; diff --git a/src/windows/mainwindow.cpp b/src/windows/mainwindow.cpp index 7f4395c..446089a 100644 --- a/src/windows/mainwindow.cpp +++ b/src/windows/mainwindow.cpp @@ -1,6 +1,8 @@ #include "mainwindow.hpp" #include "abaddon.hpp" +#include "components/memberlist.hpp" // TMP!!!! + MainWindow::MainWindow() : m_main_box(Gtk::ORIENTATION_VERTICAL) , m_content_box(Gtk::ORIENTATION_HORIZONTAL) @@ -20,7 +22,6 @@ MainWindow::MainWindow() m_main_box.add(m_content_box); m_main_box.show(); - auto *member_list = m_members.GetRoot(); auto *chat = m_chat.GetRoot(); chat->set_vexpand(true); @@ -37,8 +38,8 @@ MainWindow::MainWindow() m_channel_list.set_size_request(-1, -1); m_channel_list.show(); - member_list->set_vexpand(true); - member_list->show(); + m_members.set_vexpand(true); + m_members.show(); m_friends.set_vexpand(true); m_friends.set_hexpand(true); @@ -63,11 +64,11 @@ MainWindow::MainWindow() m_channel_list.UsePanedHack(m_chan_content_paned); m_content_members_paned.pack1(m_content_stack); - m_content_members_paned.pack2(*member_list); + m_content_members_paned.pack2(m_members); m_content_members_paned.child_property_shrink(m_content_stack) = true; m_content_members_paned.child_property_resize(m_content_stack) = true; - m_content_members_paned.child_property_shrink(*member_list) = true; - m_content_members_paned.child_property_resize(*member_list) = true; + m_content_members_paned.child_property_shrink(m_members) = true; + m_content_members_paned.child_property_resize(m_members) = true; int w, h; get_default_size(w, h); // :s m_content_members_paned.set_position(w - m_chan_content_paned.get_position() - 150); diff --git a/src/windows/mainwindow.hpp b/src/windows/mainwindow.hpp index 534df1b..858a513 100644 --- a/src/windows/mainwindow.hpp +++ b/src/windows/mainwindow.hpp @@ -1,8 +1,8 @@ #pragma once #include "components/channels.hpp" #include "components/chatwindow.hpp" -#include "components/memberlist.hpp" #include "components/friendslist.hpp" +#include "components/memberlist.hpp" #include class MainWindow : public Gtk::Window {