mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 14:28:12 +00:00
LibGUI: Add a GToolBar class that can be populated with GActions.
The same action can be added to both a menu and a toolbar. Use this to put a toolbar into FileManager. This is pretty neat. :^)
This commit is contained in:
parent
4804609b7e
commit
b704d3d295
24 changed files with 196 additions and 44 deletions
|
@ -3,47 +3,52 @@
|
||||||
#include <LibGUI/GBoxLayout.h>
|
#include <LibGUI/GBoxLayout.h>
|
||||||
#include <LibGUI/GApplication.h>
|
#include <LibGUI/GApplication.h>
|
||||||
#include <LibGUI/GStatusBar.h>
|
#include <LibGUI/GStatusBar.h>
|
||||||
|
#include <LibGUI/GToolBar.h>
|
||||||
#include <LibGUI/GMenuBar.h>
|
#include <LibGUI/GMenuBar.h>
|
||||||
#include <LibGUI/GAction.h>
|
#include <LibGUI/GAction.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "DirectoryView.h"
|
#include "DirectoryView.h"
|
||||||
|
|
||||||
static GWindow* make_window();
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
GApplication app(argc, argv);
|
GApplication app(argc, argv);
|
||||||
|
|
||||||
|
auto mkdir_action = GAction::create("New directory...", GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, "/res/icons/mkdir16.rgb", { 16, 16 }), [] (const GAction&) {
|
||||||
|
dbgprintf("'New directory' action activated!\n");
|
||||||
|
});
|
||||||
|
|
||||||
|
auto copy_action = GAction::create("Copy", GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, "/res/icons/copyfile16.rgb", { 16, 16 }), [] (const GAction&) {
|
||||||
|
dbgprintf("'Copy' action activated!\n");
|
||||||
|
});
|
||||||
|
|
||||||
|
auto delete_action = GAction::create("Delete", GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, "/res/icons/trash16.rgb", { 16, 16 }), [] (const GAction&) {
|
||||||
|
dbgprintf("'Delete' action activated!\n");
|
||||||
|
});
|
||||||
|
|
||||||
auto menubar = make<GMenuBar>();
|
auto menubar = make<GMenuBar>();
|
||||||
|
|
||||||
auto app_menu = make<GMenu>("FileManager");
|
auto app_menu = make<GMenu>("FileManager");
|
||||||
app_menu->add_action(make<GAction>("Quit", String(), [] (const GAction&) {
|
app_menu->add_action(GAction::create("Quit", String(), [] (const GAction&) {
|
||||||
GApplication::the().quit(0);
|
GApplication::the().quit(0);
|
||||||
return;
|
return;
|
||||||
}));
|
}));
|
||||||
menubar->add_menu(move(app_menu));
|
menubar->add_menu(move(app_menu));
|
||||||
|
|
||||||
auto file_menu = make<GMenu>("File");
|
auto file_menu = make<GMenu>("File");
|
||||||
|
file_menu->add_action(mkdir_action.copy_ref());
|
||||||
|
file_menu->add_action(copy_action.copy_ref());
|
||||||
|
file_menu->add_action(delete_action.copy_ref());
|
||||||
menubar->add_menu(move(file_menu));
|
menubar->add_menu(move(file_menu));
|
||||||
|
|
||||||
auto help_menu = make<GMenu>("Help");
|
auto help_menu = make<GMenu>("Help");
|
||||||
help_menu->add_action(make<GAction>("About", [] (const GAction&) {
|
help_menu->add_action(GAction::create("About", [] (const GAction&) {
|
||||||
dbgprintf("FIXME: Implement Help/About\n");
|
dbgprintf("FIXME: Implement Help/About\n");
|
||||||
}));
|
}));
|
||||||
menubar->add_menu(move(help_menu));
|
menubar->add_menu(move(help_menu));
|
||||||
|
|
||||||
app.set_menubar(move(menubar));
|
app.set_menubar(move(menubar));
|
||||||
|
|
||||||
auto* window = make_window();
|
|
||||||
window->set_should_exit_app_on_close(true);
|
|
||||||
window->show();
|
|
||||||
|
|
||||||
return app.exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
GWindow* make_window()
|
|
||||||
{
|
|
||||||
auto* window = new GWindow;
|
auto* window = new GWindow;
|
||||||
window->set_title("FileManager");
|
window->set_title("FileManager");
|
||||||
window->set_rect(20, 200, 240, 300);
|
window->set_rect(20, 200, 240, 300);
|
||||||
|
@ -53,6 +58,11 @@ GWindow* make_window()
|
||||||
|
|
||||||
widget->set_layout(make<GBoxLayout>(Orientation::Vertical));
|
widget->set_layout(make<GBoxLayout>(Orientation::Vertical));
|
||||||
|
|
||||||
|
auto* toolbar = new GToolBar(widget);
|
||||||
|
toolbar->add_action(mkdir_action.copy_ref());
|
||||||
|
toolbar->add_action(copy_action.copy_ref());
|
||||||
|
toolbar->add_action(delete_action.copy_ref());
|
||||||
|
|
||||||
auto* directory_view = new DirectoryView(widget);
|
auto* directory_view = new DirectoryView(widget);
|
||||||
|
|
||||||
auto* statusbar = new GStatusBar(widget);
|
auto* statusbar = new GStatusBar(widget);
|
||||||
|
@ -68,6 +78,8 @@ GWindow* make_window()
|
||||||
|
|
||||||
directory_view->open("/");
|
directory_view->open("/");
|
||||||
|
|
||||||
return window;
|
window->set_should_exit_app_on_close(true);
|
||||||
}
|
window->show();
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ int main(int argc, char** argv)
|
||||||
auto menubar = make<GMenuBar>();
|
auto menubar = make<GMenuBar>();
|
||||||
|
|
||||||
auto app_menu = make<GMenu>("Terminal");
|
auto app_menu = make<GMenu>("Terminal");
|
||||||
app_menu->add_action(make<GAction>("Quit", String(), [] (const GAction&) {
|
app_menu->add_action(GAction::create("Quit", String(), [] (const GAction&) {
|
||||||
dbgprintf("Terminal: Quit menu activated!\n");
|
dbgprintf("Terminal: Quit menu activated!\n");
|
||||||
GApplication::the().quit(0);
|
GApplication::the().quit(0);
|
||||||
return;
|
return;
|
||||||
|
@ -106,7 +106,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
auto font_menu = make<GMenu>("Font");
|
auto font_menu = make<GMenu>("Font");
|
||||||
GFontDatabase::the().for_each_font([&] (const String& font_name) {
|
GFontDatabase::the().for_each_font([&] (const String& font_name) {
|
||||||
font_menu->add_action(make<GAction>(font_name, [&terminal] (const GAction& action) {
|
font_menu->add_action(GAction::create(font_name, [&terminal] (const GAction& action) {
|
||||||
terminal.set_font(GFontDatabase::the().get_by_name(action.text()));
|
terminal.set_font(GFontDatabase::the().get_by_name(action.text()));
|
||||||
terminal.force_repaint();
|
terminal.force_repaint();
|
||||||
}));
|
}));
|
||||||
|
@ -114,7 +114,7 @@ int main(int argc, char** argv)
|
||||||
menubar->add_menu(move(font_menu));
|
menubar->add_menu(move(font_menu));
|
||||||
|
|
||||||
auto help_menu = make<GMenu>("Help");
|
auto help_menu = make<GMenu>("Help");
|
||||||
help_menu->add_action(make<GAction>("About", [] (const GAction&) {
|
help_menu->add_action(GAction::create("About", [] (const GAction&) {
|
||||||
dbgprintf("FIXME: Implement Help/About\n");
|
dbgprintf("FIXME: Implement Help/About\n");
|
||||||
}));
|
}));
|
||||||
menubar->add_menu(move(help_menu));
|
menubar->add_menu(move(help_menu));
|
||||||
|
|
BIN
Base/res/icons/copyfile16.data
Normal file
BIN
Base/res/icons/copyfile16.data
Normal file
Binary file not shown.
BIN
Base/res/icons/copyfile16.png
Normal file
BIN
Base/res/icons/copyfile16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
Base/res/icons/copyfile16.rgb
Normal file
BIN
Base/res/icons/copyfile16.rgb
Normal file
Binary file not shown.
BIN
Base/res/icons/mkdir16.data
Normal file
BIN
Base/res/icons/mkdir16.data
Normal file
Binary file not shown.
BIN
Base/res/icons/mkdir16.png
Normal file
BIN
Base/res/icons/mkdir16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
Base/res/icons/mkdir16.rgb
Normal file
BIN
Base/res/icons/mkdir16.rgb
Normal file
Binary file not shown.
BIN
Base/res/icons/trash16.data
Normal file
BIN
Base/res/icons/trash16.data
Normal file
Binary file not shown.
BIN
Base/res/icons/trash16.png
Normal file
BIN
Base/res/icons/trash16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 452 B |
BIN
Base/res/icons/trash16.rgb
Normal file
BIN
Base/res/icons/trash16.rgb
Normal file
Binary file not shown.
|
@ -195,6 +195,36 @@ void exception_7_handler(RegisterDump& regs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 0: Divide error
|
||||||
|
EH_ENTRY_NO_CODE(0);
|
||||||
|
void exception_0_handler(RegisterDump& regs)
|
||||||
|
{
|
||||||
|
kprintf("%s DIVIDE ERROR: %u(%s)\n", current->is_ring0() ? "Kernel" : "User", current->pid(), current->name().characters());
|
||||||
|
|
||||||
|
word ss;
|
||||||
|
dword esp;
|
||||||
|
if (current->is_ring0()) {
|
||||||
|
ss = regs.ds;
|
||||||
|
esp = regs.esp;
|
||||||
|
} else {
|
||||||
|
ss = regs.ss_if_crossRing;
|
||||||
|
esp = regs.esp_if_crossRing;
|
||||||
|
}
|
||||||
|
|
||||||
|
kprintf("pc=%w:%x ds=%w es=%w fs=%w gs=%w\n", regs.cs, regs.eip, regs.ds, regs.es, regs.fs, regs.gs);
|
||||||
|
kprintf("stk=%w:%x\n", ss, esp);
|
||||||
|
kprintf("eax=%x ebx=%x ecx=%x edx=%x\n", regs.eax, regs.ebx, regs.ecx, regs.edx);
|
||||||
|
kprintf("ebp=%x esp=%x esi=%x edi=%x\n", regs.ebp, esp, regs.esi, regs.edi);
|
||||||
|
|
||||||
|
if (current->is_ring0()) {
|
||||||
|
kprintf("Oh shit, we've crashed in ring 0 :(\n");
|
||||||
|
hang();
|
||||||
|
}
|
||||||
|
|
||||||
|
current->crash();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 13: General Protection Fault
|
// 13: General Protection Fault
|
||||||
EH_ENTRY(13);
|
EH_ENTRY(13);
|
||||||
void exception_13_handler(RegisterDumpWithExceptionCode& regs)
|
void exception_13_handler(RegisterDumpWithExceptionCode& regs)
|
||||||
|
@ -316,7 +346,6 @@ void exception_14_handler(RegisterDumpWithExceptionCode& regs)
|
||||||
hang(); \
|
hang(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
EH(0, "Divide error")
|
|
||||||
EH(1, "Debug exception")
|
EH(1, "Debug exception")
|
||||||
EH(2, "Unknown error")
|
EH(2, "Unknown error")
|
||||||
EH(3, "Breakpoint")
|
EH(3, "Breakpoint")
|
||||||
|
@ -442,7 +471,7 @@ void idt_init()
|
||||||
for (byte i = 0xff; i > 0x10; --i)
|
for (byte i = 0xff; i > 0x10; --i)
|
||||||
register_interrupt_handler(i, unimp_trap);
|
register_interrupt_handler(i, unimp_trap);
|
||||||
|
|
||||||
register_interrupt_handler(0x00, _exception0);
|
register_interrupt_handler(0x00, exception_0_entry);
|
||||||
register_interrupt_handler(0x01, _exception1);
|
register_interrupt_handler(0x01, _exception1);
|
||||||
register_interrupt_handler(0x02, _exception2);
|
register_interrupt_handler(0x02, _exception2);
|
||||||
register_interrupt_handler(0x03, _exception3);
|
register_interrupt_handler(0x03, _exception3);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include <LibGUI/GAction.h>
|
#include <LibGUI/GAction.h>
|
||||||
|
|
||||||
GAction::GAction(const String& text, const String& custom_data, Function<void(const GAction&)> on_activation_callback)
|
GAction::GAction(const String& text, const String& custom_data, Function<void(const GAction&)> on_activation_callback)
|
||||||
: m_text(text)
|
: on_activation(move(on_activation_callback))
|
||||||
, on_activation(move(on_activation_callback))
|
, m_text(text)
|
||||||
, m_custom_data(custom_data)
|
, m_custom_data(custom_data)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,13 @@ GAction::GAction(const String& text, Function<void(const GAction&)> on_activatio
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GAction::GAction(const String& text, RetainPtr<GraphicsBitmap>&& icon, Function<void(const GAction&)> on_activation_callback)
|
||||||
|
: on_activation(move(on_activation_callback))
|
||||||
|
, m_text(text)
|
||||||
|
, m_icon(move(icon))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
GAction::~GAction()
|
GAction::~GAction()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,22 +2,41 @@
|
||||||
|
|
||||||
#include <AK/AKString.h>
|
#include <AK/AKString.h>
|
||||||
#include <AK/Function.h>
|
#include <AK/Function.h>
|
||||||
|
#include <AK/Retainable.h>
|
||||||
|
#include <AK/RetainPtr.h>
|
||||||
|
#include <SharedGraphics/GraphicsBitmap.h>
|
||||||
|
|
||||||
class GAction {
|
class GAction : public Retainable<GAction> {
|
||||||
public:
|
public:
|
||||||
GAction(const String& text, Function<void(const GAction&)> = nullptr);
|
static RetainPtr<GAction> create(const String& text, Function<void(const GAction&)> callback)
|
||||||
GAction(const String& text, const String& custom_data = String(), Function<void(const GAction&)> = nullptr);
|
{
|
||||||
|
return adopt(*new GAction(text, move(callback)));
|
||||||
|
}
|
||||||
|
static RetainPtr<GAction> create(const String& text, const String& custom_data, Function<void(const GAction&)> callback)
|
||||||
|
{
|
||||||
|
return adopt(*new GAction(text, custom_data, move(callback)));
|
||||||
|
}
|
||||||
|
static RetainPtr<GAction> create(const String& text, RetainPtr<GraphicsBitmap>&& icon, Function<void(const GAction&)> callback)
|
||||||
|
{
|
||||||
|
return adopt(*new GAction(text, move(icon), move(callback)));
|
||||||
|
}
|
||||||
~GAction();
|
~GAction();
|
||||||
|
|
||||||
String text() const { return m_text; }
|
String text() const { return m_text; }
|
||||||
String custom_data() const { return m_custom_data; }
|
String custom_data() const { return m_custom_data; }
|
||||||
|
const GraphicsBitmap* icon() const { return m_icon.ptr(); }
|
||||||
|
|
||||||
Function<void(GAction&)> on_activation;
|
Function<void(GAction&)> on_activation;
|
||||||
|
|
||||||
void activate();
|
void activate();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
GAction(const String& text, Function<void(const GAction&)> = nullptr);
|
||||||
|
GAction(const String& text, RetainPtr<GraphicsBitmap>&& icon, Function<void(const GAction&)> = nullptr);
|
||||||
|
GAction(const String& text, const String& custom_data = String(), Function<void(const GAction&)> = nullptr);
|
||||||
|
|
||||||
String m_text;
|
String m_text;
|
||||||
String m_custom_data;
|
String m_custom_data;
|
||||||
|
RetainPtr<GraphicsBitmap> m_icon;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -52,12 +52,14 @@ void GBoxLayout::run(GWidget& widget)
|
||||||
|
|
||||||
Size automatic_size;
|
Size automatic_size;
|
||||||
|
|
||||||
if (m_orientation == Orientation::Horizontal) {
|
if (number_of_entries_with_automatic_size) {
|
||||||
automatic_size.set_width(available_size.width() / number_of_entries_with_automatic_size);
|
if (m_orientation == Orientation::Horizontal) {
|
||||||
automatic_size.set_height(widget.height());
|
automatic_size.set_width(available_size.width() / number_of_entries_with_automatic_size);
|
||||||
} else {
|
automatic_size.set_height(widget.height());
|
||||||
automatic_size.set_width(widget.width());
|
} else {
|
||||||
automatic_size.set_height(available_size.height() / number_of_entries_with_automatic_size);
|
automatic_size.set_width(widget.width());
|
||||||
|
automatic_size.set_height(available_size.height() / number_of_entries_with_automatic_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GBOXLAYOUT_DEBUG
|
#ifdef GBOXLAYOUT_DEBUG
|
||||||
|
|
|
@ -29,7 +29,7 @@ GMenu::~GMenu()
|
||||||
unrealize_menu();
|
unrealize_menu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMenu::add_action(OwnPtr<GAction>&& action)
|
void GMenu::add_action(RetainPtr<GAction>&& action)
|
||||||
{
|
{
|
||||||
m_items.append(make<GMenuItem>(move(action)));
|
m_items.append(make<GMenuItem>(move(action)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ public:
|
||||||
|
|
||||||
GAction* action_at(size_t);
|
GAction* action_at(size_t);
|
||||||
|
|
||||||
void add_action(OwnPtr<GAction>&&);
|
void add_action(RetainPtr<GAction>&&);
|
||||||
void add_separator();
|
void add_separator();
|
||||||
|
|
||||||
Function<void(unsigned)> on_item_activation;
|
Function<void(unsigned)> on_item_activation;
|
||||||
|
|
|
@ -6,7 +6,7 @@ GMenuItem::GMenuItem(Type type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
GMenuItem::GMenuItem(OwnPtr<GAction>&& action)
|
GMenuItem::GMenuItem(RetainPtr<GAction>&& action)
|
||||||
: m_type(Action)
|
: m_type(Action)
|
||||||
, m_action(move(action))
|
, m_action(move(action))
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,7 +9,7 @@ public:
|
||||||
enum Type { Invalid, Action, Separator };
|
enum Type { Invalid, Action, Separator };
|
||||||
|
|
||||||
explicit GMenuItem(Type);
|
explicit GMenuItem(Type);
|
||||||
explicit GMenuItem(OwnPtr<GAction>&&);
|
explicit GMenuItem(RetainPtr<GAction>&&);
|
||||||
~GMenuItem();
|
~GMenuItem();
|
||||||
|
|
||||||
Type type() const { return m_type; }
|
Type type() const { return m_type; }
|
||||||
|
@ -21,6 +21,6 @@ public:
|
||||||
private:
|
private:
|
||||||
Type m_type { Invalid };
|
Type m_type { Invalid };
|
||||||
unsigned m_identifier { 0 };
|
unsigned m_identifier { 0 };
|
||||||
OwnPtr<GAction> m_action;
|
RetainPtr<GAction> m_action;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
58
LibGUI/GToolBar.cpp
Normal file
58
LibGUI/GToolBar.cpp
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
#include <LibGUI/GToolBar.h>
|
||||||
|
#include <LibGUI/GBoxLayout.h>
|
||||||
|
#include <LibGUI/GButton.h>
|
||||||
|
#include <LibGUI/GAction.h>
|
||||||
|
#include <SharedGraphics/Painter.h>
|
||||||
|
|
||||||
|
GToolBar::GToolBar(GWidget* parent)
|
||||||
|
: GWidget(parent)
|
||||||
|
{
|
||||||
|
set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
|
||||||
|
set_preferred_size({ 0, 24 });
|
||||||
|
set_layout(make<GBoxLayout>(Orientation::Horizontal));
|
||||||
|
}
|
||||||
|
|
||||||
|
GToolBar::~GToolBar()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GToolBar::add_action(RetainPtr<GAction>&& action)
|
||||||
|
{
|
||||||
|
ASSERT(action);
|
||||||
|
GAction* raw_action_ptr = action.ptr();
|
||||||
|
auto item = make<Item>();
|
||||||
|
item->type = Item::Action;
|
||||||
|
item->action = move(action);
|
||||||
|
|
||||||
|
auto* button = new GButton(this);
|
||||||
|
if (item->action->icon())
|
||||||
|
button->set_icon(item->action->icon());
|
||||||
|
else
|
||||||
|
button->set_caption(item->action->text());
|
||||||
|
button->on_click = [raw_action_ptr] (const GButton&) {
|
||||||
|
raw_action_ptr->activate();
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// FIXME: Gotta fix GBoxLayout for this to work.
|
||||||
|
button->set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed);
|
||||||
|
button->set_preferred_size({ 16, 16 });
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_items.append(move(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GToolBar::add_separator()
|
||||||
|
{
|
||||||
|
auto item = make<Item>();
|
||||||
|
item->type = Item::Separator;
|
||||||
|
m_items.append(move(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GToolBar::paint_event(GPaintEvent& event)
|
||||||
|
{
|
||||||
|
Painter painter(*this);
|
||||||
|
painter.set_clip_rect(event.rect());
|
||||||
|
painter.fill_rect({ 0, 0, width(), height() - 1 }, Color::LightGray);
|
||||||
|
painter.draw_line({ 0, rect().bottom() }, { width() - 1, rect().bottom() }, Color::DarkGray);
|
||||||
|
}
|
25
LibGUI/GToolBar.h
Normal file
25
LibGUI/GToolBar.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibGUI/GWidget.h>
|
||||||
|
|
||||||
|
class GAction;
|
||||||
|
|
||||||
|
class GToolBar : public GWidget {
|
||||||
|
public:
|
||||||
|
explicit GToolBar(GWidget* parent);
|
||||||
|
virtual ~GToolBar() override;
|
||||||
|
|
||||||
|
void add_action(RetainPtr<GAction>&&);
|
||||||
|
void add_separator();
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual const char* class_name() const override { return "GToolBar"; }
|
||||||
|
virtual void paint_event(GPaintEvent&) override;
|
||||||
|
|
||||||
|
struct Item {
|
||||||
|
enum Type { Invalid, Separator, Action };
|
||||||
|
Type type { Invalid };
|
||||||
|
RetainPtr<GAction> action;
|
||||||
|
};
|
||||||
|
Vector<OwnPtr<Item>> m_items;
|
||||||
|
};
|
|
@ -73,6 +73,13 @@ void GWidget::handle_paint_event(GPaintEvent& event)
|
||||||
if (fill_with_background_color()) {
|
if (fill_with_background_color()) {
|
||||||
Painter painter(*this);
|
Painter painter(*this);
|
||||||
painter.fill_rect(event.rect(), background_color());
|
painter.fill_rect(event.rect(), background_color());
|
||||||
|
} else {
|
||||||
|
#ifdef DEBUG_WIDGET_UNDERDRAW
|
||||||
|
// FIXME: This is a bit broken.
|
||||||
|
// If the widget is not opaque, let's not mess it up with debugging color.
|
||||||
|
Painter painter(*this);
|
||||||
|
painter.fill_rect(rect(), Color::Red);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
paint_event(event);
|
paint_event(event);
|
||||||
for (auto* ch : children()) {
|
for (auto* ch : children()) {
|
||||||
|
|
|
@ -27,6 +27,7 @@ LIBGUI_OBJS = \
|
||||||
GApplication.o \
|
GApplication.o \
|
||||||
GAction.o \
|
GAction.o \
|
||||||
GFontDatabase.o \
|
GFontDatabase.o \
|
||||||
|
GToolBar.o \
|
||||||
GWindow.o
|
GWindow.o
|
||||||
|
|
||||||
OBJS = $(SHAREDGRAPHICS_OBJS) $(LIBGUI_OBJS)
|
OBJS = $(SHAREDGRAPHICS_OBJS) $(LIBGUI_OBJS)
|
||||||
|
|
|
@ -14,8 +14,6 @@
|
||||||
#include <LibC/string.h>
|
#include <LibC/string.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEBUG_WIDGET_UNDERDRAW
|
|
||||||
|
|
||||||
Painter::Painter(GraphicsBitmap& bitmap)
|
Painter::Painter(GraphicsBitmap& bitmap)
|
||||||
{
|
{
|
||||||
m_font = &Font::default_font();
|
m_font = &Font::default_font();
|
||||||
|
@ -42,12 +40,6 @@ Painter::Painter(GWidget& widget)
|
||||||
// NOTE: m_clip_rect is in Window coordinates since we are painting into its backing store.
|
// NOTE: m_clip_rect is in Window coordinates since we are painting into its backing store.
|
||||||
m_clip_rect = widget.window_relative_rect();
|
m_clip_rect = widget.window_relative_rect();
|
||||||
m_clip_rect.intersect(m_target->rect());
|
m_clip_rect.intersect(m_target->rect());
|
||||||
|
|
||||||
#ifdef DEBUG_WIDGET_UNDERDRAW
|
|
||||||
// If the widget is not opaque, let's not mess it up with debugging color.
|
|
||||||
if (widget.fill_with_background_color() && m_window->main_widget() != &widget)
|
|
||||||
fill_rect(widget.rect(), Color::Red);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue