1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:17:36 +00:00

LibGUI: Put all classes in the GUI namespace and remove the leading G

This took me a moment. Welcome to the new world of GUI::Widget! :^)
This commit is contained in:
Andreas Kling 2020-02-02 15:07:41 +01:00
parent 2d39da5405
commit c5bd9d4ed1
337 changed files with 5400 additions and 4816 deletions

View file

@ -30,8 +30,10 @@
#include <LibGUI/GLabel.h>
#include <LibGUI/GWidget.h>
GAboutDialog::GAboutDialog(const StringView& name, const GraphicsBitmap* icon, Core::Object* parent)
: GDialog(parent)
namespace GUI {
AboutDialog::AboutDialog(const StringView& name, const GraphicsBitmap* icon, Core::Object* parent)
: Dialog(parent)
, m_name(name)
, m_icon(icon)
{
@ -39,27 +41,27 @@ GAboutDialog::GAboutDialog(const StringView& name, const GraphicsBitmap* icon, C
set_title(String::format("About %s", m_name.characters()));
set_resizable(false);
auto widget = GWidget::construct();
auto widget = Widget::construct();
set_main_widget(widget);
widget->set_fill_with_background_color(true);
widget->set_layout(make<GHBoxLayout>());
widget->set_layout(make<HBoxLayout>());
auto left_container = GWidget::construct(widget.ptr());
auto left_container = Widget::construct(widget.ptr());
left_container->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill);
left_container->set_preferred_size(48, 0);
left_container->set_layout(make<GVBoxLayout>());
auto icon_label = GLabel::construct(left_container);
left_container->set_layout(make<VBoxLayout>());
auto icon_label = Label::construct(left_container);
icon_label->set_icon(m_icon);
icon_label->set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed);
icon_label->set_preferred_size(40, 40);
left_container->layout()->add_spacer();
auto right_container = GWidget::construct(widget.ptr());
right_container->set_layout(make<GVBoxLayout>());
auto right_container = Widget::construct(widget.ptr());
right_container->set_layout(make<VBoxLayout>());
right_container->layout()->set_margins({ 0, 4, 4, 4 });
auto make_label = [&](const StringView& text, bool bold = false) {
auto label = GLabel::construct(text, right_container);
auto label = Label::construct(text, right_container);
label->set_text_alignment(TextAlignment::CenterLeft);
label->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
label->set_preferred_size(0, 14);
@ -72,19 +74,21 @@ GAboutDialog::GAboutDialog(const StringView& name, const GraphicsBitmap* icon, C
right_container->layout()->add_spacer();
auto button_container = GWidget::construct(right_container.ptr());
auto button_container = Widget::construct(right_container.ptr());
button_container->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
button_container->set_preferred_size(0, 20);
button_container->set_layout(make<GHBoxLayout>());
button_container->set_layout(make<HBoxLayout>());
button_container->layout()->add_spacer();
auto ok_button = GButton::construct("OK", button_container);
auto ok_button = Button::construct("OK", button_container);
ok_button->set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed);
ok_button->set_preferred_size(80, 20);
ok_button->on_click = [this](auto&) {
done(GDialog::ExecOK);
done(Dialog::ExecOK);
};
}
GAboutDialog::~GAboutDialog()
AboutDialog::~AboutDialog()
{
}
}

View file

@ -28,20 +28,23 @@
#include <LibGUI/GDialog.h>
class GAboutDialog final : public GDialog {
C_OBJECT(GAboutDialog)
namespace GUI {
class AboutDialog final : public Dialog {
C_OBJECT(AboutDialog)
public:
virtual ~GAboutDialog() override;
virtual ~AboutDialog() override;
static void show(const StringView& name, const GraphicsBitmap* icon = nullptr, Core::Object* parent = nullptr)
{
auto dialog = GAboutDialog::construct(name, icon, parent);
auto dialog = AboutDialog::construct(name, icon, parent);
dialog->exec();
}
private:
GAboutDialog(const StringView& name, const GraphicsBitmap* icon = nullptr, Core::Object* parent = nullptr);
AboutDialog(const StringView& name, const GraphicsBitmap* icon = nullptr, Core::Object* parent = nullptr);
String m_name;
RefPtr<GraphicsBitmap> m_icon;
};
}

View file

@ -28,13 +28,15 @@
#include <LibGUI/GAbstractButton.h>
#include <LibGUI/GPainter.h>
GAbstractButton::GAbstractButton(GWidget* parent)
: GAbstractButton({}, parent)
namespace GUI {
AbstractButton::AbstractButton(Widget* parent)
: AbstractButton({}, parent)
{
}
GAbstractButton::GAbstractButton(const StringView& text, GWidget* parent)
: GWidget(parent)
AbstractButton::AbstractButton(const StringView& text, Widget* parent)
: Widget(parent)
, m_text(text)
{
m_auto_repeat_timer = Core::Timer::construct(this);
@ -43,11 +45,11 @@ GAbstractButton::GAbstractButton(const StringView& text, GWidget* parent)
};
}
GAbstractButton::~GAbstractButton()
AbstractButton::~AbstractButton()
{
}
void GAbstractButton::set_text(const StringView& text)
void AbstractButton::set_text(const StringView& text)
{
if (m_text == text)
return;
@ -55,14 +57,14 @@ void GAbstractButton::set_text(const StringView& text)
update();
}
void GAbstractButton::set_checked(bool checked)
void AbstractButton::set_checked(bool checked)
{
if (m_checked == checked)
return;
m_checked = checked;
if (is_exclusive() && checked) {
parent_widget()->for_each_child_of_type<GAbstractButton>([&](auto& sibling) {
parent_widget()->for_each_child_of_type<AbstractButton>([&](auto& sibling) {
if (!sibling.is_exclusive() || !sibling.is_checked())
return IterationDecision::Continue;
sibling.m_checked = false;
@ -79,7 +81,7 @@ void GAbstractButton::set_checked(bool checked)
on_checked(checked);
}
void GAbstractButton::set_checkable(bool checkable)
void AbstractButton::set_checkable(bool checkable)
{
if (m_checkable == checkable)
return;
@ -87,11 +89,11 @@ void GAbstractButton::set_checkable(bool checkable)
update();
}
void GAbstractButton::mousemove_event(GMouseEvent& event)
void AbstractButton::mousemove_event(MouseEvent& event)
{
bool is_over = rect().contains(event.position());
m_hovered = is_over;
if (event.buttons() & GMouseButton::Left) {
if (event.buttons() & MouseButton::Left) {
if (is_enabled()) {
bool being_pressed = is_over;
if (being_pressed != m_being_pressed) {
@ -106,15 +108,15 @@ void GAbstractButton::mousemove_event(GMouseEvent& event)
}
}
}
GWidget::mousemove_event(event);
Widget::mousemove_event(event);
}
void GAbstractButton::mousedown_event(GMouseEvent& event)
void AbstractButton::mousedown_event(MouseEvent& event)
{
#ifdef GABSTRACTBUTTON_DEBUG
dbgprintf("GAbstractButton::mouse_down_event: x=%d, y=%d, button=%u\n", event.x(), event.y(), (unsigned)event.button());
dbgprintf("AbstractButton::mouse_down_event: x=%d, y=%d, button=%u\n", event.x(), event.y(), (unsigned)event.button());
#endif
if (event.button() == GMouseButton::Left) {
if (event.button() == MouseButton::Left) {
if (is_enabled()) {
m_being_pressed = true;
update();
@ -125,15 +127,15 @@ void GAbstractButton::mousedown_event(GMouseEvent& event)
}
}
}
GWidget::mousedown_event(event);
Widget::mousedown_event(event);
}
void GAbstractButton::mouseup_event(GMouseEvent& event)
void AbstractButton::mouseup_event(MouseEvent& event)
{
#ifdef GABSTRACTBUTTON_DEBUG
dbgprintf("GAbstractButton::mouse_up_event: x=%d, y=%d, button=%u\n", event.x(), event.y(), (unsigned)event.button());
dbgprintf("AbstractButton::mouse_up_event: x=%d, y=%d, button=%u\n", event.x(), event.y(), (unsigned)event.button());
#endif
if (event.button() == GMouseButton::Left) {
if (event.button() == MouseButton::Left) {
bool was_auto_repeating = m_auto_repeat_timer->is_active();
m_auto_repeat_timer->stop();
if (is_enabled()) {
@ -144,32 +146,32 @@ void GAbstractButton::mouseup_event(GMouseEvent& event)
click();
}
}
GWidget::mouseup_event(event);
Widget::mouseup_event(event);
}
void GAbstractButton::enter_event(Core::Event&)
void AbstractButton::enter_event(Core::Event&)
{
m_hovered = true;
update();
}
void GAbstractButton::leave_event(Core::Event&)
void AbstractButton::leave_event(Core::Event&)
{
m_hovered = false;
update();
}
void GAbstractButton::keydown_event(GKeyEvent& event)
void AbstractButton::keydown_event(KeyEvent& event)
{
if (event.key() == KeyCode::Key_Return) {
click();
event.accept();
return;
}
GWidget::keydown_event(event);
Widget::keydown_event(event);
}
void GAbstractButton::paint_text(GPainter& painter, const Rect& rect, const Font& font, TextAlignment text_alignment)
void AbstractButton::paint_text(Painter& painter, const Rect& rect, const Font& font, TextAlignment text_alignment)
{
auto clipped_rect = rect.intersected(this->rect());
@ -186,9 +188,9 @@ void GAbstractButton::paint_text(GPainter& painter, const Rect& rect, const Font
painter.draw_rect(clipped_rect.inflated(6, 4), Color(140, 140, 140));
}
void GAbstractButton::change_event(GEvent& event)
void AbstractButton::change_event(Event& event)
{
if (event.type() == GEvent::Type::EnabledChange) {
if (event.type() == Event::Type::EnabledChange) {
if (!is_enabled()) {
bool was_being_pressed = m_being_pressed;
m_being_pressed = false;
@ -196,5 +198,7 @@ void GAbstractButton::change_event(GEvent& event)
update();
}
}
GWidget::change_event(event);
Widget::change_event(event);
}
}

View file

@ -30,12 +30,14 @@
#include <LibDraw/TextAlignment.h>
#include <LibGUI/GWidget.h>
class GPainter;
namespace GUI {
class GAbstractButton : public GWidget {
class Painter;
class AbstractButton : public Widget {
C_OBJECT_ABSTRACT(GAbstractButton)
public:
virtual ~GAbstractButton() override;
virtual ~AbstractButton() override;
Function<void(bool)> on_checked;
@ -62,18 +64,18 @@ public:
void set_auto_repeat_interval(int interval) { m_auto_repeat_interval = interval; }
protected:
explicit GAbstractButton(GWidget* parent);
GAbstractButton(const StringView&, GWidget* parent);
explicit AbstractButton(Widget* parent);
AbstractButton(const StringView&, Widget* parent);
virtual void mousedown_event(GMouseEvent&) override;
virtual void mousemove_event(GMouseEvent&) override;
virtual void mouseup_event(GMouseEvent&) override;
virtual void keydown_event(GKeyEvent&) override;
virtual void mousedown_event(MouseEvent&) override;
virtual void mousemove_event(MouseEvent&) override;
virtual void mouseup_event(MouseEvent&) override;
virtual void keydown_event(KeyEvent&) override;
virtual void enter_event(Core::Event&) override;
virtual void leave_event(Core::Event&) override;
virtual void change_event(GEvent&) override;
virtual void change_event(Event&) override;
void paint_text(GPainter&, const Rect&, const Font&, TextAlignment);
void paint_text(Painter&, const Rect&, const Font&, TextAlignment);
private:
virtual bool is_abstract_button() const final { return true; }
@ -89,10 +91,12 @@ private:
RefPtr<Core::Timer> m_auto_repeat_timer;
};
template<>
inline bool Core::is<GAbstractButton>(const Core::Object& object)
{
if (!is<GWidget>(object))
return false;
return to<GWidget>(object).is_abstract_button();
}
template<>
inline bool Core::is<GUI::AbstractButton>(const Core::Object& object)
{
if (!is<GUI::Widget>(object))
return false;
return to<GUI::Widget>(object).is_abstract_button();
}

View file

@ -32,10 +32,12 @@
#include <LibGUI/GPainter.h>
#include <LibGUI/GScrollBar.h>
namespace GUI {
static const int minimum_column_width = 2;
GAbstractTableView::GAbstractTableView(GWidget* parent)
: GAbstractView(parent)
AbstractTableView::AbstractTableView(Widget* parent)
: AbstractView(parent)
{
set_frame_shape(FrameShape::Container);
set_frame_shadow(FrameShadow::Sunken);
@ -44,11 +46,11 @@ GAbstractTableView::GAbstractTableView(GWidget* parent)
set_should_hide_unnecessary_scrollbars(true);
}
GAbstractTableView::~GAbstractTableView()
AbstractTableView::~AbstractTableView()
{
}
void GAbstractTableView::update_column_sizes()
void AbstractTableView::update_column_sizes()
{
if (!m_size_columns_to_fit_content)
return;
@ -84,7 +86,7 @@ void GAbstractTableView::update_column_sizes()
}
}
void GAbstractTableView::update_content_size()
void AbstractTableView::update_content_size()
{
if (!model())
return set_content_size({});
@ -101,7 +103,7 @@ void GAbstractTableView::update_content_size()
set_size_occupied_by_fixed_elements({ 0, header_height() });
}
Rect GAbstractTableView::header_rect(int column_index) const
Rect AbstractTableView::header_rect(int column_index) const
{
if (!model())
return {};
@ -116,7 +118,7 @@ Rect GAbstractTableView::header_rect(int column_index) const
return { x_offset, 0, column_width(column_index) + horizontal_padding() * 2, header_height() };
}
void GAbstractTableView::set_hovered_header_index(int index)
void AbstractTableView::set_hovered_header_index(int index)
{
if (m_hovered_column_header_index == index)
return;
@ -124,7 +126,7 @@ void GAbstractTableView::set_hovered_header_index(int index)
update_headers();
}
void GAbstractTableView::paint_headers(GPainter& painter)
void AbstractTableView::paint_headers(Painter& painter)
{
if (!headers_visible())
return;
@ -141,16 +143,16 @@ void GAbstractTableView::paint_headers(GPainter& painter)
bool is_key_column = model()->key_column() == column_index;
Rect cell_rect(x_offset, 0, column_width + horizontal_padding() * 2, header_height());
bool pressed = column_index == m_pressed_column_header_index && m_pressed_column_header_is_pressed;
bool hovered = column_index == m_hovered_column_header_index && model()->column_metadata(column_index).sortable == GModel::ColumnMetadata::Sortable::True;
bool hovered = column_index == m_hovered_column_header_index && model()->column_metadata(column_index).sortable == Model::ColumnMetadata::Sortable::True;
StylePainter::paint_button(painter, cell_rect, palette(), ButtonStyle::Normal, pressed, hovered);
String text;
if (is_key_column) {
StringBuilder builder;
builder.append(model()->column_name(column_index));
auto sort_order = model()->sort_order();
if (sort_order == GSortOrder::Ascending)
if (sort_order == SortOrder::Ascending)
builder.append(" \xc3\xb6");
else if (sort_order == GSortOrder::Descending)
else if (sort_order == SortOrder::Descending)
builder.append(" \xc3\xb7");
text = builder.to_string();
} else {
@ -164,12 +166,12 @@ void GAbstractTableView::paint_headers(GPainter& painter)
}
}
bool GAbstractTableView::is_column_hidden(int column) const
bool AbstractTableView::is_column_hidden(int column) const
{
return !column_data(column).visibility;
}
void GAbstractTableView::set_column_hidden(int column, bool hidden)
void AbstractTableView::set_column_hidden(int column, bool hidden)
{
auto& column_data = this->column_data(column);
if (column_data.visibility == !hidden)
@ -179,18 +181,18 @@ void GAbstractTableView::set_column_hidden(int column, bool hidden)
update();
}
GMenu& GAbstractTableView::ensure_header_context_menu()
Menu& AbstractTableView::ensure_header_context_menu()
{
// FIXME: This menu needs to be rebuilt if the model is swapped out,
// or if the column count/names change.
if (!m_header_context_menu) {
ASSERT(model());
m_header_context_menu = GMenu::construct();
m_header_context_menu = Menu::construct();
for (int column = 0; column < model()->column_count(); ++column) {
auto& column_data = this->column_data(column);
auto name = model()->column_name(column);
column_data.visibility_action = GAction::create(name, [this, column](GAction& action) {
column_data.visibility_action = Action::create(name, [this, column](Action& action) {
action.set_checked(!action.is_checked());
set_column_hidden(column, !action.is_checked());
});
@ -203,31 +205,31 @@ GMenu& GAbstractTableView::ensure_header_context_menu()
return *m_header_context_menu;
}
const Font& GAbstractTableView::header_font()
const Font& AbstractTableView::header_font()
{
return Font::default_bold_font();
}
void GAbstractTableView::set_cell_painting_delegate(int column, OwnPtr<GTableCellPaintingDelegate>&& delegate)
void AbstractTableView::set_cell_painting_delegate(int column, OwnPtr<TableCellPaintingDelegate>&& delegate)
{
column_data(column).cell_painting_delegate = move(delegate);
}
void GAbstractTableView::update_headers()
void AbstractTableView::update_headers()
{
Rect rect { 0, 0, frame_inner_rect().width(), header_height() };
rect.move_by(frame_thickness(), frame_thickness());
update(rect);
}
GAbstractTableView::ColumnData& GAbstractTableView::column_data(int column) const
AbstractTableView::ColumnData& AbstractTableView::column_data(int column) const
{
if (column >= m_column_data.size())
m_column_data.resize(column + 1);
return m_column_data.at(column);
}
Rect GAbstractTableView::column_resize_grabbable_rect(int column) const
Rect AbstractTableView::column_resize_grabbable_rect(int column) const
{
if (!model())
return {};
@ -235,7 +237,7 @@ Rect GAbstractTableView::column_resize_grabbable_rect(int column) const
return { header_rect.right() - 1, header_rect.top(), 4, header_rect.height() };
}
int GAbstractTableView::column_width(int column_index) const
int AbstractTableView::column_width(int column_index) const
{
if (!model())
return 0;
@ -248,10 +250,10 @@ int GAbstractTableView::column_width(int column_index) const
return column_data.width;
}
void GAbstractTableView::mousemove_event(GMouseEvent& event)
void AbstractTableView::mousemove_event(MouseEvent& event)
{
if (!model())
return GAbstractView::mousemove_event(event);
return AbstractView::mousemove_event(event);
if (m_in_column_resize) {
auto delta = event.position() - m_column_resize_origin;
@ -288,7 +290,7 @@ void GAbstractTableView::mousemove_event(GMouseEvent& event)
bool found_hovered_header = false;
for (int i = 0; i < column_count; ++i) {
if (column_resize_grabbable_rect(i).contains(event.position())) {
window()->set_override_cursor(GStandardCursor::ResizeHorizontal);
window()->set_override_cursor(StandardCursor::ResizeHorizontal);
set_hovered_header_index(-1);
return;
}
@ -300,29 +302,29 @@ void GAbstractTableView::mousemove_event(GMouseEvent& event)
if (!found_hovered_header)
set_hovered_header_index(-1);
}
window()->set_override_cursor(GStandardCursor::None);
window()->set_override_cursor(StandardCursor::None);
GAbstractView::mousemove_event(event);
AbstractView::mousemove_event(event);
}
void GAbstractTableView::mouseup_event(GMouseEvent& event)
void AbstractTableView::mouseup_event(MouseEvent& event)
{
auto adjusted_position = this->adjusted_position(event.position());
if (event.button() == GMouseButton::Left) {
if (event.button() == MouseButton::Left) {
if (m_in_column_resize) {
if (!column_resize_grabbable_rect(m_resizing_column).contains(adjusted_position))
window()->set_override_cursor(GStandardCursor::None);
window()->set_override_cursor(StandardCursor::None);
m_in_column_resize = false;
return;
}
if (m_pressed_column_header_index != -1) {
auto header_rect = this->header_rect(m_pressed_column_header_index);
if (header_rect.contains(event.position())) {
auto new_sort_order = GSortOrder::Ascending;
auto new_sort_order = SortOrder::Ascending;
if (model()->key_column() == m_pressed_column_header_index)
new_sort_order = model()->sort_order() == GSortOrder::Ascending
? GSortOrder::Descending
: GSortOrder::Ascending;
new_sort_order = model()->sort_order() == SortOrder::Ascending
? SortOrder::Descending
: SortOrder::Ascending;
model()->set_key_column_and_sort_order(m_pressed_column_header_index, new_sort_order);
}
m_pressed_column_header_index = -1;
@ -332,16 +334,16 @@ void GAbstractTableView::mouseup_event(GMouseEvent& event)
}
}
GAbstractView::mouseup_event(event);
AbstractView::mouseup_event(event);
}
void GAbstractTableView::mousedown_event(GMouseEvent& event)
void AbstractTableView::mousedown_event(MouseEvent& event)
{
if (!model())
return GAbstractView::mousedown_event(event);
return AbstractView::mousedown_event(event);
if (event.button() != GMouseButton::Left)
return GAbstractView::mousedown_event(event);
if (event.button() != MouseButton::Left)
return AbstractView::mousedown_event(event);
if (event.y() < header_height()) {
int column_count = model()->column_count();
@ -355,7 +357,7 @@ void GAbstractTableView::mousedown_event(GMouseEvent& event)
}
auto header_rect = this->header_rect(i);
auto column_metadata = model()->column_metadata(i);
if (header_rect.contains(event.position()) && column_metadata.sortable == GModel::ColumnMetadata::Sortable::True) {
if (header_rect.contains(event.position()) && column_metadata.sortable == Model::ColumnMetadata::Sortable::True) {
m_pressed_column_header_index = i;
m_pressed_column_header_is_pressed = true;
update_headers();
@ -373,10 +375,10 @@ void GAbstractTableView::mousedown_event(GMouseEvent& event)
return;
}
GAbstractView::mousedown_event(event);
AbstractView::mousedown_event(event);
}
GModelIndex GAbstractTableView::index_at_event_position(const Point& position, bool& is_toggle) const
ModelIndex AbstractTableView::index_at_event_position(const Point& position, bool& is_toggle) const
{
is_toggle = false;
if (!model())
@ -396,21 +398,21 @@ GModelIndex GAbstractTableView::index_at_event_position(const Point& position, b
return {};
}
GModelIndex GAbstractTableView::index_at_event_position(const Point& position) const
ModelIndex AbstractTableView::index_at_event_position(const Point& position) const
{
bool is_toggle;
auto index = index_at_event_position(position, is_toggle);
return is_toggle ? GModelIndex() : index;
return is_toggle ? ModelIndex() : index;
}
int GAbstractTableView::item_count() const
int AbstractTableView::item_count() const
{
if (!model())
return 0;
return model()->row_count();
}
void GAbstractTableView::keydown_event(GKeyEvent& event)
void AbstractTableView::keydown_event(KeyEvent& event)
{
if (!model())
return;
@ -420,7 +422,7 @@ void GAbstractTableView::keydown_event(GKeyEvent& event)
return;
}
if (event.key() == KeyCode::Key_Up) {
GModelIndex new_index;
ModelIndex new_index;
if (!selection().is_empty()) {
auto old_index = selection().first();
new_index = model.index(old_index.row() - 1, old_index.column());
@ -435,7 +437,7 @@ void GAbstractTableView::keydown_event(GKeyEvent& event)
return;
}
if (event.key() == KeyCode::Key_Down) {
GModelIndex new_index;
ModelIndex new_index;
if (!selection().is_empty()) {
auto old_index = selection().first();
new_index = model.index(old_index.row() + 1, old_index.column());
@ -471,20 +473,20 @@ void GAbstractTableView::keydown_event(GKeyEvent& event)
}
return;
}
return GWidget::keydown_event(event);
return Widget::keydown_event(event);
}
void GAbstractTableView::scroll_into_view(const GModelIndex& index, Orientation orientation)
void AbstractTableView::scroll_into_view(const ModelIndex& index, Orientation orientation)
{
auto rect = row_rect(index.row()).translated(0, -header_height());
GScrollableWidget::scroll_into_view(rect, orientation);
ScrollableWidget::scroll_into_view(rect, orientation);
}
void GAbstractTableView::doubleclick_event(GMouseEvent& event)
void AbstractTableView::doubleclick_event(MouseEvent& event)
{
if (!model())
return;
if (event.button() == GMouseButton::Left) {
if (event.button() == MouseButton::Left) {
if (event.y() < header_height())
return;
if (!selection().is_empty()) {
@ -496,7 +498,7 @@ void GAbstractTableView::doubleclick_event(GMouseEvent& event)
}
}
void GAbstractTableView::context_menu_event(GContextMenuEvent& event)
void AbstractTableView::context_menu_event(ContextMenuEvent& event)
{
if (!model())
return;
@ -517,13 +519,13 @@ void GAbstractTableView::context_menu_event(GContextMenuEvent& event)
on_context_menu_request(index, event);
}
void GAbstractTableView::leave_event(Core::Event&)
void AbstractTableView::leave_event(Core::Event&)
{
window()->set_override_cursor(GStandardCursor::None);
window()->set_override_cursor(StandardCursor::None);
set_hovered_header_index(-1);
}
Rect GAbstractTableView::content_rect(int row, int column) const
Rect AbstractTableView::content_rect(int row, int column) const
{
auto row_rect = this->row_rect(row);
int x = 0;
@ -533,25 +535,27 @@ Rect GAbstractTableView::content_rect(int row, int column) const
return { row_rect.x() + x, row_rect.y(), column_width(column) + horizontal_padding() * 2, item_height() };
}
Rect GAbstractTableView::content_rect(const GModelIndex& index) const
Rect AbstractTableView::content_rect(const ModelIndex& index) const
{
return content_rect(index.row(), index.column());
}
Rect GAbstractTableView::row_rect(int item_index) const
Rect AbstractTableView::row_rect(int item_index) const
{
return { 0, header_height() + (item_index * item_height()), max(content_size().width(), width()), item_height() };
}
Point GAbstractTableView::adjusted_position(const Point& position) const
Point AbstractTableView::adjusted_position(const Point& position) const
{
return position.translated(horizontal_scrollbar().value() - frame_thickness(), vertical_scrollbar().value() - frame_thickness());
}
void GAbstractTableView::did_update_model()
void AbstractTableView::did_update_model()
{
GAbstractView::did_update_model();
AbstractView::did_update_model();
update_column_sizes();
update_content_size();
update();
}
}

View file

@ -28,17 +28,19 @@
#include <LibGUI/GAbstractView.h>
class GPainter;
namespace GUI {
class Painter;
// FIXME: Rename this to something without "table cell" in the name.
class GTableCellPaintingDelegate {
class TableCellPaintingDelegate {
public:
virtual ~GTableCellPaintingDelegate() {}
virtual ~TableCellPaintingDelegate() {}
virtual void paint(GPainter&, const Rect&, const Palette&, const GModel&, const GModelIndex&) = 0;
virtual void paint(Painter&, const Rect&, const Palette&, const Model&, const ModelIndex&) = 0;
};
class GAbstractTableView : public GAbstractView {
class AbstractTableView : public AbstractView {
public:
int item_height() const { return 16; }
@ -56,37 +58,37 @@ public:
void set_size_columns_to_fit_content(bool b) { m_size_columns_to_fit_content = b; }
bool size_columns_to_fit_content() const { return m_size_columns_to_fit_content; }
void set_cell_painting_delegate(int column, OwnPtr<GTableCellPaintingDelegate>&&);
void set_cell_painting_delegate(int column, OwnPtr<TableCellPaintingDelegate>&&);
int horizontal_padding() const { return m_horizontal_padding; }
Point adjusted_position(const Point&) const;
virtual Rect content_rect(const GModelIndex&) const override;
virtual Rect content_rect(const ModelIndex&) const override;
Rect content_rect(int row, int column) const;
Rect row_rect(int item_index) const;
void scroll_into_view(const GModelIndex&, Orientation);
void scroll_into_view(const ModelIndex&, Orientation);
virtual GModelIndex index_at_event_position(const Point&, bool& is_toggle) const;
virtual GModelIndex index_at_event_position(const Point&) const override;
virtual ModelIndex index_at_event_position(const Point&, bool& is_toggle) const;
virtual ModelIndex index_at_event_position(const Point&) const override;
protected:
virtual ~GAbstractTableView() override;
explicit GAbstractTableView(GWidget* parent);
virtual ~AbstractTableView() override;
explicit AbstractTableView(Widget* parent);
virtual void did_update_model() override;
virtual void mouseup_event(GMouseEvent&) override;
virtual void mousedown_event(GMouseEvent&) override;
virtual void mousemove_event(GMouseEvent&) override;
virtual void doubleclick_event(GMouseEvent&) override;
virtual void keydown_event(GKeyEvent&) override;
virtual void mouseup_event(MouseEvent&) override;
virtual void mousedown_event(MouseEvent&) override;
virtual void mousemove_event(MouseEvent&) override;
virtual void doubleclick_event(MouseEvent&) override;
virtual void keydown_event(KeyEvent&) override;
virtual void leave_event(Core::Event&) override;
virtual void context_menu_event(GContextMenuEvent&) override;
virtual void context_menu_event(ContextMenuEvent&) override;
virtual void toggle_index(const GModelIndex&) {}
virtual void toggle_index(const ModelIndex&) {}
void paint_headers(GPainter&);
void paint_headers(Painter&);
Rect header_rect(int column) const;
static const Font& header_font();
@ -97,15 +99,15 @@ protected:
int width { 0 };
bool has_initialized_width { false };
bool visibility { true };
RefPtr<GAction> visibility_action;
OwnPtr<GTableCellPaintingDelegate> cell_painting_delegate;
RefPtr<Action> visibility_action;
OwnPtr<TableCellPaintingDelegate> cell_painting_delegate;
};
ColumnData& column_data(int column) const;
mutable Vector<ColumnData> m_column_data;
GMenu& ensure_header_context_menu();
RefPtr<GMenu> m_header_context_menu;
Menu& ensure_header_context_menu();
RefPtr<Menu> m_header_context_menu;
Rect column_resize_grabbable_rect(int) const;
int column_width(int) const;
@ -126,3 +128,5 @@ private:
bool m_pressed_column_header_is_pressed { false };
int m_hovered_column_header_index { -1 };
};
}

View file

@ -34,17 +34,19 @@
#include <LibGUI/GScrollBar.h>
#include <LibGUI/GTextBox.h>
GAbstractView::GAbstractView(GWidget* parent)
: GScrollableWidget(parent)
namespace GUI {
AbstractView::AbstractView(Widget* parent)
: ScrollableWidget(parent)
, m_selection(*this)
{
}
GAbstractView::~GAbstractView()
AbstractView::~AbstractView()
{
}
void GAbstractView::set_model(RefPtr<GModel>&& model)
void AbstractView::set_model(RefPtr<Model>&& model)
{
if (model == m_model)
return;
@ -56,13 +58,13 @@ void GAbstractView::set_model(RefPtr<GModel>&& model)
did_update_model();
}
void GAbstractView::did_update_model()
void AbstractView::did_update_model()
{
if (!model() || selection().first() != m_edit_index)
stop_editing();
}
void GAbstractView::did_update_selection()
void AbstractView::did_update_selection()
{
if (!model() || selection().first() != m_edit_index)
stop_editing();
@ -70,19 +72,19 @@ void GAbstractView::did_update_selection()
on_selection(selection().first());
}
void GAbstractView::did_scroll()
void AbstractView::did_scroll()
{
update_edit_widget_position();
}
void GAbstractView::update_edit_widget_position()
void AbstractView::update_edit_widget_position()
{
if (!m_edit_widget)
return;
m_edit_widget->set_relative_rect(m_edit_widget_content_rect.translated(-horizontal_scrollbar().value(), -vertical_scrollbar().value()));
}
void GAbstractView::begin_editing(const GModelIndex& index)
void AbstractView::begin_editing(const ModelIndex& index)
{
ASSERT(is_editable());
ASSERT(model());
@ -99,7 +101,7 @@ void GAbstractView::begin_editing(const GModelIndex& index)
ASSERT(aid_create_editing_delegate);
m_editing_delegate = aid_create_editing_delegate(index);
m_editing_delegate->bind(*model(), index);
m_editing_delegate->set_value(model()->data(index, GModel::Role::Display));
m_editing_delegate->set_value(model()->data(index, Model::Role::Display));
m_edit_widget = m_editing_delegate->widget();
add_child(*m_edit_widget);
m_edit_widget->move_to_back();
@ -114,7 +116,7 @@ void GAbstractView::begin_editing(const GModelIndex& index)
};
}
void GAbstractView::stop_editing()
void AbstractView::stop_editing()
{
m_edit_index = {};
if (m_edit_widget) {
@ -123,7 +125,7 @@ void GAbstractView::stop_editing()
}
}
void GAbstractView::select_all()
void AbstractView::select_all()
{
ASSERT(model());
int rows = model()->row_count();
@ -135,13 +137,13 @@ void GAbstractView::select_all()
}
}
void GAbstractView::activate(const GModelIndex& index)
void AbstractView::activate(const ModelIndex& index)
{
if (on_activation)
on_activation(index);
}
void GAbstractView::activate_selected()
void AbstractView::activate_selected()
{
if (!on_activation)
return;
@ -151,7 +153,7 @@ void GAbstractView::activate_selected()
});
}
void GAbstractView::notify_selection_changed(Badge<GModelSelection>)
void AbstractView::notify_selection_changed(Badge<ModelSelection>)
{
did_update_selection();
if (on_selection_change)
@ -159,12 +161,12 @@ void GAbstractView::notify_selection_changed(Badge<GModelSelection>)
update();
}
NonnullRefPtr<Font> GAbstractView::font_for_index(const GModelIndex& index) const
NonnullRefPtr<Font> AbstractView::font_for_index(const ModelIndex& index) const
{
if (!model())
return font();
auto font_data = model()->data(index, GModel::Role::Font);
auto font_data = model()->data(index, Model::Role::Font);
if (font_data.is_font())
return font_data.as_font();
@ -174,14 +176,14 @@ NonnullRefPtr<Font> GAbstractView::font_for_index(const GModelIndex& index) cons
return font();
}
void GAbstractView::mousedown_event(GMouseEvent& event)
void AbstractView::mousedown_event(MouseEvent& event)
{
GScrollableWidget::mousedown_event(event);
ScrollableWidget::mousedown_event(event);
if (!model())
return;
if (event.button() == GMouseButton::Left)
if (event.button() == MouseButton::Left)
m_left_mousedown_position = event.position();
auto index = index_at_event_position(event.position());
@ -191,7 +193,7 @@ void GAbstractView::mousedown_event(GMouseEvent& event)
m_selection.clear();
} else if (event.modifiers() & Mod_Ctrl) {
m_selection.toggle(index);
} else if (event.button() == GMouseButton::Left && m_selection.contains(index) && !m_model->drag_data_type().is_null()) {
} else if (event.button() == MouseButton::Left && m_selection.contains(index) && !m_model->drag_data_type().is_null()) {
// We might be starting a drag, so don't throw away other selected items yet.
m_might_drag = true;
} else {
@ -201,14 +203,14 @@ void GAbstractView::mousedown_event(GMouseEvent& event)
update();
}
void GAbstractView::mousemove_event(GMouseEvent& event)
void AbstractView::mousemove_event(MouseEvent& event)
{
if (!model() || !m_might_drag)
return GScrollableWidget::mousemove_event(event);
return ScrollableWidget::mousemove_event(event);
if (!(event.buttons() & GMouseButton::Left) || m_selection.is_empty()) {
if (!(event.buttons() & MouseButton::Left) || m_selection.is_empty()) {
m_might_drag = false;
return GScrollableWidget::mousemove_event(event);
return ScrollableWidget::mousemove_event(event);
}
auto diff = event.position() - m_left_mousedown_position;
@ -216,13 +218,13 @@ void GAbstractView::mousemove_event(GMouseEvent& event)
constexpr int drag_distance_threshold = 5;
if (distance_travelled_squared <= drag_distance_threshold)
return GScrollableWidget::mousemove_event(event);
return ScrollableWidget::mousemove_event(event);
auto data_type = m_model->drag_data_type();
ASSERT(!data_type.is_null());
dbg() << "Initiate drag!";
auto drag_operation = GDragOperation::construct();
auto drag_operation = DragOperation::construct();
RefPtr<GraphicsBitmap> bitmap;
@ -235,14 +237,14 @@ void GAbstractView::mousemove_event(GMouseEvent& event)
text_builder.append(", ");
text_builder.append(text_data.to_string());
auto drag_data = m_model->data(index, GModel::Role::DragData);
auto drag_data = m_model->data(index, Model::Role::DragData);
data_builder.append(drag_data.to_string());
data_builder.append('\n');
first = false;
if (!bitmap) {
GVariant icon_data = model()->data(index, GModel::Role::Icon);
Variant icon_data = model()->data(index, Model::Role::Icon);
if (icon_data.is_icon())
bitmap = icon_data.as_icon().bitmap_for_size(32);
}
@ -255,10 +257,10 @@ void GAbstractView::mousemove_event(GMouseEvent& event)
auto outcome = drag_operation->exec();
switch (outcome) {
case GDragOperation::Outcome::Accepted:
case DragOperation::Outcome::Accepted:
dbg() << "Drag was accepted!";
break;
case GDragOperation::Outcome::Cancelled:
case DragOperation::Outcome::Cancelled:
dbg() << "Drag was cancelled!";
break;
default:
@ -267,9 +269,9 @@ void GAbstractView::mousemove_event(GMouseEvent& event)
}
}
void GAbstractView::mouseup_event(GMouseEvent& event)
void AbstractView::mouseup_event(MouseEvent& event)
{
GScrollableWidget::mouseup_event(event);
ScrollableWidget::mouseup_event(event);
if (!model())
return;
@ -288,12 +290,12 @@ void GAbstractView::mouseup_event(GMouseEvent& event)
}
}
void GAbstractView::doubleclick_event(GMouseEvent& event)
void AbstractView::doubleclick_event(MouseEvent& event)
{
if (!model())
return;
if (event.button() != GMouseButton::Left)
if (event.button() != MouseButton::Left)
return;
m_might_drag = false;
@ -308,7 +310,7 @@ void GAbstractView::doubleclick_event(GMouseEvent& event)
activate_selected();
}
void GAbstractView::context_menu_event(GContextMenuEvent& event)
void AbstractView::context_menu_event(ContextMenuEvent& event)
{
if (!model())
return;
@ -323,3 +325,5 @@ void GAbstractView::context_menu_event(GContextMenuEvent& event)
if (on_context_menu_request)
on_context_menu_request(index, event);
}
}

View file

@ -31,19 +31,21 @@
#include <LibGUI/GModelSelection.h>
#include <LibGUI/GScrollableWidget.h>
class GModelEditingDelegate;
namespace GUI {
class GAbstractView : public GScrollableWidget {
C_OBJECT(GAbstractView)
friend class GModel;
class ModelEditingDelegate;
class AbstractView : public ScrollableWidget {
C_OBJECT_ABSTRACT(AbstractView)
friend class Model;
public:
void set_model(RefPtr<GModel>&&);
GModel* model() { return m_model.ptr(); }
const GModel* model() const { return m_model.ptr(); }
void set_model(RefPtr<Model>&&);
Model* model() { return m_model.ptr(); }
const Model* model() const { return m_model.ptr(); }
GModelSelection& selection() { return m_selection; }
const GModelSelection& selection() const { return m_selection; }
ModelSelection& selection() { return m_selection; }
const ModelSelection& selection() const { return m_selection; }
void select_all();
bool is_editable() const { return m_editable; }
@ -53,51 +55,53 @@ public:
virtual void did_update_model();
virtual void did_update_selection();
virtual Rect content_rect(const GModelIndex&) const { return {}; }
virtual GModelIndex index_at_event_position(const Point&) const = 0;
void begin_editing(const GModelIndex&);
virtual Rect content_rect(const ModelIndex&) const { return {}; }
virtual ModelIndex index_at_event_position(const Point&) const = 0;
void begin_editing(const ModelIndex&);
void stop_editing();
void set_activates_on_selection(bool b) { m_activates_on_selection = b; }
bool activates_on_selection() const { return m_activates_on_selection; }
Function<void()> on_selection_change;
Function<void(const GModelIndex&)> on_activation;
Function<void(const GModelIndex&)> on_selection;
Function<void(const GModelIndex&, const GContextMenuEvent&)> on_context_menu_request;
Function<void(const ModelIndex&)> on_activation;
Function<void(const ModelIndex&)> on_selection;
Function<void(const ModelIndex&, const ContextMenuEvent&)> on_context_menu_request;
Function<OwnPtr<GModelEditingDelegate>(const GModelIndex&)> aid_create_editing_delegate;
Function<OwnPtr<ModelEditingDelegate>(const ModelIndex&)> aid_create_editing_delegate;
void notify_selection_changed(Badge<GModelSelection>);
void notify_selection_changed(Badge<ModelSelection>);
NonnullRefPtr<Font> font_for_index(const GModelIndex&) const;
NonnullRefPtr<Font> font_for_index(const ModelIndex&) const;
protected:
explicit GAbstractView(GWidget* parent);
virtual ~GAbstractView() override;
explicit AbstractView(Widget* parent);
virtual ~AbstractView() override;
virtual void mousedown_event(GMouseEvent&) override;
virtual void mousemove_event(GMouseEvent&) override;
virtual void mouseup_event(GMouseEvent&) override;
virtual void doubleclick_event(GMouseEvent&) override;
virtual void context_menu_event(GContextMenuEvent&) override;
virtual void mousedown_event(MouseEvent&) override;
virtual void mousemove_event(MouseEvent&) override;
virtual void mouseup_event(MouseEvent&) override;
virtual void doubleclick_event(MouseEvent&) override;
virtual void context_menu_event(ContextMenuEvent&) override;
virtual void did_scroll() override;
void activate(const GModelIndex&);
void activate(const ModelIndex&);
void activate_selected();
void update_edit_widget_position();
bool m_editable { false };
GModelIndex m_edit_index;
RefPtr<GWidget> m_edit_widget;
ModelIndex m_edit_index;
RefPtr<Widget> m_edit_widget;
Rect m_edit_widget_content_rect;
Point m_left_mousedown_position;
bool m_might_drag { false };
private:
RefPtr<GModel> m_model;
OwnPtr<GModelEditingDelegate> m_editing_delegate;
GModelSelection m_selection;
RefPtr<Model> m_model;
OwnPtr<ModelEditingDelegate> m_editing_delegate;
ModelSelection m_selection;
bool m_activates_on_selection { false };
};
}

View file

@ -30,93 +30,95 @@
#include <LibGUI/GButton.h>
#include <LibGUI/GMenuItem.h>
namespace GCommonActions {
namespace GUI {
NonnullRefPtr<GAction> make_open_action(Function<void(GAction&)> callback, Core::Object* parent)
namespace CommonActions {
NonnullRefPtr<Action> make_open_action(Function<void(Action&)> callback, Core::Object* parent)
{
return GAction::create("Open...", { Mod_Ctrl, Key_O }, GraphicsBitmap::load_from_file("/res/icons/16x16/open.png"), move(callback), parent);
return Action::create("Open...", { Mod_Ctrl, Key_O }, GraphicsBitmap::load_from_file("/res/icons/16x16/open.png"), move(callback), parent);
}
NonnullRefPtr<GAction> make_move_to_front_action(Function<void(GAction&)> callback, Core::Object* parent)
NonnullRefPtr<Action> make_move_to_front_action(Function<void(Action&)> callback, Core::Object* parent)
{
return GAction::create("Move to front", { Mod_Ctrl | Mod_Shift, Key_Up }, GraphicsBitmap::load_from_file("/res/icons/16x16/move-to-front.png"), move(callback), parent);
return Action::create("Move to front", { Mod_Ctrl | Mod_Shift, Key_Up }, GraphicsBitmap::load_from_file("/res/icons/16x16/move-to-front.png"), move(callback), parent);
}
NonnullRefPtr<GAction> make_move_to_back_action(Function<void(GAction&)> callback, Core::Object* parent)
NonnullRefPtr<Action> make_move_to_back_action(Function<void(Action&)> callback, Core::Object* parent)
{
return GAction::create("Move to back", { Mod_Ctrl | Mod_Shift, Key_Down }, GraphicsBitmap::load_from_file("/res/icons/16x16/move-to-back.png"), move(callback), parent);
return Action::create("Move to back", { Mod_Ctrl | Mod_Shift, Key_Down }, GraphicsBitmap::load_from_file("/res/icons/16x16/move-to-back.png"), move(callback), parent);
}
NonnullRefPtr<GAction> make_undo_action(Function<void(GAction&)> callback, Core::Object* parent)
NonnullRefPtr<Action> make_undo_action(Function<void(Action&)> callback, Core::Object* parent)
{
return GAction::create("Undo", { Mod_Ctrl, Key_Z }, GraphicsBitmap::load_from_file("/res/icons/16x16/undo.png"), move(callback), parent);
return Action::create("Undo", { Mod_Ctrl, Key_Z }, GraphicsBitmap::load_from_file("/res/icons/16x16/undo.png"), move(callback), parent);
}
NonnullRefPtr<GAction> make_redo_action(Function<void(GAction&)> callback, Core::Object* parent)
NonnullRefPtr<Action> make_redo_action(Function<void(Action&)> callback, Core::Object* parent)
{
return GAction::create("Redo", { Mod_Ctrl, Key_Y }, GraphicsBitmap::load_from_file("/res/icons/16x16/redo.png"), move(callback), parent);
return Action::create("Redo", { Mod_Ctrl, Key_Y }, GraphicsBitmap::load_from_file("/res/icons/16x16/redo.png"), move(callback), parent);
}
NonnullRefPtr<GAction> make_delete_action(Function<void(GAction&)> callback, Core::Object* parent)
NonnullRefPtr<Action> make_delete_action(Function<void(Action&)> callback, Core::Object* parent)
{
return GAction::create("Delete", { Mod_None, Key_Delete }, GraphicsBitmap::load_from_file("/res/icons/16x16/delete.png"), move(callback), parent);
return Action::create("Delete", { Mod_None, Key_Delete }, GraphicsBitmap::load_from_file("/res/icons/16x16/delete.png"), move(callback), parent);
}
NonnullRefPtr<GAction> make_cut_action(Function<void(GAction&)> callback, Core::Object* parent)
NonnullRefPtr<Action> make_cut_action(Function<void(Action&)> callback, Core::Object* parent)
{
return GAction::create("Cut", { Mod_Ctrl, Key_X }, GraphicsBitmap::load_from_file("/res/icons/cut16.png"), move(callback), parent);
return Action::create("Cut", { Mod_Ctrl, Key_X }, GraphicsBitmap::load_from_file("/res/icons/cut16.png"), move(callback), parent);
}
NonnullRefPtr<GAction> make_copy_action(Function<void(GAction&)> callback, Core::Object* parent)
NonnullRefPtr<Action> make_copy_action(Function<void(Action&)> callback, Core::Object* parent)
{
return GAction::create("Copy", { Mod_Ctrl, Key_C }, GraphicsBitmap::load_from_file("/res/icons/16x16/edit-copy.png"), move(callback), parent);
return Action::create("Copy", { Mod_Ctrl, Key_C }, GraphicsBitmap::load_from_file("/res/icons/16x16/edit-copy.png"), move(callback), parent);
}
NonnullRefPtr<GAction> make_paste_action(Function<void(GAction&)> callback, Core::Object* parent)
NonnullRefPtr<Action> make_paste_action(Function<void(Action&)> callback, Core::Object* parent)
{
return GAction::create("Paste", { Mod_Ctrl, Key_V }, GraphicsBitmap::load_from_file("/res/icons/paste16.png"), move(callback), parent);
return Action::create("Paste", { Mod_Ctrl, Key_V }, GraphicsBitmap::load_from_file("/res/icons/paste16.png"), move(callback), parent);
}
NonnullRefPtr<GAction> make_fullscreen_action(Function<void(GAction&)> callback, Core::Object* parent)
NonnullRefPtr<Action> make_fullscreen_action(Function<void(Action&)> callback, Core::Object* parent)
{
return GAction::create("Fullscreen", { Mod_None, Key_F11 }, move(callback), parent);
return Action::create("Fullscreen", { Mod_None, Key_F11 }, move(callback), parent);
}
NonnullRefPtr<GAction> make_quit_action(Function<void(GAction&)> callback)
NonnullRefPtr<Action> make_quit_action(Function<void(Action&)> callback)
{
return GAction::create("Quit", { Mod_Alt, Key_F4 }, move(callback));
return Action::create("Quit", { Mod_Alt, Key_F4 }, move(callback));
}
NonnullRefPtr<GAction> make_go_back_action(Function<void(GAction&)> callback, Core::Object* parent)
NonnullRefPtr<Action> make_go_back_action(Function<void(Action&)> callback, Core::Object* parent)
{
return GAction::create("Go back", { Mod_Alt, Key_Left }, GraphicsBitmap::load_from_file("/res/icons/16x16/go-back.png"), move(callback), parent);
return Action::create("Go back", { Mod_Alt, Key_Left }, GraphicsBitmap::load_from_file("/res/icons/16x16/go-back.png"), move(callback), parent);
}
NonnullRefPtr<GAction> make_go_forward_action(Function<void(GAction&)> callback, Core::Object* parent)
NonnullRefPtr<Action> make_go_forward_action(Function<void(Action&)> callback, Core::Object* parent)
{
return GAction::create("Go forward", { Mod_Alt, Key_Right }, GraphicsBitmap::load_from_file("/res/icons/16x16/go-forward.png"), move(callback), parent);
return Action::create("Go forward", { Mod_Alt, Key_Right }, GraphicsBitmap::load_from_file("/res/icons/16x16/go-forward.png"), move(callback), parent);
}
NonnullRefPtr<GAction> make_go_home_action(Function<void(GAction&)> callback, Core::Object* parent)
NonnullRefPtr<Action> make_go_home_action(Function<void(Action&)> callback, Core::Object* parent)
{
return GAction::create("Go home", { Mod_Alt, Key_Home }, GraphicsBitmap::load_from_file("/res/icons/16x16/go-home.png"), move(callback), parent);
return Action::create("Go home", { Mod_Alt, Key_Home }, GraphicsBitmap::load_from_file("/res/icons/16x16/go-home.png"), move(callback), parent);
}
NonnullRefPtr<GAction> make_reload_action(Function<void(GAction&)> callback, Core::Object* parent)
NonnullRefPtr<Action> make_reload_action(Function<void(Action&)> callback, Core::Object* parent)
{
return GAction::create("Reload", { Mod_Ctrl, Key_R }, GraphicsBitmap::load_from_file("/res/icons/16x16/reload.png"), move(callback), parent);
return Action::create("Reload", { Mod_Ctrl, Key_R }, GraphicsBitmap::load_from_file("/res/icons/16x16/reload.png"), move(callback), parent);
}
}
GAction::GAction(const StringView& text, Function<void(GAction&)> on_activation_callback, Core::Object* parent)
Action::Action(const StringView& text, Function<void(Action&)> on_activation_callback, Core::Object* parent)
: Core::Object(parent)
, on_activation(move(on_activation_callback))
, m_text(text)
{
}
GAction::GAction(const StringView& text, RefPtr<GraphicsBitmap>&& icon, Function<void(GAction&)> on_activation_callback, Core::Object* parent)
Action::Action(const StringView& text, RefPtr<GraphicsBitmap>&& icon, Function<void(Action&)> on_activation_callback, Core::Object* parent)
: Core::Object(parent)
, on_activation(move(on_activation_callback))
, m_text(text)
@ -124,35 +126,35 @@ GAction::GAction(const StringView& text, RefPtr<GraphicsBitmap>&& icon, Function
{
}
GAction::GAction(const StringView& text, const GShortcut& shortcut, Function<void(GAction&)> on_activation_callback, Core::Object* parent)
: GAction(text, shortcut, nullptr, move(on_activation_callback), parent)
Action::Action(const StringView& text, const Shortcut& shortcut, Function<void(Action&)> on_activation_callback, Core::Object* parent)
: Action(text, shortcut, nullptr, move(on_activation_callback), parent)
{
}
GAction::GAction(const StringView& text, const GShortcut& shortcut, RefPtr<GraphicsBitmap>&& icon, Function<void(GAction&)> on_activation_callback, Core::Object* parent)
Action::Action(const StringView& text, const Shortcut& shortcut, RefPtr<GraphicsBitmap>&& icon, Function<void(Action&)> on_activation_callback, Core::Object* parent)
: Core::Object(parent)
, on_activation(move(on_activation_callback))
, m_text(text)
, m_icon(move(icon))
, m_shortcut(shortcut)
{
if (parent && Core::is<GWidget>(*parent)) {
if (parent && Core::is<Widget>(*parent)) {
m_scope = ShortcutScope::WidgetLocal;
} else if (parent && Core::is<GWindow>(*parent)) {
} else if (parent && Core::is<Window>(*parent)) {
m_scope = ShortcutScope::WindowLocal;
} else {
m_scope = ShortcutScope::ApplicationGlobal;
GApplication::the().register_global_shortcut_action({}, *this);
Application::the().register_global_shortcut_action({}, *this);
}
}
GAction::~GAction()
Action::~Action()
{
if (m_shortcut.is_valid() && m_scope == ShortcutScope::ApplicationGlobal)
GApplication::the().unregister_global_shortcut_action({}, *this);
Application::the().unregister_global_shortcut_action({}, *this);
}
void GAction::activate(Core::Object* activator)
void Action::activate(Core::Object* activator)
{
if (activator)
m_activator = activator->make_weak_ptr();
@ -161,54 +163,54 @@ void GAction::activate(Core::Object* activator)
m_activator = nullptr;
}
void GAction::register_button(Badge<GButton>, GButton& button)
void Action::register_button(Badge<Button>, Button& button)
{
m_buttons.set(&button);
}
void GAction::unregister_button(Badge<GButton>, GButton& button)
void Action::unregister_button(Badge<Button>, Button& button)
{
m_buttons.remove(&button);
}
void GAction::register_menu_item(Badge<GMenuItem>, GMenuItem& menu_item)
void Action::register_menu_item(Badge<MenuItem>, MenuItem& menu_item)
{
m_menu_items.set(&menu_item);
}
void GAction::unregister_menu_item(Badge<GMenuItem>, GMenuItem& menu_item)
void Action::unregister_menu_item(Badge<MenuItem>, MenuItem& menu_item)
{
m_menu_items.remove(&menu_item);
}
template<typename Callback>
void GAction::for_each_toolbar_button(Callback callback)
void Action::for_each_toolbar_button(Callback callback)
{
for (auto& it : m_buttons)
callback(*it);
}
template<typename Callback>
void GAction::for_each_menu_item(Callback callback)
void Action::for_each_menu_item(Callback callback)
{
for (auto& it : m_menu_items)
callback(*it);
}
void GAction::set_enabled(bool enabled)
void Action::set_enabled(bool enabled)
{
if (m_enabled == enabled)
return;
m_enabled = enabled;
for_each_toolbar_button([enabled](GButton& button) {
for_each_toolbar_button([enabled](auto& button) {
button.set_enabled(enabled);
});
for_each_menu_item([enabled](GMenuItem& item) {
for_each_menu_item([enabled](auto& item) {
item.set_enabled(enabled);
});
}
void GAction::set_checked(bool checked)
void Action::set_checked(bool checked)
{
if (m_checked == checked)
return;
@ -224,15 +226,17 @@ void GAction::set_checked(bool checked)
});
}
for_each_toolbar_button([checked](GButton& button) {
for_each_toolbar_button([checked](auto& button) {
button.set_checked(checked);
});
for_each_menu_item([checked](GMenuItem& item) {
for_each_menu_item([checked](MenuItem& item) {
item.set_checked(checked);
});
}
void GAction::set_group(Badge<GActionGroup>, GActionGroup* group)
void Action::set_group(Badge<ActionGroup>, ActionGroup* group)
{
m_action_group = group ? group->make_weak_ptr() : nullptr;
}
}

View file

@ -38,31 +38,33 @@
#include <LibGUI/GShortcut.h>
#include <LibGUI/GWindow.h>
class GAction;
class GActionGroup;
class GButton;
class GMenuItem;
namespace GUI {
namespace GCommonActions {
NonnullRefPtr<GAction> make_open_action(Function<void(GAction&)>, Core::Object* parent = nullptr);
NonnullRefPtr<GAction> make_undo_action(Function<void(GAction&)>, Core::Object* parent = nullptr);
NonnullRefPtr<GAction> make_redo_action(Function<void(GAction&)>, Core::Object* parent = nullptr);
NonnullRefPtr<GAction> make_cut_action(Function<void(GAction&)>, Core::Object* parent = nullptr);
NonnullRefPtr<GAction> make_copy_action(Function<void(GAction&)>, Core::Object* parent = nullptr);
NonnullRefPtr<GAction> make_paste_action(Function<void(GAction&)>, Core::Object* parent = nullptr);
NonnullRefPtr<GAction> make_delete_action(Function<void(GAction&)>, Core::Object* parent = nullptr);
NonnullRefPtr<GAction> make_move_to_front_action(Function<void(GAction&)>, Core::Object* parent = nullptr);
NonnullRefPtr<GAction> make_move_to_back_action(Function<void(GAction&)>, Core::Object* parent = nullptr);
NonnullRefPtr<GAction> make_fullscreen_action(Function<void(GAction&)>, Core::Object* parent = nullptr);
NonnullRefPtr<GAction> make_quit_action(Function<void(GAction&)>);
NonnullRefPtr<GAction> make_go_back_action(Function<void(GAction&)>, Core::Object* parent = nullptr);
NonnullRefPtr<GAction> make_go_forward_action(Function<void(GAction&)>, Core::Object* parent = nullptr);
NonnullRefPtr<GAction> make_go_home_action(Function<void(GAction&)> callback, Core::Object* parent = nullptr);
NonnullRefPtr<GAction> make_reload_action(Function<void(GAction&)>, Core::Object* parent = nullptr);
class Action;
class ActionGroup;
class Button;
class MenuItem;
namespace CommonActions {
NonnullRefPtr<Action> make_open_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_undo_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_redo_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_cut_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_copy_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_paste_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_delete_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_move_to_front_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_move_to_back_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_fullscreen_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_quit_action(Function<void(Action&)>);
NonnullRefPtr<Action> make_go_back_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_go_forward_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_go_home_action(Function<void(Action&)> callback, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_reload_action(Function<void(Action&)>, Core::Object* parent = nullptr);
};
class GAction final : public Core::Object {
C_OBJECT(GAction)
class Action final : public Core::Object {
C_OBJECT(Action)
public:
enum class ShortcutScope {
None,
@ -70,33 +72,33 @@ public:
WindowLocal,
ApplicationGlobal,
};
static NonnullRefPtr<GAction> create(const StringView& text, Function<void(GAction&)> callback, Core::Object* parent = nullptr)
static NonnullRefPtr<Action> create(const StringView& text, Function<void(Action&)> callback, Core::Object* parent = nullptr)
{
return adopt(*new GAction(text, move(callback), parent));
return adopt(*new Action(text, move(callback), parent));
}
static NonnullRefPtr<GAction> create(const StringView& text, RefPtr<GraphicsBitmap>&& icon, Function<void(GAction&)> callback, Core::Object* parent = nullptr)
static NonnullRefPtr<Action> create(const StringView& text, RefPtr<GraphicsBitmap>&& icon, Function<void(Action&)> callback, Core::Object* parent = nullptr)
{
return adopt(*new GAction(text, move(icon), move(callback), parent));
return adopt(*new Action(text, move(icon), move(callback), parent));
}
static NonnullRefPtr<GAction> create(const StringView& text, const GShortcut& shortcut, Function<void(GAction&)> callback, Core::Object* parent = nullptr)
static NonnullRefPtr<Action> create(const StringView& text, const Shortcut& shortcut, Function<void(Action&)> callback, Core::Object* parent = nullptr)
{
return adopt(*new GAction(text, shortcut, move(callback), parent));
return adopt(*new Action(text, shortcut, move(callback), parent));
}
static NonnullRefPtr<GAction> create(const StringView& text, const GShortcut& shortcut, RefPtr<GraphicsBitmap>&& icon, Function<void(GAction&)> callback, Core::Object* parent = nullptr)
static NonnullRefPtr<Action> create(const StringView& text, const Shortcut& shortcut, RefPtr<GraphicsBitmap>&& icon, Function<void(Action&)> callback, Core::Object* parent = nullptr)
{
return adopt(*new GAction(text, shortcut, move(icon), move(callback), parent));
return adopt(*new Action(text, shortcut, move(icon), move(callback), parent));
}
virtual ~GAction() override;
virtual ~Action() override;
String text() const { return m_text; }
GShortcut shortcut() const { return m_shortcut; }
Shortcut shortcut() const { return m_shortcut; }
const GraphicsBitmap* icon() const { return m_icon.ptr(); }
void set_icon(const GraphicsBitmap* icon) { m_icon = icon; }
const Core::Object* activator() const { return m_activator.ptr(); }
Core::Object* activator() { return m_activator.ptr(); }
Function<void(GAction&)> on_activation;
Function<void(Action&)> on_activation;
void activate(Core::Object* activator = nullptr);
@ -113,21 +115,21 @@ public:
}
void set_checked(bool);
void register_button(Badge<GButton>, GButton&);
void unregister_button(Badge<GButton>, GButton&);
void register_menu_item(Badge<GMenuItem>, GMenuItem&);
void unregister_menu_item(Badge<GMenuItem>, GMenuItem&);
void register_button(Badge<Button>, Button&);
void unregister_button(Badge<Button>, Button&);
void register_menu_item(Badge<MenuItem>, MenuItem&);
void unregister_menu_item(Badge<MenuItem>, MenuItem&);
const GActionGroup* group() const { return m_action_group.ptr(); }
void set_group(Badge<GActionGroup>, GActionGroup*);
const ActionGroup* group() const { return m_action_group.ptr(); }
void set_group(Badge<ActionGroup>, ActionGroup*);
private:
virtual bool is_action() const override { return true; }
GAction(const StringView& text, Function<void(GAction&)> = nullptr, Core::Object* = nullptr);
GAction(const StringView& text, const GShortcut&, Function<void(GAction&)> = nullptr, Core::Object* = nullptr);
GAction(const StringView& text, const GShortcut&, RefPtr<GraphicsBitmap>&& icon, Function<void(GAction&)> = nullptr, Core::Object* = nullptr);
GAction(const StringView& text, RefPtr<GraphicsBitmap>&& icon, Function<void(GAction&)> = nullptr, Core::Object* = nullptr);
Action(const StringView& text, Function<void(Action&)> = nullptr, Core::Object* = nullptr);
Action(const StringView& text, const Shortcut&, Function<void(Action&)> = nullptr, Core::Object* = nullptr);
Action(const StringView& text, const Shortcut&, RefPtr<GraphicsBitmap>&& icon, Function<void(Action&)> = nullptr, Core::Object* = nullptr);
Action(const StringView& text, RefPtr<GraphicsBitmap>&& icon, Function<void(Action&)> = nullptr, Core::Object* = nullptr);
template<typename Callback>
void for_each_toolbar_button(Callback);
@ -136,20 +138,22 @@ private:
String m_text;
RefPtr<GraphicsBitmap> m_icon;
GShortcut m_shortcut;
Shortcut m_shortcut;
bool m_enabled { true };
bool m_checkable { false };
bool m_checked { false };
ShortcutScope m_scope { ShortcutScope::None };
HashTable<GButton*> m_buttons;
HashTable<GMenuItem*> m_menu_items;
WeakPtr<GActionGroup> m_action_group;
HashTable<Button*> m_buttons;
HashTable<MenuItem*> m_menu_items;
WeakPtr<ActionGroup> m_action_group;
WeakPtr<Core::Object> m_activator;
};
}
template<>
inline bool Core::is<GAction>(const Core::Object& object)
inline bool Core::is<GUI::Action>(const Core::Object& object)
{
return object.is_action();
}

View file

@ -27,14 +27,18 @@
#include <LibGUI/GAction.h>
#include <LibGUI/GActionGroup.h>
void GActionGroup::add_action(GAction& action)
namespace GUI {
void ActionGroup::add_action(Action& action)
{
action.set_group({}, this);
m_actions.set(&action);
}
void GActionGroup::remove_action(GAction& action)
void ActionGroup::remove_action(Action& action)
{
action.set_group({}, nullptr);
m_actions.remove(&action);
}
}

View file

@ -29,15 +29,17 @@
#include <AK/HashTable.h>
#include <AK/Weakable.h>
class GAction;
namespace GUI {
class GActionGroup : public Weakable<GActionGroup> {
class Action;
class ActionGroup : public Weakable<ActionGroup> {
public:
GActionGroup() {}
~GActionGroup() {}
ActionGroup() {}
~ActionGroup() {}
void add_action(GAction&);
void remove_action(GAction&);
void add_action(Action&);
void remove_action(Action&);
bool is_exclusive() const { return m_exclusive; }
void set_exclusive(bool exclusive) { m_exclusive = exclusive; }
@ -55,7 +57,9 @@ public:
}
private:
HashTable<GAction*> m_actions;
HashTable<Action*> m_actions;
bool m_exclusive { false };
bool m_unchecking_allowed { false };
};
}

View file

@ -34,34 +34,36 @@
#include <LibGUI/GWindow.h>
#include <LibGUI/GWindowServerConnection.h>
static GApplication* s_the;
namespace GUI {
GApplication& GApplication::the()
static Application* s_the;
Application& Application::the()
{
ASSERT(s_the);
return *s_the;
}
GApplication::GApplication(int argc, char** argv)
Application::Application(int argc, char** argv)
{
(void)argc;
(void)argv;
ASSERT(!s_the);
s_the = this;
m_event_loop = make<Core::EventLoop>();
GWindowServerConnection::the();
WindowServerConnection::the();
if (argc > 0)
m_invoked_as = argv[0];
for (int i = 1; i < argc; i++)
m_args.append(argv[i]);
}
GApplication::~GApplication()
Application::~Application()
{
s_the = nullptr;
}
int GApplication::exec()
int Application::exec()
{
int exit_code = m_event_loop->exec();
// NOTE: Maybe it would be cool to return instead of exit()?
@ -70,12 +72,12 @@ int GApplication::exec()
return exit_code;
}
void GApplication::quit(int exit_code)
void Application::quit(int exit_code)
{
m_event_loop->quit(exit_code);
}
void GApplication::set_menubar(OwnPtr<GMenuBar>&& menubar)
void Application::set_menubar(OwnPtr<MenuBar>&& menubar)
{
if (m_menubar)
m_menubar->notify_removed_from_application({});
@ -84,30 +86,30 @@ void GApplication::set_menubar(OwnPtr<GMenuBar>&& menubar)
m_menubar->notify_added_to_application({});
}
void GApplication::register_global_shortcut_action(Badge<GAction>, GAction& action)
void Application::register_global_shortcut_action(Badge<Action>, Action& action)
{
m_global_shortcut_actions.set(action.shortcut(), &action);
}
void GApplication::unregister_global_shortcut_action(Badge<GAction>, GAction& action)
void Application::unregister_global_shortcut_action(Badge<Action>, Action& action)
{
m_global_shortcut_actions.remove(action.shortcut());
}
GAction* GApplication::action_for_key_event(const GKeyEvent& event)
Action* Application::action_for_key_event(const KeyEvent& event)
{
auto it = m_global_shortcut_actions.find(GShortcut(event.modifiers(), (KeyCode)event.key()));
auto it = m_global_shortcut_actions.find(Shortcut(event.modifiers(), (KeyCode)event.key()));
if (it == m_global_shortcut_actions.end())
return nullptr;
return (*it).value;
}
class GApplication::TooltipWindow final : public GWindow {
class Application::TooltipWindow final : public Window {
public:
TooltipWindow()
{
set_window_type(GWindowType::Tooltip);
m_label = GLabel::construct();
set_window_type(WindowType::Tooltip);
m_label = Label::construct();
m_label->set_background_color(Color::from_rgb(0xdac7b5));
m_label->set_fill_with_background_color(true);
m_label->set_frame_thickness(1);
@ -124,10 +126,10 @@ public:
m_label->set_text(tooltip);
}
RefPtr<GLabel> m_label;
RefPtr<Label> m_label;
};
void GApplication::show_tooltip(const StringView& tooltip, const Point& screen_location)
void Application::show_tooltip(const StringView& tooltip, const Point& screen_location)
{
if (!m_tooltip_window) {
m_tooltip_window = new TooltipWindow;
@ -135,7 +137,7 @@ void GApplication::show_tooltip(const StringView& tooltip, const Point& screen_l
}
m_tooltip_window->set_tooltip(tooltip);
Rect desktop_rect = GDesktop::the().rect();
Rect desktop_rect = Desktop::the().rect();
const int margin = 30;
Point adjusted_pos = screen_location;
@ -150,7 +152,7 @@ void GApplication::show_tooltip(const StringView& tooltip, const Point& screen_l
m_tooltip_window->show();
}
void GApplication::hide_tooltip()
void Application::hide_tooltip()
{
if (m_tooltip_window) {
m_tooltip_window->hide();
@ -158,19 +160,19 @@ void GApplication::hide_tooltip()
}
}
void GApplication::did_create_window(Badge<GWindow>)
void Application::did_create_window(Badge<Window>)
{
if (m_event_loop->was_exit_requested())
m_event_loop->unquit();
}
void GApplication::did_delete_last_window(Badge<GWindow>)
void Application::did_delete_last_window(Badge<Window>)
{
if (m_quit_when_last_window_deleted)
m_event_loop->quit(0);
}
void GApplication::set_system_palette(SharedBuffer& buffer)
void Application::set_system_palette(SharedBuffer& buffer)
{
if (!m_system_palette)
m_system_palette = PaletteImpl::create_with_shared_buffer(buffer);
@ -181,7 +183,9 @@ void GApplication::set_system_palette(SharedBuffer& buffer)
m_palette = m_system_palette;
}
void GApplication::set_palette(const Palette& palette)
void Application::set_palette(const Palette& palette)
{
m_palette = palette.impl();
}
}

View file

@ -38,29 +38,30 @@ class SharedBuffer;
namespace Core {
class EventLoop;
}
class GAction;
class GKeyEvent;
class GMenuBar;
class GWindow;
class GWindowServerConnection;
class Palette;
class Point;
class GApplication {
namespace GUI {
class Action;
class KeyEvent;
class MenuBar;
class Window;
class WindowServerConnection;
class Application {
public:
static GApplication& the();
GApplication(int argc, char** argv);
~GApplication();
static Application& the();
Application(int argc, char** argv);
~Application();
int exec();
void quit(int = 0);
void set_menubar(OwnPtr<GMenuBar>&&);
GAction* action_for_key_event(const GKeyEvent&);
void set_menubar(OwnPtr<MenuBar>&&);
Action* action_for_key_event(const KeyEvent&);
void register_global_shortcut_action(Badge<GAction>, GAction&);
void unregister_global_shortcut_action(Badge<GAction>, GAction&);
void register_global_shortcut_action(Badge<Action>, Action&);
void unregister_global_shortcut_action(Badge<Action>, Action&);
void show_tooltip(const StringView&, const Point& screen_location);
void hide_tooltip();
@ -68,8 +69,8 @@ public:
bool quit_when_last_window_deleted() const { return m_quit_when_last_window_deleted; }
void set_quit_when_last_window_deleted(bool b) { m_quit_when_last_window_deleted = b; }
void did_create_window(Badge<GWindow>);
void did_delete_last_window(Badge<GWindow>);
void did_create_window(Badge<Window>);
void did_delete_last_window(Badge<Window>);
const String& invoked_as() const { return m_invoked_as; }
const Vector<String>& args() const { return m_args; }
@ -81,13 +82,15 @@ public:
private:
OwnPtr<Core::EventLoop> m_event_loop;
OwnPtr<GMenuBar> m_menubar;
OwnPtr<MenuBar> m_menubar;
RefPtr<PaletteImpl> m_palette;
RefPtr<PaletteImpl> m_system_palette;
HashMap<GShortcut, GAction*> m_global_shortcut_actions;
HashMap<Shortcut, Action*> m_global_shortcut_actions;
class TooltipWindow;
TooltipWindow* m_tooltip_window { nullptr };
bool m_quit_when_last_window_deleted { true };
String m_invoked_as;
Vector<String> m_args;
};
}

View file

@ -25,24 +25,25 @@
*/
#include <LibGUI/GBoxLayout.h>
#include <LibGUI/GWidget.h>
#include <stdio.h>
//#define GBOXLAYOUT_DEBUG
GBoxLayout::GBoxLayout(Orientation orientation)
namespace GUI {
BoxLayout::BoxLayout(Orientation orientation)
: m_orientation(orientation)
{
}
void GBoxLayout::run(GWidget& widget)
void BoxLayout::run(Widget& widget)
{
bool should_log = false;
#ifdef GBOXLAYOUT_DEBUG
should_log = true;
#endif
if (should_log)
dbgprintf("GBoxLayout: running layout on %s{%p}, entry count: %d\n", widget.class_name(), &widget, m_entries.size());
dbgprintf("BoxLayout: running layout on %s{%p}, entry count: %d\n", widget.class_name(), &widget, m_entries.size());
if (m_entries.is_empty())
return;
@ -53,7 +54,7 @@ void GBoxLayout::run(GWidget& widget)
int number_of_visible_entries = 0;
if (should_log)
dbgprintf("GBoxLayout: Starting with available size: %s\n", available_size.to_string().characters());
dbgprintf("BoxLayout: Starting with available size: %s\n", available_size.to_string().characters());
for (auto& entry : m_entries) {
if (entry.type == Entry::Type::Spacer) {
@ -67,12 +68,12 @@ void GBoxLayout::run(GWidget& widget)
++number_of_visible_entries;
if (entry.widget && entry.widget->size_policy(orientation()) == SizePolicy::Fixed) {
if (should_log) {
dbgprintf("GBoxLayout: Subtracting for fixed %s{%p}, size: %s\n", entry.widget->class_name(), entry.widget.ptr(), entry.widget->preferred_size().to_string().characters());
dbgprintf("GBoxLayout: Available size before: %s\n", available_size.to_string().characters());
dbgprintf("BoxLayout: Subtracting for fixed %s{%p}, size: %s\n", entry.widget->class_name(), entry.widget.ptr(), entry.widget->preferred_size().to_string().characters());
dbgprintf("BoxLayout: Available size before: %s\n", available_size.to_string().characters());
}
available_size -= entry.widget->preferred_size();
if (should_log)
dbgprintf("GBoxLayout: Available size after: %s\n", available_size.to_string().characters());
dbgprintf("BoxLayout: Available size after: %s\n", available_size.to_string().characters());
++number_of_entries_with_fixed_size;
}
available_size -= { spacing(), spacing() };
@ -83,12 +84,12 @@ void GBoxLayout::run(GWidget& widget)
available_size -= { margins().left() + margins().right(), margins().top() + margins().bottom() };
if (should_log)
dbgprintf("GBoxLayout: Number of visible: %d/%d\n", number_of_visible_entries, m_entries.size());
dbgprintf("BoxLayout: Number of visible: %d/%d\n", number_of_visible_entries, m_entries.size());
int number_of_entries_with_automatic_size = number_of_visible_entries - number_of_entries_with_fixed_size;
if (should_log)
dbgprintf("GBoxLayout: available_size=%s, fixed=%d, fill=%d\n", available_size.to_string().characters(), number_of_entries_with_fixed_size, number_of_entries_with_automatic_size);
dbgprintf("BoxLayout: available_size=%s, fixed=%d, fill=%d\n", available_size.to_string().characters(), number_of_entries_with_fixed_size, number_of_entries_with_automatic_size);
Size automatic_size;
@ -103,7 +104,7 @@ void GBoxLayout::run(GWidget& widget)
}
if (should_log)
dbgprintf("GBoxLayout: automatic_size=%s\n", automatic_size.to_string().characters());
dbgprintf("BoxLayout: automatic_size=%s\n", automatic_size.to_string().characters());
int current_x = margins().left();
int current_y = margins().top();
@ -143,7 +144,7 @@ void GBoxLayout::run(GWidget& widget)
}
if (should_log)
dbgprintf("GBoxLayout: apply, %s{%p} <- %s\n", entry.widget->class_name(), entry.widget.ptr(), rect.to_string().characters());
dbgprintf("BoxLayout: apply, %s{%p} <- %s\n", entry.widget->class_name(), entry.widget.ptr(), rect.to_string().characters());
entry.widget->set_relative_rect(rect);
if (orientation() == Orientation::Horizontal)
@ -152,3 +153,5 @@ void GBoxLayout::run(GWidget& widget)
current_y += rect.height() + spacing();
}
}
}

View file

@ -29,33 +29,37 @@
#include <LibGUI/GLayout.h>
#include <LibGUI/GWidget.h>
class GBoxLayout : public GLayout {
namespace GUI {
class BoxLayout : public Layout {
public:
explicit GBoxLayout(Orientation);
virtual ~GBoxLayout() override {}
explicit BoxLayout(Orientation);
virtual ~BoxLayout() override {}
Orientation orientation() const { return m_orientation; }
virtual void run(GWidget&) override;
virtual void run(Widget&) override;
private:
Orientation m_orientation;
};
class GVBoxLayout final : public GBoxLayout {
class VBoxLayout final : public BoxLayout {
public:
explicit GVBoxLayout()
: GBoxLayout(Orientation::Vertical)
explicit VBoxLayout()
: BoxLayout(Orientation::Vertical)
{
}
virtual ~GVBoxLayout() override {}
virtual ~VBoxLayout() override {}
};
class GHBoxLayout final : public GBoxLayout {
class HBoxLayout final : public BoxLayout {
public:
explicit GHBoxLayout()
: GBoxLayout(Orientation::Horizontal)
explicit HBoxLayout()
: BoxLayout(Orientation::Horizontal)
{
}
virtual ~GHBoxLayout() override {}
virtual ~HBoxLayout() override {}
};
}

View file

@ -32,25 +32,27 @@
#include <LibGUI/GButton.h>
#include <LibGUI/GPainter.h>
GButton::GButton(GWidget* parent)
: GAbstractButton(parent)
namespace GUI {
Button::Button(Widget* parent)
: AbstractButton(parent)
{
}
GButton::GButton(const StringView& text, GWidget* parent)
: GAbstractButton(text, parent)
Button::Button(const StringView& text, Widget* parent)
: AbstractButton(text, parent)
{
}
GButton::~GButton()
Button::~Button()
{
if (m_action)
m_action->unregister_button({}, *this);
}
void GButton::paint_event(GPaintEvent& event)
void Button::paint_event(PaintEvent& event)
{
GPainter painter(*this);
Painter painter(*this);
painter.add_clip_rect(event.rect());
StylePainter::paint_button(painter, rect(), palette(), m_button_style, is_being_pressed(), is_hovered(), is_checked(), is_enabled());
@ -83,7 +85,7 @@ void GButton::paint_event(GPaintEvent& event)
paint_text(painter, text_rect, font, text_alignment());
}
void GButton::click()
void Button::click()
{
if (!is_enabled())
return;
@ -98,7 +100,7 @@ void GButton::click()
m_action->activate(this);
}
void GButton::set_action(GAction& action)
void Button::set_action(Action& action)
{
m_action = action.make_weak_ptr();
action.register_button({}, *this);
@ -108,7 +110,7 @@ void GButton::set_action(GAction& action)
set_checked(action.is_checked());
}
void GButton::set_icon(RefPtr<GraphicsBitmap>&& icon)
void Button::set_icon(RefPtr<GraphicsBitmap>&& icon)
{
if (m_icon == icon)
return;
@ -116,7 +118,7 @@ void GButton::set_icon(RefPtr<GraphicsBitmap>&& icon)
update();
}
bool GButton::is_uncheckable() const
bool Button::is_uncheckable() const
{
if (!m_action)
return true;
@ -124,3 +126,5 @@ bool GButton::is_uncheckable() const
return true;
return m_action->group()->is_unchecking_allowed();
}
}

View file

@ -33,12 +33,14 @@
#include <LibDraw/TextAlignment.h>
#include <LibGUI/GAbstractButton.h>
class GAction;
namespace GUI {
class GButton : public GAbstractButton {
C_OBJECT(GButton)
class Action;
class Button : public AbstractButton {
C_OBJECT(Button)
public:
virtual ~GButton() override;
virtual ~Button() override;
void set_icon(RefPtr<GraphicsBitmap>&&);
const GraphicsBitmap* icon() const { return m_icon.ptr(); }
@ -47,14 +49,14 @@ public:
void set_text_alignment(TextAlignment text_alignment) { m_text_alignment = text_alignment; }
TextAlignment text_alignment() const { return m_text_alignment; }
Function<void(GButton&)> on_click;
Function<void(Button&)> on_click;
void set_button_style(ButtonStyle style) { m_button_style = style; }
ButtonStyle button_style() const { return m_button_style; }
virtual void click() override;
void set_action(GAction&);
void set_action(Action&);
virtual bool accepts_focus() const override { return m_focusable; }
virtual bool is_uncheckable() const override;
@ -62,14 +64,16 @@ public:
void set_focusable(bool b) { m_focusable = b; }
protected:
GButton(const StringView& text, GWidget* parent);
explicit GButton(GWidget* parent);
virtual void paint_event(GPaintEvent&) override;
Button(const StringView& text, Widget* parent);
explicit Button(Widget* parent);
virtual void paint_event(PaintEvent&) override;
private:
RefPtr<GraphicsBitmap> m_icon;
ButtonStyle m_button_style { ButtonStyle::Normal };
TextAlignment m_text_alignment { TextAlignment::Center };
WeakPtr<GAction> m_action;
WeakPtr<Action> m_action;
bool m_focusable { true };
};
}

View file

@ -31,6 +31,8 @@
#include <LibGUI/GCheckBox.h>
#include <LibGUI/GPainter.h>
namespace GUI {
static const char* s_checked_bitmap_data = {
" "
" # "
@ -49,23 +51,23 @@ static const int s_checked_bitmap_height = 9;
static const int s_box_width = 13;
static const int s_box_height = 13;
GCheckBox::GCheckBox(GWidget* parent)
: GAbstractButton(parent)
CheckBox::CheckBox(Widget* parent)
: AbstractButton(parent)
{
}
GCheckBox::GCheckBox(const StringView& text, GWidget* parent)
: GAbstractButton(text, parent)
CheckBox::CheckBox(const StringView& text, Widget* parent)
: AbstractButton(text, parent)
{
}
GCheckBox::~GCheckBox()
CheckBox::~CheckBox()
{
}
void GCheckBox::paint_event(GPaintEvent& event)
void CheckBox::paint_event(PaintEvent& event)
{
GPainter painter(*this);
Painter painter(*this);
painter.add_clip_rect(event.rect());
auto text_rect = rect();
@ -96,9 +98,11 @@ void GCheckBox::paint_event(GPaintEvent& event)
paint_text(painter, text_rect, font(), TextAlignment::TopLeft);
}
void GCheckBox::click()
void CheckBox::click()
{
if (!is_enabled())
return;
set_checked(!is_checked());
}
}

View file

@ -30,20 +30,24 @@
#include <AK/String.h>
#include <LibGUI/GAbstractButton.h>
class GCheckBox : public GAbstractButton {
C_OBJECT(GCheckBox)
namespace GUI {
class CheckBox : public AbstractButton {
C_OBJECT(CheckBox)
public:
virtual ~GCheckBox() override;
virtual ~CheckBox() override;
virtual void click() override;
private:
GCheckBox(const StringView&, GWidget* parent);
explicit GCheckBox(GWidget* parent);
CheckBox(const StringView&, Widget* parent);
explicit CheckBox(Widget* parent);
// These don't make sense for a check box, so hide them.
using GAbstractButton::auto_repeat_interval;
using GAbstractButton::set_auto_repeat_interval;
using AbstractButton::auto_repeat_interval;
using AbstractButton::set_auto_repeat_interval;
virtual void paint_event(GPaintEvent&) override;
virtual void paint_event(PaintEvent&) override;
};
}

View file

@ -28,30 +28,32 @@
#include <LibGUI/GClipboard.h>
#include <LibGUI/GWindowServerConnection.h>
GClipboard& GClipboard::the()
namespace GUI {
Clipboard& Clipboard::the()
{
static GClipboard* s_the;
static Clipboard* s_the;
if (!s_the)
s_the = new GClipboard;
s_the = new Clipboard;
return *s_the;
}
GClipboard::GClipboard()
Clipboard::Clipboard()
{
}
GClipboard::DataAndType GClipboard::data_and_type() const
Clipboard::DataAndType Clipboard::data_and_type() const
{
auto response = GWindowServerConnection::the().send_sync<WindowServer::GetClipboardContents>();
auto response = WindowServerConnection::the().send_sync<WindowServer::GetClipboardContents>();
if (response->shared_buffer_id() < 0)
return {};
auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(response->shared_buffer_id());
if (!shared_buffer) {
dbgprintf("GClipboard::data() failed to attach to the shared buffer\n");
dbgprintf("GUI::Clipboard::data() failed to attach to the shared buffer\n");
return {};
}
if (response->content_size() > shared_buffer->size()) {
dbgprintf("GClipboard::data() clipping contents size is greater than shared buffer size\n");
dbgprintf("GUI::Clipboard::data() clipping contents size is greater than shared buffer size\n");
return {};
}
auto data = String((const char*)shared_buffer->data(), response->content_size());
@ -59,11 +61,11 @@ GClipboard::DataAndType GClipboard::data_and_type() const
return { data, type };
}
void GClipboard::set_data(const StringView& data, const String& type)
void Clipboard::set_data(const StringView& data, const String& type)
{
auto shared_buffer = SharedBuffer::create_with_size(data.length() + 1);
if (!shared_buffer) {
dbgprintf("GClipboard::set_data() failed to create a shared buffer\n");
dbgprintf("GUI::Clipboard::set_data() failed to create a shared buffer\n");
return;
}
if (!data.is_empty())
@ -71,13 +73,15 @@ void GClipboard::set_data(const StringView& data, const String& type)
else
((u8*)shared_buffer->data())[0] = '\0';
shared_buffer->seal();
shared_buffer->share_with(GWindowServerConnection::the().server_pid());
shared_buffer->share_with(WindowServerConnection::the().server_pid());
GWindowServerConnection::the().send_sync<WindowServer::SetClipboardContents>(shared_buffer->shared_buffer_id(), data.length(), type);
WindowServerConnection::the().send_sync<WindowServer::SetClipboardContents>(shared_buffer->shared_buffer_id(), data.length(), type);
}
void GClipboard::did_receive_clipboard_contents_changed(Badge<GWindowServerConnection>, const String& data_type)
void Clipboard::did_receive_clipboard_contents_changed(Badge<WindowServerConnection>, const String& data_type)
{
if (on_content_change)
on_content_change(data_type);
}
}

View file

@ -30,11 +30,13 @@
#include <AK/Function.h>
#include <AK/String.h>
class GWindowServerConnection;
namespace GUI {
class GClipboard {
class WindowServerConnection;
class Clipboard {
public:
static GClipboard& the();
static Clipboard& the();
String data() const { return data_and_type().data; }
String type() const { return data_and_type().type; }
@ -47,10 +49,12 @@ public:
DataAndType data_and_type() const;
void did_receive_clipboard_contents_changed(Badge<GWindowServerConnection>, const String& data_type);
void did_receive_clipboard_contents_changed(Badge<WindowServerConnection>, const String& data_type);
Function<void(const String& data_type)> on_content_change;
private:
GClipboard();
Clipboard();
};
}

View file

@ -31,31 +31,33 @@
#include <LibGUI/GSpinBox.h>
#include <LibGUI/GWidget.h>
GColorPicker::GColorPicker(Color color, Core::Object* parent)
: GDialog(parent)
namespace GUI {
ColorPicker::ColorPicker(Color color, Core::Object* parent)
: Dialog(parent)
, m_color(color)
{
set_title("Edit Color");
build();
}
GColorPicker::~GColorPicker()
ColorPicker::~ColorPicker()
{
}
void GColorPicker::build()
void ColorPicker::build()
{
auto horizontal_container = GWidget::construct();
auto horizontal_container = Widget::construct();
horizontal_container->set_fill_with_background_color(true);
horizontal_container->set_layout(make<GHBoxLayout>());
horizontal_container->set_layout(make<HBoxLayout>());
horizontal_container->layout()->set_margins({ 4, 4, 4, 4 });
set_main_widget(horizontal_container);
auto left_vertical_container = GWidget::construct(horizontal_container.ptr());
left_vertical_container->set_layout(make<GVBoxLayout>());
auto left_vertical_container = Widget::construct(horizontal_container.ptr());
left_vertical_container->set_layout(make<VBoxLayout>());
auto right_vertical_container = GWidget::construct(horizontal_container.ptr());
right_vertical_container->set_layout(make<GVBoxLayout>());
auto right_vertical_container = Widget::construct(horizontal_container.ptr());
right_vertical_container->set_layout(make<VBoxLayout>());
enum RGBComponent {
Red,
@ -63,27 +65,27 @@ void GColorPicker::build()
Blue
};
m_preview_widget = GFrame::construct(right_vertical_container);
m_preview_widget = Frame::construct(right_vertical_container);
auto pal = m_preview_widget->palette();
pal.set_color(ColorRole::Background, m_color);
m_preview_widget->set_fill_with_background_color(true);
m_preview_widget->set_palette(pal);
right_vertical_container->layout()->add_spacer();
auto cancel_button = GButton::construct("Cancel", right_vertical_container);
auto cancel_button = Button::construct("Cancel", right_vertical_container);
cancel_button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
cancel_button->set_preferred_size(0, 20);
cancel_button->on_click = [&](auto&) {
done(GDialog::ExecCancel);
done(Dialog::ExecCancel);
};
auto ok_button = GButton::construct("Okay", right_vertical_container);
auto ok_button = Button::construct("Okay", right_vertical_container);
ok_button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
ok_button->set_preferred_size(0, 20);
ok_button->on_click = [&](auto&) {
done(GDialog::ExecOK);
done(Dialog::ExecOK);
};
auto make_spinbox = [&](RGBComponent component, int initial_value) {
auto spinbox = GSpinBox::construct(left_vertical_container);
auto spinbox = SpinBox::construct(left_vertical_container);
spinbox->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
spinbox->set_preferred_size(0, 20);
spinbox->set_min(0);
@ -110,3 +112,5 @@ void GColorPicker::build()
make_spinbox(Green, m_color.green());
make_spinbox(Blue, m_color.blue());
}
}

View file

@ -28,20 +28,24 @@
#include <LibGUI/GDialog.h>
class GFrame;
namespace GUI {
class GColorPicker final : public GDialog {
C_OBJECT(GColorPicker)
class Frame;
class ColorPicker final : public Dialog {
C_OBJECT(ColorPicker)
public:
virtual ~GColorPicker() override;
virtual ~ColorPicker() override;
Color color() const { return m_color; }
private:
explicit GColorPicker(Color, Core::Object* parent = nullptr);
explicit ColorPicker(Color, Core::Object* parent = nullptr);
void build();
Color m_color;
RefPtr<GFrame> m_preview_widget;
RefPtr<Frame> m_preview_widget;
};
}

View file

@ -29,6 +29,8 @@
#include <LibGUI/GPainter.h>
#include <LibGUI/GScrollBar.h>
namespace GUI {
static const char* s_arrow_bitmap_data = {
" "
" # "
@ -43,8 +45,8 @@ static const char* s_arrow_bitmap_data = {
static const int s_arrow_bitmap_width = 9;
static const int s_arrow_bitmap_height = 9;
GColumnsView::GColumnsView(GWidget* parent)
: GAbstractView(parent)
ColumnsView::ColumnsView(Widget* parent)
: AbstractView(parent)
{
set_fill_with_background_color(true);
set_background_role(ColorRole::Base);
@ -56,18 +58,18 @@ GColumnsView::GColumnsView(GWidget* parent)
m_columns.append({ {}, 0 });
}
GColumnsView::~GColumnsView()
ColumnsView::~ColumnsView()
{
}
void GColumnsView::paint_event(GPaintEvent& event)
void ColumnsView::paint_event(PaintEvent& event)
{
GAbstractView::paint_event(event);
AbstractView::paint_event(event);
if (!model())
return;
GPainter painter(*this);
Painter painter(*this);
painter.add_clip_rect(frame_inner_rect());
painter.add_clip_rect(event.rect());
painter.translate(frame_thickness(), frame_thickness());
@ -83,7 +85,7 @@ void GColumnsView::paint_event(GPaintEvent& event)
int row_count = model()->row_count(column.parent_index);
for (int row = 0; row < row_count; row++) {
GModelIndex index = model()->index(row, m_model_column, column.parent_index);
ModelIndex index = model()->index(row, m_model_column, column.parent_index);
ASSERT(index.is_valid());
bool is_selected_row = selection().contains(index);
@ -102,7 +104,7 @@ void GColumnsView::paint_event(GPaintEvent& event)
Rect row_rect { column_x, row * item_height(), column.width, item_height() };
painter.fill_rect(row_rect, background_color);
auto icon = model()->data(index, GModel::Role::Icon);
auto icon = model()->data(index, Model::Role::Icon);
Rect icon_rect = { column_x + icon_spacing(), 0, icon_size(), icon_size() };
icon_rect.center_vertically_within(row_rect);
if (icon.is_icon())
@ -136,12 +138,12 @@ void GColumnsView::paint_event(GPaintEvent& event)
}
}
void GColumnsView::push_column(GModelIndex& parent_index)
void ColumnsView::push_column(ModelIndex& parent_index)
{
ASSERT(model());
// Drop columns at the end.
GModelIndex grandparent = model()->parent_index(parent_index);
ModelIndex grandparent = model()->parent_index(parent_index);
for (int i = m_columns.size() - 1; i > 0; i--) {
if (m_columns[i].parent_index == grandparent)
break;
@ -156,7 +158,7 @@ void GColumnsView::push_column(GModelIndex& parent_index)
update();
}
void GColumnsView::update_column_sizes()
void ColumnsView::update_column_sizes()
{
if (!model())
return;
@ -173,7 +175,7 @@ void GColumnsView::update_column_sizes()
column.width = 10;
for (int row = 0; row < row_count; row++) {
GModelIndex index = model()->index(row, m_model_column, column.parent_index);
ModelIndex index = model()->index(row, m_model_column, column.parent_index);
ASSERT(index.is_valid());
auto text = model()->data(index).to_string();
int row_width = icon_spacing() + icon_size() + icon_spacing() + font().width(text) + icon_spacing() + s_arrow_bitmap_width + icon_spacing();
@ -186,7 +188,7 @@ void GColumnsView::update_column_sizes()
set_content_size({ total_width, total_height });
}
GModelIndex GColumnsView::index_at_event_position(const Point& a_position) const
ModelIndex ColumnsView::index_at_event_position(const Point& a_position) const
{
if (!model())
return {};
@ -214,14 +216,14 @@ GModelIndex GColumnsView::index_at_event_position(const Point& a_position) const
return {};
}
void GColumnsView::mousedown_event(GMouseEvent& event)
void ColumnsView::mousedown_event(MouseEvent& event)
{
GAbstractView::mousedown_event(event);
AbstractView::mousedown_event(event);
if (!model())
return;
if (event.button() != GMouseButton::Left)
if (event.button() != MouseButton::Left)
return;
auto index = index_at_event_position(event.position());
@ -231,9 +233,9 @@ void GColumnsView::mousedown_event(GMouseEvent& event)
}
}
void GColumnsView::did_update_model()
void ColumnsView::did_update_model()
{
GAbstractView::did_update_model();
AbstractView::did_update_model();
// FIXME: Don't drop the columns on minor updates.
dbg() << "Model was updated; dropping columns :(";
@ -244,7 +246,7 @@ void GColumnsView::did_update_model()
update();
}
void GColumnsView::keydown_event(GKeyEvent& event)
void ColumnsView::keydown_event(KeyEvent& event)
{
if (!model())
return;
@ -256,7 +258,7 @@ void GColumnsView::keydown_event(GKeyEvent& event)
}
if (event.key() == KeyCode::Key_Up) {
GModelIndex new_index;
ModelIndex new_index;
if (!selection().is_empty()) {
auto old_index = selection().first();
auto parent_index = model.parent_index(old_index);
@ -273,7 +275,7 @@ void GColumnsView::keydown_event(GKeyEvent& event)
}
if (event.key() == KeyCode::Key_Down) {
GModelIndex new_index;
ModelIndex new_index;
if (!selection().is_empty()) {
auto old_index = selection().first();
auto parent_index = model.parent_index(old_index);
@ -290,7 +292,7 @@ void GColumnsView::keydown_event(GKeyEvent& event)
}
if (event.key() == KeyCode::Key_Left) {
GModelIndex new_index;
ModelIndex new_index;
if (!selection().is_empty()) {
auto old_index = selection().first();
new_index = model.parent_index(old_index);
@ -305,7 +307,7 @@ void GColumnsView::keydown_event(GKeyEvent& event)
}
if (event.key() == KeyCode::Key_Right) {
GModelIndex old_index, new_index;
ModelIndex old_index, new_index;
if (!selection().is_empty()) {
old_index = selection().first();
new_index = model.index(0, m_model_column, old_index);
@ -321,3 +323,5 @@ void GColumnsView::keydown_event(GKeyEvent& event)
return;
}
}
}

View file

@ -29,18 +29,20 @@
#include <AK/Vector.h>
#include <LibGUI/GAbstractView.h>
class GColumnsView : public GAbstractView {
C_OBJECT(GColumnsView)
namespace GUI {
class ColumnsView : public AbstractView {
C_OBJECT(ColumnsView)
public:
int model_column() const { return m_model_column; }
void set_model_column(int column) { m_model_column = column; }
virtual GModelIndex index_at_event_position(const Point&) const override;
virtual ModelIndex index_at_event_position(const Point&) const override;
private:
GColumnsView(GWidget* parent = nullptr);
virtual ~GColumnsView();
void push_column(GModelIndex& parent_index);
ColumnsView(Widget* parent = nullptr);
virtual ~ColumnsView();
void push_column(ModelIndex& parent_index);
void update_column_sizes();
int item_height() const { return 16; }
@ -49,12 +51,12 @@ private:
int text_padding() const { return 2; }
virtual void did_update_model() override;
virtual void paint_event(GPaintEvent&) override;
virtual void mousedown_event(GMouseEvent& event) override;
virtual void keydown_event(GKeyEvent& event) override;
virtual void paint_event(PaintEvent&) override;
virtual void mousedown_event(MouseEvent& event) override;
virtual void keydown_event(KeyEvent& event) override;
struct Column {
GModelIndex parent_index;
ModelIndex parent_index;
int width;
// TODO: per-column vertical scroll?
};
@ -62,3 +64,5 @@ private:
Vector<Column> m_columns;
int m_model_column { 0 };
};
}

View file

@ -32,10 +32,12 @@
#include <LibGUI/GTextEditor.h>
#include <LibGUI/GWindow.h>
GComboBox::GComboBox(GWidget* parent)
: GWidget(parent)
namespace GUI {
ComboBox::ComboBox(Widget* parent)
: Widget(parent)
{
m_editor = GTextEditor::construct(GTextEditor::Type::SingleLine, this);
m_editor = TextEditor::construct(TextEditor::Type::SingleLine, this);
m_editor->on_change = [this] {
if (on_change)
on_change(m_editor->text(), m_list_view->selection().first());
@ -44,7 +46,7 @@ GComboBox::GComboBox(GWidget* parent)
if (on_return_pressed)
on_return_pressed();
};
m_open_button = GButton::construct(this);
m_open_button = Button::construct(this);
m_open_button->set_focusable(false);
m_open_button->set_text("\xc3\xb7");
m_open_button->on_click = [this](auto&) {
@ -54,11 +56,11 @@ GComboBox::GComboBox(GWidget* parent)
open();
};
m_list_window = GWindow::construct(this);
m_list_window = Window::construct(this);
// FIXME: This is obviously not a tooltip window, but it's the closest thing to what we want atm.
m_list_window->set_window_type(GWindowType::Tooltip);
m_list_window->set_window_type(WindowType::Tooltip);
m_list_view = GListView::construct(nullptr);
m_list_view = ListView::construct(nullptr);
m_list_view->horizontal_scrollbar().set_visible(false);
m_list_window->set_main_widget(m_list_view);
@ -75,11 +77,11 @@ GComboBox::GComboBox(GWidget* parent)
};
}
GComboBox::~GComboBox()
ComboBox::~ComboBox()
{
}
void GComboBox::resize_event(GResizeEvent& event)
void ComboBox::resize_event(ResizeEvent& event)
{
int frame_thickness = m_editor->frame_thickness();
int button_height = event.size().height() - frame_thickness * 2;
@ -88,17 +90,17 @@ void GComboBox::resize_event(GResizeEvent& event)
m_editor->set_relative_rect(0, 0, width(), height());
}
void GComboBox::set_model(NonnullRefPtr<GModel> model)
void ComboBox::set_model(NonnullRefPtr<Model> model)
{
m_list_view->set_model(move(model));
}
void GComboBox::select_all()
void ComboBox::select_all()
{
m_editor->select_all();
}
void GComboBox::open()
void ComboBox::open()
{
if (!model())
return;
@ -117,32 +119,34 @@ void GComboBox::open()
};
Rect list_window_rect { my_screen_rect.bottom_left(), size };
list_window_rect.intersect(GDesktop::the().rect().shrunken(0, 128));
list_window_rect.intersect(Desktop::the().rect().shrunken(0, 128));
m_list_window->set_rect(list_window_rect);
m_list_window->show();
}
void GComboBox::close()
void ComboBox::close()
{
m_list_window->hide();
m_editor->set_focus(true);
}
String GComboBox::text() const
String ComboBox::text() const
{
return m_editor->text();
}
void GComboBox::set_text(const String& text)
void ComboBox::set_text(const String& text)
{
m_editor->set_text(text);
}
void GComboBox::set_only_allow_values_from_model(bool b)
void ComboBox::set_only_allow_values_from_model(bool b)
{
if (m_only_allow_values_from_model == b)
return;
m_only_allow_values_from_model = b;
m_editor->set_readonly(m_only_allow_values_from_model);
}
}

View file

@ -29,13 +29,15 @@
#include <LibGUI/GListView.h>
#include <LibGUI/GWidget.h>
class GButton;
class GTextEditor;
namespace GUI {
class GComboBox : public GWidget {
C_OBJECT(GComboBox)
class Button;
class TextEditor;
class ComboBox : public Widget {
C_OBJECT(ComboBox)
public:
virtual ~GComboBox() override;
virtual ~ComboBox() override;
String text() const;
void set_text(const String&);
@ -44,9 +46,9 @@ public:
void close();
void select_all();
GModel* model() { return m_list_view->model(); }
const GModel* model() const { return m_list_view->model(); }
void set_model(NonnullRefPtr<GModel>);
Model* model() { return m_list_view->model(); }
const Model* model() const { return m_list_view->model(); }
void set_model(NonnullRefPtr<Model>);
bool only_allow_values_from_model() const { return m_only_allow_values_from_model; }
void set_only_allow_values_from_model(bool);
@ -54,17 +56,19 @@ public:
int model_column() const { return m_list_view->model_column(); }
void set_model_column(int column) { m_list_view->set_model_column(column); }
Function<void(const String&, const GModelIndex&)> on_change;
Function<void(const String&, const ModelIndex&)> on_change;
Function<void()> on_return_pressed;
protected:
explicit GComboBox(GWidget* parent = nullptr);
virtual void resize_event(GResizeEvent&) override;
explicit ComboBox(Widget* parent = nullptr);
virtual void resize_event(ResizeEvent&) override;
private:
RefPtr<GTextEditor> m_editor;
RefPtr<GButton> m_open_button;
RefPtr<GWindow> m_list_window;
RefPtr<GListView> m_list_view;
RefPtr<TextEditor> m_editor;
RefPtr<Button> m_open_button;
RefPtr<Window> m_list_window;
RefPtr<ListView> m_list_view;
bool m_only_allow_values_from_model { false };
};
}

View file

@ -26,6 +26,10 @@
#include <LibGUI/GCommand.h>
GCommand::~GCommand()
namespace GUI {
Command::~Command()
{
}
}

View file

@ -28,9 +28,11 @@
#include <AK/String.h>
class GCommand {
namespace GUI {
class Command {
public:
virtual ~GCommand();
virtual ~Command();
virtual void undo() {}
virtual void redo() {}
@ -38,9 +40,11 @@ public:
String action_text() const { return m_action_text; }
protected:
GCommand() {}
Command() {}
void set_action_text(const String& text) { m_action_text = text; }
private:
String m_action_text;
};
}

View file

@ -30,19 +30,21 @@
#include <string.h>
#include <unistd.h>
GDesktop& GDesktop::the()
namespace GUI {
Desktop& Desktop::the()
{
static GDesktop* the;
static Desktop* the;
if (!the)
the = new GDesktop;
the = new Desktop;
return *the;
}
GDesktop::GDesktop()
Desktop::Desktop()
{
}
void GDesktop::did_receive_screen_rect(Badge<GWindowServerConnection>, const Rect& rect)
void Desktop::did_receive_screen_rect(Badge<WindowServerConnection>, const Rect& rect)
{
if (m_rect == rect)
return;
@ -51,15 +53,14 @@ void GDesktop::did_receive_screen_rect(Badge<GWindowServerConnection>, const Rec
on_rect_change(rect);
}
bool GDesktop::set_wallpaper(const StringView& path)
bool Desktop::set_wallpaper(const StringView& path)
{
GWindowServerConnection::the().post_message(WindowServer::AsyncSetWallpaper(path));
auto ret_val = GWindowServerConnection::the().wait_for_specific_message<WindowClient::AsyncSetWallpaperFinished>()->success();
WindowServerConnection::the().post_message(WindowServer::AsyncSetWallpaper(path));
auto ret_val = WindowServerConnection::the().wait_for_specific_message<WindowClient::AsyncSetWallpaperFinished>()->success();
if (ret_val) {
RefPtr<Core::ConfigFile> config = Core::ConfigFile::get_for_app("WindowManager");
dbg() << "Saving wallpaper path '" << path << "' to config file at " << config->file_name();
RefPtr<CConfigFile> config = CConfigFile::get_for_app("WindowManager");
config->write_entry("Background", "Wallpaper", path);
config->sync();
}
@ -67,7 +68,9 @@ bool GDesktop::set_wallpaper(const StringView& path)
return ret_val;
}
String GDesktop::wallpaper() const
String Desktop::wallpaper() const
{
return GWindowServerConnection::the().send_sync<WindowServer::GetWallpaper>()->path();
return WindowServerConnection::the().send_sync<WindowServer::GetWallpaper>()->path();
}
}

View file

@ -31,21 +31,25 @@
#include <AK/String.h>
#include <LibDraw/Rect.h>
class GWindowServerConnection;
namespace GUI {
class GDesktop {
class WindowServerConnection;
class Desktop {
public:
static GDesktop& the();
GDesktop();
static Desktop& the();
Desktop();
String wallpaper() const;
bool set_wallpaper(const StringView& path);
Rect rect() const { return m_rect; }
void did_receive_screen_rect(Badge<GWindowServerConnection>, const Rect&);
void did_receive_screen_rect(Badge<WindowServerConnection>, const Rect&);
Function<void(const Rect&)> on_rect_change;
private:
Rect m_rect;
};
}

View file

@ -28,26 +28,28 @@
#include <LibGUI/GDialog.h>
#include <LibGUI/GEvent.h>
GDialog::GDialog(Core::Object* parent)
: GWindow(parent)
namespace GUI {
Dialog::Dialog(Core::Object* parent)
: Window(parent)
{
set_modal(true);
}
GDialog::~GDialog()
Dialog::~Dialog()
{
}
int GDialog::exec()
int Dialog::exec()
{
ASSERT(!m_event_loop);
m_event_loop = make<Core::EventLoop>();
auto new_rect = rect();
if (parent() && parent()->is_window()) {
auto& parent_window = *static_cast<GWindow*>(parent());
auto& parent_window = *static_cast<Window*>(parent());
new_rect.center_within(parent_window.rect());
} else {
new_rect.center_within(GDesktop::the().rect());
new_rect.center_within(Desktop::the().rect());
}
set_rect(new_rect);
show();
@ -58,7 +60,7 @@ int GDialog::exec()
return result;
}
void GDialog::done(int result)
void Dialog::done(int result)
{
if (!m_event_loop)
return;
@ -67,10 +69,10 @@ void GDialog::done(int result)
m_event_loop->quit(result);
}
void GDialog::event(Core::Event& event)
void Dialog::event(Core::Event& event)
{
if (event.type() == GEvent::KeyUp) {
auto& key_event = static_cast<GKeyEvent&>(event);
if (event.type() == Event::KeyUp) {
auto& key_event = static_cast<KeyEvent&>(event);
if (key_event.key() == KeyCode::Key_Escape) {
done(ExecCancel);
event.accept();
@ -78,11 +80,13 @@ void GDialog::event(Core::Event& event)
}
}
GWindow::event(event);
Window::event(event);
}
void GDialog::close()
void Dialog::close()
{
GWindow::close();
Window::close();
m_event_loop->quit(ExecCancel);
}
}

View file

@ -29,8 +29,10 @@
#include <LibCore/CEventLoop.h>
#include <LibGUI/GWindow.h>
class GDialog : public GWindow {
C_OBJECT(GDialog)
namespace GUI {
class Dialog : public Window {
C_OBJECT(Dialog)
public:
enum ExecResult {
ExecOK = 0,
@ -38,7 +40,7 @@ public:
ExecAborted = 2
};
virtual ~GDialog() override;
virtual ~Dialog() override;
int exec();
@ -50,9 +52,11 @@ public:
virtual void close() override;
protected:
explicit GDialog(Core::Object* parent);
explicit Dialog(Core::Object* parent);
private:
OwnPtr<Core::EventLoop> m_event_loop;
int m_result { ExecAborted };
};
}

View file

@ -28,18 +28,20 @@
#include <LibGUI/GDragOperation.h>
#include <LibGUI/GWindowServerConnection.h>
static GDragOperation* s_current_drag_operation;
namespace GUI {
GDragOperation::GDragOperation(Core::Object* parent)
static DragOperation* s_current_drag_operation;
DragOperation::DragOperation(Core::Object* parent)
: Core::Object(parent)
{
}
GDragOperation::~GDragOperation()
DragOperation::~DragOperation()
{
}
GDragOperation::Outcome GDragOperation::exec()
DragOperation::Outcome DragOperation::exec()
{
ASSERT(!s_current_drag_operation);
ASSERT(!m_event_loop);
@ -49,12 +51,12 @@ GDragOperation::Outcome GDragOperation::exec()
RefPtr<GraphicsBitmap> shared_bitmap;
if (m_bitmap) {
shared_bitmap = m_bitmap->to_shareable_bitmap();
shared_bitmap->shared_buffer()->share_with(GWindowServerConnection::the().server_pid());
shared_bitmap->shared_buffer()->share_with(WindowServerConnection::the().server_pid());
bitmap_id = shared_bitmap->shared_buffer_id();
bitmap_size = shared_bitmap->size();
}
auto response = GWindowServerConnection::the().send_sync<WindowServer::StartDrag>(m_text, m_data_type, m_data, bitmap_id, bitmap_size);
auto response = WindowServerConnection::the().send_sync<WindowServer::StartDrag>(m_text, m_data_type, m_data, bitmap_id, bitmap_size);
if (!response->started()) {
m_outcome = Outcome::Cancelled;
return m_outcome;
@ -70,21 +72,23 @@ GDragOperation::Outcome GDragOperation::exec()
return m_outcome;
}
void GDragOperation::done(Outcome outcome)
void DragOperation::done(Outcome outcome)
{
ASSERT(m_outcome == Outcome::None);
m_outcome = outcome;
m_event_loop->quit(0);
}
void GDragOperation::notify_accepted(Badge<GWindowServerConnection>)
void DragOperation::notify_accepted(Badge<WindowServerConnection>)
{
ASSERT(s_current_drag_operation);
s_current_drag_operation->done(Outcome::Accepted);
}
void GDragOperation::notify_cancelled(Badge<GWindowServerConnection>)
void DragOperation::notify_cancelled(Badge<WindowServerConnection>)
{
ASSERT(s_current_drag_operation);
s_current_drag_operation->done(Outcome::Cancelled);
}
}

View file

@ -30,10 +30,13 @@
#include <LibCore/CObject.h>
class GraphicsBitmap;
class GWindowServerConnection;
class GDragOperation : public Core::Object {
C_OBJECT(GDragOperation)
namespace GUI {
class WindowServerConnection;
class DragOperation : public Core::Object {
C_OBJECT(DragOperation)
public:
enum class Outcome {
None,
@ -41,7 +44,7 @@ public:
Cancelled,
};
virtual ~GDragOperation() override;
virtual ~DragOperation() override;
void set_text(const String& text) { m_text = text; }
void set_bitmap(const GraphicsBitmap* bitmap) { m_bitmap = bitmap; }
@ -54,11 +57,11 @@ public:
Outcome exec();
Outcome outcome() const { return m_outcome; }
static void notify_accepted(Badge<GWindowServerConnection>);
static void notify_cancelled(Badge<GWindowServerConnection>);
static void notify_accepted(Badge<WindowServerConnection>);
static void notify_cancelled(Badge<WindowServerConnection>);
protected:
explicit GDragOperation(Core::Object* parent = nullptr);
explicit DragOperation(Core::Object* parent = nullptr);
private:
void done(Outcome);
@ -70,3 +73,5 @@ private:
String m_data;
RefPtr<GraphicsBitmap> m_bitmap;
};
}

View file

@ -32,7 +32,9 @@
#include <LibDraw/Rect.h>
#include <LibGUI/GWindowType.h>
class GEvent : public Core::Event {
namespace GUI {
class Event : public Core::Event {
public:
enum Type {
Show = 1000,
@ -68,21 +70,21 @@ public:
__End_WM_Events,
};
GEvent() {}
explicit GEvent(Type type)
Event() {}
explicit Event(Type type)
: Core::Event(type)
{
}
virtual ~GEvent() {}
virtual ~Event() {}
bool is_key_event() const { return type() == KeyUp || type() == KeyDown; }
bool is_paint_event() const { return type() == Paint; }
};
class GWMEvent : public GEvent {
class WMEvent : public Event {
public:
GWMEvent(Type type, int client_id, int window_id)
: GEvent(type)
WMEvent(Type type, int client_id, int window_id)
: Event(type)
, m_client_id(client_id)
, m_window_id(window_id)
{
@ -96,18 +98,18 @@ private:
int m_window_id { -1 };
};
class GWMWindowRemovedEvent : public GWMEvent {
class WMWindowRemovedEvent : public WMEvent {
public:
GWMWindowRemovedEvent(int client_id, int window_id)
: GWMEvent(GEvent::Type::WM_WindowRemoved, client_id, window_id)
WMWindowRemovedEvent(int client_id, int window_id)
: WMEvent(Event::Type::WM_WindowRemoved, client_id, window_id)
{
}
};
class GWMWindowStateChangedEvent : public GWMEvent {
class WMWindowStateChangedEvent : public WMEvent {
public:
GWMWindowStateChangedEvent(int client_id, int window_id, const StringView& title, const Rect& rect, bool is_active, GWindowType window_type, bool is_minimized)
: GWMEvent(GEvent::Type::WM_WindowStateChanged, client_id, window_id)
WMWindowStateChangedEvent(int client_id, int window_id, const StringView& title, const Rect& rect, bool is_active, WindowType window_type, bool is_minimized)
: WMEvent(Event::Type::WM_WindowStateChanged, client_id, window_id)
, m_title(title)
, m_rect(rect)
, m_window_type(window_type)
@ -119,21 +121,21 @@ public:
String title() const { return m_title; }
Rect rect() const { return m_rect; }
bool is_active() const { return m_active; }
GWindowType window_type() const { return m_window_type; }
WindowType window_type() const { return m_window_type; }
bool is_minimized() const { return m_minimized; }
private:
String m_title;
Rect m_rect;
GWindowType m_window_type;
WindowType m_window_type;
bool m_active;
bool m_minimized;
};
class GWMWindowRectChangedEvent : public GWMEvent {
class WMWindowRectChangedEvent : public WMEvent {
public:
GWMWindowRectChangedEvent(int client_id, int window_id, const Rect& rect)
: GWMEvent(GEvent::Type::WM_WindowRectChanged, client_id, window_id)
WMWindowRectChangedEvent(int client_id, int window_id, const Rect& rect)
: WMEvent(Event::Type::WM_WindowRectChanged, client_id, window_id)
, m_rect(rect)
{
}
@ -144,10 +146,10 @@ private:
Rect m_rect;
};
class GWMWindowIconBitmapChangedEvent : public GWMEvent {
class WMWindowIconBitmapChangedEvent : public WMEvent {
public:
GWMWindowIconBitmapChangedEvent(int client_id, int window_id, int icon_buffer_id, const Size& icon_size)
: GWMEvent(GEvent::Type::WM_WindowIconBitmapChanged, client_id, window_id)
WMWindowIconBitmapChangedEvent(int client_id, int window_id, int icon_buffer_id, const Size& icon_size)
: WMEvent(Event::Type::WM_WindowIconBitmapChanged, client_id, window_id)
, m_icon_buffer_id(icon_buffer_id)
, m_icon_size(icon_size)
{
@ -161,10 +163,10 @@ private:
Size m_icon_size;
};
class GMultiPaintEvent final : public GEvent {
class MultiPaintEvent final : public Event {
public:
explicit GMultiPaintEvent(const Vector<Rect, 32>& rects, const Size& window_size)
: GEvent(GEvent::MultiPaint)
explicit MultiPaintEvent(const Vector<Rect, 32>& rects, const Size& window_size)
: Event(Event::MultiPaint)
, m_rects(rects)
, m_window_size(window_size)
{
@ -178,10 +180,10 @@ private:
Size m_window_size;
};
class GPaintEvent final : public GEvent {
class PaintEvent final : public Event {
public:
explicit GPaintEvent(const Rect& rect, const Size& window_size = Size())
: GEvent(GEvent::Paint)
explicit PaintEvent(const Rect& rect, const Size& window_size = Size())
: Event(Event::Paint)
, m_rect(rect)
, m_window_size(window_size)
{
@ -195,10 +197,10 @@ private:
Size m_window_size;
};
class GResizeEvent final : public GEvent {
class ResizeEvent final : public Event {
public:
explicit GResizeEvent(const Size& old_size, const Size& size)
: GEvent(GEvent::Resize)
explicit ResizeEvent(const Size& old_size, const Size& size)
: Event(Event::Resize)
, m_old_size(old_size)
, m_size(size)
{
@ -212,10 +214,10 @@ private:
Size m_size;
};
class GContextMenuEvent final : public GEvent {
class ContextMenuEvent final : public Event {
public:
explicit GContextMenuEvent(const Point& position, const Point& screen_position)
: GEvent(GEvent::ContextMenu)
explicit ContextMenuEvent(const Point& position, const Point& screen_position)
: Event(Event::ContextMenu)
, m_position(position)
, m_screen_position(screen_position)
{
@ -229,33 +231,33 @@ private:
Point m_screen_position;
};
class GShowEvent final : public GEvent {
class ShowEvent final : public Event {
public:
GShowEvent()
: GEvent(GEvent::Show)
ShowEvent()
: Event(Event::Show)
{
}
};
class GHideEvent final : public GEvent {
class HideEvent final : public Event {
public:
GHideEvent()
: GEvent(GEvent::Hide)
HideEvent()
: Event(Event::Hide)
{
}
};
enum GMouseButton : u8 {
enum MouseButton : u8 {
None = 0,
Left = 1,
Right = 2,
Middle = 4,
};
class GKeyEvent final : public GEvent {
class KeyEvent final : public Event {
public:
GKeyEvent(Type type, int key, u8 modifiers)
: GEvent(type)
KeyEvent(Type type, int key, u8 modifiers)
: Event(type)
, m_key(key)
, m_modifiers(modifiers)
{
@ -270,16 +272,16 @@ public:
String text() const { return m_text; }
private:
friend class GWindowServerConnection;
friend class WindowServerConnection;
int m_key { 0 };
u8 m_modifiers { 0 };
String m_text;
};
class GMouseEvent final : public GEvent {
class MouseEvent final : public Event {
public:
GMouseEvent(Type type, const Point& position, unsigned buttons, GMouseButton button, unsigned modifiers, int wheel_delta)
: GEvent(type)
MouseEvent(Type type, const Point& position, unsigned buttons, MouseButton button, unsigned modifiers, int wheel_delta)
: Event(type)
, m_position(position)
, m_buttons(buttons)
, m_button(button)
@ -291,7 +293,7 @@ public:
Point position() const { return m_position; }
int x() const { return m_position.x(); }
int y() const { return m_position.y(); }
GMouseButton button() const { return m_button; }
MouseButton button() const { return m_button; }
unsigned buttons() const { return m_buttons; }
unsigned modifiers() const { return m_modifiers; }
int wheel_delta() const { return m_wheel_delta; }
@ -299,15 +301,15 @@ public:
private:
Point m_position;
unsigned m_buttons { 0 };
GMouseButton m_button { GMouseButton::None };
MouseButton m_button { MouseButton::None };
unsigned m_modifiers { 0 };
int m_wheel_delta { 0 };
};
class GDropEvent final : public GEvent {
class DropEvent final : public Event {
public:
GDropEvent(const Point& position, const String& text, const String& data_type, const String& data)
: GEvent(GEvent::Drop)
DropEvent(const Point& position, const String& text, const String& data_type, const String& data)
: Event(Event::Drop)
, m_position(position)
, m_text(text)
, m_data_type(data_type)
@ -326,3 +328,5 @@ private:
String m_data_type;
String m_data;
};
}

View file

@ -39,14 +39,16 @@
#include <LibGUI/GTextBox.h>
#include <LibGUI/GToolBar.h>
Optional<String> GFilePicker::get_open_filepath(const String& window_title)
namespace GUI {
Optional<String> FilePicker::get_open_filepath(const String& window_title)
{
auto picker = GFilePicker::construct(Mode::Open);
auto picker = FilePicker::construct(Mode::Open);
if (!window_title.is_null())
picker->set_title(window_title);
if (picker->exec() == GDialog::ExecOK) {
if (picker->exec() == Dialog::ExecOK) {
String file_path = picker->selected_file().string();
if (file_path.is_null())
@ -57,11 +59,11 @@ Optional<String> GFilePicker::get_open_filepath(const String& window_title)
return {};
}
Optional<String> GFilePicker::get_save_filepath(const String& title, const String& extension)
Optional<String> FilePicker::get_save_filepath(const String& title, const String& extension)
{
auto picker = GFilePicker::construct(Mode::Save, String::format("%s.%s", title.characters(), extension.characters()));
auto picker = FilePicker::construct(Mode::Save, String::format("%s.%s", title.characters(), extension.characters()));
if (picker->exec() == GDialog::ExecOK) {
if (picker->exec() == Dialog::ExecOK) {
String file_path = picker->selected_file().string();
if (file_path.is_null())
@ -72,45 +74,45 @@ Optional<String> GFilePicker::get_save_filepath(const String& title, const Strin
return {};
}
GFilePicker::GFilePicker(Mode mode, const StringView& file_name, const StringView& path, Core::Object* parent)
: GDialog(parent)
, m_model(GFileSystemModel::create())
FilePicker::FilePicker(Mode mode, const StringView& file_name, const StringView& path, Core::Object* parent)
: Dialog(parent)
, m_model(FileSystemModel::create())
, m_mode(mode)
{
set_title(m_mode == Mode::Open ? "Open File" : "Save File");
set_rect(200, 200, 700, 400);
auto horizontal_container = GWidget::construct();
auto horizontal_container = Widget::construct();
set_main_widget(horizontal_container);
horizontal_container->set_layout(make<GHBoxLayout>());
horizontal_container->set_layout(make<HBoxLayout>());
horizontal_container->layout()->set_margins({ 4, 4, 4, 4 });
horizontal_container->set_fill_with_background_color(true);
auto vertical_container = GWidget::construct(horizontal_container.ptr());
vertical_container->set_layout(make<GVBoxLayout>());
auto vertical_container = Widget::construct(horizontal_container.ptr());
vertical_container->set_layout(make<VBoxLayout>());
vertical_container->layout()->set_spacing(4);
auto upper_container = GWidget::construct(vertical_container.ptr());
upper_container->set_layout(make<GHBoxLayout>());
auto upper_container = Widget::construct(vertical_container.ptr());
upper_container->set_layout(make<HBoxLayout>());
upper_container->layout()->set_spacing(4);
upper_container->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
upper_container->set_preferred_size(0, 26);
auto toolbar = GToolBar::construct(upper_container);
auto toolbar = ToolBar::construct(upper_container);
toolbar->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill);
toolbar->set_preferred_size(85, 0);
toolbar->set_has_frame(false);
auto location_textbox = GTextBox::construct(upper_container);
auto location_textbox = TextBox::construct(upper_container);
location_textbox->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
location_textbox->set_preferred_size(0, 20);
m_view = GTableView::construct(vertical_container);
m_view->set_model(GSortingProxyModel::create(*m_model));
m_view->set_column_hidden(GFileSystemModel::Column::Owner, true);
m_view->set_column_hidden(GFileSystemModel::Column::Group, true);
m_view->set_column_hidden(GFileSystemModel::Column::Permissions, true);
m_view->set_column_hidden(GFileSystemModel::Column::Inode, true);
m_view->set_column_hidden(GFileSystemModel::Column::SymlinkTarget, true);
m_view = TableView::construct(vertical_container);
m_view->set_model(SortingProxyModel::create(*m_model));
m_view->set_column_hidden(FileSystemModel::Column::Owner, true);
m_view->set_column_hidden(FileSystemModel::Column::Group, true);
m_view->set_column_hidden(FileSystemModel::Column::Permissions, true);
m_view->set_column_hidden(FileSystemModel::Column::Inode, true);
m_view->set_column_hidden(FileSystemModel::Column::SymlinkTarget, true);
m_model->set_root_path(path);
location_textbox->on_return_pressed = [&] {
@ -118,28 +120,28 @@ GFilePicker::GFilePicker(Mode mode, const StringView& file_name, const StringVie
clear_preview();
};
auto open_parent_directory_action = GAction::create("Open parent directory", { Mod_Alt, Key_Up }, GraphicsBitmap::load_from_file("/res/icons/16x16/open-parent-directory.png"), [this](const GAction&) {
auto open_parent_directory_action = Action::create("Open parent directory", { Mod_Alt, Key_Up }, GraphicsBitmap::load_from_file("/res/icons/16x16/open-parent-directory.png"), [this](const Action&) {
m_model->set_root_path(String::format("%s/..", m_model->root_path().characters()));
clear_preview();
});
toolbar->add_action(*open_parent_directory_action);
auto go_home_action = GCommonActions::make_go_home_action([this](auto&) {
auto go_home_action = CommonActions::make_go_home_action([this](auto&) {
m_model->set_root_path(get_current_user_home_path());
});
toolbar->add_action(go_home_action);
toolbar->add_separator();
auto mkdir_action = GAction::create("New directory...", GraphicsBitmap::load_from_file("/res/icons/16x16/mkdir.png"), [this](const GAction&) {
auto input_box = GInputBox::construct("Enter name:", "New directory", this);
if (input_box->exec() == GInputBox::ExecOK && !input_box->text_value().is_empty()) {
auto mkdir_action = Action::create("New directory...", GraphicsBitmap::load_from_file("/res/icons/16x16/mkdir.png"), [this](const Action&) {
auto input_box = InputBox::construct("Enter name:", "New directory", this);
if (input_box->exec() == InputBox::ExecOK && !input_box->text_value().is_empty()) {
auto new_dir_path = FileSystemPath(String::format("%s/%s",
m_model->root_path().characters(),
input_box->text_value().characters()))
.string();
int rc = mkdir(new_dir_path.characters(), 0777);
if (rc < 0) {
GMessageBox::show(String::format("mkdir(\"%s\") failed: %s", new_dir_path.characters(), strerror(errno)), "Error", GMessageBox::Type::Error, GMessageBox::InputType::OK, this);
MessageBox::show(String::format("mkdir(\"%s\") failed: %s", new_dir_path.characters(), strerror(errno)), "Error", MessageBox::Type::Error, MessageBox::InputType::OK, this);
} else {
m_model->update();
}
@ -147,21 +149,21 @@ GFilePicker::GFilePicker(Mode mode, const StringView& file_name, const StringVie
});
toolbar->add_action(*mkdir_action);
auto lower_container = GWidget::construct(vertical_container.ptr());
lower_container->set_layout(make<GVBoxLayout>());
auto lower_container = Widget::construct(vertical_container.ptr());
lower_container->set_layout(make<VBoxLayout>());
lower_container->layout()->set_spacing(4);
lower_container->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
lower_container->set_preferred_size(0, 60);
auto filename_container = GWidget::construct(lower_container.ptr());
auto filename_container = Widget::construct(lower_container.ptr());
filename_container->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
filename_container->set_preferred_size(0, 20);
filename_container->set_layout(make<GHBoxLayout>());
auto filename_label = GLabel::construct("File name:", filename_container);
filename_container->set_layout(make<HBoxLayout>());
auto filename_label = Label::construct("File name:", filename_container);
filename_label->set_text_alignment(TextAlignment::CenterLeft);
filename_label->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill);
filename_label->set_preferred_size(60, 0);
m_filename_textbox = GTextBox::construct(filename_container.ptr());
m_filename_textbox = TextBox::construct(filename_container.ptr());
if (m_mode == Mode::Save) {
m_filename_textbox->set_text(file_name);
m_filename_textbox->set_focus(true);
@ -172,9 +174,9 @@ GFilePicker::GFilePicker(Mode mode, const StringView& file_name, const StringVie
};
m_view->on_selection = [this](auto& index) {
auto& filter_model = (GSortingProxyModel&)*m_view->model();
auto& filter_model = (SortingProxyModel&)*m_view->model();
auto local_index = filter_model.map_to_target(index);
const GFileSystemModel::Node& node = m_model->node(local_index);
const FileSystemModel::Node& node = m_model->node(local_index);
FileSystemPath path { node.full_path(m_model) };
clear_preview();
@ -184,14 +186,14 @@ GFilePicker::GFilePicker(Mode mode, const StringView& file_name, const StringVie
set_preview(path);
};
auto button_container = GWidget::construct(lower_container.ptr());
auto button_container = Widget::construct(lower_container.ptr());
button_container->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
button_container->set_preferred_size(0, 20);
button_container->set_layout(make<GHBoxLayout>());
button_container->set_layout(make<HBoxLayout>());
button_container->layout()->set_spacing(4);
button_container->layout()->add_spacer();
auto cancel_button = GButton::construct(button_container);
auto cancel_button = Button::construct(button_container);
cancel_button->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill);
cancel_button->set_preferred_size(80, 0);
cancel_button->set_text("Cancel");
@ -199,7 +201,7 @@ GFilePicker::GFilePicker(Mode mode, const StringView& file_name, const StringVie
done(ExecCancel);
};
auto ok_button = GButton::construct(button_container);
auto ok_button = Button::construct(button_container);
ok_button->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill);
ok_button->set_preferred_size(80, 0);
ok_button->set_text(ok_button_name(m_mode));
@ -208,9 +210,9 @@ GFilePicker::GFilePicker(Mode mode, const StringView& file_name, const StringVie
};
m_view->on_activation = [this](auto& index) {
auto& filter_model = (GSortingProxyModel&)*m_view->model();
auto& filter_model = (SortingProxyModel&)*m_view->model();
auto local_index = filter_model.map_to_target(index);
const GFileSystemModel::Node& node = m_model->node(local_index);
const FileSystemModel::Node& node = m_model->node(local_index);
auto path = node.full_path(m_model);
if (node.is_directory()) {
@ -221,35 +223,35 @@ GFilePicker::GFilePicker(Mode mode, const StringView& file_name, const StringVie
}
};
auto preview_container = GFrame::construct(horizontal_container);
auto preview_container = Frame::construct(horizontal_container);
preview_container->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill);
preview_container->set_preferred_size(180, 0);
preview_container->set_frame_shape(FrameShape::Container);
preview_container->set_frame_shadow(FrameShadow::Sunken);
preview_container->set_frame_thickness(2);
preview_container->set_layout(make<GVBoxLayout>());
preview_container->set_layout(make<VBoxLayout>());
preview_container->layout()->set_margins({ 8, 8, 8, 8 });
m_preview_image_label = GLabel::construct(preview_container);
m_preview_image_label = Label::construct(preview_container);
m_preview_image_label->set_should_stretch_icon(true);
m_preview_image_label->set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed);
m_preview_image_label->set_preferred_size(160, 160);
m_preview_name_label = GLabel::construct(preview_container);
m_preview_name_label = Label::construct(preview_container);
m_preview_name_label->set_font(Font::default_bold_font());
m_preview_name_label->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
m_preview_name_label->set_preferred_size(0, m_preview_name_label->font().glyph_height());
m_preview_geometry_label = GLabel::construct(preview_container);
m_preview_geometry_label = Label::construct(preview_container);
m_preview_geometry_label->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
m_preview_geometry_label->set_preferred_size(0, m_preview_name_label->font().glyph_height());
}
GFilePicker::~GFilePicker()
FilePicker::~FilePicker()
{
}
void GFilePicker::set_preview(const FileSystemPath& path)
void FilePicker::set_preview(const FileSystemPath& path)
{
if (path.has_extension(".png")) {
auto bitmap = load_png(path.string());
@ -265,20 +267,20 @@ void GFilePicker::set_preview(const FileSystemPath& path)
}
}
void GFilePicker::clear_preview()
void FilePicker::clear_preview()
{
m_preview_image_label->set_icon(nullptr);
m_preview_name_label->set_text(String::empty());
m_preview_geometry_label->set_text(String::empty());
}
void GFilePicker::on_file_return()
void FilePicker::on_file_return()
{
FileSystemPath path(String::format("%s/%s", m_model->root_path().characters(), m_filename_textbox->text().characters()));
if (GFilePicker::file_exists(path.string()) && m_mode == Mode::Save) {
auto result = GMessageBox::show("File already exists, overwrite?", "Existing File", GMessageBox::Type::Warning, GMessageBox::InputType::OKCancel);
if (result == GMessageBox::ExecCancel)
if (FilePicker::file_exists(path.string()) && m_mode == Mode::Save) {
auto result = MessageBox::show("File already exists, overwrite?", "Existing File", MessageBox::Type::Warning, MessageBox::InputType::OKCancel);
if (result == MessageBox::ExecCancel)
return;
}
@ -286,7 +288,7 @@ void GFilePicker::on_file_return()
done(ExecOK);
}
bool GFilePicker::file_exists(const StringView& path)
bool FilePicker::file_exists(const StringView& path)
{
struct stat st;
int rc = stat(String(path).characters(), &st);
@ -299,3 +301,5 @@ bool GFilePicker::file_exists(const StringView& path)
}
return false;
}
}

View file

@ -30,12 +30,14 @@
#include <LibGUI/GDialog.h>
#include <LibGUI/GTableView.h>
class GFileSystemModel;
class GLabel;
class GTextBox;
namespace GUI {
class GFilePicker final : public GDialog {
C_OBJECT(GFilePicker)
class FileSystemModel;
class Label;
class TextBox;
class FilePicker final : public Dialog {
C_OBJECT(FilePicker)
public:
enum class Mode {
Open,
@ -46,7 +48,7 @@ public:
static Optional<String> get_save_filepath(const String& title, const String& extension);
static bool file_exists(const StringView& path);
virtual ~GFilePicker() override;
virtual ~FilePicker() override;
FileSystemPath selected_file() const { return m_selected_file; }
@ -55,7 +57,7 @@ private:
void clear_preview();
void on_file_return();
GFilePicker(Mode type = Mode::Open, const StringView& file_name = "Untitled", const StringView& path = String(get_current_user_home_path()), Core::Object* parent = nullptr);
FilePicker(Mode type = Mode::Open, const StringView& file_name = "Untitled", const StringView& path = String(get_current_user_home_path()), Core::Object* parent = nullptr);
static String ok_button_name(Mode mode)
{
@ -69,13 +71,15 @@ private:
}
}
RefPtr<GTableView> m_view;
NonnullRefPtr<GFileSystemModel> m_model;
RefPtr<TableView> m_view;
NonnullRefPtr<FileSystemModel> m_model;
FileSystemPath m_selected_file;
RefPtr<GTextBox> m_filename_textbox;
RefPtr<GLabel> m_preview_image_label;
RefPtr<GLabel> m_preview_name_label;
RefPtr<GLabel> m_preview_geometry_label;
RefPtr<TextBox> m_filename_textbox;
RefPtr<Label> m_preview_image_label;
RefPtr<Label> m_preview_name_label;
RefPtr<Label> m_preview_geometry_label;
Mode m_mode { Mode::Open };
};
}

View file

@ -38,7 +38,9 @@
#include <sys/stat.h>
#include <unistd.h>
GModelIndex GFileSystemModel::Node::index(const GFileSystemModel& model, int column) const
namespace GUI {
ModelIndex FileSystemModel::Node::index(const FileSystemModel& model, int column) const
{
if (!parent)
return {};
@ -49,7 +51,7 @@ GModelIndex GFileSystemModel::Node::index(const GFileSystemModel& model, int col
ASSERT_NOT_REACHED();
}
bool GFileSystemModel::Node::fetch_data(const String& full_path, bool is_root)
bool FileSystemModel::Node::fetch_data(const String& full_path, bool is_root)
{
struct stat st;
int rc;
@ -83,7 +85,7 @@ bool GFileSystemModel::Node::fetch_data(const String& full_path, bool is_root)
return true;
}
void GFileSystemModel::Node::traverse_if_needed(const GFileSystemModel& model)
void FileSystemModel::Node::traverse_if_needed(const FileSystemModel& model)
{
if (!is_directory() || has_traversed)
return;
@ -132,11 +134,11 @@ void GFileSystemModel::Node::traverse_if_needed(const GFileSystemModel& model)
mode = 0;
children.clear();
reify_if_needed(model);
const_cast<GFileSystemModel&>(model).did_update();
const_cast<FileSystemModel&>(model).did_update();
};
}
void GFileSystemModel::Node::reify_if_needed(const GFileSystemModel& model)
void FileSystemModel::Node::reify_if_needed(const FileSystemModel& model)
{
traverse_if_needed(model);
if (mode != 0)
@ -144,7 +146,7 @@ void GFileSystemModel::Node::reify_if_needed(const GFileSystemModel& model)
fetch_data(full_path(model), parent == nullptr);
}
String GFileSystemModel::Node::full_path(const GFileSystemModel& model) const
String FileSystemModel::Node::full_path(const FileSystemModel& model) const
{
Vector<String, 32> lineage;
for (auto* ancestor = parent; ancestor; ancestor = ancestor->parent) {
@ -161,7 +163,7 @@ String GFileSystemModel::Node::full_path(const GFileSystemModel& model) const
return canonicalized_path(builder.to_string());
}
GModelIndex GFileSystemModel::index(const StringView& path, int column) const
ModelIndex FileSystemModel::index(const StringView& path, int column) const
{
FileSystemPath canonical_path(path);
const Node* node = m_root;
@ -186,14 +188,14 @@ GModelIndex GFileSystemModel::index(const StringView& path, int column) const
return {};
}
String GFileSystemModel::full_path(const GModelIndex& index) const
String FileSystemModel::full_path(const ModelIndex& index) const
{
auto& node = this->node(index);
const_cast<Node&>(node).reify_if_needed(*this);
return node.full_path(*this);
}
GFileSystemModel::GFileSystemModel(const StringView& root_path, Mode mode)
FileSystemModel::FileSystemModel(const StringView& root_path, Mode mode)
: m_root_path(canonicalized_path(root_path))
, m_mode(mode)
{
@ -219,11 +221,11 @@ GFileSystemModel::GFileSystemModel(const StringView& root_path, Mode mode)
update();
}
GFileSystemModel::~GFileSystemModel()
FileSystemModel::~FileSystemModel()
{
}
String GFileSystemModel::name_for_uid(uid_t uid) const
String FileSystemModel::name_for_uid(uid_t uid) const
{
auto it = m_user_names.find(uid);
if (it == m_user_names.end())
@ -231,7 +233,7 @@ String GFileSystemModel::name_for_uid(uid_t uid) const
return (*it).value;
}
String GFileSystemModel::name_for_gid(uid_t gid) const
String FileSystemModel::name_for_gid(uid_t gid) const
{
auto it = m_user_names.find(gid);
if (it == m_user_names.end())
@ -276,7 +278,7 @@ static String permission_string(mode_t mode)
return builder.to_string();
}
void GFileSystemModel::set_root_path(const StringView& root_path)
void FileSystemModel::set_root_path(const StringView& root_path)
{
m_root_path = canonicalized_path(root_path);
@ -286,7 +288,7 @@ void GFileSystemModel::set_root_path(const StringView& root_path)
update();
}
void GFileSystemModel::update()
void FileSystemModel::update()
{
m_root = make<Node>();
m_root->reify_if_needed(*this);
@ -294,7 +296,7 @@ void GFileSystemModel::update()
did_update();
}
int GFileSystemModel::row_count(const GModelIndex& index) const
int FileSystemModel::row_count(const ModelIndex& index) const
{
Node& node = const_cast<Node&>(this->node(index));
node.reify_if_needed(*this);
@ -303,14 +305,14 @@ int GFileSystemModel::row_count(const GModelIndex& index) const
return 0;
}
const GFileSystemModel::Node& GFileSystemModel::node(const GModelIndex& index) const
const FileSystemModel::Node& FileSystemModel::node(const ModelIndex& index) const
{
if (!index.is_valid())
return *m_root;
return *(Node*)index.internal_data();
}
GModelIndex GFileSystemModel::index(int row, int column, const GModelIndex& parent) const
ModelIndex FileSystemModel::index(int row, int column, const ModelIndex& parent) const
{
if (row < 0 || column < 0)
return {};
@ -321,7 +323,7 @@ GModelIndex GFileSystemModel::index(int row, int column, const GModelIndex& pare
return create_index(row, column, &node.children[row]);
}
GModelIndex GFileSystemModel::parent_index(const GModelIndex& index) const
ModelIndex FileSystemModel::parent_index(const ModelIndex& index) const
{
if (!index.is_valid())
return {};
@ -333,7 +335,7 @@ GModelIndex GFileSystemModel::parent_index(const GModelIndex& index) const
return node.parent->index(*this, index.column());
}
GVariant GFileSystemModel::data(const GModelIndex& index, Role role) const
Variant FileSystemModel::data(const ModelIndex& index, Role role) const
{
ASSERT(index.is_valid());
auto& node = this->node(index);
@ -407,7 +409,7 @@ GVariant GFileSystemModel::data(const GModelIndex& index, Role role) const
return {};
}
GIcon GFileSystemModel::icon_for_file(const mode_t mode, const String& name) const
GIcon FileSystemModel::icon_for_file(const mode_t mode, const String& name) const
{
if (S_ISDIR(mode))
return m_directory_icon;
@ -426,11 +428,11 @@ GIcon GFileSystemModel::icon_for_file(const mode_t mode, const String& name) con
return m_file_icon;
}
GIcon GFileSystemModel::icon_for(const Node& node) const
GIcon FileSystemModel::icon_for(const Node& node) const
{
if (node.name.to_lowercase().ends_with(".png")) {
if (!node.thumbnail) {
if (!const_cast<GFileSystemModel*>(this)->fetch_thumbnail_for(node))
if (!const_cast<FileSystemModel*>(this)->fetch_thumbnail_for(node))
return m_filetype_image_icon;
}
return GIcon(m_filetype_image_icon.bitmap_for_size(16), *node.thumbnail);
@ -452,7 +454,7 @@ static RefPtr<GraphicsBitmap> render_thumbnail(const StringView& path)
return thumbnail;
}
bool GFileSystemModel::fetch_thumbnail_for(const Node& node)
bool FileSystemModel::fetch_thumbnail_for(const Node& node)
{
// See if we already have the thumbnail
// we're looking for in the cache.
@ -500,12 +502,12 @@ bool GFileSystemModel::fetch_thumbnail_for(const Node& node)
return false;
}
int GFileSystemModel::column_count(const GModelIndex&) const
int FileSystemModel::column_count(const ModelIndex&) const
{
return Column::__Count;
}
String GFileSystemModel::column_name(int column) const
String FileSystemModel::column_name(int column) const
{
switch (column) {
case Column::Icon:
@ -530,11 +532,11 @@ String GFileSystemModel::column_name(int column) const
ASSERT_NOT_REACHED();
}
GModel::ColumnMetadata GFileSystemModel::column_metadata(int column) const
Model::ColumnMetadata FileSystemModel::column_metadata(int column) const
{
switch (column) {
case Column::Icon:
return { 16, TextAlignment::Center, nullptr, GModel::ColumnMetadata::Sortable::False };
return { 16, TextAlignment::Center, nullptr, Model::ColumnMetadata::Sortable::False };
case Column::Name:
return { 120, TextAlignment::CenterLeft };
case Column::Size:
@ -554,3 +556,5 @@ GModel::ColumnMetadata GFileSystemModel::column_metadata(int column) const
}
ASSERT_NOT_REACHED();
}
}

View file

@ -33,8 +33,11 @@
#include <sys/stat.h>
#include <time.h>
class GFileSystemModel : public GModel
, public Weakable<GFileSystemModel> {
namespace GUI {
class FileSystemModel
: public Model
, public Weakable<FileSystemModel> {
friend struct Node;
public:
@ -75,10 +78,10 @@ public:
bool is_directory() const { return S_ISDIR(mode); }
bool is_executable() const { return mode & (S_IXUSR | S_IXGRP | S_IXOTH); }
String full_path(const GFileSystemModel&) const;
String full_path(const FileSystemModel&) const;
private:
friend class GFileSystemModel;
friend class FileSystemModel;
Node* parent { nullptr };
NonnullOwnPtrVector<Node> children;
@ -87,38 +90,38 @@ public:
int m_watch_fd { -1 };
RefPtr<Core::Notifier> m_notifier;
GModelIndex index(const GFileSystemModel&, int column) const;
void traverse_if_needed(const GFileSystemModel&);
void reify_if_needed(const GFileSystemModel&);
ModelIndex index(const FileSystemModel&, int column) const;
void traverse_if_needed(const FileSystemModel&);
void reify_if_needed(const FileSystemModel&);
bool fetch_data(const String& full_path, bool is_root);
};
static NonnullRefPtr<GFileSystemModel> create(const StringView& root_path = "/", Mode mode = Mode::FilesAndDirectories)
static NonnullRefPtr<FileSystemModel> create(const StringView& root_path = "/", Mode mode = Mode::FilesAndDirectories)
{
return adopt(*new GFileSystemModel(root_path, mode));
return adopt(*new FileSystemModel(root_path, mode));
}
virtual ~GFileSystemModel() override;
virtual ~FileSystemModel() override;
String root_path() const { return m_root_path; }
void set_root_path(const StringView&);
String full_path(const GModelIndex&) const;
GModelIndex index(const StringView& path, int column) const;
String full_path(const ModelIndex&) const;
ModelIndex index(const StringView& path, int column) const;
const Node& node(const GModelIndex& index) const;
const Node& node(const ModelIndex& index) const;
GIcon icon_for_file(const mode_t mode, const String& name) const;
Function<void(int done, int total)> on_thumbnail_progress;
Function<void()> on_root_path_change;
virtual int tree_column() const { return Column::Name; }
virtual int row_count(const GModelIndex& = GModelIndex()) const override;
virtual int column_count(const GModelIndex& = GModelIndex()) const override;
virtual int tree_column() const override { return Column::Name; }
virtual int row_count(const ModelIndex& = ModelIndex()) const override;
virtual int column_count(const ModelIndex& = ModelIndex()) const override;
virtual String column_name(int column) const override;
virtual ColumnMetadata column_metadata(int column) const override;
virtual GVariant data(const GModelIndex&, Role = Role::Display) const override;
virtual Variant data(const ModelIndex&, Role = Role::Display) const override;
virtual void update() override;
virtual GModelIndex parent_index(const GModelIndex&) const override;
virtual GModelIndex index(int row, int column = 0, const GModelIndex& parent = GModelIndex()) const override;
virtual ModelIndex parent_index(const ModelIndex&) const override;
virtual ModelIndex index(int row, int column = 0, const ModelIndex& parent = ModelIndex()) const override;
virtual StringView drag_data_type() const override { return "url-list"; }
static String timestamp_string(time_t timestamp)
@ -134,7 +137,7 @@ public:
}
private:
GFileSystemModel(const StringView& root_path, Mode);
FileSystemModel(const StringView& root_path, Mode);
String name_for_uid(uid_t) const;
String name_for_gid(gid_t) const;
@ -161,3 +164,5 @@ private:
unsigned m_thumbnail_progress { 0 };
unsigned m_thumbnail_progress_total { 0 };
};
}

View file

@ -28,21 +28,24 @@
#include <LibGUI/GFrame.h>
#include <LibGUI/GPainter.h>
GFrame::GFrame(GWidget* parent)
: GWidget(parent)
namespace GUI {
Frame::Frame(Widget* parent)
: Widget(parent)
{
}
GFrame::~GFrame()
Frame::~Frame()
{
}
void GFrame::paint_event(GPaintEvent& event)
void Frame::paint_event(PaintEvent& event)
{
if (m_shape == FrameShape::NoFrame)
return;
GPainter painter(*this);
Painter painter(*this);
painter.add_clip_rect(event.rect());
StylePainter::paint_frame(painter, rect(), palette(), m_shape, m_shadow, m_thickness, spans_entire_window_horizontally());
}
}

View file

@ -29,10 +29,12 @@
#include <LibDraw/StylePainter.h>
#include <LibGUI/GWidget.h>
class GFrame : public GWidget {
C_OBJECT(GFrame)
namespace GUI {
class Frame : public Widget {
C_OBJECT(Frame)
public:
virtual ~GFrame() override;
virtual ~Frame() override;
int frame_thickness() const { return m_thickness; }
void set_frame_thickness(int thickness) { m_thickness = thickness; }
@ -47,11 +49,13 @@ public:
Rect frame_inner_rect() const { return frame_inner_rect_for_size(size()); }
protected:
explicit GFrame(GWidget* parent = nullptr);
void paint_event(GPaintEvent&) override;
explicit Frame(Widget* parent = nullptr);
void paint_event(PaintEvent&) override;
private:
int m_thickness { 0 };
FrameShadow m_shadow { FrameShadow::Plain };
FrameShape m_shape { FrameShape::NoFrame };
};
}

View file

@ -29,24 +29,26 @@
#include <LibGUI/GGroupBox.h>
#include <LibGUI/GPainter.h>
GGroupBox::GGroupBox(GWidget* parent)
: GGroupBox({}, parent)
namespace GUI {
GroupBox::GroupBox(Widget* parent)
: GroupBox({}, parent)
{
}
GGroupBox::GGroupBox(const StringView& title, GWidget* parent)
: GWidget(parent)
GroupBox::GroupBox(const StringView& title, Widget* parent)
: Widget(parent)
, m_title(title)
{
}
GGroupBox::~GGroupBox()
GroupBox::~GroupBox()
{
}
void GGroupBox::paint_event(GPaintEvent& event)
void GroupBox::paint_event(PaintEvent& event)
{
GPainter painter(*this);
Painter painter(*this);
painter.add_clip_rect(event.rect());
Rect frame_rect {
@ -60,10 +62,12 @@ void GGroupBox::paint_event(GPaintEvent& event)
painter.draw_text(text_rect, m_title, TextAlignment::Center, palette().button_text());
}
void GGroupBox::set_title(const StringView& title)
void GroupBox::set_title(const StringView& title)
{
if (m_title == title)
return;
m_title = title;
update();
}
}

View file

@ -28,20 +28,24 @@
#include <LibGUI/GWidget.h>
class GGroupBox : public GWidget {
C_OBJECT(GGroupBox)
namespace GUI {
class GroupBox : public Widget {
C_OBJECT(GroupBox)
public:
virtual ~GGroupBox() override;
virtual ~GroupBox() override;
String title() const { return m_title; }
void set_title(const StringView&);
protected:
explicit GGroupBox(GWidget* parent);
GGroupBox(const StringView& title, GWidget* parent);
explicit GroupBox(Widget* parent);
GroupBox(const StringView& title, Widget* parent);
virtual void paint_event(GPaintEvent&) override;
virtual void paint_event(PaintEvent&) override;
private:
String m_title;
};
}

View file

@ -31,21 +31,23 @@
#include <LibGUI/GTextEditor.h>
#include <stdio.h>
GInputBox::GInputBox(const StringView& prompt, const StringView& title, Core::Object* parent)
: GDialog(parent)
namespace GUI {
InputBox::InputBox(const StringView& prompt, const StringView& title, Core::Object* parent)
: Dialog(parent)
, m_prompt(prompt)
{
set_title(title);
build();
}
GInputBox::~GInputBox()
InputBox::~InputBox()
{
}
void GInputBox::build()
void InputBox::build()
{
auto widget = GWidget::construct();
auto widget = Widget::construct();
set_main_widget(widget);
int text_width = widget->font().width(m_prompt);
@ -54,30 +56,30 @@ void GInputBox::build()
set_rect(x(), y(), max_width + 80, 80);
widget->set_layout(make<GVBoxLayout>());
widget->set_layout(make<VBoxLayout>());
widget->set_fill_with_background_color(true);
widget->layout()->set_margins({ 8, 8, 8, 8 });
widget->layout()->set_spacing(8);
auto label = GLabel::construct(m_prompt, widget);
auto label = Label::construct(m_prompt, widget);
label->set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed);
label->set_preferred_size(text_width, 16);
m_text_editor = GTextEditor::construct(GTextEditor::SingleLine, widget);
m_text_editor = TextEditor::construct(TextEditor::SingleLine, widget);
m_text_editor->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
m_text_editor->set_preferred_size(0, 19);
auto button_container_outer = GWidget::construct(widget.ptr());
auto button_container_outer = Widget::construct(widget.ptr());
button_container_outer->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
button_container_outer->set_preferred_size(0, 20);
button_container_outer->set_layout(make<GVBoxLayout>());
button_container_outer->set_layout(make<VBoxLayout>());
auto button_container_inner = GWidget::construct(button_container_outer.ptr());
button_container_inner->set_layout(make<GHBoxLayout>());
auto button_container_inner = Widget::construct(button_container_outer.ptr());
button_container_inner->set_layout(make<HBoxLayout>());
button_container_inner->layout()->set_spacing(8);
m_cancel_button = GButton::construct(button_container_inner);
m_cancel_button = Button::construct(button_container_inner);
m_cancel_button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
m_cancel_button->set_preferred_size(0, 20);
m_cancel_button->set_text("Cancel");
@ -86,7 +88,7 @@ void GInputBox::build()
done(ExecCancel);
};
m_ok_button = GButton::construct(button_container_inner);
m_ok_button = Button::construct(button_container_inner);
m_ok_button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
m_ok_button->set_preferred_size(0, 20);
m_ok_button->set_text("OK");
@ -104,3 +106,5 @@ void GInputBox::build()
};
m_text_editor->set_focus(true);
}
}

View file

@ -28,14 +28,16 @@
#include <LibGUI/GDialog.h>
class GButton;
class GTextEditor;
namespace GUI {
class GInputBox : public GDialog {
C_OBJECT(GInputBox)
class Button;
class TextEditor;
class InputBox : public Dialog {
C_OBJECT(InputBox)
public:
explicit GInputBox(const StringView& prompt, const StringView& title, Core::Object* parent = nullptr);
virtual ~GInputBox() override;
explicit InputBox(const StringView& prompt, const StringView& title, Core::Object* parent = nullptr);
virtual ~InputBox() override;
String text_value() const { return m_text_value; }
@ -44,7 +46,9 @@ private:
String m_prompt;
String m_text_value;
RefPtr<GButton> m_ok_button;
RefPtr<GButton> m_cancel_button;
RefPtr<GTextEditor> m_text_editor;
RefPtr<Button> m_ok_button;
RefPtr<Button> m_cancel_button;
RefPtr<TextEditor> m_text_editor;
};
}

View file

@ -33,8 +33,10 @@
#include <LibGUI/GPainter.h>
#include <LibGUI/GScrollBar.h>
GItemView::GItemView(GWidget* parent)
: GAbstractView(parent)
namespace GUI {
ItemView::ItemView(Widget* parent)
: AbstractView(parent)
{
set_background_role(ColorRole::Base);
set_foreground_role(ColorRole::BaseText);
@ -44,29 +46,29 @@ GItemView::GItemView(GWidget* parent)
horizontal_scrollbar().set_visible(false);
}
GItemView::~GItemView()
ItemView::~ItemView()
{
}
void GItemView::scroll_into_view(const GModelIndex& index, Orientation orientation)
void ItemView::scroll_into_view(const ModelIndex& index, Orientation orientation)
{
GScrollableWidget::scroll_into_view(item_rect(index.row()), orientation);
ScrollableWidget::scroll_into_view(item_rect(index.row()), orientation);
}
void GItemView::resize_event(GResizeEvent& event)
void ItemView::resize_event(ResizeEvent& event)
{
GAbstractView::resize_event(event);
AbstractView::resize_event(event);
update_content_size();
}
void GItemView::did_update_model()
void ItemView::did_update_model()
{
GAbstractView::did_update_model();
AbstractView::did_update_model();
update_content_size();
update();
}
void GItemView::update_content_size()
void ItemView::update_content_size()
{
if (!model())
return set_content_size({});
@ -83,7 +85,7 @@ void GItemView::update_content_size()
set_content_size({ content_width, content_height });
}
Rect GItemView::item_rect(int item_index) const
Rect ItemView::item_rect(int item_index) const
{
if (!m_visual_row_count || !m_visual_column_count)
return {};
@ -97,7 +99,7 @@ Rect GItemView::item_rect(int item_index) const
};
}
Vector<int> GItemView::items_intersecting_rect(const Rect& rect) const
Vector<int> ItemView::items_intersecting_rect(const Rect& rect) const
{
ASSERT(model());
const auto& column_metadata = model()->column_metadata(model_column());
@ -115,7 +117,7 @@ Vector<int> GItemView::items_intersecting_rect(const Rect& rect) const
return item_indexes;
}
GModelIndex GItemView::index_at_event_position(const Point& position) const
ModelIndex ItemView::index_at_event_position(const Point& position) const
{
ASSERT(model());
// FIXME: Since all items are the same size, just compute the clicked item index
@ -136,18 +138,18 @@ GModelIndex GItemView::index_at_event_position(const Point& position) const
return {};
}
void GItemView::mousedown_event(GMouseEvent& event)
void ItemView::mousedown_event(MouseEvent& event)
{
if (!model())
return GAbstractView::mousedown_event(event);
return AbstractView::mousedown_event(event);
if (event.button() != GMouseButton::Left)
return GAbstractView::mousedown_event(event);
if (event.button() != MouseButton::Left)
return AbstractView::mousedown_event(event);
auto index = index_at_event_position(event.position());
if (index.is_valid()) {
// We might start dragging this item, but not rubber-banding.
return GAbstractView::mousedown_event(event);
return AbstractView::mousedown_event(event);
}
ASSERT(m_rubber_band_remembered_selection.is_empty());
@ -166,20 +168,20 @@ void GItemView::mousedown_event(GMouseEvent& event)
m_rubber_band_current = event.position();
}
void GItemView::mouseup_event(GMouseEvent& event)
void ItemView::mouseup_event(MouseEvent& event)
{
if (m_rubber_banding && event.button() == GMouseButton::Left) {
if (m_rubber_banding && event.button() == MouseButton::Left) {
m_rubber_banding = false;
m_rubber_band_remembered_selection.clear();
update();
}
GAbstractView::mouseup_event(event);
AbstractView::mouseup_event(event);
}
void GItemView::mousemove_event(GMouseEvent& event)
void ItemView::mousemove_event(MouseEvent& event)
{
if (!model())
return GAbstractView::mousemove_event(event);
return AbstractView::mousemove_event(event);
if (m_rubber_banding) {
if (m_rubber_band_current != event.position()) {
@ -199,10 +201,10 @@ void GItemView::mousemove_event(GMouseEvent& event)
}
}
GAbstractView::mousemove_event(event);
AbstractView::mousemove_event(event);
}
void GItemView::get_item_rects(int item_index, const Font& font, const GVariant& item_text, Rect& item_rect, Rect& icon_rect, Rect& text_rect) const
void ItemView::get_item_rects(int item_index, const Font& font, const Variant& item_text, Rect& item_rect, Rect& icon_rect, Rect& text_rect) const
{
item_rect = this->item_rect(item_index);
icon_rect = { 0, 0, 32, 32 };
@ -214,12 +216,12 @@ void GItemView::get_item_rects(int item_index, const Font& font, const GVariant&
text_rect.intersect(item_rect);
}
void GItemView::second_paint_event(GPaintEvent& event)
void ItemView::second_paint_event(PaintEvent& event)
{
if (!m_rubber_banding)
return;
GPainter painter(*this);
Painter painter(*this);
painter.add_clip_rect(event.rect());
auto rubber_band_rect = Rect::from_two_points(m_rubber_band_origin, m_rubber_band_current);
@ -227,12 +229,12 @@ void GItemView::second_paint_event(GPaintEvent& event)
painter.draw_rect(rubber_band_rect, parent_widget()->palette().rubber_band_border());
}
void GItemView::paint_event(GPaintEvent& event)
void ItemView::paint_event(PaintEvent& event)
{
Color widget_background_color = palette().color(background_role());
GFrame::paint_event(event);
Frame::paint_event(event);
GPainter painter(*this);
Painter painter(*this);
painter.add_clip_rect(widget_inner_rect());
painter.add_clip_rect(event.rect());
painter.fill_rect(event.rect(), widget_background_color);
@ -251,8 +253,8 @@ void GItemView::paint_event(GPaintEvent& event)
background_color = widget_background_color;
}
auto icon = model()->data(model_index, GModel::Role::Icon);
auto item_text = model()->data(model_index, GModel::Role::Display);
auto icon = model()->data(model_index, Model::Role::Icon);
auto item_text = model()->data(model_index, Model::Role::Display);
Rect item_rect;
Rect icon_rect;
@ -268,20 +270,20 @@ void GItemView::paint_event(GPaintEvent& event)
if (is_selected_item)
text_color = palette().selection_text();
else
text_color = model()->data(model_index, GModel::Role::ForegroundColor).to_color(palette().color(foreground_role()));
text_color = model()->data(model_index, Model::Role::ForegroundColor).to_color(palette().color(foreground_role()));
painter.fill_rect(text_rect, background_color);
painter.draw_text(text_rect, item_text.to_string(), font, TextAlignment::Center, text_color, TextElision::Right);
};
}
int GItemView::item_count() const
int ItemView::item_count() const
{
if (!model())
return 0;
return model()->row_count();
}
void GItemView::keydown_event(GKeyEvent& event)
void ItemView::keydown_event(KeyEvent& event)
{
if (!model())
return;
@ -312,7 +314,7 @@ void GItemView::keydown_event(GKeyEvent& event)
return;
}
if (event.key() == KeyCode::Key_Up) {
GModelIndex new_index;
ModelIndex new_index;
if (!selection().is_empty()) {
auto old_index = selection().first();
new_index = model.index(old_index.row() - m_visual_column_count, old_index.column());
@ -327,7 +329,7 @@ void GItemView::keydown_event(GKeyEvent& event)
return;
}
if (event.key() == KeyCode::Key_Down) {
GModelIndex new_index;
ModelIndex new_index;
if (!selection().is_empty()) {
auto old_index = selection().first();
new_index = model.index(old_index.row() + m_visual_column_count, old_index.column());
@ -342,7 +344,7 @@ void GItemView::keydown_event(GKeyEvent& event)
return;
}
if (event.key() == KeyCode::Key_Left) {
GModelIndex new_index;
ModelIndex new_index;
if (!selection().is_empty()) {
auto old_index = selection().first();
new_index = model.index(old_index.row() - 1, old_index.column());
@ -357,7 +359,7 @@ void GItemView::keydown_event(GKeyEvent& event)
return;
}
if (event.key() == KeyCode::Key_Right) {
GModelIndex new_index;
ModelIndex new_index;
if (!selection().is_empty()) {
auto old_index = selection().first();
new_index = model.index(old_index.row() + 1, old_index.column());
@ -393,5 +395,7 @@ void GItemView::keydown_event(GKeyEvent& event)
}
return;
}
return GWidget::keydown_event(event);
return Widget::keydown_event(event);
}
}

View file

@ -31,42 +31,44 @@
#include <LibGUI/GAbstractView.h>
#include <LibGUI/GModel.h>
class GScrollBar;
namespace GUI {
class ScrollBar;
class Painter;
class GItemView : public GAbstractView {
C_OBJECT(GItemView)
class ItemView : public AbstractView {
C_OBJECT(ItemView)
public:
virtual ~GItemView() override;
virtual ~ItemView() override;
int content_width() const;
int horizontal_padding() const { return m_horizontal_padding; }
void scroll_into_view(const GModelIndex&, Orientation);
void scroll_into_view(const ModelIndex&, Orientation);
Size effective_item_size() const { return m_effective_item_size; }
int model_column() const { return m_model_column; }
void set_model_column(int column) { m_model_column = column; }
virtual GModelIndex index_at_event_position(const Point&) const override;
virtual ModelIndex index_at_event_position(const Point&) const override;
private:
explicit GItemView(GWidget* parent);
explicit ItemView(Widget* parent);
virtual void did_update_model() override;
virtual void paint_event(GPaintEvent&) override;
virtual void second_paint_event(GPaintEvent&) override;
virtual void resize_event(GResizeEvent&) override;
virtual void mousedown_event(GMouseEvent&) override;
virtual void mousemove_event(GMouseEvent&) override;
virtual void mouseup_event(GMouseEvent&) override;
virtual void keydown_event(GKeyEvent&) override;
virtual void paint_event(PaintEvent&) override;
virtual void second_paint_event(PaintEvent&) override;
virtual void resize_event(ResizeEvent&) override;
virtual void mousedown_event(MouseEvent&) override;
virtual void mousemove_event(MouseEvent&) override;
virtual void mouseup_event(MouseEvent&) override;
virtual void keydown_event(KeyEvent&) override;
int item_count() const;
Rect item_rect(int item_index) const;
Vector<int> items_intersecting_rect(const Rect&) const;
void update_content_size();
void get_item_rects(int item_index, const Font&, const GVariant& item_text, Rect& item_rect, Rect& icon_rect, Rect& text_rect) const;
void get_item_rects(int item_index, const Font&, const Variant& item_text, Rect& item_rect, Rect& icon_rect, Rect& text_rect) const;
int m_horizontal_padding { 5 };
int m_model_column { 0 };
@ -78,5 +80,7 @@ private:
bool m_rubber_banding { false };
Point m_rubber_band_origin;
Point m_rubber_band_current;
Vector<GModelIndex> m_rubber_band_remembered_selection;
Vector<ModelIndex> m_rubber_band_remembered_selection;
};
}

View file

@ -28,7 +28,9 @@
#include <LibCore/CFile.h>
#include <LibGUI/GJsonArrayModel.h>
void GJsonArrayModel::update()
namespace GUI {
void JsonArrayModel::update()
{
auto file = Core::File::construct(m_json_path);
if (!file->open(Core::IODevice::ReadOnly)) {
@ -46,18 +48,18 @@ void GJsonArrayModel::update()
did_update();
}
GModel::ColumnMetadata GJsonArrayModel::column_metadata(int column) const
Model::ColumnMetadata JsonArrayModel::column_metadata(int column) const
{
ASSERT(column < m_fields.size());
return { 100, m_fields[column].text_alignment };
}
GVariant GJsonArrayModel::data(const GModelIndex& index, Role role) const
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 == GModel::Role::Display) {
if (role == Model::Role::Display) {
auto& json_field_name = field_spec.json_field_name;
auto data = object.get(json_field_name);
if (field_spec.massage_for_display)
@ -67,13 +69,13 @@ GVariant GJsonArrayModel::data(const GModelIndex& index, Role role) const
return object.get(json_field_name).to_string();
}
if (role == GModel::Role::Sort) {
if (role == Model::Role::Sort) {
if (field_spec.massage_for_sort)
return field_spec.massage_for_sort(object);
return data(index, Role::Display);
}
if (role == GModel::Role::Custom) {
if (role == Model::Role::Custom) {
if (field_spec.massage_for_custom)
return field_spec.massage_for_custom(object);
return {};
@ -82,7 +84,7 @@ GVariant GJsonArrayModel::data(const GModelIndex& index, Role role) const
return {};
}
void GJsonArrayModel::set_json_path(const String& json_path)
void JsonArrayModel::set_json_path(const String& json_path)
{
if (m_json_path == json_path)
return;
@ -90,3 +92,5 @@ void GJsonArrayModel::set_json_path(const String& json_path)
m_json_path = json_path;
update();
}
}

View file

@ -30,10 +30,12 @@
#include <AK/JsonObject.h>
#include <LibGUI/GModel.h>
class GJsonArrayModel final : public GModel {
namespace GUI {
class JsonArrayModel final : public Model {
public:
struct FieldSpec {
FieldSpec(const String& a_column_name, TextAlignment a_text_alignment, Function<GVariant(const JsonObject&)>&& a_massage_for_display, Function<GVariant(const JsonObject&)>&& a_massage_for_sort = {}, Function<GVariant(const JsonObject&)>&& a_massage_for_custom = {})
FieldSpec(const String& a_column_name, TextAlignment a_text_alignment, Function<Variant(const JsonObject&)>&& a_massage_for_display, Function<Variant(const JsonObject&)>&& a_massage_for_sort = {}, Function<Variant(const JsonObject&)>&& a_massage_for_custom = {})
: column_name(a_column_name)
, text_alignment(a_text_alignment)
, massage_for_display(move(a_massage_for_display))
@ -52,30 +54,30 @@ public:
String json_field_name;
String column_name;
TextAlignment text_alignment;
Function<GVariant(const JsonObject&)> massage_for_display;
Function<GVariant(const JsonObject&)> massage_for_sort;
Function<GVariant(const JsonObject&)> massage_for_custom;
Function<Variant(const JsonObject&)> massage_for_display;
Function<Variant(const JsonObject&)> massage_for_sort;
Function<Variant(const JsonObject&)> massage_for_custom;
};
static NonnullRefPtr<GJsonArrayModel> create(const String& json_path, Vector<FieldSpec>&& fields)
static NonnullRefPtr<JsonArrayModel> create(const String& json_path, Vector<FieldSpec>&& fields)
{
return adopt(*new GJsonArrayModel(json_path, move(fields)));
return adopt(*new JsonArrayModel(json_path, move(fields)));
}
virtual ~GJsonArrayModel() override {}
virtual ~JsonArrayModel() override {}
virtual int row_count(const GModelIndex& = GModelIndex()) const override { return m_array.size(); }
virtual int column_count(const GModelIndex& = GModelIndex()) const override { return m_fields.size(); }
virtual int row_count(const ModelIndex& = ModelIndex()) const override { return m_array.size(); }
virtual int column_count(const ModelIndex& = ModelIndex()) const override { return m_fields.size(); }
virtual String column_name(int column) const override { return m_fields[column].column_name; }
virtual ColumnMetadata column_metadata(int) const override;
virtual GVariant data(const GModelIndex&, Role = Role::Display) const override;
virtual Variant data(const ModelIndex&, Role = Role::Display) const override;
virtual void update() override;
const String& json_path() const { return m_json_path; }
void set_json_path(const String& json_path);
private:
GJsonArrayModel(const String& json_path, Vector<FieldSpec>&& fields)
JsonArrayModel(const String& json_path, Vector<FieldSpec>&& fields)
: m_json_path(json_path)
, m_fields(move(fields))
{
@ -85,3 +87,5 @@ private:
Vector<FieldSpec> m_fields;
JsonArray m_array;
};
}

View file

@ -29,22 +29,24 @@
#include <LibGUI/GLabel.h>
#include <LibGUI/GPainter.h>
GLabel::GLabel(GWidget* parent)
: GFrame(parent)
namespace GUI {
Label::Label(Widget* parent)
: Frame(parent)
{
}
GLabel::GLabel(const StringView& text, GWidget* parent)
: GFrame(parent)
Label::Label(const StringView& text, Widget* parent)
: Frame(parent)
, m_text(text)
{
}
GLabel::~GLabel()
Label::~Label()
{
}
void GLabel::set_icon(GraphicsBitmap* icon)
void Label::set_icon(GraphicsBitmap* icon)
{
if (m_icon == icon)
return;
@ -52,7 +54,7 @@ void GLabel::set_icon(GraphicsBitmap* icon)
update();
}
void GLabel::set_text(const StringView& text)
void Label::set_text(const StringView& text)
{
if (text == m_text)
return;
@ -60,11 +62,11 @@ void GLabel::set_text(const StringView& text)
update();
}
void GLabel::paint_event(GPaintEvent& event)
void Label::paint_event(PaintEvent& event)
{
GFrame::paint_event(event);
Frame::paint_event(event);
GPainter painter(*this);
Painter painter(*this);
painter.add_clip_rect(event.rect());
if (m_icon) {
@ -92,8 +94,10 @@ void GLabel::paint_event(GPaintEvent& event)
}
}
void GLabel::size_to_fit()
void Label::size_to_fit()
{
set_size_policy(SizePolicy::Fixed, SizePolicy::Fill);
set_preferred_size(font().width(m_text), 0);
}
}

View file

@ -31,10 +31,12 @@
class GraphicsBitmap;
class GLabel : public GFrame {
C_OBJECT(GLabel)
namespace GUI {
class Label : public Frame {
C_OBJECT(Label)
public:
virtual ~GLabel() override;
virtual ~Label() override;
String text() const { return m_text; }
void set_text(const StringView&);
@ -52,10 +54,10 @@ public:
void size_to_fit();
protected:
explicit GLabel(GWidget* parent = nullptr);
GLabel(const StringView& text, GWidget* parent = nullptr);
explicit Label(Widget* parent = nullptr);
Label(const StringView& text, Widget* parent = nullptr);
virtual void paint_event(GPaintEvent&) override;
virtual void paint_event(PaintEvent&) override;
private:
String m_text;
@ -63,3 +65,5 @@ private:
TextAlignment m_text_alignment { TextAlignment::Center };
bool m_should_stretch_icon { false };
};
}

View file

@ -27,42 +27,44 @@
#include <LibGUI/GLayout.h>
#include <LibGUI/GWidget.h>
GLayout::GLayout()
namespace GUI {
Layout::Layout()
{
}
GLayout::~GLayout()
Layout::~Layout()
{
}
void GLayout::notify_adopted(Badge<GWidget>, GWidget& widget)
void Layout::notify_adopted(Badge<Widget>, Widget& widget)
{
if (m_owner == &widget)
return;
m_owner = widget.make_weak_ptr();
}
void GLayout::notify_disowned(Badge<GWidget>, GWidget& widget)
void Layout::notify_disowned(Badge<Widget>, Widget& widget)
{
ASSERT(m_owner == &widget);
m_owner.clear();
}
void GLayout::add_entry(Entry&& entry)
void Layout::add_entry(Entry&& entry)
{
m_entries.append(move(entry));
if (m_owner)
m_owner->notify_layout_changed({});
}
void GLayout::add_spacer()
void Layout::add_spacer()
{
Entry entry;
entry.type = Entry::Type::Spacer;
add_entry(move(entry));
}
void GLayout::add_layout(OwnPtr<GLayout>&& layout)
void Layout::add_layout(OwnPtr<Layout>&& layout)
{
Entry entry;
entry.type = Entry::Type::Layout;
@ -70,7 +72,7 @@ void GLayout::add_layout(OwnPtr<GLayout>&& layout)
add_entry(move(entry));
}
void GLayout::add_widget(GWidget& widget)
void Layout::add_widget(Widget& widget)
{
Entry entry;
entry.type = Entry::Type::Widget;
@ -78,7 +80,7 @@ void GLayout::add_widget(GWidget& widget)
add_entry(move(entry));
}
void GLayout::insert_widget_before(GWidget& widget, GWidget& before_widget)
void Layout::insert_widget_before(Widget& widget, Widget& before_widget)
{
Entry entry;
entry.type = Entry::Type::Widget;
@ -90,7 +92,7 @@ void GLayout::insert_widget_before(GWidget& widget, GWidget& before_widget)
m_owner->notify_layout_changed({});
}
void GLayout::remove_widget(GWidget& widget)
void Layout::remove_widget(Widget& widget)
{
m_entries.remove_first_matching([&](auto& entry) {
return entry.widget == &widget;
@ -99,7 +101,7 @@ void GLayout::remove_widget(GWidget& widget)
m_owner->notify_layout_changed({});
}
void GLayout::set_spacing(int spacing)
void Layout::set_spacing(int spacing)
{
if (m_spacing == spacing)
return;
@ -108,7 +110,7 @@ void GLayout::set_spacing(int spacing)
m_owner->notify_layout_changed({});
}
void GLayout::set_margins(const GMargins& margins)
void Layout::set_margins(const Margins& margins)
{
if (m_margins == margins)
return;
@ -116,3 +118,5 @@ void GLayout::set_margins(const GMargins& margins)
if (m_owner)
m_owner->notify_layout_changed({});
}
}

View file

@ -32,27 +32,29 @@
#include <AK/WeakPtr.h>
#include <LibGUI/GMargins.h>
class GWidget;
namespace GUI {
class GLayout {
class Widget;
class Layout {
public:
GLayout();
virtual ~GLayout();
Layout();
virtual ~Layout();
void add_widget(GWidget&);
void insert_widget_before(GWidget& widget, GWidget& before_widget);
void add_layout(OwnPtr<GLayout>&&);
void add_widget(Widget&);
void insert_widget_before(Widget& widget, Widget& before_widget);
void add_layout(OwnPtr<Layout>&&);
void add_spacer();
void remove_widget(GWidget&);
void remove_widget(Widget&);
virtual void run(GWidget&) = 0;
virtual void run(Widget&) = 0;
void notify_adopted(Badge<GWidget>, GWidget&);
void notify_disowned(Badge<GWidget>, GWidget&);
void notify_adopted(Badge<Widget>, Widget&);
void notify_disowned(Badge<Widget>, Widget&);
GMargins margins() const { return m_margins; }
void set_margins(const GMargins&);
Margins margins() const { return m_margins; }
void set_margins(const Margins&);
int spacing() const { return m_spacing; }
void set_spacing(int);
@ -67,14 +69,16 @@ protected:
};
Type type { Type::Invalid };
WeakPtr<GWidget> widget;
OwnPtr<GLayout> layout;
WeakPtr<Widget> widget;
OwnPtr<Layout> layout;
};
void add_entry(Entry&&);
WeakPtr<GWidget> m_owner;
WeakPtr<Widget> m_owner;
Vector<Entry> m_entries;
GMargins m_margins;
Margins m_margins;
int m_spacing { 3 };
};
}

View file

@ -26,16 +26,18 @@
#include <LibGUI/GLazyWidget.h>
GLazyWidget::GLazyWidget(GWidget* parent)
: GWidget(parent)
namespace GUI {
LazyWidget::LazyWidget(Widget* parent)
: Widget(parent)
{
}
GLazyWidget::~GLazyWidget()
LazyWidget::~LazyWidget()
{
}
void GLazyWidget::show_event(GShowEvent&)
void LazyWidget::show_event(ShowEvent&)
{
if (m_has_been_shown)
return;
@ -44,3 +46,5 @@ void GLazyWidget::show_event(GShowEvent&)
ASSERT(on_first_show);
on_first_show(*this);
}
}

View file

@ -28,18 +28,21 @@
#include <LibGUI/GWidget.h>
class GLazyWidget : public GWidget {
C_OBJECT(GLazyWidget)
public:
virtual ~GLazyWidget() override;
namespace GUI {
Function<void(GLazyWidget&)> on_first_show;
class LazyWidget : public Widget {
C_OBJECT(LazyWidget)
public:
virtual ~LazyWidget() override;
Function<void(LazyWidget&)> on_first_show;
protected:
explicit GLazyWidget(GWidget* parent = nullptr);
explicit LazyWidget(Widget* parent = nullptr);
private:
virtual void show_event(GShowEvent&) override;
virtual void show_event(ShowEvent&) override;
bool m_has_been_shown { false };
};
}

View file

@ -30,8 +30,10 @@
#include <LibGUI/GPainter.h>
#include <LibGUI/GScrollBar.h>
GListView::GListView(GWidget* parent)
: GAbstractView(parent)
namespace GUI {
ListView::ListView(Widget* parent)
: AbstractView(parent)
{
set_background_role(ColorRole::Base);
set_foreground_role(ColorRole::BaseText);
@ -40,18 +42,18 @@ GListView::GListView(GWidget* parent)
set_frame_thickness(2);
}
GListView::~GListView()
ListView::~ListView()
{
}
void GListView::update_content_size()
void ListView::update_content_size()
{
if (!model())
return set_content_size({});
int content_width = 0;
for (int row = 0, row_count = model()->row_count(); row < row_count; ++row) {
auto text = model()->data(model()->index(row, m_model_column), GModel::Role::Display);
auto text = model()->data(model()->index(row, m_model_column), Model::Role::Display);
content_width = max(content_width, font().width(text.to_string()));
}
@ -61,30 +63,30 @@ void GListView::update_content_size()
set_content_size({ content_width, content_height });
}
void GListView::resize_event(GResizeEvent& event)
void ListView::resize_event(ResizeEvent& event)
{
update_content_size();
GAbstractView::resize_event(event);
AbstractView::resize_event(event);
}
void GListView::did_update_model()
void ListView::did_update_model()
{
GAbstractView::did_update_model();
AbstractView::did_update_model();
update_content_size();
update();
}
Rect GListView::content_rect(int row) const
Rect ListView::content_rect(int row) const
{
return { 0, row * item_height(), content_width(), item_height() };
}
Rect GListView::content_rect(const GModelIndex& index) const
Rect ListView::content_rect(const ModelIndex& index) const
{
return content_rect(index.row());
}
GModelIndex GListView::index_at_event_position(const Point& point) const
ModelIndex ListView::index_at_event_position(const Point& point) const
{
ASSERT(model());
@ -97,19 +99,19 @@ GModelIndex GListView::index_at_event_position(const Point& point) const
return {};
}
Point GListView::adjusted_position(const Point& position) const
Point ListView::adjusted_position(const Point& position) const
{
return position.translated(horizontal_scrollbar().value() - frame_thickness(), vertical_scrollbar().value() - frame_thickness());
}
void GListView::paint_event(GPaintEvent& event)
void ListView::paint_event(PaintEvent& event)
{
GFrame::paint_event(event);
Frame::paint_event(event);
if (!model())
return;
GPainter painter(*this);
Painter painter(*this);
painter.add_clip_rect(frame_inner_rect());
painter.add_clip_rect(event.rect());
painter.translate(frame_thickness(), frame_thickness());
@ -151,7 +153,7 @@ void GListView::paint_event(GPaintEvent& event)
if (is_selected_row)
text_color = palette().selection_text();
else
text_color = model()->data(index, GModel::Role::ForegroundColor).to_color(palette().color(foreground_role()));
text_color = model()->data(index, Model::Role::ForegroundColor).to_color(palette().color(foreground_role()));
auto text_rect = row_rect;
text_rect.move_by(horizontal_padding(), 0);
text_rect.set_width(text_rect.width() - horizontal_padding() * 2);
@ -165,14 +167,14 @@ void GListView::paint_event(GPaintEvent& event)
painter.fill_rect(unpainted_rect, palette().color(background_role()));
}
int GListView::item_count() const
int ListView::item_count() const
{
if (!model())
return 0;
return model()->row_count();
}
void GListView::keydown_event(GKeyEvent& event)
void ListView::keydown_event(KeyEvent& event)
{
if (!model())
return;
@ -182,7 +184,7 @@ void GListView::keydown_event(GKeyEvent& event)
return;
}
if (event.key() == KeyCode::Key_Up) {
GModelIndex new_index;
ModelIndex new_index;
if (!selection().is_empty()) {
auto old_index = selection().first();
new_index = model.index(old_index.row() - 1, old_index.column());
@ -197,7 +199,7 @@ void GListView::keydown_event(GKeyEvent& event)
return;
}
if (event.key() == KeyCode::Key_Down) {
GModelIndex new_index;
ModelIndex new_index;
if (!selection().is_empty()) {
auto old_index = selection().first();
new_index = model.index(old_index.row() + 1, old_index.column());
@ -233,20 +235,20 @@ void GListView::keydown_event(GKeyEvent& event)
}
return;
}
return GWidget::keydown_event(event);
return Widget::keydown_event(event);
}
void GListView::scroll_into_view(const GModelIndex& index, Orientation orientation)
void ListView::scroll_into_view(const ModelIndex& index, Orientation orientation)
{
auto rect = content_rect(index.row());
GScrollableWidget::scroll_into_view(rect, orientation);
ScrollableWidget::scroll_into_view(rect, orientation);
}
void GListView::doubleclick_event(GMouseEvent& event)
void ListView::doubleclick_event(MouseEvent& event)
{
if (!model())
return;
if (event.button() == GMouseButton::Left) {
if (event.button() == MouseButton::Left) {
if (!selection().is_empty()) {
if (is_editable())
begin_editing(selection().first());
@ -255,3 +257,5 @@ void GListView::doubleclick_event(GMouseEvent& event)
}
}
}
}

View file

@ -31,14 +31,16 @@
#include <LibGUI/GAbstractView.h>
#include <LibGUI/GModel.h>
class GScrollBar;
namespace GUI {
class ScrollBar;
class Painter;
class GListView : public GAbstractView {
C_OBJECT(GListView)
class ListView : public AbstractView {
C_OBJECT(ListView)
public:
explicit GListView(GWidget* parent);
virtual ~GListView() override;
explicit ListView(Widget* parent);
virtual ~ListView() override;
int item_height() const { return 16; }
@ -47,22 +49,22 @@ public:
int horizontal_padding() const { return m_horizontal_padding; }
void scroll_into_view(const GModelIndex&, Orientation);
void scroll_into_view(const ModelIndex&, Orientation);
Point adjusted_position(const Point&) const;
virtual GModelIndex index_at_event_position(const Point&) const override;
virtual Rect content_rect(const GModelIndex&) const override;
virtual ModelIndex index_at_event_position(const Point&) const override;
virtual Rect content_rect(const ModelIndex&) const override;
int model_column() const { return m_model_column; }
void set_model_column(int column) { m_model_column = column; }
private:
virtual void did_update_model() override;
virtual void paint_event(GPaintEvent&) override;
virtual void doubleclick_event(GMouseEvent&) override;
virtual void keydown_event(GKeyEvent&) override;
virtual void resize_event(GResizeEvent&) override;
virtual void paint_event(PaintEvent&) override;
virtual void doubleclick_event(MouseEvent&) override;
virtual void keydown_event(KeyEvent&) override;
virtual void resize_event(ResizeEvent&) override;
Rect content_rect(int row) const;
int item_count() const;
@ -72,3 +74,5 @@ private:
int m_model_column { 0 };
bool m_alternating_row_colors { true };
};
}

View file

@ -26,17 +26,19 @@
#pragma once
class GMargins {
namespace GUI {
class Margins {
public:
GMargins() {}
GMargins(int left, int top, int right, int bottom)
Margins() {}
Margins(int left, int top, int right, int bottom)
: m_left(left)
, m_top(top)
, m_right(right)
, m_bottom(bottom)
{
}
~GMargins() {}
~Margins() {}
bool is_null() const { return !m_left && !m_top && !m_right && !m_bottom; }
@ -50,7 +52,7 @@ public:
void set_right(int value) { m_right = value; }
void set_bottom(int value) { m_bottom = value; }
bool operator==(const GMargins& other) const
bool operator==(const Margins& other) const
{
return m_left == other.m_left
&& m_top == other.m_top
@ -64,3 +66,4 @@ private:
int m_right { 0 };
int m_bottom { 0 };
};
}

View file

@ -30,17 +30,19 @@
#include <LibGUI/GMenu.h>
#include <LibGUI/GWindowServerConnection.h>
//#define GMENU_DEBUG
//#define MENU_DEBUG
static HashMap<int, GMenu*>& all_menus()
namespace GUI {
static HashMap<int, Menu*>& all_menus()
{
static HashMap<int, GMenu*>* map;
static HashMap<int, Menu*>* map;
if (!map)
map = new HashMap<int, GMenu*>();
map = new HashMap<int, Menu*>();
return *map;
}
GMenu* GMenu::from_menu_id(int menu_id)
Menu* Menu::from_menu_id(int menu_id)
{
auto it = all_menus().find(menu_id);
if (it == all_menus().end())
@ -48,76 +50,76 @@ GMenu* GMenu::from_menu_id(int menu_id)
return (*it).value;
}
GMenu::GMenu(const StringView& name)
Menu::Menu(const StringView& name)
: m_name(name)
{
}
GMenu::~GMenu()
Menu::~Menu()
{
unrealize_menu();
}
void GMenu::add_action(NonnullRefPtr<GAction> action)
void Menu::add_action(NonnullRefPtr<Action> action)
{
m_items.append(make<GMenuItem>(m_menu_id, move(action)));
m_items.append(make<MenuItem>(m_menu_id, move(action)));
#ifdef GMENU_DEBUG
dbgprintf("GMenu::add_action(): MenuItem Menu ID: %d\n", m_menu_id);
dbgprintf("GUI::Menu::add_action(): MenuItem Menu ID: %d\n", m_menu_id);
#endif
}
void GMenu::add_submenu(NonnullRefPtr<GMenu> submenu)
void Menu::add_submenu(NonnullRefPtr<Menu> submenu)
{
m_items.append(make<GMenuItem>(m_menu_id, move(submenu)));
m_items.append(make<MenuItem>(m_menu_id, move(submenu)));
}
void GMenu::add_separator()
void Menu::add_separator()
{
m_items.append(make<GMenuItem>(m_menu_id, GMenuItem::Separator));
m_items.append(make<MenuItem>(m_menu_id, MenuItem::Type::Separator));
}
void GMenu::realize_if_needed()
void Menu::realize_if_needed()
{
if (m_menu_id == -1)
realize_menu();
}
void GMenu::popup(const Point& screen_position)
void Menu::popup(const Point& screen_position)
{
realize_if_needed();
GWindowServerConnection::the().post_message(WindowServer::PopupMenu(m_menu_id, screen_position));
WindowServerConnection::the().post_message(WindowServer::PopupMenu(m_menu_id, screen_position));
}
void GMenu::dismiss()
void Menu::dismiss()
{
if (m_menu_id == -1)
return;
GWindowServerConnection::the().post_message(WindowServer::DismissMenu(m_menu_id));
WindowServerConnection::the().post_message(WindowServer::DismissMenu(m_menu_id));
}
int GMenu::realize_menu()
int Menu::realize_menu()
{
m_menu_id = GWindowServerConnection::the().send_sync<WindowServer::CreateMenu>(m_name)->menu_id();
m_menu_id = WindowServerConnection::the().send_sync<WindowServer::CreateMenu>(m_name)->menu_id();
#ifdef GMENU_DEBUG
dbgprintf("GMenu::realize_menu(): New menu ID: %d\n", m_menu_id);
#ifdef MENU_DEBUG
dbgprintf("GUI::Menu::realize_menu(): New menu ID: %d\n", m_menu_id);
#endif
ASSERT(m_menu_id > 0);
for (int i = 0; i < m_items.size(); ++i) {
auto& item = m_items[i];
item.set_menu_id({}, m_menu_id);
item.set_identifier({}, i);
if (item.type() == GMenuItem::Separator) {
GWindowServerConnection::the().send_sync<WindowServer::AddMenuSeparator>(m_menu_id);
if (item.type() == MenuItem::Type::Separator) {
WindowServerConnection::the().send_sync<WindowServer::AddMenuSeparator>(m_menu_id);
continue;
}
if (item.type() == GMenuItem::Submenu) {
if (item.type() == MenuItem::Type::Submenu) {
auto& submenu = *item.submenu();
submenu.realize_if_needed();
GWindowServerConnection::the().send_sync<WindowServer::AddMenuItem>(m_menu_id, i, submenu.menu_id(), submenu.name(), true, false, false, "", -1, false);
WindowServerConnection::the().send_sync<WindowServer::AddMenuItem>(m_menu_id, i, submenu.menu_id(), submenu.name(), true, false, false, "", -1, false);
continue;
}
if (item.type() == GMenuItem::Action) {
if (item.type() == MenuItem::Type::Action) {
auto& action = *item.action();
int icon_buffer_id = -1;
if (action.icon()) {
@ -129,32 +131,34 @@ int GMenu::realize_menu()
auto shared_icon = GraphicsBitmap::create_with_shared_buffer(GraphicsBitmap::Format::RGBA32, *shared_buffer, action.icon()->size());
memcpy(shared_buffer->data(), action.icon()->bits(0), action.icon()->size_in_bytes());
shared_buffer->seal();
shared_buffer->share_with(GWindowServerConnection::the().server_pid());
shared_buffer->share_with(WindowServerConnection::the().server_pid());
action.set_icon(shared_icon);
}
icon_buffer_id = action.icon()->shared_buffer_id();
}
auto shortcut_text = action.shortcut().is_valid() ? action.shortcut().to_string() : String();
bool exclusive = action.group() && action.group()->is_exclusive() && action.is_checkable();
GWindowServerConnection::the().send_sync<WindowServer::AddMenuItem>(m_menu_id, i, -1, action.text(), action.is_enabled(), action.is_checkable(), action.is_checkable() ? action.is_checked() : false, shortcut_text, icon_buffer_id, exclusive);
WindowServerConnection::the().send_sync<WindowServer::AddMenuItem>(m_menu_id, i, -1, action.text(), action.is_enabled(), action.is_checkable(), action.is_checkable() ? action.is_checked() : false, shortcut_text, icon_buffer_id, exclusive);
}
}
all_menus().set(m_menu_id, this);
return m_menu_id;
}
void GMenu::unrealize_menu()
void Menu::unrealize_menu()
{
if (m_menu_id == -1)
return;
all_menus().remove(m_menu_id);
GWindowServerConnection::the().send_sync<WindowServer::DestroyMenu>(m_menu_id);
WindowServerConnection::the().send_sync<WindowServer::DestroyMenu>(m_menu_id);
m_menu_id = 0;
}
GAction* GMenu::action_at(int index)
Action* Menu::action_at(int index)
{
if (index >= m_items.size())
return nullptr;
return m_items[index].action();
}
}

View file

@ -32,24 +32,27 @@
#include <LibCore/CObject.h>
#include <LibGUI/GMenuItem.h>
class GAction;
class Point;
class GMenu final : public Core::Object {
C_OBJECT(GMenu)
public:
explicit GMenu(const StringView& name = "");
virtual ~GMenu() override;
namespace GUI {
static GMenu* from_menu_id(int);
class Action;
class Menu final : public Core::Object {
C_OBJECT(Menu)
public:
explicit Menu(const StringView& name = "");
virtual ~Menu() override;
static Menu* from_menu_id(int);
const String& name() const { return m_name; }
GAction* action_at(int);
Action* action_at(int);
void add_action(NonnullRefPtr<GAction>);
void add_action(NonnullRefPtr<Action>);
void add_separator();
void add_submenu(NonnullRefPtr<GMenu>);
void add_submenu(NonnullRefPtr<Menu>);
void popup(const Point& screen_position);
void dismiss();
@ -57,7 +60,7 @@ public:
Function<void(unsigned)> on_item_activation;
private:
friend class GMenuBar;
friend class MenuBar;
int menu_id() const { return m_menu_id; }
int realize_menu();
@ -66,5 +69,7 @@ private:
int m_menu_id { -1 };
String m_name;
NonnullOwnPtrVector<GMenuItem> m_items;
NonnullOwnPtrVector<MenuItem> m_items;
};
}

View file

@ -27,34 +27,36 @@
#include <LibGUI/GMenuBar.h>
#include <LibGUI/GWindowServerConnection.h>
GMenuBar::GMenuBar()
namespace GUI {
MenuBar::MenuBar()
{
}
GMenuBar::~GMenuBar()
MenuBar::~MenuBar()
{
unrealize_menubar();
}
void GMenuBar::add_menu(NonnullRefPtr<GMenu> menu)
void MenuBar::add_menu(NonnullRefPtr<Menu> menu)
{
m_menus.append(move(menu));
}
int GMenuBar::realize_menubar()
int MenuBar::realize_menubar()
{
return GWindowServerConnection::the().send_sync<WindowServer::CreateMenubar>()->menubar_id();
return WindowServerConnection::the().send_sync<WindowServer::CreateMenubar>()->menubar_id();
}
void GMenuBar::unrealize_menubar()
void MenuBar::unrealize_menubar()
{
if (m_menubar_id == -1)
return;
GWindowServerConnection::the().send_sync<WindowServer::DestroyMenubar>(m_menubar_id);
WindowServerConnection::the().send_sync<WindowServer::DestroyMenubar>(m_menubar_id);
m_menubar_id = -1;
}
void GMenuBar::notify_added_to_application(Badge<GApplication>)
void MenuBar::notify_added_to_application(Badge<Application>)
{
ASSERT(m_menubar_id == -1);
m_menubar_id = realize_menubar();
@ -62,12 +64,14 @@ void GMenuBar::notify_added_to_application(Badge<GApplication>)
for (auto& menu : m_menus) {
int menu_id = menu.realize_menu();
ASSERT(menu_id != -1);
GWindowServerConnection::the().send_sync<WindowServer::AddMenuToMenubar>(m_menubar_id, menu_id);
WindowServerConnection::the().send_sync<WindowServer::AddMenuToMenubar>(m_menubar_id, menu_id);
}
GWindowServerConnection::the().send_sync<WindowServer::SetApplicationMenubar>(m_menubar_id);
WindowServerConnection::the().send_sync<WindowServer::SetApplicationMenubar>(m_menubar_id);
}
void GMenuBar::notify_removed_from_application(Badge<GApplication>)
void MenuBar::notify_removed_from_application(Badge<Application>)
{
unrealize_menubar();
}
}

View file

@ -30,22 +30,26 @@
#include <AK/NonnullOwnPtrVector.h>
#include <LibGUI/GMenu.h>
class GApplication;
namespace GUI {
class GMenuBar {
class Application;
class MenuBar {
public:
GMenuBar();
~GMenuBar();
MenuBar();
~MenuBar();
void add_menu(NonnullRefPtr<GMenu>);
void add_menu(NonnullRefPtr<Menu>);
void notify_added_to_application(Badge<GApplication>);
void notify_removed_from_application(Badge<GApplication>);
void notify_added_to_application(Badge<Application>);
void notify_removed_from_application(Badge<Application>);
private:
int realize_menubar();
void unrealize_menubar();
int m_menubar_id { -1 };
NonnullRefPtrVector<GMenu> m_menus;
NonnullRefPtrVector<Menu> m_menus;
};
}

View file

@ -29,14 +29,16 @@
#include <LibGUI/GMenuItem.h>
#include <LibGUI/GWindowServerConnection.h>
GMenuItem::GMenuItem(unsigned menu_id, Type type)
namespace GUI {
MenuItem::MenuItem(unsigned menu_id, Type type)
: m_type(type)
, m_menu_id(menu_id)
{
}
GMenuItem::GMenuItem(unsigned menu_id, NonnullRefPtr<GAction>&& action)
: m_type(Action)
MenuItem::MenuItem(unsigned menu_id, NonnullRefPtr<Action>&& action)
: m_type(Type::Action)
, m_menu_id(menu_id)
, m_action(move(action))
{
@ -47,20 +49,20 @@ GMenuItem::GMenuItem(unsigned menu_id, NonnullRefPtr<GAction>&& action)
m_checked = m_action->is_checked();
}
GMenuItem::GMenuItem(unsigned menu_id, NonnullRefPtr<GMenu>&& submenu)
: m_type(Submenu)
MenuItem::MenuItem(unsigned menu_id, NonnullRefPtr<Menu>&& submenu)
: m_type(Type::Submenu)
, m_menu_id(menu_id)
, m_submenu(move(submenu))
{
}
GMenuItem::~GMenuItem()
MenuItem::~MenuItem()
{
if (m_action)
m_action->unregister_menu_item({}, *this);
}
void GMenuItem::set_enabled(bool enabled)
void MenuItem::set_enabled(bool enabled)
{
if (m_enabled == enabled)
return;
@ -68,7 +70,7 @@ void GMenuItem::set_enabled(bool enabled)
update_window_server();
}
void GMenuItem::set_checked(bool checked)
void MenuItem::set_checked(bool checked)
{
ASSERT(is_checkable());
if (m_checked == checked)
@ -77,11 +79,13 @@ void GMenuItem::set_checked(bool checked)
update_window_server();
}
void GMenuItem::update_window_server()
void MenuItem::update_window_server()
{
if (m_menu_id < 0)
return;
auto& action = *m_action;
auto shortcut_text = action.shortcut().is_valid() ? action.shortcut().to_string() : String();
GWindowServerConnection::the().send_sync<WindowServer::UpdateMenuItem>(m_menu_id, m_identifier, -1, action.text(), action.is_enabled(), action.is_checkable(), action.is_checkable() ? action.is_checked() : false, shortcut_text);
WindowServerConnection::the().send_sync<WindowServer::UpdateMenuItem>(m_menu_id, m_identifier, -1, action.text(), action.is_enabled(), action.is_checkable(), action.is_checkable() ? action.is_checked() : false, shortcut_text);
}
}

View file

@ -31,31 +31,33 @@
#include <AK/OwnPtr.h>
#include <AK/String.h>
class GAction;
class GMenu;
namespace GUI {
class GMenuItem {
class Action;
class Menu;
class MenuItem {
public:
enum Type {
enum class Type {
Invalid,
Action,
Separator,
Submenu,
};
GMenuItem(unsigned menu_id, Type);
GMenuItem(unsigned menu_id, NonnullRefPtr<GAction>&&);
GMenuItem(unsigned menu_id, NonnullRefPtr<GMenu>&&);
~GMenuItem();
MenuItem(unsigned menu_id, Type);
MenuItem(unsigned menu_id, NonnullRefPtr<Action>&&);
MenuItem(unsigned menu_id, NonnullRefPtr<Menu>&&);
~MenuItem();
Type type() const { return m_type; }
String text() const;
const GAction* action() const { return m_action.ptr(); }
GAction* action() { return m_action.ptr(); }
const Action* action() const { return m_action.ptr(); }
Action* action() { return m_action.ptr(); }
unsigned identifier() const { return m_identifier; }
GMenu* submenu() { return m_submenu.ptr(); }
const GMenu* submenu() const { return m_submenu.ptr(); }
Menu* submenu() { return m_submenu.ptr(); }
const Menu* submenu() const { return m_submenu.ptr(); }
bool is_checkable() const { return m_checkable; }
void set_checkable(bool checkable) { m_checkable = checkable; }
@ -66,18 +68,20 @@ public:
bool is_enabled() const { return m_enabled; }
void set_enabled(bool);
void set_menu_id(Badge<GMenu>, unsigned menu_id) { m_menu_id = menu_id; }
void set_identifier(Badge<GMenu>, unsigned identifier) { m_identifier = identifier; }
void set_menu_id(Badge<Menu>, unsigned menu_id) { m_menu_id = menu_id; }
void set_identifier(Badge<Menu>, unsigned identifier) { m_identifier = identifier; }
private:
void update_window_server();
Type m_type { Invalid };
Type m_type { Type::Invalid };
int m_menu_id { -1 };
unsigned m_identifier { 0 };
bool m_enabled { true };
bool m_checkable { false };
bool m_checked { false };
RefPtr<GAction> m_action;
RefPtr<GMenu> m_submenu;
RefPtr<Action> m_action;
RefPtr<Menu> m_submenu;
};
}

View file

@ -30,14 +30,16 @@
#include <LibGUI/GMessageBox.h>
#include <stdio.h>
int GMessageBox::show(const StringView& text, const StringView& title, Type type, InputType input_type, Core::Object* parent)
namespace GUI {
int MessageBox::show(const StringView& text, const StringView& title, Type type, InputType input_type, Core::Object* parent)
{
auto box = GMessageBox::construct(text, title, type, input_type, parent);
auto box = MessageBox::construct(text, title, type, input_type, parent);
return box->exec();
}
GMessageBox::GMessageBox(const StringView& text, const StringView& title, Type type, InputType input_type, Core::Object* parent)
: GDialog(parent)
MessageBox::MessageBox(const StringView& text, const StringView& title, Type type, InputType input_type, Core::Object* parent)
: Dialog(parent)
, m_text(text)
, m_type(type)
, m_input_type(input_type)
@ -46,11 +48,11 @@ GMessageBox::GMessageBox(const StringView& text, const StringView& title, Type t
build();
}
GMessageBox::~GMessageBox()
MessageBox::~MessageBox()
{
}
RefPtr<GraphicsBitmap> GMessageBox::icon() const
RefPtr<GraphicsBitmap> MessageBox::icon() const
{
switch (m_type) {
case Type::Information:
@ -64,75 +66,77 @@ RefPtr<GraphicsBitmap> GMessageBox::icon() const
}
}
bool GMessageBox::should_include_ok_button() const
bool MessageBox::should_include_ok_button() const
{
return m_input_type == InputType::OK || m_input_type == InputType::OKCancel;
}
bool GMessageBox::should_include_cancel_button() const
bool MessageBox::should_include_cancel_button() const
{
return m_input_type == InputType::OKCancel;
}
void GMessageBox::build()
void MessageBox::build()
{
auto widget = GWidget::construct();
auto widget = Widget::construct();
set_main_widget(widget);
int text_width = widget->font().width(m_text);
int icon_width = 0;
widget->set_layout(make<GVBoxLayout>());
widget->set_layout(make<VBoxLayout>());
widget->set_fill_with_background_color(true);
widget->layout()->set_margins({ 0, 15, 0, 15 });
widget->layout()->set_spacing(15);
RefPtr<GWidget> message_container = widget;
RefPtr<Widget> message_container = widget;
if (m_type != Type::None) {
message_container = GWidget::construct(widget.ptr());
message_container->set_layout(make<GHBoxLayout>());
message_container = Widget::construct(widget.ptr());
message_container->set_layout(make<HBoxLayout>());
message_container->layout()->set_margins({ 8, 0, 8, 0 });
message_container->layout()->set_spacing(8);
auto icon_label = GLabel::construct(message_container);
auto icon_label = Label::construct(message_container);
icon_label->set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed);
icon_label->set_preferred_size(32, 32);
icon_label->set_icon(icon());
icon_width = icon_label->icon()->width();
}
auto label = GLabel::construct(m_text, message_container);
auto label = Label::construct(m_text, message_container);
label->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
label->set_preferred_size(text_width, 16);
auto button_container = GWidget::construct(widget.ptr());
button_container->set_layout(make<GHBoxLayout>());
auto button_container = Widget::construct(widget.ptr());
button_container->set_layout(make<HBoxLayout>());
button_container->layout()->set_spacing(5);
button_container->layout()->set_margins({ 15, 0, 15, 0 });
if (should_include_ok_button()) {
auto ok_button = GButton::construct(button_container);
auto ok_button = Button::construct(button_container);
ok_button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
ok_button->set_preferred_size(0, 20);
ok_button->set_text("OK");
ok_button->on_click = [this](auto&) {
dbgprintf("GMessageBox: OK button clicked\n");
done(GDialog::ExecOK);
done(Dialog::ExecOK);
};
}
if (should_include_cancel_button()) {
auto cancel_button = GButton::construct(button_container);
auto cancel_button = Button::construct(button_container);
cancel_button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
cancel_button->set_preferred_size(0, 20);
cancel_button->set_text("Cancel");
cancel_button->on_click = [this](auto&) {
dbgprintf("GMessageBox: Cancel button clicked\n");
done(GDialog::ExecCancel);
done(Dialog::ExecCancel);
};
}
set_rect(x(), y(), text_width + icon_width + 80, 100);
set_resizable(false);
}
}

View file

@ -28,8 +28,10 @@
#include <LibGUI/GDialog.h>
class GMessageBox : public GDialog {
C_OBJECT(GMessageBox)
namespace GUI {
class MessageBox : public Dialog {
C_OBJECT(MessageBox)
public:
enum class Type {
None,
@ -43,12 +45,12 @@ public:
OKCancel,
};
virtual ~GMessageBox() override;
virtual ~MessageBox() override;
static int show(const StringView& text, const StringView& title, Type type = Type::None, InputType = InputType::OK, Core::Object* parent = nullptr);
private:
explicit GMessageBox(const StringView& text, const StringView& title, Type type = Type::None, InputType = InputType::OK, Core::Object* parent = nullptr);
explicit MessageBox(const StringView& text, const StringView& title, Type type = Type::None, InputType = InputType::OK, Core::Object* parent = nullptr);
bool should_include_ok_button() const;
bool should_include_cancel_button() const;
@ -59,3 +61,5 @@ private:
Type m_type { Type::None };
InputType m_input_type { InputType::OK };
};
}

View file

@ -27,31 +27,33 @@
#include <LibGUI/GAbstractView.h>
#include <LibGUI/GModel.h>
GModel::GModel()
namespace GUI {
Model::Model()
{
}
GModel::~GModel()
Model::~Model()
{
}
void GModel::register_view(Badge<GAbstractView>, GAbstractView& view)
void Model::register_view(Badge<AbstractView>, AbstractView& view)
{
m_views.set(&view);
}
void GModel::unregister_view(Badge<GAbstractView>, GAbstractView& view)
void Model::unregister_view(Badge<AbstractView>, AbstractView& view)
{
m_views.remove(&view);
}
void GModel::for_each_view(Function<void(GAbstractView&)> callback)
void Model::for_each_view(Function<void(AbstractView&)> callback)
{
for (auto* view : m_views)
callback(*view);
}
void GModel::did_update()
void Model::did_update()
{
if (on_update)
on_update();
@ -60,12 +62,12 @@ void GModel::did_update()
});
}
GModelIndex GModel::create_index(int row, int column, const void* data) const
ModelIndex Model::create_index(int row, int column, const void* data) const
{
return GModelIndex(*this, row, column, const_cast<void*>(data));
return ModelIndex(*this, row, column, const_cast<void*>(data));
}
GModelIndex GModel::sibling(int row, int column, const GModelIndex& parent) const
ModelIndex Model::sibling(int row, int column, const ModelIndex& parent) const
{
if (!parent.is_valid())
return index(row, column, {});
@ -74,3 +76,5 @@ GModelIndex GModel::sibling(int row, int column, const GModelIndex& parent) cons
return {};
return index(row, column, parent);
}
}

View file

@ -36,15 +36,18 @@
#include <LibGUI/GVariant.h>
class Font;
class GAbstractView;
enum class GSortOrder {
namespace GUI {
class AbstractView;
enum class SortOrder {
None,
Ascending,
Descending
};
class GModel : public RefCounted<GModel> {
class Model : public RefCounted<Model> {
public:
struct ColumnMetadata {
int preferred_width { 0 };
@ -68,52 +71,54 @@ public:
DragData,
};
virtual ~GModel();
virtual ~Model();
virtual int row_count(const GModelIndex& = GModelIndex()) const = 0;
virtual int column_count(const GModelIndex& = GModelIndex()) const = 0;
virtual int row_count(const ModelIndex& = ModelIndex()) const = 0;
virtual int column_count(const ModelIndex& = ModelIndex()) const = 0;
virtual String row_name(int) const { return {}; }
virtual String column_name(int) const { return {}; }
virtual ColumnMetadata column_metadata(int) const { return {}; }
virtual GVariant data(const GModelIndex&, Role = Role::Display) const = 0;
virtual Variant data(const ModelIndex&, Role = Role::Display) const = 0;
virtual void update() = 0;
virtual GModelIndex parent_index(const GModelIndex&) const { return {}; }
virtual GModelIndex index(int row, int column = 0, const GModelIndex& = GModelIndex()) const { return create_index(row, column); }
virtual GModelIndex sibling(int row, int column, const GModelIndex& parent) const;
virtual bool is_editable(const GModelIndex&) const { return false; }
virtual void set_data(const GModelIndex&, const GVariant&) {}
virtual ModelIndex parent_index(const ModelIndex&) const { return {}; }
virtual ModelIndex index(int row, int column = 0, const ModelIndex& = ModelIndex()) const { return create_index(row, column); }
virtual ModelIndex sibling(int row, int column, const ModelIndex& parent) const;
virtual bool is_editable(const ModelIndex&) const { return false; }
virtual void set_data(const ModelIndex&, const Variant&) {}
virtual int tree_column() const { return 0; }
bool is_valid(const GModelIndex& index) const
bool is_valid(const ModelIndex& index) const
{
auto parent_index = this->parent_index(index);
return index.row() >= 0 && index.row() < row_count(parent_index) && index.column() >= 0 && index.column() < column_count(parent_index);
}
virtual int key_column() const { return -1; }
virtual GSortOrder sort_order() const { return GSortOrder::None; }
virtual void set_key_column_and_sort_order(int, GSortOrder) {}
virtual SortOrder sort_order() const { return SortOrder::None; }
virtual void set_key_column_and_sort_order(int, SortOrder) {}
virtual StringView drag_data_type() const { return {}; }
void register_view(Badge<GAbstractView>, GAbstractView&);
void unregister_view(Badge<GAbstractView>, GAbstractView&);
void register_view(Badge<AbstractView>, AbstractView&);
void unregister_view(Badge<AbstractView>, AbstractView&);
Function<void()> on_update;
protected:
GModel();
Model();
void for_each_view(Function<void(GAbstractView&)>);
void for_each_view(Function<void(AbstractView&)>);
void did_update();
GModelIndex create_index(int row, int column, const void* data = nullptr) const;
ModelIndex create_index(int row, int column, const void* data = nullptr) const;
private:
HashTable<GAbstractView*> m_views;
HashTable<AbstractView*> m_views;
};
inline GModelIndex GModelIndex::parent() const
inline ModelIndex ModelIndex::parent() const
{
return m_model ? m_model->parent_index(*this) : GModelIndex();
return m_model ? m_model->parent_index(*this) : ModelIndex();
}
}

View file

@ -30,12 +30,14 @@
#include <LibGUI/GTextBox.h>
#include <LibGUI/GWidget.h>
class GModelEditingDelegate {
public:
GModelEditingDelegate() {}
virtual ~GModelEditingDelegate() {}
namespace GUI {
void bind(GModel& model, const GModelIndex& index)
class ModelEditingDelegate {
public:
ModelEditingDelegate() {}
virtual ~ModelEditingDelegate() {}
void bind(Model& model, const ModelIndex& index)
{
if (m_model.ptr() == &model && m_index == index)
return;
@ -44,18 +46,18 @@ public:
m_widget = create_widget();
}
GWidget* widget() { return m_widget; }
const GWidget* widget() const { return m_widget; }
Widget* widget() { return m_widget; }
const Widget* widget() const { return m_widget; }
Function<void()> on_commit;
virtual GVariant value() const = 0;
virtual void set_value(const GVariant&) = 0;
virtual Variant value() const = 0;
virtual void set_value(const Variant&) = 0;
virtual void will_begin_editing() {}
protected:
virtual RefPtr<GWidget> create_widget() = 0;
virtual RefPtr<Widget> create_widget() = 0;
void commit()
{
if (on_commit)
@ -63,24 +65,26 @@ protected:
}
private:
RefPtr<GModel> m_model;
GModelIndex m_index;
RefPtr<GWidget> m_widget;
RefPtr<Model> m_model;
ModelIndex m_index;
RefPtr<Widget> m_widget;
};
class GStringModelEditingDelegate : public GModelEditingDelegate {
class StringModelEditingDelegate : public ModelEditingDelegate {
public:
GStringModelEditingDelegate() {}
virtual ~GStringModelEditingDelegate() override {}
StringModelEditingDelegate() {}
virtual ~StringModelEditingDelegate() override {}
virtual RefPtr<GWidget> create_widget() override
virtual RefPtr<Widget> create_widget() override
{
auto textbox = GTextBox::construct(nullptr);
auto textbox = TextBox::construct(nullptr);
textbox->on_return_pressed = [this] {
commit();
};
return textbox;
}
virtual GVariant value() const override { return static_cast<const GTextBox*>(widget())->text(); }
virtual void set_value(const GVariant& value) override { static_cast<GTextBox*>(widget())->set_text(value.to_string()); }
virtual Variant value() const override { return static_cast<const TextBox*>(widget())->text(); }
virtual void set_value(const Variant& value) override { static_cast<TextBox*>(widget())->set_text(value.to_string()); }
};
}

View file

@ -29,13 +29,15 @@
#include <AK/LogStream.h>
#include <AK/String.h>
class GModel;
namespace GUI {
class GModelIndex {
friend class GModel;
class Model;
class ModelIndex {
friend class Model;
public:
GModelIndex() {}
ModelIndex() {}
bool is_valid() const { return m_row != -1 && m_column != -1; }
int row() const { return m_row; }
@ -43,20 +45,20 @@ public:
void* internal_data() const { return m_internal_data; }
GModelIndex parent() const;
ModelIndex parent() const;
bool operator==(const GModelIndex& other) const
bool operator==(const ModelIndex& other) const
{
return m_model == other.m_model && m_row == other.m_row && m_column == other.m_column && m_internal_data == other.m_internal_data;
}
bool operator!=(const GModelIndex& other) const
bool operator!=(const ModelIndex& other) const
{
return !(*this == other);
}
private:
GModelIndex(const GModel& model, int row, int column, void* internal_data)
ModelIndex(const Model& model, int row, int column, void* internal_data)
: m_model(&model)
, m_row(row)
, m_column(column)
@ -64,22 +66,24 @@ private:
{
}
const GModel* m_model { nullptr };
const Model* m_model { nullptr };
int m_row { -1 };
int m_column { -1 };
void* m_internal_data { nullptr };
};
inline const LogStream& operator<<(const LogStream& stream, const GModelIndex& value)
inline const LogStream& operator<<(const LogStream& stream, const ModelIndex& value)
{
if (value.internal_data())
return stream << String::format("GModelIndex(%d,%d,%p)", value.row(), value.column(), value.internal_data());
return stream << String::format("GModelIndex(%d,%d)", value.row(), value.column());
return stream << String::format("ModelIndex(%d,%d,%p)", value.row(), value.column(), value.internal_data());
return stream << String::format("ModelIndex(%d,%d)", value.row(), value.column());
}
}
namespace AK {
template<>
struct Traits<GModelIndex> : public GenericTraits<GModelIndex> {
static unsigned hash(const GModelIndex& index) { return pair_int_hash(index.row(), index.column()); }
struct Traits<GUI::ModelIndex> : public GenericTraits<GUI::ModelIndex> {
static unsigned hash(const GUI::ModelIndex& index) { return pair_int_hash(index.row(), index.column()); }
};
}

View file

@ -27,7 +27,9 @@
#include <LibGUI/GAbstractView.h>
#include <LibGUI/GModelSelection.h>
void GModelSelection::set(const GModelIndex& index)
namespace GUI {
void ModelSelection::set(const ModelIndex& index)
{
ASSERT(index.is_valid());
if (m_indexes.size() == 1 && m_indexes.contains(index))
@ -37,7 +39,7 @@ void GModelSelection::set(const GModelIndex& index)
m_view.notify_selection_changed({});
}
void GModelSelection::add(const GModelIndex& index)
void ModelSelection::add(const ModelIndex& index)
{
ASSERT(index.is_valid());
if (m_indexes.contains(index))
@ -46,7 +48,7 @@ void GModelSelection::add(const GModelIndex& index)
m_view.notify_selection_changed({});
}
void GModelSelection::toggle(const GModelIndex& index)
void ModelSelection::toggle(const ModelIndex& index)
{
ASSERT(index.is_valid());
if (m_indexes.contains(index))
@ -56,7 +58,7 @@ void GModelSelection::toggle(const GModelIndex& index)
m_view.notify_selection_changed({});
}
bool GModelSelection::remove(const GModelIndex& index)
bool ModelSelection::remove(const ModelIndex& index)
{
ASSERT(index.is_valid());
if (!m_indexes.contains(index))
@ -66,10 +68,12 @@ bool GModelSelection::remove(const GModelIndex& index)
return true;
}
void GModelSelection::clear()
void ModelSelection::clear()
{
if (m_indexes.is_empty())
return;
m_indexes.clear();
m_view.notify_selection_changed({});
}
}

View file

@ -29,18 +29,20 @@
#include <AK/HashTable.h>
#include <LibGUI/GModelIndex.h>
class GAbstractView;
namespace GUI {
class GModelSelection {
class AbstractView;
class ModelSelection {
public:
GModelSelection(GAbstractView& view)
ModelSelection(AbstractView& view)
: m_view(view)
{
}
int size() const { return m_indexes.size(); }
bool is_empty() const { return m_indexes.is_empty(); }
bool contains(const GModelIndex& index) const { return m_indexes.contains(index); }
bool contains(const ModelIndex& index) const { return m_indexes.contains(index); }
bool contains_row(int row) const
{
for (auto& index : m_indexes) {
@ -50,10 +52,10 @@ public:
return false;
}
void set(const GModelIndex&);
void add(const GModelIndex&);
void toggle(const GModelIndex&);
bool remove(const GModelIndex&);
void set(const ModelIndex&);
void add(const ModelIndex&);
void toggle(const ModelIndex&);
bool remove(const ModelIndex&);
void clear();
template<typename Callback>
@ -70,9 +72,9 @@ public:
callback(index);
}
Vector<GModelIndex> indexes() const
Vector<ModelIndex> indexes() const
{
Vector<GModelIndex> selected_indexes;
Vector<ModelIndex> selected_indexes;
for (auto& index : m_indexes)
selected_indexes.append(index);
@ -81,7 +83,7 @@ public:
}
// FIXME: This doesn't guarantee that what you get is the lowest or "first" index selected..
GModelIndex first() const
ModelIndex first() const
{
if (m_indexes.is_empty())
return {};
@ -89,6 +91,8 @@ public:
}
private:
GAbstractView& m_view;
HashTable<GModelIndex> m_indexes;
AbstractView& m_view;
HashTable<ModelIndex> m_indexes;
};
}

View file

@ -28,12 +28,13 @@
#include <LibGUI/GWidget.h>
#include <LibGUI/GWindow.h>
GPainter::GPainter(GraphicsBitmap& bitmap)
: Painter(bitmap)
namespace GUI {
Painter::Painter(GraphicsBitmap& bitmap)
: ::Painter(bitmap)
{
}
GPainter::GPainter(GWidget& widget)
Painter::Painter(Widget& widget)
: Painter(*widget.window()->back_bitmap())
{
state().font = &widget.font();
@ -43,3 +44,5 @@ GPainter::GPainter(GWidget& widget)
m_clip_origin = origin_rect;
state().clip_rect.intersect(m_target->rect());
}
}

View file

@ -28,11 +28,14 @@
#include <LibDraw/Painter.h>
class GWidget;
class GraphicsBitmap;
namespace GUI {
class GPainter : public Painter {
class Widget;
class Painter : public ::Painter {
public:
explicit GPainter(GWidget&);
explicit GPainter(GraphicsBitmap&);
explicit Painter(Widget&);
explicit Painter(GraphicsBitmap&);
};
}

View file

@ -28,19 +28,21 @@
#include <LibGUI/GPainter.h>
#include <LibGUI/GProgressBar.h>
GProgressBar::GProgressBar(GWidget* parent)
: GFrame(parent)
namespace GUI {
ProgressBar::ProgressBar(Widget* parent)
: Frame(parent)
{
set_frame_shape(FrameShape::Container);
set_frame_shadow(FrameShadow::Sunken);
set_frame_thickness(2);
}
GProgressBar::~GProgressBar()
ProgressBar::~ProgressBar()
{
}
void GProgressBar::set_value(int value)
void ProgressBar::set_value(int value)
{
if (m_value == value)
return;
@ -48,7 +50,7 @@ void GProgressBar::set_value(int value)
update();
}
void GProgressBar::set_range(int min, int max)
void ProgressBar::set_range(int min, int max)
{
ASSERT(min < max);
m_min = min;
@ -56,11 +58,11 @@ void GProgressBar::set_range(int min, int max)
m_value = clamp(m_value, m_min, m_max);
}
void GProgressBar::paint_event(GPaintEvent& event)
void ProgressBar::paint_event(PaintEvent& event)
{
GFrame::paint_event(event);
Frame::paint_event(event);
GPainter painter(*this);
Painter painter(*this);
auto rect = frame_inner_rect();
painter.add_clip_rect(rect);
painter.add_clip_rect(event.rect());
@ -83,3 +85,5 @@ void GProgressBar::paint_event(GPaintEvent& event)
StylePainter::paint_progress_bar(painter, rect, palette(), m_min, m_max, m_value, progress_text);
}
}

View file

@ -28,10 +28,12 @@
#include <LibGUI/GFrame.h>
class GProgressBar : public GFrame {
C_OBJECT(GProgressBar)
namespace GUI {
class ProgressBar : public Frame {
C_OBJECT(ProgressBar)
public:
virtual ~GProgressBar() override;
virtual ~ProgressBar() override;
void set_range(int min, int max);
void set_min(int min) { set_range(min, max()); }
@ -54,9 +56,9 @@ public:
void set_format(Format format) { m_format = format; }
protected:
explicit GProgressBar(GWidget* parent);
explicit ProgressBar(Widget* parent);
virtual void paint_event(GPaintEvent&) override;
virtual void paint_event(PaintEvent&) override;
private:
Format m_format { Percentage };
@ -65,3 +67,5 @@ private:
int m_value { 0 };
String m_caption;
};
}

View file

@ -29,28 +29,30 @@
#include <LibGUI/GPainter.h>
#include <LibGUI/GRadioButton.h>
GRadioButton::GRadioButton(GWidget* parent)
: GRadioButton({}, parent)
namespace GUI {
RadioButton::RadioButton(Widget* parent)
: RadioButton({}, parent)
{
}
GRadioButton::GRadioButton(const StringView& text, GWidget* parent)
: GAbstractButton(text, parent)
RadioButton::RadioButton(const StringView& text, Widget* parent)
: AbstractButton(text, parent)
{
}
GRadioButton::~GRadioButton()
RadioButton::~RadioButton()
{
}
Size GRadioButton::circle_size()
Size RadioButton::circle_size()
{
return { 12, 12 };
}
void GRadioButton::paint_event(GPaintEvent& event)
void RadioButton::paint_event(PaintEvent& event)
{
GPainter painter(*this);
Painter painter(*this);
painter.add_clip_rect(event.rect());
Rect circle_rect { { 2, 0 }, circle_size() };
@ -64,16 +66,16 @@ void GRadioButton::paint_event(GPaintEvent& event)
}
template<typename Callback>
void GRadioButton::for_each_in_group(Callback callback)
void RadioButton::for_each_in_group(Callback callback)
{
if (!parent())
return;
parent()->for_each_child_of_type<GRadioButton>([&](auto& child) {
return callback(static_cast<GRadioButton&>(child));
parent()->for_each_child_of_type<RadioButton>([&](auto& child) {
return callback(static_cast<RadioButton&>(child));
});
}
void GRadioButton::click()
void RadioButton::click()
{
if (!is_enabled())
return;
@ -84,3 +86,5 @@ void GRadioButton::click()
});
set_checked(true);
}
}

View file

@ -28,22 +28,24 @@
#include <LibGUI/GAbstractButton.h>
class GRadioButton : public GAbstractButton {
C_OBJECT(GRadioButton)
namespace GUI {
class RadioButton : public AbstractButton {
C_OBJECT(RadioButton)
public:
virtual ~GRadioButton() override;
virtual ~RadioButton() override;
virtual void click() override;
protected:
explicit GRadioButton(GWidget* parent);
explicit GRadioButton(const StringView& text, GWidget* parent);
virtual void paint_event(GPaintEvent&) override;
explicit RadioButton(Widget* parent);
explicit RadioButton(const StringView& text, Widget* parent);
virtual void paint_event(PaintEvent&) override;
private:
// These don't make sense for a radio button, so hide them.
using GAbstractButton::auto_repeat_interval;
using GAbstractButton::set_auto_repeat_interval;
using AbstractButton::auto_repeat_interval;
using AbstractButton::set_auto_repeat_interval;
virtual bool is_radio_button() const final { return true; }
@ -52,10 +54,12 @@ private:
static Size circle_size();
};
template<>
inline bool Core::is<GRadioButton>(const Core::Object& object)
{
if (!is<GWidget>(object))
return false;
return to<GWidget>(object).is_radio_button();
}
template<>
inline bool Core::is<GUI::RadioButton>(const Core::Object& object)
{
if (!is<GUI::Widget>(object))
return false;
return to<GUI::Widget>(object).is_radio_button();
}

View file

@ -30,8 +30,10 @@
#include <LibGUI/GResizeCorner.h>
#include <LibGUI/GWindow.h>
GResizeCorner::GResizeCorner(GWidget* parent)
: GWidget(parent)
namespace GUI {
ResizeCorner::ResizeCorner(Widget* parent)
: Widget(parent)
{
set_background_role(ColorRole::Button);
set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed);
@ -40,34 +42,36 @@ GResizeCorner::GResizeCorner(GWidget* parent)
ASSERT(m_bitmap);
}
GResizeCorner::~GResizeCorner()
ResizeCorner::~ResizeCorner()
{
}
void GResizeCorner::paint_event(GPaintEvent& event)
void ResizeCorner::paint_event(PaintEvent& event)
{
GPainter painter(*this);
Painter painter(*this);
painter.add_clip_rect(event.rect());
painter.fill_rect(rect(), palette().color(background_role()));
painter.blit({ 0, 0 }, *m_bitmap, m_bitmap->rect());
GWidget::paint_event(event);
Widget::paint_event(event);
}
void GResizeCorner::mousedown_event(GMouseEvent& event)
void ResizeCorner::mousedown_event(MouseEvent& event)
{
if (event.button() == GMouseButton::Left)
if (event.button() == MouseButton::Left)
window()->start_wm_resize();
GWidget::mousedown_event(event);
Widget::mousedown_event(event);
}
void GResizeCorner::enter_event(Core::Event& event)
void ResizeCorner::enter_event(Core::Event& event)
{
window()->set_override_cursor(GStandardCursor::ResizeDiagonalTLBR);
GWidget::enter_event(event);
window()->set_override_cursor(StandardCursor::ResizeDiagonalTLBR);
Widget::enter_event(event);
}
void GResizeCorner::leave_event(Core::Event& event)
void ResizeCorner::leave_event(Core::Event& event)
{
window()->set_override_cursor(GStandardCursor::None);
GWidget::leave_event(event);
window()->set_override_cursor(StandardCursor::None);
Widget::leave_event(event);
}
}

View file

@ -26,19 +26,23 @@
#include <LibGUI/GWidget.h>
class GResizeCorner : public GWidget {
C_OBJECT(GResizeCorner)
namespace GUI {
class ResizeCorner : public Widget {
C_OBJECT(ResizeCorner)
public:
virtual ~GResizeCorner() override;
virtual ~ResizeCorner() override;
protected:
explicit GResizeCorner(GWidget* parent);
explicit ResizeCorner(Widget* parent);
virtual void paint_event(GPaintEvent&) override;
virtual void mousedown_event(GMouseEvent&) override;
virtual void paint_event(PaintEvent&) override;
virtual void mousedown_event(MouseEvent&) override;
virtual void enter_event(Core::Event&) override;
virtual void leave_event(Core::Event&) override;
private:
RefPtr<GraphicsBitmap> m_bitmap;
};
}

View file

@ -31,6 +31,8 @@
#include <LibGUI/GPainter.h>
#include <LibGUI/GScrollBar.h>
namespace GUI {
static const char* s_up_arrow_bitmap_data = {
" "
" # "
@ -84,13 +86,13 @@ static CharacterBitmap* s_down_arrow_bitmap;
static CharacterBitmap* s_left_arrow_bitmap;
static CharacterBitmap* s_right_arrow_bitmap;
GScrollBar::GScrollBar(GWidget* parent)
: GScrollBar(Orientation::Vertical, parent)
ScrollBar::ScrollBar(Widget* parent)
: ScrollBar(Orientation::Vertical, parent)
{
}
GScrollBar::GScrollBar(Orientation orientation, GWidget* parent)
: GWidget(parent)
ScrollBar::ScrollBar(Orientation orientation, Widget* parent)
: Widget(parent)
, m_orientation(orientation)
{
m_automatic_scrolling_timer = Core::Timer::construct(this);
@ -115,11 +117,11 @@ GScrollBar::GScrollBar(Orientation orientation, GWidget* parent)
};
}
GScrollBar::~GScrollBar()
ScrollBar::~ScrollBar()
{
}
void GScrollBar::set_range(int min, int max)
void ScrollBar::set_range(int min, int max)
{
ASSERT(min <= max);
if (m_min == min && m_max == max)
@ -136,7 +138,7 @@ void GScrollBar::set_range(int min, int max)
update();
}
void GScrollBar::set_value(int value)
void ScrollBar::set_value(int value)
{
value = clamp(value, m_min, m_max);
if (value == m_value)
@ -147,12 +149,12 @@ void GScrollBar::set_value(int value)
update();
}
Rect GScrollBar::decrement_button_rect() const
Rect ScrollBar::decrement_button_rect() const
{
return { 0, 0, button_width(), button_height() };
}
Rect GScrollBar::increment_button_rect() const
Rect ScrollBar::increment_button_rect() const
{
if (orientation() == Orientation::Vertical)
return { 0, height() - button_height(), button_width(), button_height() };
@ -160,7 +162,7 @@ Rect GScrollBar::increment_button_rect() const
return { width() - button_width(), 0, button_width(), button_height() };
}
Rect GScrollBar::decrement_gutter_rect() const
Rect ScrollBar::decrement_gutter_rect() const
{
if (orientation() == Orientation::Vertical)
return { 0, button_height(), button_width(), scrubber_rect().top() - button_height() };
@ -168,7 +170,7 @@ Rect GScrollBar::decrement_gutter_rect() const
return { button_width(), 0, scrubber_rect().x() - button_width(), button_height() };
}
Rect GScrollBar::increment_gutter_rect() const
Rect ScrollBar::increment_gutter_rect() const
{
auto scrubber_rect = this->scrubber_rect();
if (orientation() == Orientation::Vertical)
@ -177,7 +179,7 @@ Rect GScrollBar::increment_gutter_rect() const
return { scrubber_rect.right() + 1, 0, width() - button_width() - scrubber_rect.right() - 1, button_width() };
}
int GScrollBar::scrubbable_range_in_pixels() const
int ScrollBar::scrubbable_range_in_pixels() const
{
if (orientation() == Orientation::Vertical)
return height() - button_height() * 2 - scrubber_size();
@ -185,19 +187,19 @@ int GScrollBar::scrubbable_range_in_pixels() const
return width() - button_width() * 2 - scrubber_size();
}
bool GScrollBar::has_scrubber() const
bool ScrollBar::has_scrubber() const
{
return m_max != m_min;
}
int GScrollBar::scrubber_size() const
int ScrollBar::scrubber_size() const
{
int pixel_range = length(orientation()) - button_size() * 2;
int value_range = m_max - m_min;
return ::max(pixel_range - value_range, button_size());
}
Rect GScrollBar::scrubber_rect() const
Rect ScrollBar::scrubber_rect() const
{
if (!has_scrubber() || length(orientation()) <= (button_size() * 2) + scrubber_size())
return {};
@ -219,9 +221,9 @@ Rect GScrollBar::scrubber_rect() const
return { (int)x_or_y, 0, scrubber_size(), button_height() };
}
void GScrollBar::paint_event(GPaintEvent& event)
void ScrollBar::paint_event(PaintEvent& event)
{
GPainter painter(*this);
Painter painter(*this);
painter.add_clip_rect(event.rect());
painter.fill_rect(rect(), palette().button().lightened());
@ -238,7 +240,7 @@ void GScrollBar::paint_event(GPaintEvent& event)
StylePainter::paint_button(painter, scrubber_rect(), palette(), ButtonStyle::Normal, false, m_hovered_component == Component::Scrubber || m_scrubber_in_use);
}
void GScrollBar::on_automatic_scrolling_timer_fired()
void ScrollBar::on_automatic_scrolling_timer_fired()
{
if (m_automatic_scrolling_direction == AutomaticScrollingDirection::Decrement) {
set_value(value() - m_step);
@ -250,9 +252,9 @@ void GScrollBar::on_automatic_scrolling_timer_fired()
}
}
void GScrollBar::mousedown_event(GMouseEvent& event)
void ScrollBar::mousedown_event(MouseEvent& event)
{
if (event.button() != GMouseButton::Left)
if (event.button() != MouseButton::Left)
return;
if (decrement_button_rect().contains(event.position())) {
m_automatic_scrolling_direction = AutomaticScrollingDirection::Decrement;
@ -294,9 +296,9 @@ void GScrollBar::mousedown_event(GMouseEvent& event)
}
}
void GScrollBar::mouseup_event(GMouseEvent& event)
void ScrollBar::mouseup_event(MouseEvent& event)
{
if (event.button() != GMouseButton::Left)
if (event.button() != MouseButton::Left)
return;
m_scrubber_in_use = false;
m_automatic_scrolling_direction = AutomaticScrollingDirection::None;
@ -307,15 +309,15 @@ void GScrollBar::mouseup_event(GMouseEvent& event)
update();
}
void GScrollBar::mousewheel_event(GMouseEvent& event)
void ScrollBar::mousewheel_event(MouseEvent& event)
{
if (!is_scrollable())
return;
set_value(value() + event.wheel_delta() * m_step);
GWidget::mousewheel_event(event);
Widget::mousewheel_event(event);
}
void GScrollBar::set_automatic_scrolling_active(bool active)
void ScrollBar::set_automatic_scrolling_active(bool active)
{
if (active) {
on_automatic_scrolling_timer_fired();
@ -325,7 +327,7 @@ void GScrollBar::set_automatic_scrolling_active(bool active)
}
}
void GScrollBar::mousemove_event(GMouseEvent& event)
void ScrollBar::mousemove_event(MouseEvent& event)
{
auto old_hovered_component = m_hovered_component;
if (scrubber_rect().contains(event.position()))
@ -355,7 +357,7 @@ void GScrollBar::mousemove_event(GMouseEvent& event)
set_value(new_value);
}
void GScrollBar::leave_event(Core::Event&)
void ScrollBar::leave_event(Core::Event&)
{
if (m_hovered_component != Component::Invalid) {
m_hovered_component = Component::Invalid;
@ -363,11 +365,13 @@ void GScrollBar::leave_event(Core::Event&)
}
}
void GScrollBar::change_event(GEvent& event)
void ScrollBar::change_event(Event& event)
{
if (event.type() == GEvent::Type::EnabledChange) {
if (event.type() == Event::Type::EnabledChange) {
if (!is_enabled())
m_scrubbing = false;
}
return GWidget::change_event(event);
return Widget::change_event(event);
}
}

View file

@ -30,10 +30,12 @@
#include <LibCore/CTimer.h>
#include <LibGUI/GWidget.h>
class GScrollBar final : public GWidget {
C_OBJECT(GScrollBar)
namespace GUI {
class ScrollBar final : public Widget {
C_OBJECT(ScrollBar)
public:
virtual ~GScrollBar() override;
virtual ~ScrollBar() override;
Orientation orientation() const { return m_orientation; }
@ -64,16 +66,16 @@ public:
};
private:
explicit GScrollBar(GWidget* parent);
explicit GScrollBar(Orientation, GWidget* parent);
explicit ScrollBar(Widget* parent);
explicit ScrollBar(Orientation, Widget* parent);
virtual void paint_event(GPaintEvent&) override;
virtual void mousedown_event(GMouseEvent&) override;
virtual void mouseup_event(GMouseEvent&) override;
virtual void mousemove_event(GMouseEvent&) override;
virtual void mousewheel_event(GMouseEvent&) override;
virtual void paint_event(PaintEvent&) override;
virtual void mousedown_event(MouseEvent&) override;
virtual void mouseup_event(MouseEvent&) override;
virtual void mousemove_event(MouseEvent&) override;
virtual void mousewheel_event(MouseEvent&) override;
virtual void leave_event(Core::Event&) override;
virtual void change_event(GEvent&) override;
virtual void change_event(Event&) override;
int default_button_size() const { return 16; }
int button_size() const { return length(orientation()) <= (default_button_size() * 2) ? length(orientation()) / 2 : default_button_size(); }
@ -112,3 +114,5 @@ private:
AutomaticScrollingDirection m_automatic_scrolling_direction { AutomaticScrollingDirection::None };
RefPtr<Core::Timer> m_automatic_scrolling_timer;
};
}

View file

@ -27,17 +27,19 @@
#include <LibGUI/GScrollBar.h>
#include <LibGUI/GScrollableWidget.h>
GScrollableWidget::GScrollableWidget(GWidget* parent)
: GFrame(parent)
namespace GUI {
ScrollableWidget::ScrollableWidget(Widget* parent)
: Frame(parent)
{
m_vertical_scrollbar = GScrollBar::construct(Orientation::Vertical, this);
m_vertical_scrollbar = ScrollBar::construct(Orientation::Vertical, this);
m_vertical_scrollbar->set_step(4);
m_vertical_scrollbar->on_change = [this](int) {
did_scroll();
update();
};
m_horizontal_scrollbar = GScrollBar::construct(Orientation::Horizontal, this);
m_horizontal_scrollbar = ScrollBar::construct(Orientation::Horizontal, this);
m_horizontal_scrollbar->set_step(4);
m_horizontal_scrollbar->set_big_step(30);
m_horizontal_scrollbar->on_change = [this](int) {
@ -45,21 +47,21 @@ GScrollableWidget::GScrollableWidget(GWidget* parent)
update();
};
m_corner_widget = GWidget::construct(this);
m_corner_widget = Widget::construct(this);
m_corner_widget->set_fill_with_background_color(true);
}
GScrollableWidget::~GScrollableWidget()
ScrollableWidget::~ScrollableWidget()
{
}
void GScrollableWidget::mousewheel_event(GMouseEvent& event)
void ScrollableWidget::mousewheel_event(MouseEvent& event)
{
// FIXME: The wheel delta multiplier should probably come from... somewhere?
vertical_scrollbar().set_value(vertical_scrollbar().value() + event.wheel_delta() * 20);
}
void GScrollableWidget::custom_layout()
void ScrollableWidget::custom_layout()
{
auto inner_rect = frame_inner_rect_for_size(size());
int height_wanted_by_horizontal_scrollbar = m_horizontal_scrollbar->is_visible() ? m_horizontal_scrollbar->preferred_size().height() : 0;
@ -84,20 +86,20 @@ void GScrollableWidget::custom_layout()
}
}
void GScrollableWidget::resize_event(GResizeEvent& event)
void ScrollableWidget::resize_event(ResizeEvent& event)
{
GFrame::resize_event(event);
Frame::resize_event(event);
update_scrollbar_ranges();
}
Size GScrollableWidget::available_size() const
Size ScrollableWidget::available_size() const
{
int available_width = frame_inner_rect().width() - m_size_occupied_by_fixed_elements.width() - width_occupied_by_vertical_scrollbar();
int available_height = frame_inner_rect().height() - m_size_occupied_by_fixed_elements.height() - height_occupied_by_horizontal_scrollbar();
return { available_width, available_height };
}
void GScrollableWidget::update_scrollbar_ranges()
void ScrollableWidget::update_scrollbar_ranges()
{
auto available_size = this->available_size();
@ -116,7 +118,7 @@ void GScrollableWidget::update_scrollbar_ranges()
m_vertical_scrollbar->set_big_step(visible_content_rect().height() - m_vertical_scrollbar->step());
}
void GScrollableWidget::set_content_size(const Size& size)
void ScrollableWidget::set_content_size(const Size& size)
{
if (m_content_size == size)
return;
@ -124,7 +126,7 @@ void GScrollableWidget::set_content_size(const Size& size)
update_scrollbar_ranges();
}
void GScrollableWidget::set_size_occupied_by_fixed_elements(const Size& size)
void ScrollableWidget::set_size_occupied_by_fixed_elements(const Size& size)
{
if (m_size_occupied_by_fixed_elements == size)
return;
@ -132,17 +134,17 @@ void GScrollableWidget::set_size_occupied_by_fixed_elements(const Size& size)
update_scrollbar_ranges();
}
int GScrollableWidget::height_occupied_by_horizontal_scrollbar() const
int ScrollableWidget::height_occupied_by_horizontal_scrollbar() const
{
return m_horizontal_scrollbar->is_visible() ? m_horizontal_scrollbar->height() : 0;
}
int GScrollableWidget::width_occupied_by_vertical_scrollbar() const
int ScrollableWidget::width_occupied_by_vertical_scrollbar() const
{
return m_vertical_scrollbar->is_visible() ? m_vertical_scrollbar->width() : 0;
}
Rect GScrollableWidget::visible_content_rect() const
Rect ScrollableWidget::visible_content_rect() const
{
return {
m_horizontal_scrollbar->value(),
@ -152,14 +154,14 @@ Rect GScrollableWidget::visible_content_rect() const
};
}
void GScrollableWidget::scroll_into_view(const Rect& rect, Orientation orientation)
void ScrollableWidget::scroll_into_view(const Rect& rect, Orientation orientation)
{
if (orientation == Orientation::Vertical)
return scroll_into_view(rect, false, true);
return scroll_into_view(rect, true, false);
}
void GScrollableWidget::scroll_into_view(const Rect& rect, bool scroll_horizontally, bool scroll_vertically)
void ScrollableWidget::scroll_into_view(const Rect& rect, bool scroll_horizontally, bool scroll_vertically)
{
auto visible_content_rect = this->visible_content_rect();
if (visible_content_rect.contains(rect))
@ -179,7 +181,7 @@ void GScrollableWidget::scroll_into_view(const Rect& rect, bool scroll_horizonta
}
}
void GScrollableWidget::set_scrollbars_enabled(bool scrollbars_enabled)
void ScrollableWidget::set_scrollbars_enabled(bool scrollbars_enabled)
{
if (m_scrollbars_enabled == scrollbars_enabled)
return;
@ -189,17 +191,17 @@ void GScrollableWidget::set_scrollbars_enabled(bool scrollbars_enabled)
m_corner_widget->set_visible(m_scrollbars_enabled);
}
void GScrollableWidget::scroll_to_top()
void ScrollableWidget::scroll_to_top()
{
scroll_into_view({ 0, 0, 1, 1 }, Orientation::Vertical);
}
void GScrollableWidget::scroll_to_bottom()
void ScrollableWidget::scroll_to_bottom()
{
scroll_into_view({ 0, content_height(), 1, 1 }, Orientation::Vertical);
}
Rect GScrollableWidget::widget_inner_rect() const
Rect ScrollableWidget::widget_inner_rect() const
{
auto rect = frame_inner_rect();
rect.set_width(rect.width() - width_occupied_by_vertical_scrollbar());
@ -207,7 +209,7 @@ Rect GScrollableWidget::widget_inner_rect() const
return rect;
}
Point GScrollableWidget::to_content_position(const Point& widget_position) const
Point ScrollableWidget::to_content_position(const Point& widget_position) const
{
auto content_position = widget_position;
content_position.move_by(horizontal_scrollbar().value(), vertical_scrollbar().value());
@ -215,10 +217,12 @@ Point GScrollableWidget::to_content_position(const Point& widget_position) const
return content_position;
}
Point GScrollableWidget::to_widget_position(const Point& content_position) const
Point ScrollableWidget::to_widget_position(const Point& content_position) const
{
auto widget_position = content_position;
widget_position.move_by(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
widget_position.move_by(frame_thickness(), frame_thickness());
return widget_position;
}
}

View file

@ -28,12 +28,14 @@
#include <LibGUI/GFrame.h>
class GScrollBar;
namespace GUI {
class GScrollableWidget : public GFrame {
C_OBJECT(GScrollableWidget)
class ScrollBar;
class ScrollableWidget : public Frame {
C_OBJECT(ScrollableWidget)
public:
virtual ~GScrollableWidget() override;
virtual ~ScrollableWidget() override;
Size content_size() const { return m_content_size; }
int content_width() const { return m_content_size.width(); }
@ -51,12 +53,12 @@ public:
Size available_size() const;
GScrollBar& vertical_scrollbar() { return *m_vertical_scrollbar; }
const GScrollBar& vertical_scrollbar() const { return *m_vertical_scrollbar; }
GScrollBar& horizontal_scrollbar() { return *m_horizontal_scrollbar; }
const GScrollBar& horizontal_scrollbar() const { return *m_horizontal_scrollbar; }
GWidget& corner_widget() { return *m_corner_widget; }
const GWidget& corner_widget() const { return *m_corner_widget; }
ScrollBar& vertical_scrollbar() { return *m_vertical_scrollbar; }
const ScrollBar& vertical_scrollbar() const { return *m_vertical_scrollbar; }
ScrollBar& horizontal_scrollbar() { return *m_horizontal_scrollbar; }
const ScrollBar& horizontal_scrollbar() const { return *m_horizontal_scrollbar; }
Widget& corner_widget() { return *m_corner_widget; }
const Widget& corner_widget() const { return *m_corner_widget; }
void scroll_to_top();
void scroll_to_bottom();
@ -71,10 +73,10 @@ public:
Point to_widget_position(const Point& content_position) const;
protected:
explicit GScrollableWidget(GWidget* parent);
explicit ScrollableWidget(Widget* parent);
virtual void custom_layout() override;
virtual void resize_event(GResizeEvent&) override;
virtual void mousewheel_event(GMouseEvent&) override;
virtual void resize_event(ResizeEvent&) override;
virtual void mousewheel_event(MouseEvent&) override;
virtual void did_scroll() {}
void set_content_size(const Size&);
void set_size_occupied_by_fixed_elements(const Size&);
@ -82,11 +84,13 @@ protected:
private:
void update_scrollbar_ranges();
RefPtr<GScrollBar> m_vertical_scrollbar;
RefPtr<GScrollBar> m_horizontal_scrollbar;
RefPtr<GWidget> m_corner_widget;
RefPtr<ScrollBar> m_vertical_scrollbar;
RefPtr<ScrollBar> m_horizontal_scrollbar;
RefPtr<Widget> m_corner_widget;
Size m_content_size;
Size m_size_occupied_by_fixed_elements;
bool m_scrollbars_enabled { true };
bool m_should_hide_unnecessary_scrollbars { false };
};
}

View file

@ -27,7 +27,9 @@
#include <AK/StringBuilder.h>
#include <LibGUI/GShortcut.h>
static String to_string(KeyCode key)
namespace GUI {
static String key_code_to_string(KeyCode key)
{
switch (key) {
case Key_Escape:
@ -244,7 +246,7 @@ static String to_string(KeyCode key)
}
}
String GShortcut::to_string() const
String Shortcut::to_string() const
{
Vector<String, 8> parts;
@ -257,7 +259,7 @@ String GShortcut::to_string() const
if (m_modifiers & Mod_Logo)
parts.append("Logo");
parts.append(::to_string(m_key));
parts.append(key_code_to_string(m_key));
StringBuilder builder;
for (int i = 0; i < parts.size(); ++i) {
@ -267,3 +269,5 @@ String GShortcut::to_string() const
}
return builder.to_string();
}
}

View file

@ -30,10 +30,12 @@
#include <AK/Traits.h>
#include <Kernel/KeyCode.h>
class GShortcut {
namespace GUI {
class Shortcut {
public:
GShortcut() {}
GShortcut(u8 modifiers, KeyCode key)
Shortcut() {}
Shortcut(u8 modifiers, KeyCode key)
: m_modifiers(modifiers)
, m_key(key)
{
@ -44,7 +46,7 @@ public:
KeyCode key() const { return m_key; }
String to_string() const;
bool operator==(const GShortcut& other) const
bool operator==(const Shortcut& other) const
{
return m_modifiers == other.m_modifiers
&& m_key == other.m_key;
@ -55,11 +57,13 @@ private:
KeyCode m_key { KeyCode::Key_Invalid };
};
}
namespace AK {
template<>
struct Traits<GShortcut> : public GenericTraits<GShortcut> {
static unsigned hash(const GShortcut& shortcut)
struct Traits<GUI::Shortcut> : public GenericTraits<GUI::Shortcut> {
static unsigned hash(const GUI::Shortcut& shortcut)
{
return pair_int_hash(shortcut.modifiers(), shortcut.key());
}

View file

@ -28,22 +28,24 @@
#include <LibGUI/GPainter.h>
#include <LibGUI/GSlider.h>
GSlider::GSlider(GWidget* parent)
: GSlider(Orientation::Horizontal, parent)
namespace GUI {
Slider::Slider(Widget* parent)
: Slider(Orientation::Horizontal, parent)
{
}
GSlider::GSlider(Orientation orientation, GWidget* parent)
: GWidget(parent)
Slider::Slider(Orientation orientation, Widget* parent)
: Widget(parent)
, m_orientation(orientation)
{
}
GSlider::~GSlider()
Slider::~Slider()
{
}
void GSlider::set_range(int min, int max)
void Slider::set_range(int min, int max)
{
ASSERT(min <= max);
if (m_min == min && m_max == max)
@ -54,7 +56,7 @@ void GSlider::set_range(int min, int max)
update();
}
void GSlider::set_value(int value)
void Slider::set_value(int value)
{
value = clamp(value, m_min, m_max);
if (m_value == value)
@ -66,9 +68,9 @@ void GSlider::set_value(int value)
on_value_changed(m_value);
}
void GSlider::paint_event(GPaintEvent& event)
void Slider::paint_event(PaintEvent& event)
{
GPainter painter(*this);
Painter painter(*this);
painter.add_clip_rect(event.rect());
Rect track_rect;
@ -85,7 +87,7 @@ void GSlider::paint_event(GPaintEvent& event)
StylePainter::paint_button(painter, knob_rect(), palette(), ButtonStyle::Normal, false, m_knob_hovered);
}
Rect GSlider::knob_rect() const
Rect Slider::knob_rect() const
{
auto inner_rect = this->inner_rect();
Rect rect;
@ -114,11 +116,11 @@ Rect GSlider::knob_rect() const
return rect;
}
void GSlider::mousedown_event(GMouseEvent& event)
void Slider::mousedown_event(MouseEvent& event)
{
if (!is_enabled())
return;
if (event.button() == GMouseButton::Left) {
if (event.button() == MouseButton::Left) {
if (knob_rect().contains(event.position())) {
m_dragging = true;
m_drag_origin = event.position();
@ -131,10 +133,10 @@ void GSlider::mousedown_event(GMouseEvent& event)
set_value(m_value - 1);
}
}
return GWidget::mousedown_event(event);
return Widget::mousedown_event(event);
}
void GSlider::mousemove_event(GMouseEvent& event)
void Slider::mousemove_event(MouseEvent& event)
{
if (!is_enabled())
return;
@ -147,42 +149,44 @@ void GSlider::mousemove_event(GMouseEvent& event)
set_value((int)new_value);
return;
}
return GWidget::mousemove_event(event);
return Widget::mousemove_event(event);
}
void GSlider::mouseup_event(GMouseEvent& event)
void Slider::mouseup_event(MouseEvent& event)
{
if (!is_enabled())
return;
if (event.button() == GMouseButton::Left) {
if (event.button() == MouseButton::Left) {
m_dragging = false;
return;
}
return GWidget::mouseup_event(event);
return Widget::mouseup_event(event);
}
void GSlider::leave_event(Core::Event& event)
void Slider::leave_event(Core::Event& event)
{
if (!is_enabled())
return;
set_knob_hovered(false);
GWidget::leave_event(event);
Widget::leave_event(event);
}
void GSlider::change_event(GEvent& event)
void Slider::change_event(Event& event)
{
if (event.type() == GEvent::Type::EnabledChange) {
if (event.type() == Event::Type::EnabledChange) {
if (!is_enabled())
m_dragging = false;
}
GWidget::change_event(event);
Widget::change_event(event);
}
void GSlider::set_knob_hovered(bool hovered)
void Slider::set_knob_hovered(bool hovered)
{
if (m_knob_hovered == hovered)
return;
m_knob_hovered = hovered;
update(knob_rect());
}
}

View file

@ -28,15 +28,17 @@
#include <LibGUI/GWidget.h>
class GSlider : public GWidget {
C_OBJECT(GSlider)
namespace GUI {
class Slider : public Widget {
C_OBJECT(Slider)
public:
enum class KnobSizeMode {
Fixed,
Proportional,
};
virtual ~GSlider() override;
virtual ~Slider() override;
Orientation orientation() const { return m_orientation; }
@ -70,15 +72,15 @@ public:
Function<void(int)> on_value_changed;
protected:
explicit GSlider(GWidget*);
explicit GSlider(Orientation, GWidget*);
explicit Slider(Widget*);
explicit Slider(Orientation, Widget*);
virtual void paint_event(GPaintEvent&) override;
virtual void mousedown_event(GMouseEvent&) override;
virtual void mousemove_event(GMouseEvent&) override;
virtual void mouseup_event(GMouseEvent&) override;
virtual void paint_event(PaintEvent&) override;
virtual void mousedown_event(MouseEvent&) override;
virtual void mousemove_event(MouseEvent&) override;
virtual void mouseup_event(MouseEvent&) override;
virtual void leave_event(Core::Event&) override;
virtual void change_event(GEvent&) override;
virtual void change_event(Event&) override;
private:
void set_knob_hovered(bool);
@ -93,3 +95,5 @@ private:
KnobSizeMode m_knob_size_mode { KnobSizeMode::Fixed };
Orientation m_orientation { Orientation::Horizontal };
};
}

View file

@ -30,7 +30,9 @@
#include <stdio.h>
#include <stdlib.h>
GSortingProxyModel::GSortingProxyModel(NonnullRefPtr<GModel>&& target)
namespace GUI {
SortingProxyModel::SortingProxyModel(NonnullRefPtr<Model>&& target)
: m_target(move(target))
, m_key_column(-1)
{
@ -39,21 +41,21 @@ GSortingProxyModel::GSortingProxyModel(NonnullRefPtr<GModel>&& target)
};
}
GSortingProxyModel::~GSortingProxyModel()
SortingProxyModel::~SortingProxyModel()
{
}
int GSortingProxyModel::row_count(const GModelIndex& index) const
int SortingProxyModel::row_count(const ModelIndex& index) const
{
return target().row_count(index);
}
int GSortingProxyModel::column_count(const GModelIndex& index) const
int SortingProxyModel::column_count(const ModelIndex& index) const
{
return target().column_count(index);
}
GModelIndex GSortingProxyModel::map_to_target(const GModelIndex& index) const
ModelIndex SortingProxyModel::map_to_target(const ModelIndex& index) const
{
if (!index.is_valid())
return {};
@ -62,37 +64,37 @@ GModelIndex GSortingProxyModel::map_to_target(const GModelIndex& index) const
return target().index(m_row_mappings[index.row()], index.column());
}
String GSortingProxyModel::row_name(int index) const
String SortingProxyModel::row_name(int index) const
{
return target().row_name(index);
}
String GSortingProxyModel::column_name(int index) const
String SortingProxyModel::column_name(int index) const
{
return target().column_name(index);
}
GModel::ColumnMetadata GSortingProxyModel::column_metadata(int index) const
Model::ColumnMetadata SortingProxyModel::column_metadata(int index) const
{
return target().column_metadata(index);
}
GVariant GSortingProxyModel::data(const GModelIndex& index, Role role) const
Variant SortingProxyModel::data(const ModelIndex& index, Role role) const
{
return target().data(map_to_target(index), role);
}
void GSortingProxyModel::update()
void SortingProxyModel::update()
{
target().update();
}
StringView GSortingProxyModel::drag_data_type() const
StringView SortingProxyModel::drag_data_type() const
{
return target().drag_data_type();
}
void GSortingProxyModel::set_key_column_and_sort_order(int column, GSortOrder sort_order)
void SortingProxyModel::set_key_column_and_sort_order(int column, SortOrder sort_order)
{
if (column == m_key_column && sort_order == m_sort_order)
return;
@ -103,7 +105,7 @@ void GSortingProxyModel::set_key_column_and_sort_order(int column, GSortOrder so
resort();
}
void GSortingProxyModel::resort()
void SortingProxyModel::resort()
{
auto old_row_mappings = m_row_mappings;
int row_count = target().row_count();
@ -115,8 +117,8 @@ void GSortingProxyModel::resort()
return;
}
quick_sort(m_row_mappings.begin(), m_row_mappings.end(), [&](auto row1, auto row2) -> bool {
auto data1 = target().data(target().index(row1, m_key_column), GModel::Role::Sort);
auto data2 = target().data(target().index(row2, m_key_column), GModel::Role::Sort);
auto data1 = target().data(target().index(row1, m_key_column), Model::Role::Sort);
auto data2 = target().data(target().index(row2, m_key_column), Model::Role::Sort);
if (data1 == data2)
return 0;
bool is_less_than;
@ -124,13 +126,13 @@ void GSortingProxyModel::resort()
is_less_than = data1.as_string().to_lowercase() < data2.as_string().to_lowercase();
else
is_less_than = data1 < data2;
return m_sort_order == GSortOrder::Ascending ? is_less_than : !is_less_than;
return m_sort_order == SortOrder::Ascending ? is_less_than : !is_less_than;
});
did_update();
for_each_view([&](GAbstractView& view) {
for_each_view([&](AbstractView& view) {
auto& selection = view.selection();
Vector<GModelIndex> selected_indexes_in_target;
selection.for_each_index([&](const GModelIndex& index) {
Vector<ModelIndex> selected_indexes_in_target;
selection.for_each_index([&](const ModelIndex& index) {
selected_indexes_in_target.append(target().index(old_row_mappings[index.row()], index.column()));
});
@ -145,3 +147,5 @@ void GSortingProxyModel::resort()
}
});
}
}

View file

@ -28,40 +28,44 @@
#include <LibGUI/GModel.h>
class GSortingProxyModel final : public GModel {
public:
static NonnullRefPtr<GSortingProxyModel> create(NonnullRefPtr<GModel>&& model) { return adopt(*new GSortingProxyModel(move(model))); }
virtual ~GSortingProxyModel() override;
namespace GUI {
virtual int row_count(const GModelIndex& = GModelIndex()) const override;
virtual int column_count(const GModelIndex& = GModelIndex()) const override;
class SortingProxyModel final : public Model {
public:
static NonnullRefPtr<SortingProxyModel> create(NonnullRefPtr<Model>&& model) { return adopt(*new SortingProxyModel(move(model))); }
virtual ~SortingProxyModel() override;
virtual int row_count(const ModelIndex& = ModelIndex()) const override;
virtual int column_count(const ModelIndex& = ModelIndex()) const override;
virtual String row_name(int) const override;
virtual String column_name(int) const override;
virtual ColumnMetadata column_metadata(int) const override;
virtual GVariant data(const GModelIndex&, Role = Role::Display) const override;
virtual Variant data(const ModelIndex&, Role = Role::Display) const override;
virtual void update() override;
virtual StringView drag_data_type() const override;
virtual int key_column() const override { return m_key_column; }
virtual GSortOrder sort_order() const override { return m_sort_order; }
virtual void set_key_column_and_sort_order(int, GSortOrder) override;
virtual SortOrder sort_order() const override { return m_sort_order; }
virtual void set_key_column_and_sort_order(int, SortOrder) override;
GModelIndex map_to_target(const GModelIndex&) const;
ModelIndex map_to_target(const ModelIndex&) const;
private:
explicit GSortingProxyModel(NonnullRefPtr<GModel>&&);
explicit SortingProxyModel(NonnullRefPtr<Model>&&);
GModel& target() { return *m_target; }
const GModel& target() const { return *m_target; }
Model& target() { return *m_target; }
const Model& target() const { return *m_target; }
void resort();
void set_sorting_case_sensitive(bool b) { m_sorting_case_sensitive = b; }
bool is_sorting_case_sensitive() { return m_sorting_case_sensitive; }
NonnullRefPtr<GModel> m_target;
NonnullRefPtr<Model> m_target;
Vector<int> m_row_mappings;
int m_key_column { -1 };
GSortOrder m_sort_order { GSortOrder::Ascending };
SortOrder m_sort_order { SortOrder::Ascending };
bool m_sorting_case_sensitive { false };
};
}

View file

@ -28,10 +28,12 @@
#include <LibGUI/GSpinBox.h>
#include <LibGUI/GTextEditor.h>
GSpinBox::GSpinBox(GWidget* parent)
: GWidget(parent)
namespace GUI {
SpinBox::SpinBox(Widget* parent)
: Widget(parent)
{
m_editor = GTextEditor::construct(GTextEditor::Type::SingleLine, this);
m_editor = TextEditor::construct(TextEditor::Type::SingleLine, this);
m_editor->set_text("0");
m_editor->on_change = [this] {
bool ok;
@ -41,23 +43,23 @@ GSpinBox::GSpinBox(GWidget* parent)
else
m_editor->set_text(String::number(m_value));
};
m_increment_button = GButton::construct(this);
m_increment_button = Button::construct(this);
m_increment_button->set_focusable(false);
m_increment_button->set_text("\xc3\xb6");
m_increment_button->on_click = [this](GButton&) { set_value(m_value + 1); };
m_increment_button->on_click = [this](auto&) { set_value(m_value + 1); };
m_increment_button->set_auto_repeat_interval(150);
m_decrement_button = GButton::construct(this);
m_decrement_button = Button::construct(this);
m_decrement_button->set_focusable(false);
m_decrement_button->set_text("\xc3\xb7");
m_decrement_button->on_click = [this](GButton&) { set_value(m_value - 1); };
m_decrement_button->on_click = [this](auto&) { set_value(m_value - 1); };
m_decrement_button->set_auto_repeat_interval(150);
}
GSpinBox::~GSpinBox()
SpinBox::~SpinBox()
{
}
void GSpinBox::set_value(int value)
void SpinBox::set_value(int value)
{
value = clamp(value, m_min, m_max);
if (m_value == value)
@ -69,7 +71,7 @@ void GSpinBox::set_value(int value)
on_change(value);
}
void GSpinBox::set_range(int min, int max)
void SpinBox::set_range(int min, int max)
{
ASSERT(min <= max);
if (m_min == min && m_max == max)
@ -86,7 +88,7 @@ void GSpinBox::set_range(int min, int max)
update();
}
void GSpinBox::resize_event(GResizeEvent& event)
void SpinBox::resize_event(ResizeEvent& event)
{
int frame_thickness = m_editor->frame_thickness();
int button_height = (event.size().height() / 2) - frame_thickness;
@ -95,3 +97,5 @@ void GSpinBox::resize_event(GResizeEvent& event)
m_decrement_button->set_relative_rect(width() - button_width - frame_thickness, frame_thickness + button_height, button_width, button_height);
m_editor->set_relative_rect(0, 0, width(), height());
}
}

View file

@ -28,13 +28,15 @@
#include <LibGUI/GWidget.h>
class GButton;
class GTextEditor;
namespace GUI {
class GSpinBox : public GWidget {
C_OBJECT(GSpinBox)
class Button;
class TextEditor;
class SpinBox : public Widget {
C_OBJECT(SpinBox)
public:
virtual ~GSpinBox() override;
virtual ~SpinBox() override;
int value() const { return m_value; }
void set_value(int);
@ -48,16 +50,18 @@ public:
Function<void(int value)> on_change;
protected:
explicit GSpinBox(GWidget* parent = nullptr);
explicit SpinBox(Widget* parent = nullptr);
virtual void resize_event(GResizeEvent&) override;
virtual void resize_event(ResizeEvent&) override;
private:
RefPtr<GTextEditor> m_editor;
RefPtr<GButton> m_increment_button;
RefPtr<GButton> m_decrement_button;
RefPtr<TextEditor> m_editor;
RefPtr<Button> m_increment_button;
RefPtr<Button> m_decrement_button;
int m_min { 0 };
int m_max { 100 };
int m_value { 0 };
};
}

View file

@ -29,43 +29,45 @@
#include <LibGUI/GSplitter.h>
#include <LibGUI/GWindow.h>
GSplitter::GSplitter(Orientation orientation, GWidget* parent)
: GFrame(parent)
namespace GUI {
Splitter::Splitter(Orientation orientation, Widget* parent)
: Frame(parent)
, m_orientation(orientation)
{
set_background_role(ColorRole::Button);
set_layout(make<GBoxLayout>(orientation));
set_layout(make<BoxLayout>(orientation));
set_fill_with_background_color(true);
layout()->set_spacing(3);
}
GSplitter::~GSplitter()
Splitter::~Splitter()
{
}
void GSplitter::enter_event(Core::Event&)
void Splitter::enter_event(Core::Event&)
{
set_background_role(ColorRole::HoverHighlight);
window()->set_override_cursor(m_orientation == Orientation::Horizontal ? GStandardCursor::ResizeHorizontal : GStandardCursor::ResizeVertical);
window()->set_override_cursor(m_orientation == Orientation::Horizontal ? StandardCursor::ResizeHorizontal : StandardCursor::ResizeVertical);
update();
}
void GSplitter::leave_event(Core::Event&)
void Splitter::leave_event(Core::Event&)
{
set_background_role(ColorRole::Button);
if (!m_resizing)
window()->set_override_cursor(GStandardCursor::None);
window()->set_override_cursor(StandardCursor::None);
update();
}
void GSplitter::mousedown_event(GMouseEvent& event)
void Splitter::mousedown_event(MouseEvent& event)
{
if (event.button() != GMouseButton::Left)
if (event.button() != MouseButton::Left)
return;
m_resizing = true;
int x_or_y = event.position().primary_offset_for_orientation(m_orientation);
GWidget* first_resizee { nullptr };
GWidget* second_resizee { nullptr };
Widget* first_resizee { nullptr };
Widget* second_resizee { nullptr };
int fudge = layout()->spacing();
for_each_child_widget([&](auto& child) {
int child_start = child.relative_rect().first_edge_for_orientation(m_orientation);
@ -84,7 +86,7 @@ void GSplitter::mousedown_event(GMouseEvent& event)
m_resize_origin = event.position();
}
void GSplitter::mousemove_event(GMouseEvent& event)
void Splitter::mousemove_event(MouseEvent& event)
{
if (!m_resizing)
return;
@ -120,11 +122,13 @@ void GSplitter::mousemove_event(GMouseEvent& event)
invalidate_layout();
}
void GSplitter::mouseup_event(GMouseEvent& event)
void Splitter::mouseup_event(MouseEvent& event)
{
if (event.button() != GMouseButton::Left)
if (event.button() != MouseButton::Left)
return;
m_resizing = false;
if (!rect().contains(event.position()))
window()->set_override_cursor(GStandardCursor::None);
window()->set_override_cursor(StandardCursor::None);
}
}

View file

@ -28,17 +28,19 @@
#include <LibGUI/GFrame.h>
class GSplitter : public GFrame {
C_OBJECT(GSplitter)
namespace GUI {
class Splitter : public Frame {
C_OBJECT(Splitter)
public:
virtual ~GSplitter() override;
virtual ~Splitter() override;
protected:
GSplitter(Orientation, GWidget* parent);
Splitter(Orientation, Widget* parent);
virtual void mousedown_event(GMouseEvent&) override;
virtual void mousemove_event(GMouseEvent&) override;
virtual void mouseup_event(GMouseEvent&) override;
virtual void mousedown_event(MouseEvent&) override;
virtual void mousemove_event(MouseEvent&) override;
virtual void mouseup_event(MouseEvent&) override;
virtual void enter_event(Core::Event&) override;
virtual void leave_event(Core::Event&) override;
@ -46,8 +48,10 @@ private:
Orientation m_orientation;
bool m_resizing { false };
Point m_resize_origin;
WeakPtr<GWidget> m_first_resizee;
WeakPtr<GWidget> m_second_resizee;
WeakPtr<Widget> m_first_resizee;
WeakPtr<Widget> m_second_resizee;
Size m_first_resizee_start_size;
Size m_second_resizee_start_size;
};
}

View file

@ -27,16 +27,18 @@
#include <LibGUI/GBoxLayout.h>
#include <LibGUI/GStackWidget.h>
GStackWidget::GStackWidget(GWidget* parent)
: GWidget(parent)
namespace GUI {
StackWidget::StackWidget(Widget* parent)
: Widget(parent)
{
}
GStackWidget::~GStackWidget()
StackWidget::~StackWidget()
{
}
void GStackWidget::set_active_widget(GWidget* widget)
void StackWidget::set_active_widget(Widget* widget)
{
if (widget == m_active_widget)
return;
@ -52,26 +54,26 @@ void GStackWidget::set_active_widget(GWidget* widget)
on_active_widget_change(m_active_widget);
}
void GStackWidget::resize_event(GResizeEvent& event)
void StackWidget::resize_event(ResizeEvent& event)
{
if (!m_active_widget)
return;
m_active_widget->set_relative_rect({ {}, event.size() });
}
void GStackWidget::child_event(Core::ChildEvent& event)
void StackWidget::child_event(Core::ChildEvent& event)
{
if (!event.child() || !Core::is<GWidget>(*event.child()))
return GWidget::child_event(event);
auto& child = Core::to<GWidget>(*event.child());
if (event.type() == GEvent::ChildAdded) {
if (!event.child() || !Core::is<Widget>(*event.child()))
return Widget::child_event(event);
auto& child = Core::to<Widget>(*event.child());
if (event.type() == Event::ChildAdded) {
if (!m_active_widget)
set_active_widget(&child);
else if (m_active_widget != &child)
child.set_visible(false);
} else if (event.type() == GEvent::ChildRemoved) {
} else if (event.type() == Event::ChildRemoved) {
if (m_active_widget == &child) {
GWidget* new_active_widget = nullptr;
Widget* new_active_widget = nullptr;
for_each_child_widget([&](auto& new_child) {
new_active_widget = &new_child;
return IterationDecision::Break;
@ -79,5 +81,7 @@ void GStackWidget::child_event(Core::ChildEvent& event)
set_active_widget(new_active_widget);
}
}
GWidget::child_event(event);
Widget::child_event(event);
}
}

View file

@ -28,22 +28,26 @@
#include <LibGUI/GWidget.h>
class GStackWidget : public GWidget {
C_OBJECT(GStackWidget)
namespace GUI {
class StackWidget : public Widget {
C_OBJECT(StackWidget)
public:
virtual ~GStackWidget() override;
virtual ~StackWidget() override;
GWidget* active_widget() { return m_active_widget.ptr(); }
const GWidget* active_widget() const { return m_active_widget.ptr(); }
void set_active_widget(GWidget*);
Widget* active_widget() { return m_active_widget.ptr(); }
const Widget* active_widget() const { return m_active_widget.ptr(); }
void set_active_widget(Widget*);
Function<void(GWidget*)> on_active_widget_change;
Function<void(Widget*)> on_active_widget_change;
protected:
explicit GStackWidget(GWidget* parent);
explicit StackWidget(Widget* parent);
virtual void child_event(Core::ChildEvent&) override;
virtual void resize_event(GResizeEvent&) override;
virtual void resize_event(ResizeEvent&) override;
private:
RefPtr<GWidget> m_active_widget;
RefPtr<Widget> m_active_widget;
};
}

View file

@ -31,17 +31,19 @@
#include <LibGUI/GResizeCorner.h>
#include <LibGUI/GStatusBar.h>
GStatusBar::GStatusBar(GWidget* parent)
: GStatusBar(1, parent)
namespace GUI {
StatusBar::StatusBar(Widget* parent)
: StatusBar(1, parent)
{
}
GStatusBar::GStatusBar(int label_count, GWidget* parent)
: GWidget(parent)
StatusBar::StatusBar(int label_count, Widget* parent)
: Widget(parent)
{
set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
set_preferred_size(0, 20);
set_layout(make<GHBoxLayout>());
set_layout(make<HBoxLayout>());
layout()->set_margins({ 2, 2, 2, 2 });
layout()->set_spacing(2);
@ -51,16 +53,16 @@ GStatusBar::GStatusBar(int label_count, GWidget* parent)
for (auto i = 0; i < label_count; i++)
m_labels.append(create_label());
m_corner = GResizeCorner::construct(this);
m_corner = ResizeCorner::construct(this);
}
GStatusBar::~GStatusBar()
StatusBar::~StatusBar()
{
}
NonnullRefPtr<GLabel> GStatusBar::create_label()
NonnullRefPtr<Label> StatusBar::create_label()
{
auto label = GLabel::construct(this);
auto label = Label::construct(this);
label->set_frame_shadow(FrameShadow::Sunken);
label->set_frame_shape(FrameShape::Panel);
label->set_frame_thickness(1);
@ -68,29 +70,31 @@ NonnullRefPtr<GLabel> GStatusBar::create_label()
return label;
}
void GStatusBar::set_text(const StringView& text)
void StatusBar::set_text(const StringView& text)
{
m_labels.first().set_text(text);
}
String GStatusBar::text() const
String StatusBar::text() const
{
return m_labels.first().text();
}
void GStatusBar::set_text(int index, const StringView& text)
void StatusBar::set_text(int index, const StringView& text)
{
m_labels.at(index).set_text(text);
}
String GStatusBar::text(int index) const
String StatusBar::text(int index) const
{
return m_labels.at(index).text();
}
void GStatusBar::paint_event(GPaintEvent& event)
void StatusBar::paint_event(PaintEvent& event)
{
GPainter painter(*this);
Painter painter(*this);
painter.add_clip_rect(event.rect());
StylePainter::paint_surface(painter, rect(), palette(), !spans_entire_window_horizontally());
}
}

View file

@ -28,13 +28,15 @@
#include <LibGUI/GWidget.h>
class GLabel;
class GResizeCorner;
namespace GUI {
class GStatusBar : public GWidget {
C_OBJECT(GStatusBar)
class Label;
class ResizeCorner;
class StatusBar : public Widget {
C_OBJECT(StatusBar)
public:
virtual ~GStatusBar() override;
virtual ~StatusBar() override;
String text() const;
String text(int index) const;
@ -42,12 +44,14 @@ public:
void set_text(int index, const StringView&);
protected:
explicit GStatusBar(GWidget* parent);
explicit GStatusBar(int label_count, GWidget* parent);
virtual void paint_event(GPaintEvent&) override;
explicit StatusBar(Widget* parent);
explicit StatusBar(int label_count, Widget* parent);
virtual void paint_event(PaintEvent&) override;
private:
NonnullRefPtr<GLabel> create_label();
NonnullRefPtrVector<GLabel> m_labels;
RefPtr<GResizeCorner> m_corner;
NonnullRefPtr<Label> create_label();
NonnullRefPtrVector<Label> m_labels;
RefPtr<ResizeCorner> m_corner;
};
}

Some files were not shown because too many files have changed in this diff Show more