LibGUI: Add Model::Role::TextAlignment and remove from ColumnMetadata

This commit is contained in:
Andreas Kling 2020-05-21 19:36:09 +02:00
parent 3c819b8ff4
commit 2e03bded43
Notes: sideshowbarker 2024-07-19 06:16:42 +09:00
19 changed files with 211 additions and 100 deletions

View file

@ -35,7 +35,7 @@ class ItemListModel final : public GUI::Model {
public:
static NonnullRefPtr<ItemListModel> create(Vector<T>& data) { return adopt(*new ItemListModel<T>(data)); }
virtual ~ItemListModel() override {}
virtual ~ItemListModel() override { }
virtual int row_count(const GUI::ModelIndex&) const override
{
@ -54,11 +54,13 @@ public:
virtual ColumnMetadata column_metadata(int) const override
{
return { 70, Gfx::TextAlignment::CenterLeft };
return { 70 };
}
virtual GUI::Variant data(const GUI::ModelIndex& index, Role role = Role::Display) const override
{
if (role == Role::TextAlignment)
return Gfx::TextAlignment::CenterLeft;
if (role == Role::Display)
return m_data.at(index.row());

View file

@ -61,13 +61,15 @@ GUI::Model::ColumnMetadata IRCChannelMemberListModel::column_metadata(int column
{
switch (column) {
case Column::Name:
return { 70, Gfx::TextAlignment::CenterLeft };
return { 70 };
}
ASSERT_NOT_REACHED();
}
GUI::Variant IRCChannelMemberListModel::data(const GUI::ModelIndex& index, Role role) const
{
if (role == Role::TextAlignment)
return Gfx::TextAlignment::CenterLeft;
if (role == Role::Display) {
switch (index.column()) {
case Column::Name:

View file

@ -63,13 +63,15 @@ GUI::Model::ColumnMetadata IRCWindowListModel::column_metadata(int column) const
{
switch (column) {
case Column::Name:
return { 70, Gfx::TextAlignment::CenterLeft };
return { 70 };
}
ASSERT_NOT_REACHED();
}
GUI::Variant IRCWindowListModel::data(const GUI::ModelIndex& index, Role role) const
{
if (role == Role::TextAlignment)
return Gfx::TextAlignment::CenterLeft;
if (role == Role::Display) {
switch (index.column()) {
case Column::Name: {

View file

@ -77,46 +77,66 @@ GUI::Model::ColumnMetadata DevicesModel::column_metadata(int column) const
{
switch (column) {
case Column::Device:
return { 70, Gfx::TextAlignment::CenterLeft };
return { 70 };
case Column::Major:
return { 32, Gfx::TextAlignment::CenterRight };
return { 32 };
case Column::Minor:
return { 32, Gfx::TextAlignment::CenterRight };
return { 32 };
case Column::ClassName:
return { 120, Gfx::TextAlignment::CenterLeft };
return { 120 };
case Column::Type:
return { 120, Gfx::TextAlignment::CenterLeft };
return { 120 };
default:
ASSERT_NOT_REACHED();
}
}
GUI::Variant DevicesModel::data(const GUI::ModelIndex& index, Role) const
GUI::Variant DevicesModel::data(const GUI::ModelIndex& index, Role role) const
{
ASSERT(is_valid(index));
const DeviceInfo& device = m_devices[index.row()];
switch (index.column()) {
case Column::Device:
return device.path;
case Column::Major:
return device.major;
case Column::Minor:
return device.minor;
case Column::ClassName:
return device.class_name;
case Column::Type:
switch (device.type) {
case DeviceInfo::Type::Block:
return "Block";
case DeviceInfo::Type::Character:
return "Character";
if (role == Role::TextAlignment) {
switch (index.column()) {
case Column::Device:
return Gfx::TextAlignment::CenterLeft;
case Column::Major:
return Gfx::TextAlignment::CenterRight;
case Column::Minor:
return Gfx::TextAlignment::CenterRight;
case Column::ClassName:
return Gfx::TextAlignment::CenterLeft;
case Column::Type:
return Gfx::TextAlignment::CenterLeft;
}
return {};
}
if (role == Role::Display) {
const DeviceInfo& device = m_devices[index.row()];
switch (index.column()) {
case Column::Device:
return device.path;
case Column::Major:
return device.major;
case Column::Minor:
return device.minor;
case Column::ClassName:
return device.class_name;
case Column::Type:
switch (device.type) {
case DeviceInfo::Type::Block:
return "Block";
case DeviceInfo::Type::Character:
return "Character";
default:
ASSERT_NOT_REACHED();
}
default:
ASSERT_NOT_REACHED();
}
default:
ASSERT_NOT_REACHED();
}
return {};
}
void DevicesModel::update()

View file

@ -132,59 +132,59 @@ GUI::Model::ColumnMetadata ProcessModel::column_metadata(int column) const
{
switch (column) {
case Column::Icon:
return { 16, Gfx::TextAlignment::CenterLeft };
return { 16 };
case Column::PID:
return { 32, Gfx::TextAlignment::CenterRight };
return { 32 };
case Column::TID:
return { 32, Gfx::TextAlignment::CenterRight };
return { 32 };
case Column::State:
return { 75, Gfx::TextAlignment::CenterLeft };
return { 75 };
case Column::Priority:
return { 16, Gfx::TextAlignment::CenterRight };
return { 16 };
case Column::EffectivePriority:
return { 16, Gfx::TextAlignment::CenterRight };
return { 16 };
case Column::User:
return { 50, Gfx::TextAlignment::CenterLeft };
return { 50 };
case Column::Virtual:
return { 65, Gfx::TextAlignment::CenterRight };
return { 65 };
case Column::Physical:
return { 65, Gfx::TextAlignment::CenterRight };
return { 65 };
case Column::DirtyPrivate:
return { 65, Gfx::TextAlignment::CenterRight };
return { 65 };
case Column::CleanInode:
return { 65, Gfx::TextAlignment::CenterRight };
return { 65 };
case Column::PurgeableVolatile:
return { 65, Gfx::TextAlignment::CenterRight };
return { 65 };
case Column::PurgeableNonvolatile:
return { 65, Gfx::TextAlignment::CenterRight };
return { 65 };
case Column::CPU:
return { 32, Gfx::TextAlignment::CenterRight };
return { 32 };
case Column::Name:
return { 140, Gfx::TextAlignment::CenterLeft };
return { 140 };
case Column::Syscalls:
return { 60, Gfx::TextAlignment::CenterRight };
return { 60 };
case Column::InodeFaults:
return { 60, Gfx::TextAlignment::CenterRight };
return { 60 };
case Column::ZeroFaults:
return { 60, Gfx::TextAlignment::CenterRight };
return { 60 };
case Column::CowFaults:
return { 60, Gfx::TextAlignment::CenterRight };
return { 60 };
case Column::FileReadBytes:
return { 60, Gfx::TextAlignment::CenterRight };
return { 60 };
case Column::FileWriteBytes:
return { 60, Gfx::TextAlignment::CenterRight };
return { 60 };
case Column::UnixSocketReadBytes:
return { 60, Gfx::TextAlignment::CenterRight };
return { 60 };
case Column::UnixSocketWriteBytes:
return { 60, Gfx::TextAlignment::CenterRight };
return { 60 };
case Column::IPv4SocketReadBytes:
return { 60, Gfx::TextAlignment::CenterRight };
return { 60 };
case Column::IPv4SocketWriteBytes:
return { 60, Gfx::TextAlignment::CenterRight };
return { 60 };
case Column::Pledge:
return { 60, Gfx::TextAlignment::CenterLeft };
return { 60 };
case Column::Veil:
return { 60, Gfx::TextAlignment::CenterLeft };
return { 60 };
default:
ASSERT_NOT_REACHED();
}
@ -199,6 +199,42 @@ GUI::Variant ProcessModel::data(const GUI::ModelIndex& index, Role role) const
{
ASSERT(is_valid(index));
if (role == Role::TextAlignment) {
switch (index.column()) {
case Column::Icon:
case Column::Name:
case Column::State:
case Column::User:
case Column::Pledge:
case Column::Veil:
return Gfx::TextAlignment::CenterLeft;
case Column::PID:
case Column::TID:
case Column::Priority:
case Column::EffectivePriority:
case Column::Virtual:
case Column::Physical:
case Column::DirtyPrivate:
case Column::CleanInode:
case Column::PurgeableVolatile:
case Column::PurgeableNonvolatile:
case Column::CPU:
case Column::Syscalls:
case Column::InodeFaults:
case Column::ZeroFaults:
case Column::CowFaults:
case Column::FileReadBytes:
case Column::FileWriteBytes:
case Column::UnixSocketReadBytes:
case Column::UnixSocketWriteBytes:
case Column::IPv4SocketReadBytes:
case Column::IPv4SocketWriteBytes:
return Gfx::TextAlignment::CenterRight;
default:
ASSERT_NOT_REACHED();
}
}
auto it = m_threads.find(m_pids[index.row()]);
auto& thread = *(*it).value;

View file

@ -75,6 +75,8 @@ public:
virtual GUI::Variant data(const GUI::ModelIndex& index, Role role = Role::Display) const override
{
if (role == Role::TextAlignment)
return Gfx::TextAlignment::CenterLeft;
if (role == Role::Font) {
if (index.column() == Column::MatchedText)
return Gfx::Font::default_fixed_width_font();
@ -94,14 +96,6 @@ public:
return {};
}
virtual ColumnMetadata column_metadata(int column) const override
{
if (column == Column::MatchedText) {
return { 0, Gfx::TextAlignment::CenterLeft };
}
return {};
}
virtual void update() override { }
virtual GUI::ModelIndex index(int row, int column = 0, const GUI::ModelIndex& = GUI::ModelIndex()) const override { return create_index(row, column, &m_matches.at(row)); }

View file

@ -138,13 +138,6 @@ String DisassemblyModel::column_name(int column) const
}
}
GUI::Model::ColumnMetadata DisassemblyModel::column_metadata(int column) const
{
if (column == Column::SampleCount)
return ColumnMetadata { 0, Gfx::TextAlignment::CenterRight };
return {};
}
struct ColorPair {
Color background;
Color foreground;

View file

@ -61,7 +61,6 @@ public:
virtual int row_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override;
virtual int column_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override { return Column::__Count; }
virtual String column_name(int) const override;
virtual ColumnMetadata column_metadata(int) const override;
virtual GUI::Variant data(const GUI::ModelIndex&, Role = Role::Display) const override;
virtual void update() override;

View file

@ -108,16 +108,13 @@ String ProfileModel::column_name(int column) const
}
}
GUI::Model::ColumnMetadata ProfileModel::column_metadata(int column) const
{
if (column == Column::SampleCount || column == Column::SelfCount)
return ColumnMetadata { 0, Gfx::TextAlignment::CenterRight };
return {};
}
GUI::Variant ProfileModel::data(const GUI::ModelIndex& index, Role role) const
{
auto* node = static_cast<ProfileNode*>(index.internal_data());
if (role == Role::TextAlignment) {
if (index.column() == Column::SampleCount || index.column() == Column::SelfCount)
return Gfx::TextAlignment::CenterRight;
}
if (role == Role::Icon) {
if (index.column() == Column::StackFrame) {
if (node->address() >= 0xc0000000)

View file

@ -50,7 +50,6 @@ public:
virtual int row_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override;
virtual int column_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override;
virtual String column_name(int) const override;
virtual ColumnMetadata column_metadata(int) const override;
virtual GUI::Variant data(const GUI::ModelIndex&, Role = Role::Display) const override;
virtual GUI::ModelIndex index(int row, int column, const GUI::ModelIndex& parent = GUI::ModelIndex()) const override;
virtual GUI::ModelIndex parent_index(const GUI::ModelIndex&) const override;

View file

@ -61,12 +61,15 @@ GUI::Model::ColumnMetadata VBWidgetPropertyModel::column_metadata(int column) co
{
UNUSED_PARAM(column);
if (column == Column::Name)
return { 110, Gfx::TextAlignment::CenterLeft };
return { 90, Gfx::TextAlignment::CenterLeft };
return { 110 };
return { 90 };
}
GUI::Variant VBWidgetPropertyModel::data(const GUI::ModelIndex& index, Role role) const
{
if (role == Role::TextAlignment) {
return Gfx::TextAlignment::CenterLeft;
}
if (role == Role::Font) {
if (index.column() == Column::Name)
return Gfx::Font::default_bold_font();

View file

@ -345,6 +345,26 @@ ModelIndex FileSystemModel::parent_index(const ModelIndex& index) const
Variant FileSystemModel::data(const ModelIndex& index, Role role) const
{
ASSERT(index.is_valid());
if (role == Role::TextAlignment) {
switch (index.column()) {
case Column::Icon:
return Gfx::TextAlignment::Center;
case Column::Size:
case Column::Inode:
return Gfx::TextAlignment::CenterRight;
case Column::Name:
case Column::Owner:
case Column::Group:
case Column::ModificationTime:
case Column::Permissions:
case Column::SymlinkTarget:
return Gfx::TextAlignment::CenterLeft;
default:
ASSERT_NOT_REACHED();
}
}
auto& node = this->node(index);
if (role == Role::Custom) {
@ -552,23 +572,23 @@ Model::ColumnMetadata FileSystemModel::column_metadata(int column) const
{
switch (column) {
case Column::Icon:
return { 16, Gfx::TextAlignment::Center, Model::ColumnMetadata::Sortable::False };
return { 16, Model::ColumnMetadata::Sortable::False };
case Column::Name:
return { 120, Gfx::TextAlignment::CenterLeft };
return { 120 };
case Column::Size:
return { 80, Gfx::TextAlignment::CenterRight };
return { 80 };
case Column::Owner:
return { 50, Gfx::TextAlignment::CenterLeft };
return { 50 };
case Column::Group:
return { 50, Gfx::TextAlignment::CenterLeft };
return { 50 };
case Column::ModificationTime:
return { 110, Gfx::TextAlignment::CenterLeft };
return { 110 };
case Column::Permissions:
return { 65, Gfx::TextAlignment::CenterLeft };
return { 65 };
case Column::Inode:
return { 60, Gfx::TextAlignment::CenterRight };
return { 60 };
case Column::SymlinkTarget:
return { 120, Gfx::TextAlignment::CenterLeft };
return { 120 };
}
ASSERT_NOT_REACHED();
}

View file

@ -94,7 +94,7 @@ bool JsonArrayModel::remove(int row)
Model::ColumnMetadata JsonArrayModel::column_metadata(int column) const
{
ASSERT(column < static_cast<int>(m_fields.size()));
return { 100, m_fields[column].text_alignment };
return { 100 };
}
Variant JsonArrayModel::data(const ModelIndex& index, Role role) const
@ -102,6 +102,10 @@ Variant JsonArrayModel::data(const ModelIndex& index, Role role) const
auto& field_spec = m_fields[index.column()];
auto& object = m_array.at(index.row()).as_object();
if (role == Model::Role::TextAlignment) {
return field_spec.text_alignment;
}
if (role == Model::Role::Display) {
auto& json_field_name = field_spec.json_field_name;
auto data = object.get(json_field_name);

View file

@ -143,8 +143,6 @@ void ListView::paint_event(PaintEvent& event)
}
}
auto column_metadata = model()->column_metadata(m_model_column);
Gfx::Rect row_rect(0, y, content_width(), item_height());
painter.fill_rect(row_rect, background_color);
auto index = model()->index(row_index, m_model_column);
@ -164,7 +162,8 @@ void ListView::paint_event(PaintEvent& event)
auto text_rect = row_rect;
text_rect.move_by(horizontal_padding(), 0);
text_rect.set_width(text_rect.width() - horizontal_padding() * 2);
painter.draw_text(text_rect, data.to_string(), font, column_metadata.text_alignment, text_color);
auto text_alignment = model()->data(index, Model::Role::TextAlignment).to_text_alignment(Gfx::TextAlignment::Center);
painter.draw_text(text_rect, data.to_string(), font, text_alignment, text_color);
}
++painted_item_index;

View file

@ -48,7 +48,6 @@ class Model : public RefCounted<Model> {
public:
struct ColumnMetadata {
int preferred_width { 0 };
Gfx::TextAlignment text_alignment { Gfx::TextAlignment::CenterLeft };
enum class Sortable {
False,
True,
@ -70,6 +69,7 @@ public:
Icon,
Font,
DragData,
TextAlignment,
};
virtual ~Model();

View file

@ -103,7 +103,6 @@ void TableView::paint_event(PaintEvent& event)
for (int column_index = 0; column_index < model()->column_count(); ++column_index) {
if (is_column_hidden(column_index))
continue;
auto column_metadata = model()->column_metadata(column_index);
int column_width = this->column_width(column_index);
bool is_key_column = model()->key_column() == column_index;
Gfx::Rect cell_rect(horizontal_padding() + x_offset, y, column_width, item_height());
@ -136,7 +135,8 @@ void TableView::paint_event(PaintEvent& event)
if (cell_background_color.is_valid())
painter.fill_rect(cell_rect_for_fill, cell_background_color.to_color(background_color));
}
painter.draw_text(cell_rect, data.to_string(), font_for_index(cell_index), column_metadata.text_alignment, text_color, Gfx::TextElision::Right);
auto text_alignment = model()->data(cell_index, Model::Role::TextAlignment).to_text_alignment(Gfx::TextAlignment::Center);
painter.draw_text(cell_rect, data.to_string(), font_for_index(cell_index), text_alignment, text_color, Gfx::TextElision::Right);
}
}
x_offset += column_width + horizontal_padding() * 2;

View file

@ -273,7 +273,6 @@ void TreeView::paint_event(PaintEvent& event)
for (int column_index = 0; column_index < model.column_count(); ++column_index) {
if (is_column_hidden(column_index))
continue;
auto column_metadata = model.column_metadata(column_index);
int column_width = this->column_width(column_index);
painter.draw_rect(toggle_rect, text_color);
@ -295,7 +294,8 @@ void TreeView::paint_event(PaintEvent& event)
} else {
if (!is_selected_row)
text_color = model.data(cell_index, Model::Role::ForegroundColor).to_color(palette().color(foreground_role()));
painter.draw_text(cell_rect, data.to_string(), font_for_index(cell_index), column_metadata.text_alignment, text_color, Gfx::TextElision::Right);
auto text_alignment = model.data(cell_index, Model::Role::TextAlignment).to_text_alignment(Gfx::TextAlignment::Center);
painter.draw_text(cell_rect, data.to_string(), font_for_index(cell_index), text_alignment, text_color, Gfx::TextElision::Right);
}
}
} else {

View file

@ -61,6 +61,8 @@ const char* to_string(Variant::Type type)
return "Rect";
case Variant::Type::Font:
return "Font";
case Variant::Type::TextAlignment:
return "TextAlignment";
}
ASSERT_NOT_REACHED();
}
@ -94,6 +96,12 @@ void Variant::clear()
m_value.as_string = nullptr;
}
Variant::Variant(Gfx::TextAlignment value)
: m_type(Type::TextAlignment)
{
m_value.as_text_alignment = value;
}
Variant::Variant(i32 value)
: m_type(Type::Int32)
{
@ -307,6 +315,9 @@ void Variant::copy_from(const Variant& other)
case Type::Rect:
m_value.as_rect = other.m_value.as_rect;
break;
case Type::TextAlignment:
m_value.as_text_alignment = other.m_value.as_text_alignment;
break;
case Type::Invalid:
break;
}
@ -343,6 +354,8 @@ bool Variant::operator==(const Variant& other) const
return as_rect() == other.as_rect();
case Type::Font:
return &as_font() == &other.as_font();
case Type::TextAlignment:
return m_value.as_text_alignment == other.m_value.as_text_alignment;
case Type::Invalid:
return true;
}
@ -378,6 +391,7 @@ bool Variant::operator<(const Variant& other) const
case Type::Size:
case Type::Rect:
case Type::Font:
case Type::TextAlignment:
// FIXME: Figure out how to compare these.
ASSERT_NOT_REACHED();
case Type::Invalid:
@ -415,9 +429,25 @@ String Variant::to_string() const
return as_rect().to_string();
case Type::Font:
return String::format("[Font: %s]", as_font().name().characters());
case Type::TextAlignment: {
switch (m_value.as_text_alignment) {
case Gfx::TextAlignment::Center:
return "Gfx::TextAlignment::Center";
case Gfx::TextAlignment::CenterLeft:
return "Gfx::TextAlignment::CenterLeft";
case Gfx::TextAlignment::CenterRight:
return "Gfx::TextAlignment::CenterRight";
case Gfx::TextAlignment::TopLeft:
return "Gfx::TextAlignment::TopLeft";
case Gfx::TextAlignment::TopRight:
return "Gfx::TextAlignment::TopRight";
default:
ASSERT_NOT_REACHED();
}
return "";
}
case Type::Invalid:
return "[null]";
break;
}
ASSERT_NOT_REACHED();
}

View file

@ -50,6 +50,7 @@ public:
Variant(const Gfx::Size&);
Variant(const Gfx::Rect&);
Variant(const Gfx::Font&);
Variant(const Gfx::TextAlignment);
Variant(const AK::JsonValue&);
Variant(Color);
@ -77,6 +78,7 @@ public:
Size,
Rect,
Font,
TextAlignment,
};
bool is_valid() const { return m_type != Type::Invalid; }
@ -93,6 +95,7 @@ public:
bool is_size() const { return m_type == Type::Size; }
bool is_rect() const { return m_type == Type::Rect; }
bool is_font() const { return m_type == Type::Font; }
bool is_text_alignment() const { return m_type == Type::TextAlignment; }
Type type() const { return m_type; }
bool as_bool() const
@ -226,6 +229,13 @@ public:
return *m_value.as_font;
}
Gfx::TextAlignment to_text_alignment(Gfx::TextAlignment default_value) const
{
if (type() != Type::TextAlignment)
return default_value;
return m_value.as_text_alignment;
}
Color to_color(Color default_value = {}) const
{
if (type() == Type::Color)
@ -272,6 +282,7 @@ private:
unsigned as_uint;
float as_float;
Gfx::RGBA32 as_color;
Gfx::TextAlignment as_text_alignment;
RawPoint as_point;
RawSize as_size;
RawRect as_rect;