Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite member list (for real this time) #220

Merged
merged 13 commits into from
Oct 3, 2023
7 changes: 1 addition & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,7 @@ spam filter's wrath:
| `.embed-field-title` | The title of an embed field |
| `.embed-field-value` | The value of an embed field |
| `.embed-footer` | The footer of an embed |
| `.members` | Container of the member list |
| `.members-row` | All rows within the members container |
| `.members-row-label` | All labels in the members container |
| `.members-row-member` | Rows containing a member |
| `.members-row-role` | Rows containing a role |
| `.members-row-avatar` | Contains the avatar for a row in the member list |
| `.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 |
Expand Down
140 changes: 140 additions & 0 deletions src/components/cellrenderermemberlist.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#include "cellrenderermemberlist.hpp"

CellRendererMemberList::CellRendererMemberList()
: Glib::ObjectBase(typeid(CellRendererMemberList))
, m_property_type(*this, "render-type")
, m_property_id(*this, "id")
, m_property_name(*this, "name")
, m_property_pixbuf(*this, "pixbuf")
, m_property_color(*this, "color") {
property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE;
property_xpad() = 2;
property_ypad() = 2;
m_property_name.get_proxy().signal_changed().connect([this]() {
m_renderer_text.property_markup() = m_property_name;
});
}

Glib::PropertyProxy<MemberListRenderType> CellRendererMemberList::property_type() {
return m_property_type.get_proxy();
}

Glib::PropertyProxy<uint64_t> CellRendererMemberList::property_id() {
return m_property_id.get_proxy();
}

Glib::PropertyProxy<Glib::ustring> CellRendererMemberList::property_name() {
return m_property_name.get_proxy();
}

Glib::PropertyProxy<Glib::RefPtr<Gdk::Pixbuf>> CellRendererMemberList::property_pixbuf() {
return m_property_pixbuf.get_proxy();
}

Glib::PropertyProxy<Gdk::RGBA> CellRendererMemberList::property_color() {
return m_property_color.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:
return get_preferred_width_vfunc_role(widget, minimum_width, natural_width);
case MemberListRenderType::Member:
return get_preferred_width_vfunc_member(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::Role:
return get_preferred_width_for_height_vfunc_role(widget, height, minimum_width, natural_width);
case MemberListRenderType::Member:
return get_preferred_width_for_height_vfunc_member(widget, height, minimum_width, natural_width);
}
}

void CellRendererMemberList::get_preferred_height_vfunc(Gtk::Widget &widget, int &minimum_width, int &natural_width) const {
switch (m_property_type.get_value()) {
case MemberListRenderType::Role:
return get_preferred_height_vfunc_role(widget, minimum_width, natural_width);
case MemberListRenderType::Member:
return get_preferred_height_vfunc_member(widget, minimum_width, natural_width);
}
}

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::Role:
return get_preferred_height_for_width_vfunc_role(widget, width, minimum_height, natural_height);
case MemberListRenderType::Member:
return get_preferred_height_for_width_vfunc_member(widget, width, minimum_height, natural_height);
}
}

void CellRendererMemberList::render_vfunc(const Cairo::RefPtr<Cairo::Context> &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::Role:
return render_vfunc_role(cr, widget, background_area, cell_area, flags);
case MemberListRenderType::Member:
return render_vfunc_member(cr, widget, background_area, cell_area, flags);
}
}

void CellRendererMemberList::get_preferred_width_vfunc_role(Gtk::Widget &widget, int &minimum_width, int &natural_width) const {
m_renderer_text.get_preferred_width(widget, minimum_width, natural_width);
}

void CellRendererMemberList::get_preferred_width_for_height_vfunc_role(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const {
m_renderer_text.get_preferred_width_for_height(widget, height, minimum_width, natural_width);
}

void CellRendererMemberList::get_preferred_height_vfunc_role(Gtk::Widget &widget, int &minimum_height, int &natural_height) const {
m_renderer_text.get_preferred_height(widget, minimum_height, natural_height);
}

void CellRendererMemberList::get_preferred_height_for_width_vfunc_role(Gtk::Widget &widget, int width, int &minimum_height, int &natural_height) const {
m_renderer_text.get_preferred_height_for_width(widget, width, minimum_height, natural_height);
}

void CellRendererMemberList::render_vfunc_role(const Cairo::RefPtr<Cairo::Context> &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area, Gtk::CellRendererState flags) {
m_renderer_text.render(cr, widget, background_area, cell_area, flags);
}

void CellRendererMemberList::get_preferred_width_vfunc_member(Gtk::Widget &widget, int &minimum_width, int &natural_width) const {
m_renderer_text.get_preferred_width(widget, minimum_width, natural_width);
}

void CellRendererMemberList::get_preferred_width_for_height_vfunc_member(Gtk::Widget &widget, int height, int &minimum_width, int &natural_width) const {
m_renderer_text.get_preferred_width_for_height(widget, height, minimum_width, natural_width);
}

void CellRendererMemberList::get_preferred_height_vfunc_member(Gtk::Widget &widget, int &minimum_height, int &natural_height) const {
m_renderer_text.get_preferred_height(widget, minimum_height, natural_height);
}

void CellRendererMemberList::get_preferred_height_for_width_vfunc_member(Gtk::Widget &widget, int width, int &minimum_height, int &natural_height) const {
m_renderer_text.get_preferred_height_for_width(widget, width, minimum_height, natural_height);
}

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) {
Gdk::Rectangle text_cell_area = cell_area;
text_cell_area.set_x(22);
const auto color = m_property_color.get_value();
if (color.get_alpha_u() > 0) {
m_renderer_text.property_foreground_rgba().set_value(color);
}
m_renderer_text.render(cr, widget, background_area, text_cell_area, flags);
m_renderer_text.property_foreground_set().set_value(false);

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);
cr->rectangle(icon_x, icon_y, 16.0, 16.0);
cr->fill();

m_signal_render.emit(m_property_id.get_value());
}

CellRendererMemberList::type_signal_render CellRendererMemberList::signal_render() {
return m_signal_render;
}
65 changes: 65 additions & 0 deletions src/components/cellrenderermemberlist.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#pragma once
#include <gtkmm/cellrenderer.h>

enum class MemberListRenderType : uint8_t {
Role,
Member,
};

class CellRendererMemberList : public Gtk::CellRenderer {
public:
CellRendererMemberList();
~CellRendererMemberList() override = default;

Glib::PropertyProxy<MemberListRenderType> property_type();
Glib::PropertyProxy<uint64_t> property_id();
Glib::PropertyProxy<Glib::ustring> property_name();
Glib::PropertyProxy<Glib::RefPtr<Gdk::Pixbuf>> property_pixbuf();
Glib::PropertyProxy<Gdk::RGBA> property_color();

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 flags) override;

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<Cairo::Context> &cr,
Gtk::Widget &widget,
const Gdk::Rectangle &background_area,
const Gdk::Rectangle &cell_area,
Gtk::CellRendererState flags);

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<Cairo::Context> &cr,
Gtk::Widget &widget,
const Gdk::Rectangle &background_area,
const Gdk::Rectangle &cell_area,
Gtk::CellRendererState flags);

private:
Gtk::CellRendererText m_renderer_text;

Glib::Property<MemberListRenderType> m_property_type;
Glib::Property<uint64_t> m_property_id;
Glib::Property<Glib::ustring> m_property_name;
Glib::Property<Glib::RefPtr<Gdk::Pixbuf>> m_property_pixbuf;
Glib::Property<Gdk::RGBA> m_property_color;

using type_signal_render = sigc::signal<void(uint64_t)>;
type_signal_render m_signal_render;

public:
type_signal_render signal_render();
};
Loading
Loading