From b704d3d295dd364279546f7b04b89420fda39751 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 20 Feb 2019 02:39:46 +0100 Subject: [PATCH] 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. :^) --- Applications/FileManager/main.cpp | 42 ++++++++++++++-------- Applications/Terminal/main.cpp | 6 ++-- Base/res/icons/copyfile16.data | Bin 0 -> 1024 bytes Base/res/icons/copyfile16.png | Bin 0 -> 1184 bytes Base/res/icons/copyfile16.rgb | Bin 0 -> 1024 bytes Base/res/icons/mkdir16.data | Bin 0 -> 1024 bytes Base/res/icons/mkdir16.png | Bin 0 -> 1785 bytes Base/res/icons/mkdir16.rgb | Bin 0 -> 1024 bytes Base/res/icons/trash16.data | Bin 0 -> 1024 bytes Base/res/icons/trash16.png | Bin 0 -> 452 bytes Base/res/icons/trash16.rgb | Bin 0 -> 1024 bytes Kernel/i386.cpp | 33 +++++++++++++++-- LibGUI/GAction.cpp | 11 ++++-- LibGUI/GAction.h | 25 +++++++++++-- LibGUI/GBoxLayout.cpp | 14 ++++---- LibGUI/GMenu.cpp | 2 +- LibGUI/GMenu.h | 2 +- LibGUI/GMenuItem.cpp | 2 +- LibGUI/GMenuItem.h | 4 +-- LibGUI/GToolBar.cpp | 58 ++++++++++++++++++++++++++++++ LibGUI/GToolBar.h | 25 +++++++++++++ LibGUI/GWidget.cpp | 7 ++++ LibGUI/Makefile | 1 + SharedGraphics/Painter.cpp | 8 ----- 24 files changed, 196 insertions(+), 44 deletions(-) create mode 100644 Base/res/icons/copyfile16.data create mode 100644 Base/res/icons/copyfile16.png create mode 100644 Base/res/icons/copyfile16.rgb create mode 100644 Base/res/icons/mkdir16.data create mode 100644 Base/res/icons/mkdir16.png create mode 100644 Base/res/icons/mkdir16.rgb create mode 100644 Base/res/icons/trash16.data create mode 100644 Base/res/icons/trash16.png create mode 100644 Base/res/icons/trash16.rgb create mode 100644 LibGUI/GToolBar.cpp create mode 100644 LibGUI/GToolBar.h diff --git a/Applications/FileManager/main.cpp b/Applications/FileManager/main.cpp index ea0560c2d66..b922ee6b5cc 100644 --- a/Applications/FileManager/main.cpp +++ b/Applications/FileManager/main.cpp @@ -3,47 +3,52 @@ #include #include #include +#include #include #include #include #include #include "DirectoryView.h" -static GWindow* make_window(); - int main(int argc, char** 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(); auto app_menu = make("FileManager"); - app_menu->add_action(make("Quit", String(), [] (const GAction&) { + app_menu->add_action(GAction::create("Quit", String(), [] (const GAction&) { GApplication::the().quit(0); return; })); menubar->add_menu(move(app_menu)); auto file_menu = make("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)); auto help_menu = make("Help"); - help_menu->add_action(make("About", [] (const GAction&) { + help_menu->add_action(GAction::create("About", [] (const GAction&) { dbgprintf("FIXME: Implement Help/About\n"); })); menubar->add_menu(move(help_menu)); 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; window->set_title("FileManager"); window->set_rect(20, 200, 240, 300); @@ -53,6 +58,11 @@ GWindow* make_window() widget->set_layout(make(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* statusbar = new GStatusBar(widget); @@ -68,6 +78,8 @@ GWindow* make_window() directory_view->open("/"); - return window; -} + window->set_should_exit_app_on_close(true); + window->show(); + return app.exec(); +} diff --git a/Applications/Terminal/main.cpp b/Applications/Terminal/main.cpp index e27d2c0f35e..a63970a7eed 100644 --- a/Applications/Terminal/main.cpp +++ b/Applications/Terminal/main.cpp @@ -97,7 +97,7 @@ int main(int argc, char** argv) auto menubar = make(); auto app_menu = make("Terminal"); - app_menu->add_action(make("Quit", String(), [] (const GAction&) { + app_menu->add_action(GAction::create("Quit", String(), [] (const GAction&) { dbgprintf("Terminal: Quit menu activated!\n"); GApplication::the().quit(0); return; @@ -106,7 +106,7 @@ int main(int argc, char** argv) auto font_menu = make("Font"); GFontDatabase::the().for_each_font([&] (const String& font_name) { - font_menu->add_action(make(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.force_repaint(); })); @@ -114,7 +114,7 @@ int main(int argc, char** argv) menubar->add_menu(move(font_menu)); auto help_menu = make("Help"); - help_menu->add_action(make("About", [] (const GAction&) { + help_menu->add_action(GAction::create("About", [] (const GAction&) { dbgprintf("FIXME: Implement Help/About\n"); })); menubar->add_menu(move(help_menu)); diff --git a/Base/res/icons/copyfile16.data b/Base/res/icons/copyfile16.data new file mode 100644 index 0000000000000000000000000000000000000000..3d772ced7ca8c49c334ea3a5e89e6a3a955b48ea GIT binary patch literal 1024 zcmZR;0{r~^{$s;flwuVE>HUueKw=<_RRaS914s@TgS1baIPpISgV-Rs-Me>#-G$8z zkUU5o2qUvWd=LhSf%Jngh>dOrNDQP7WFImc#0QCk#LzLa86Y{3IuJ%?gZS7mNDVgq zAp1aaAUz;9HVl#jsllcnCI_PNVO;t__JQO;dO>V#7$gT$Gu-V5`4bl=yu4H{?x%<{_mr~~)iq(Fix^~$_ zH|6X547nY4@cHIm-)>&DYW7RcHBAfN8nNpb_wXY|OD?>n4NH4S}T%!b^@GGoJT5X5*$=gDysOq<`O$l) zJj-T zAhTm|M9x#|-RwKp-#IbM`%X%~jA==Ivy5p;^Bwi=yjk9_@A}n=&3u8IakYd_htFYlQaLk5Lv7qx$4>3-&+>mwmXrz|J8}VLAKIe7dtC{ zt9~q)t{Lx@8Lx9ochljypS9Fvuif_C_~NzS9tE+b_k(^3boZ4%vE2Bg`Eh?zpk--} z?01oW21{p)eMyy%6YBoNMYZH1<)mCY7EHP`$6?Vmj__Vu5h`sJ{8 z_3lG2^XK&Gs>R-(f4#nUPDTEX#qr8N3|s#%eOYfe`_1g7AKx5jU|?WN@^*J&_|Ncz zp{d(#&vXU`2F?PH$YKTtJ!KGPtXOJa#=yY9UgGKN%Kn&1gh85XLrl>E1_p+DPZ!4! zi_>o>ZR9o}xypI)i%vg`IvQFgXTyS~O{+um>til2C8 z?a_C7rb}5IdITE;m>lGN?^pzQF&?P4=j~hLeJ6BP>V)EX=jK>RzTalG!Rn@2#74j0 yJaH0#-tm+bOpD8Y`=|G|&Bc8t6?3@$Fy1?&nw__b(~W_Ffx*+&&t;ucLK6VXnlhdM literal 0 HcmV?d00001 diff --git a/Base/res/icons/copyfile16.rgb b/Base/res/icons/copyfile16.rgb new file mode 100644 index 0000000000000000000000000000000000000000..3d772ced7ca8c49c334ea3a5e89e6a3a955b48ea GIT binary patch literal 1024 zcmZR;0{r~^{$s;flwuVE>HUueKw=<_RRaS914s@TgS1baIPpISgV-Rs-Me>#-G$8z zkUU5o2qUvWd=LhSf%Jngh>dOrNDQP7WFImc#0QCk#LzLa86Y{3IuJ%?gZS7mNDVgq zAp1aaAUz;9HVl#jsllcnCI_PNVO;t__JQO;dO>V#7$gT$Gu-V5`4bl=A$h6 z_Wzp$Q*h#cKRW({^n+-S`u=oVxDg;eNdN7%_5bg$Yx@6iWAp#Vo7?{X|K0@F1JZ{B zgTn))|LU^J|2J3G{J*oN{{OvojsG8QYWe?UOY8rq+dBR~-_i9SWG~1J5Diifx1522 z0mQ$&xa|M+<(2<$t*rTfcWuM}`|BJ3KiJs(|Iy~Q|Np*s{C~N#6YLg{+J8Sf!1lt- z0Et~#Sn~h!;`0ADmRJ41xw7{E-L-Z9@2zk8|7c^&|0kPU|3BLb@jpl{OdpH}iJhBY z_#bS>(h9IUKz_Lk3Xcs9V81-x+zJj4kXo2N7!49TH7oD`*?EQkFD@+oe|ZVSFCcf^ zUS0qH!TQGk4>z@d;|8P_rVmDg#EwnR`hRLp-v6_63;$nORQ&()((?b;mRJ41wF(g) zp!fx;h3SLQAh9D;)Bhivk^TSFOprT@{$E^F`v3CMivKrORD#X8y`~ zdk$A?5$!De3=@P0s}T cN`ey06$*;-(=u~X z6-p`#QWa7wGSe6sDsHU}kDT_{jOWjD%_0`22URlb-alottm~Scv-CpT$q zhzM1%UG?{Kd3gQ9!%upQuCa^Hz5HWFhLU-+ytrvUBxoMrD0R3!hJyfe%=k|uxO?TKyqt5^3|8?$&6N%Ek*D4yD!ef1=50Uy z`23>x&qWJabv8O|%`K@1@mg=i3Y0)bf7Ck&Br(2vjbECpM<>{IYlH#S` zCM?(Dys+58)NzKsj>+@h;(bnx#^HxN)KrxBe0&=8zG;7PY-g4HHPuTGA93xdsE{&f zD|#%wSb^i~*_Ctuob$H*>1NNV9dN;K7PHulk~qyxOWU`nywZ_K-x^pomF?#);RdBM zxr}WrTp8|3CntV8GmpcD?ZxDVIY$fHm{N4ZgJf@YSab+ioarsMIlD2ZvUTHD2M%pN znEVLJCSXh~{j9K!q^Uj4c`+62_;JJE&uTYEk=z;~A zN48yFde?bp|1Qn!x+T)}%jZa4`pfzB%7i@a@1fhxS6wyn7n#Y_t0glh>*b9b1`Aq` zDE1n^+#db)o8$SLXY=?yH@!Q!q;&S$mQQALtEL~@dhub5%(V6C^44FUht*m;yoxKl zzO+)adfvNIZiO1s6Q>QyK!+r6TKTQF574=&7ott72{q{}6*R4`HGA|Quwn+udnDTr6GP|_U z+iTZ%d0)+LvN-o-XAIk`y&|iOjp~cn^}Sj8ax;^xU;C=rwzqjiH?J^WZY30WS^L@N zA2+W>T-lc@Z+LqWclKCY1Z=n2nNY3sHsb0u zw(4ij9Cf`mp0O&KIkvwSPL-I)6|YjKp=P@C>{G=*YAbUVOP=K}IcWC(6~l3U#Z9~P zx7oho=c*6=%wO_q_pIrAxJ+MiKW%*(WVz$?yjLIB+>;4-quJPQ>14JdHY)>c4IIH@JXbAJL#^;V=-H&+>Q>-_uwrSA4mp9QY`s&>5Io}(V z|1-@0_2$5hb8eNLKLUy;FX`_;B%QZkr|ET!S%&YwQ{v7N4KDT7sE4d&1Z*N-# z+&}aq@i)8h!~Y4QVuAme%5U;XNzXse&cMLHmgMd3!tkHr2SZc0+n(tR3=EtF9+AZi z40_5S%viD1zKnr^fxX1j*OmP-lL&)|&eM~xCowQEMtizAhFF|lJ9&TBl|X^k{l>+D zuNCqhH{W1kzO{mX(mB<+TYFRQ81YZ?oyhGqfNYkTp^4(|iOV6ftJ~+@?z5K_s zGjpsz@L#mQcjW#~!&tw5{@;2NEUV1{ z`wk7I)-5q-}eYdg(?kDOv)U|{fc^>bP0 Hl+XkKr?_0a literal 0 HcmV?d00001 diff --git a/Base/res/icons/mkdir16.rgb b/Base/res/icons/mkdir16.rgb new file mode 100644 index 0000000000000000000000000000000000000000..4e0073f4d521e7667cd7a82e22dbe94b80f2f3a3 GIT binary patch literal 1024 zcmZP|0W|&i{|A?H+w}hbgmBZ3|6n!fW`OkBWlZ?59Z-rDw}1Z&7KiBv@sZ5{>91XN z+y9%^-T&Xb@!|ir&5!>#eg6;E1JZ{B zgTn))zjE2t|1~Rb{;ywi=YQk6d;eQDJ^J6e<;nk!ZBPGq?RfqlWG~1J5Diifx1522 z0mLs`eEEOn^6UR=R^IyGu=ei%#`Pd~Jow+X`O*K5@BjXH?tBS$3rKCpkAGl$VP=5D zN)}%DU%vSA|ElFT{@1R&`M+-M-TzJN@BMGt_~?J@<|qFIeA) MwkKBI+zBrQ&Us_$Hm3{4-O9g@8sn4AD8~~=g;ErVvgH57i4*@978d@GiHX5#KTJPJA4tE(RKx!u zOpbnyDGRm|3UVH zFi1Zr96)X&6n-H6APiCu(hIU5#0Ozw^n>CLqz;5Z;Q-PP@;^vFzW4*BCr}y!=?Ccn lxgSJ>+yHVvEc~&>JxDJIW77{ZgIN6_GeG9!!yq-(!~k3ijQ{`u literal 0 HcmV?d00001 diff --git a/Base/res/icons/trash16.png b/Base/res/icons/trash16.png new file mode 100644 index 0000000000000000000000000000000000000000..531df5934819fd1f5c5a3d4661aec754fd148fdd GIT binary patch literal 452 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^J65VDI&ZWef}q zoCO|{#S9F3${@^GvD6+U$X?><>&pI^NraJyBTD$ME&~H&pr?yth{fr(lMMY21&Fln zzf@L`GU@Iv;rfQf`x_h8j(N_NFlcG)J>n{)o-ARdQQu~=%W~2cUuTZMptu*WA6uHN zRR}PsTK@gs-tTj&&s%>uZXl-L>*oCZcdh7g!_PlumWnVG$_Tp(I&pLzRoeGHI@4d# zwqoA$@C&@jx~pIBid_5EI8tx=S&gm$uf$nu3_)ILnzEt^8`;u-frb zL3IJ|fuH|wx-n$mecXH5&8ss}qQu_X=l-&mmXfpVeirBEAK0p2X;*V{i^tcD`jUV% z<wkKBI+zBrQ&Us_$Hm3{4-O9g@8sn4AD8~~=g;ErVvgH57i4*@978d@GiHX5#KTJPJA4tF9RE_^2 zOpboTDGRm|3UVH zFi1Zr96)X&6n-H6APiCu(hIU5#0Ozw^n>CLqz;5Z;Q-PP@;^vFzW4*BCr}y!=?Ccn lxgSJ>+yHVvEc~&>JxDJIW77{ZgIN6_GeG9!!yq-(!~k9ujQ{`u literal 0 HcmV?d00001 diff --git a/Kernel/i386.cpp b/Kernel/i386.cpp index ccf27c9f331..9cb38f1921e 100644 --- a/Kernel/i386.cpp +++ b/Kernel/i386.cpp @@ -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 EH_ENTRY(13); void exception_13_handler(RegisterDumpWithExceptionCode& regs) @@ -316,7 +346,6 @@ void exception_14_handler(RegisterDumpWithExceptionCode& regs) hang(); \ } -EH(0, "Divide error") EH(1, "Debug exception") EH(2, "Unknown error") EH(3, "Breakpoint") @@ -442,7 +471,7 @@ void idt_init() for (byte i = 0xff; i > 0x10; --i) 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(0x02, _exception2); register_interrupt_handler(0x03, _exception3); diff --git a/LibGUI/GAction.cpp b/LibGUI/GAction.cpp index 1d04ea1bcb3..aa6e52c5dfc 100644 --- a/LibGUI/GAction.cpp +++ b/LibGUI/GAction.cpp @@ -1,8 +1,8 @@ #include GAction::GAction(const String& text, const String& custom_data, Function 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) { } @@ -12,6 +12,13 @@ GAction::GAction(const String& text, Function on_activatio { } +GAction::GAction(const String& text, RetainPtr&& icon, Function on_activation_callback) + : on_activation(move(on_activation_callback)) + , m_text(text) + , m_icon(move(icon)) +{ +} + GAction::~GAction() { } diff --git a/LibGUI/GAction.h b/LibGUI/GAction.h index 6e2bea04042..64797fedf7b 100644 --- a/LibGUI/GAction.h +++ b/LibGUI/GAction.h @@ -2,22 +2,41 @@ #include #include +#include +#include +#include -class GAction { +class GAction : public Retainable { public: - GAction(const String& text, Function = nullptr); - GAction(const String& text, const String& custom_data = String(), Function = nullptr); + static RetainPtr create(const String& text, Function callback) + { + return adopt(*new GAction(text, move(callback))); + } + static RetainPtr create(const String& text, const String& custom_data, Function callback) + { + return adopt(*new GAction(text, custom_data, move(callback))); + } + static RetainPtr create(const String& text, RetainPtr&& icon, Function callback) + { + return adopt(*new GAction(text, move(icon), move(callback))); + } ~GAction(); String text() const { return m_text; } String custom_data() const { return m_custom_data; } + const GraphicsBitmap* icon() const { return m_icon.ptr(); } Function on_activation; void activate(); private: + GAction(const String& text, Function = nullptr); + GAction(const String& text, RetainPtr&& icon, Function = nullptr); + GAction(const String& text, const String& custom_data = String(), Function = nullptr); + String m_text; String m_custom_data; + RetainPtr m_icon; }; diff --git a/LibGUI/GBoxLayout.cpp b/LibGUI/GBoxLayout.cpp index 273617daeec..84ac0abc0b2 100644 --- a/LibGUI/GBoxLayout.cpp +++ b/LibGUI/GBoxLayout.cpp @@ -52,12 +52,14 @@ void GBoxLayout::run(GWidget& widget) Size automatic_size; - if (m_orientation == Orientation::Horizontal) { - automatic_size.set_width(available_size.width() / number_of_entries_with_automatic_size); - automatic_size.set_height(widget.height()); - } else { - automatic_size.set_width(widget.width()); - automatic_size.set_height(available_size.height() / number_of_entries_with_automatic_size); + if (number_of_entries_with_automatic_size) { + if (m_orientation == Orientation::Horizontal) { + automatic_size.set_width(available_size.width() / number_of_entries_with_automatic_size); + automatic_size.set_height(widget.height()); + } else { + automatic_size.set_width(widget.width()); + automatic_size.set_height(available_size.height() / number_of_entries_with_automatic_size); + } } #ifdef GBOXLAYOUT_DEBUG diff --git a/LibGUI/GMenu.cpp b/LibGUI/GMenu.cpp index 105b9a93bad..0a859d5978f 100644 --- a/LibGUI/GMenu.cpp +++ b/LibGUI/GMenu.cpp @@ -29,7 +29,7 @@ GMenu::~GMenu() unrealize_menu(); } -void GMenu::add_action(OwnPtr&& action) +void GMenu::add_action(RetainPtr&& action) { m_items.append(make(move(action))); } diff --git a/LibGUI/GMenu.h b/LibGUI/GMenu.h index 5d56ac0994d..6a93f03f0b5 100644 --- a/LibGUI/GMenu.h +++ b/LibGUI/GMenu.h @@ -15,7 +15,7 @@ public: GAction* action_at(size_t); - void add_action(OwnPtr&&); + void add_action(RetainPtr&&); void add_separator(); Function on_item_activation; diff --git a/LibGUI/GMenuItem.cpp b/LibGUI/GMenuItem.cpp index 42900548ae7..ba877a927b9 100644 --- a/LibGUI/GMenuItem.cpp +++ b/LibGUI/GMenuItem.cpp @@ -6,7 +6,7 @@ GMenuItem::GMenuItem(Type type) { } -GMenuItem::GMenuItem(OwnPtr&& action) +GMenuItem::GMenuItem(RetainPtr&& action) : m_type(Action) , m_action(move(action)) { diff --git a/LibGUI/GMenuItem.h b/LibGUI/GMenuItem.h index 383c1b00fef..a26dea394c0 100644 --- a/LibGUI/GMenuItem.h +++ b/LibGUI/GMenuItem.h @@ -9,7 +9,7 @@ public: enum Type { Invalid, Action, Separator }; explicit GMenuItem(Type); - explicit GMenuItem(OwnPtr&&); + explicit GMenuItem(RetainPtr&&); ~GMenuItem(); Type type() const { return m_type; } @@ -21,6 +21,6 @@ public: private: Type m_type { Invalid }; unsigned m_identifier { 0 }; - OwnPtr m_action; + RetainPtr m_action; }; diff --git a/LibGUI/GToolBar.cpp b/LibGUI/GToolBar.cpp new file mode 100644 index 00000000000..81593a758c1 --- /dev/null +++ b/LibGUI/GToolBar.cpp @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include + +GToolBar::GToolBar(GWidget* parent) + : GWidget(parent) +{ + set_size_policy(SizePolicy::Fill, SizePolicy::Fixed); + set_preferred_size({ 0, 24 }); + set_layout(make(Orientation::Horizontal)); +} + +GToolBar::~GToolBar() +{ +} + +void GToolBar::add_action(RetainPtr&& action) +{ + ASSERT(action); + GAction* raw_action_ptr = action.ptr(); + auto item = make(); + 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->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); +} diff --git a/LibGUI/GToolBar.h b/LibGUI/GToolBar.h new file mode 100644 index 00000000000..3338c3d55af --- /dev/null +++ b/LibGUI/GToolBar.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class GAction; + +class GToolBar : public GWidget { +public: + explicit GToolBar(GWidget* parent); + virtual ~GToolBar() override; + + void add_action(RetainPtr&&); + 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 action; + }; + Vector> m_items; +}; diff --git a/LibGUI/GWidget.cpp b/LibGUI/GWidget.cpp index 3bf6cc89349..b17eb9aa482 100644 --- a/LibGUI/GWidget.cpp +++ b/LibGUI/GWidget.cpp @@ -73,6 +73,13 @@ void GWidget::handle_paint_event(GPaintEvent& event) if (fill_with_background_color()) { Painter painter(*this); 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); for (auto* ch : children()) { diff --git a/LibGUI/Makefile b/LibGUI/Makefile index cc1c2d779e0..ec8abacc1bf 100644 --- a/LibGUI/Makefile +++ b/LibGUI/Makefile @@ -27,6 +27,7 @@ LIBGUI_OBJS = \ GApplication.o \ GAction.o \ GFontDatabase.o \ + GToolBar.o \ GWindow.o OBJS = $(SHAREDGRAPHICS_OBJS) $(LIBGUI_OBJS) diff --git a/SharedGraphics/Painter.cpp b/SharedGraphics/Painter.cpp index b9f55a2af36..21ee3af8720 100644 --- a/SharedGraphics/Painter.cpp +++ b/SharedGraphics/Painter.cpp @@ -14,8 +14,6 @@ #include #endif -#define DEBUG_WIDGET_UNDERDRAW - Painter::Painter(GraphicsBitmap& bitmap) { 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. m_clip_rect = widget.window_relative_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