2020-01-18 09:38:21 +01:00
/*
* Copyright ( c ) 2018 - 2020 , Andreas Kling < kling @ serenityos . org >
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-01-18 09:38:21 +01:00
*/
2021-01-10 16:29:28 -07:00
# include <AK/WeakPtr.h>
2021-01-04 23:31:08 +01:00
# include <LibGUI/AboutDialog.h>
2020-02-06 20:33:02 +01:00
# include <LibGUI/Action.h>
# include <LibGUI/ActionGroup.h>
# include <LibGUI/Application.h>
# include <LibGUI/Button.h>
2021-01-04 23:31:08 +01:00
# include <LibGUI/Icon.h>
2020-02-06 20:33:02 +01:00
# include <LibGUI/MenuItem.h>
2020-07-23 19:52:18 +02:00
# include <LibGUI/Window.h>
2019-02-12 14:09:48 +01:00
2020-02-02 15:07:41 +01:00
namespace GUI {
2019-09-14 22:10:44 +02:00
2020-02-02 15:07:41 +01:00
namespace CommonActions {
2021-01-04 23:31:08 +01:00
NonnullRefPtr < Action > make_about_action ( const String & app_name , const Icon & app_icon , Window * parent )
{
2021-01-10 16:29:28 -07:00
auto weak_parent = AK : : try_make_weak_ptr < Window > ( parent ) ;
2021-04-18 00:42:33 +02:00
auto action = Action : : create ( String : : formatted ( " &About {} " , app_name ) , app_icon . bitmap_for_size ( 16 ) , [ = ] ( auto & ) {
2021-01-04 23:31:08 +01:00
AboutDialog : : show ( app_name , app_icon . bitmap_for_size ( 32 ) , weak_parent . ptr ( ) ) ;
} ) ;
2021-04-18 00:42:33 +02:00
action - > set_status_tip ( " Show application about box " ) ;
return action ;
2021-01-04 23:31:08 +01:00
}
2020-04-21 17:19:27 +02:00
NonnullRefPtr < Action > make_open_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-17 18:18:59 +02:00
auto action = Action : : create ( " &Open... " , { Mod_Ctrl , Key_O } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/open.png " ) , move ( callback ) , parent ) ;
2021-04-18 00:17:04 +02:00
action - > set_status_tip ( " Open an existing file " ) ;
2021-04-17 18:18:59 +02:00
return action ;
2020-04-21 17:19:27 +02:00
}
2019-09-20 19:36:39 +02:00
2020-05-27 16:53:57 +03:00
NonnullRefPtr < Action > make_save_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-17 18:18:59 +02:00
auto action = Action : : create ( " &Save " , { Mod_Ctrl , Key_S } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/save.png " ) , move ( callback ) , parent ) ;
2021-04-18 00:17:04 +02:00
action - > set_status_tip ( " Save the current file " ) ;
2021-04-17 18:18:59 +02:00
return action ;
2020-05-27 16:53:57 +03:00
}
2020-08-25 01:06:11 +04:30
NonnullRefPtr < Action > make_save_as_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-17 18:18:59 +02:00
auto action = Action : : create ( " Save &As... " , { Mod_Ctrl | Mod_Shift , Key_S } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/save.png " ) , move ( callback ) , parent ) ;
2021-04-18 00:17:04 +02:00
action - > set_status_tip ( " Save the current file with a new name " ) ;
2021-04-17 18:18:59 +02:00
return action ;
2020-08-25 01:06:11 +04:30
}
2020-04-21 17:19:27 +02:00
NonnullRefPtr < Action > make_move_to_front_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-18 00:42:33 +02:00
auto action = Action : : create ( " Move to &Front " , { Mod_Ctrl | Mod_Shift , Key_Up } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/move-to-front.png " ) , move ( callback ) , parent ) ;
action - > set_status_tip ( " Move to the top of the stack " ) ;
return action ;
2020-04-21 17:19:27 +02:00
}
2019-09-14 22:42:02 +02:00
2020-04-21 17:19:27 +02:00
NonnullRefPtr < Action > make_move_to_back_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-18 00:42:33 +02:00
auto action = Action : : create ( " Move to &Back " , { Mod_Ctrl | Mod_Shift , Key_Down } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/move-to-back.png " ) , move ( callback ) , parent ) ;
action - > set_status_tip ( " Move to the bottom of the stack " ) ;
return action ;
2020-04-21 17:19:27 +02:00
}
2019-09-14 22:42:02 +02:00
2020-04-21 17:19:27 +02:00
NonnullRefPtr < Action > make_undo_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-09 15:53:59 +02:00
return Action : : create ( " &Undo " , { Mod_Ctrl , Key_Z } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/undo.png " ) , move ( callback ) , parent ) ;
2020-04-21 17:19:27 +02:00
}
2019-09-14 22:23:49 +02:00
2020-04-21 17:19:27 +02:00
NonnullRefPtr < Action > make_redo_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-09 15:53:59 +02:00
return Action : : create ( " &Redo " , { Mod_Ctrl , Key_Y } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/redo.png " ) , move ( callback ) , parent ) ;
2020-04-21 17:19:27 +02:00
}
2019-09-14 22:23:49 +02:00
2020-04-21 17:19:27 +02:00
NonnullRefPtr < Action > make_delete_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-09 15:53:59 +02:00
return Action : : create ( " &Delete " , { Mod_None , Key_Delete } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/delete.png " ) , move ( callback ) , parent ) ;
2020-04-21 17:19:27 +02:00
}
2019-09-14 22:10:44 +02:00
2020-04-21 17:19:27 +02:00
NonnullRefPtr < Action > make_cut_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-18 00:42:33 +02:00
auto action = Action : : create ( " Cu&t " , { Mod_Ctrl , Key_X } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/edit-cut.png " ) , move ( callback ) , parent ) ;
action - > set_status_tip ( " Cut to clipboard " ) ;
return action ;
2020-04-21 17:19:27 +02:00
}
2019-09-01 15:28:07 -05:00
2020-04-21 17:19:27 +02:00
NonnullRefPtr < Action > make_copy_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-18 00:42:33 +02:00
auto action = Action : : create ( " &Copy " , { Mod_Ctrl , Key_C } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/edit-copy.png " ) , move ( callback ) , parent ) ;
action - > set_status_tip ( " Copy to clipboard " ) ;
return action ;
2020-04-21 17:19:27 +02:00
}
2019-09-01 15:28:07 -05:00
2020-04-21 17:19:27 +02:00
NonnullRefPtr < Action > make_paste_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-18 00:42:33 +02:00
auto action = Action : : create ( " &Paste " , { Mod_Ctrl , Key_V } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/paste.png " ) , move ( callback ) , parent ) ;
action - > set_status_tip ( " Paste from clipboard " ) ;
return action ;
2020-04-21 17:19:27 +02:00
}
2019-09-01 15:28:07 -05:00
2020-04-21 17:19:27 +02:00
NonnullRefPtr < Action > make_fullscreen_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-18 00:42:33 +02:00
auto action = Action : : create ( " &Fullscreen " , { Mod_None , Key_F11 } , move ( callback ) , parent ) ;
action - > set_status_tip ( " Enter fullscreen mode " ) ;
return action ;
2020-04-21 17:19:27 +02:00
}
2019-09-16 18:42:38 +02:00
2020-04-21 17:19:27 +02:00
NonnullRefPtr < Action > make_quit_action ( Function < void ( Action & ) > callback )
{
2021-04-18 00:42:33 +02:00
auto action = Action : : create ( " &Quit " , { Mod_Alt , Key_F4 } , move ( callback ) ) ;
action - > set_status_tip ( " Quit the application " ) ;
return action ;
2020-04-21 17:19:27 +02:00
}
2019-09-14 22:10:44 +02:00
2021-01-02 08:10:48 +00:00
NonnullRefPtr < Action > make_help_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-18 00:42:33 +02:00
auto action = Action : : create ( " &Contents " , { Mod_None , Key_F1 } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/app-help.png " ) , move ( callback ) , parent ) ;
action - > set_status_tip ( " Show help contents " ) ;
return action ;
2021-01-02 08:10:48 +00:00
}
2020-04-21 17:19:27 +02:00
NonnullRefPtr < Action > make_go_back_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-18 00:42:33 +02:00
auto action = Action : : create ( " Go &Back " , { Mod_Alt , Key_Left } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/go-back.png " ) , move ( callback ) , parent ) ;
action - > set_status_tip ( " Move one step backward in history " ) ;
return action ;
2020-04-21 17:19:27 +02:00
}
2019-10-05 09:21:55 +02:00
2020-04-21 17:19:27 +02:00
NonnullRefPtr < Action > make_go_forward_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-18 00:42:33 +02:00
auto action = Action : : create ( " Go &Forward " , { Mod_Alt , Key_Right } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/go-forward.png " ) , move ( callback ) , parent ) ;
action - > set_status_tip ( " Move one step forward in history " ) ;
return action ;
2020-04-21 17:19:27 +02:00
}
2019-10-05 09:21:55 +02:00
2020-04-21 17:19:27 +02:00
NonnullRefPtr < Action > make_go_home_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-09 15:53:59 +02:00
return Action : : create ( " Go &Home " , { Mod_Alt , Key_Home } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/go-home.png " ) , move ( callback ) , parent ) ;
2020-04-21 17:19:27 +02:00
}
2019-10-06 21:59:46 +02:00
2020-04-21 17:19:27 +02:00
NonnullRefPtr < Action > make_reload_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-09 15:53:59 +02:00
return Action : : create ( " &Reload " , { Mod_Ctrl , Key_R } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/reload.png " ) , move ( callback ) , parent ) ;
2020-04-21 17:19:27 +02:00
}
2019-10-05 10:14:09 +02:00
2020-07-03 20:54:38 +02:00
NonnullRefPtr < Action > make_select_all_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-09 15:53:59 +02:00
return Action : : create ( " Select &All " , { Mod_Ctrl , Key_A } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/select-all.png " ) , move ( callback ) , parent ) ;
2020-07-03 20:54:38 +02:00
}
2021-04-04 22:39:41 +02:00
NonnullRefPtr < Action > make_properties_action ( Function < void ( Action & ) > callback , Core : : Object * parent )
{
2021-04-09 15:53:59 +02:00
return Action : : create ( " &Properties " , { Mod_Alt , Key_Return } , Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/properties.png " ) , move ( callback ) , parent ) ;
2021-04-04 22:39:41 +02:00
}
2019-09-01 15:28:07 -05:00
}
2021-02-20 12:45:55 +01:00
NonnullRefPtr < Action > Action : : create ( String text , Function < void ( Action & ) > callback , Core : : Object * parent )
{
return adopt ( * new Action ( move ( text ) , move ( callback ) , parent ) ) ;
}
NonnullRefPtr < Action > Action : : create ( String text , RefPtr < Gfx : : Bitmap > icon , Function < void ( Action & ) > callback , Core : : Object * parent )
{
return adopt ( * new Action ( move ( text ) , move ( icon ) , move ( callback ) , parent ) ) ;
}
NonnullRefPtr < Action > Action : : create ( String text , const Shortcut & shortcut , Function < void ( Action & ) > callback , Core : : Object * parent )
{
return adopt ( * new Action ( move ( text ) , shortcut , move ( callback ) , parent ) ) ;
}
NonnullRefPtr < Action > Action : : create ( String text , const Shortcut & shortcut , RefPtr < Gfx : : Bitmap > icon , Function < void ( Action & ) > callback , Core : : Object * parent )
{
return adopt ( * new Action ( move ( text ) , shortcut , move ( icon ) , move ( callback ) , parent ) ) ;
}
NonnullRefPtr < Action > Action : : create_checkable ( String text , Function < void ( Action & ) > callback , Core : : Object * parent )
{
return adopt ( * new Action ( move ( text ) , move ( callback ) , parent , true ) ) ;
}
NonnullRefPtr < Action > Action : : create_checkable ( String text , RefPtr < Gfx : : Bitmap > icon , Function < void ( Action & ) > callback , Core : : Object * parent )
{
return adopt ( * new Action ( move ( text ) , move ( icon ) , move ( callback ) , parent , true ) ) ;
}
NonnullRefPtr < Action > Action : : create_checkable ( String text , const Shortcut & shortcut , Function < void ( Action & ) > callback , Core : : Object * parent )
{
return adopt ( * new Action ( move ( text ) , shortcut , move ( callback ) , parent , true ) ) ;
}
NonnullRefPtr < Action > Action : : create_checkable ( String text , const Shortcut & shortcut , RefPtr < Gfx : : Bitmap > icon , Function < void ( Action & ) > callback , Core : : Object * parent )
{
return adopt ( * new Action ( move ( text ) , shortcut , move ( icon ) , move ( callback ) , parent , true ) ) ;
}
Action : : Action ( String text , Function < void ( Action & ) > on_activation_callback , Core : : Object * parent , bool checkable )
2021-02-20 13:02:14 +01:00
: Action ( move ( text ) , Shortcut { } , nullptr , move ( on_activation_callback ) , parent , checkable )
2019-02-12 14:09:48 +01:00
{
}
2021-02-20 12:45:55 +01:00
Action : : Action ( String text , RefPtr < Gfx : : Bitmap > icon , Function < void ( Action & ) > on_activation_callback , Core : : Object * parent , bool checkable )
2021-02-20 13:02:14 +01:00
: Action ( move ( text ) , Shortcut { } , move ( icon ) , move ( on_activation_callback ) , parent , checkable )
2019-02-20 02:39:46 +01:00
{
}
2021-02-20 12:45:55 +01:00
Action : : Action ( String text , const Shortcut & shortcut , Function < void ( Action & ) > on_activation_callback , Core : : Object * parent , bool checkable )
: Action ( move ( text ) , shortcut , nullptr , move ( on_activation_callback ) , parent , checkable )
2019-03-03 02:52:22 +01:00
{
}
2021-02-20 12:45:55 +01:00
Action : : Action ( String text , const Shortcut & shortcut , RefPtr < Gfx : : Bitmap > icon , Function < void ( Action & ) > on_activation_callback , Core : : Object * parent , bool checkable )
2020-02-02 12:34:39 +01:00
: Core : : Object ( parent )
2020-02-02 01:57:57 +01:00
, on_activation ( move ( on_activation_callback ) )
2021-02-20 12:45:55 +01:00
, m_text ( move ( text ) )
2019-03-02 10:04:49 +01:00
, m_icon ( move ( icon ) )
, m_shortcut ( shortcut )
2020-04-21 17:19:27 +02:00
, m_checkable ( checkable )
2019-03-02 10:04:49 +01:00
{
2020-07-26 17:16:35 +02:00
if ( parent & & is < Widget > ( * parent ) ) {
2019-04-20 21:56:56 +02:00
m_scope = ShortcutScope : : WidgetLocal ;
2020-07-26 17:16:35 +02:00
} else if ( parent & & is < Window > ( * parent ) ) {
2020-02-02 01:57:57 +01:00
m_scope = ShortcutScope : : WindowLocal ;
2019-04-20 21:56:56 +02:00
} else {
m_scope = ShortcutScope : : ApplicationGlobal ;
2020-07-23 19:52:18 +02:00
if ( auto * app = Application : : the ( ) ) {
2020-07-04 16:52:01 +02:00
app - > register_global_shortcut_action ( { } , * this ) ;
2020-07-23 19:52:18 +02:00
}
2019-04-20 21:56:56 +02:00
}
2019-03-02 10:04:49 +01:00
}
2020-02-02 15:07:41 +01:00
Action : : ~ Action ( )
2019-02-12 14:09:48 +01:00
{
2020-07-04 16:52:01 +02:00
if ( m_shortcut . is_valid ( ) & & m_scope = = ShortcutScope : : ApplicationGlobal ) {
if ( auto * app = Application : : the ( ) )
app - > unregister_global_shortcut_action ( { } , * this ) ;
}
2019-02-12 14:09:48 +01:00
}
2020-02-02 15:07:41 +01:00
void Action : : activate ( Core : : Object * activator )
2019-02-12 14:09:48 +01:00
{
2020-04-21 17:19:27 +02:00
if ( ! on_activation )
return ;
2019-12-09 21:25:48 +01:00
if ( activator )
m_activator = activator - > make_weak_ptr ( ) ;
2020-04-21 17:19:27 +02:00
if ( is_checkable ( ) ) {
if ( m_action_group ) {
if ( m_action_group - > is_unchecking_allowed ( ) )
set_checked ( ! is_checked ( ) ) ;
else
set_checked ( true ) ;
} else {
set_checked ( ! is_checked ( ) ) ;
}
}
on_activation ( * this ) ;
2019-12-09 21:25:48 +01:00
m_activator = nullptr ;
2019-02-12 14:09:48 +01:00
}
2019-04-12 02:53:27 +02:00
2020-02-02 15:07:41 +01:00
void Action : : register_button ( Badge < Button > , Button & button )
2019-04-12 02:53:27 +02:00
{
m_buttons . set ( & button ) ;
}
2020-02-02 15:07:41 +01:00
void Action : : unregister_button ( Badge < Button > , Button & button )
2019-04-12 02:53:27 +02:00
{
m_buttons . remove ( & button ) ;
}
2020-02-02 15:07:41 +01:00
void Action : : register_menu_item ( Badge < MenuItem > , MenuItem & menu_item )
2019-04-12 02:53:27 +02:00
{
m_menu_items . set ( & menu_item ) ;
}
2020-02-02 15:07:41 +01:00
void Action : : unregister_menu_item ( Badge < MenuItem > , MenuItem & menu_item )
2019-04-12 02:53:27 +02:00
{
m_menu_items . remove ( & menu_item ) ;
}
template < typename Callback >
2020-02-02 15:07:41 +01:00
void Action : : for_each_toolbar_button ( Callback callback )
2019-04-12 02:53:27 +02:00
{
for ( auto & it : m_buttons )
callback ( * it ) ;
}
template < typename Callback >
2020-02-02 15:07:41 +01:00
void Action : : for_each_menu_item ( Callback callback )
2019-04-12 02:53:27 +02:00
{
for ( auto & it : m_menu_items )
callback ( * it ) ;
}
2020-02-02 15:07:41 +01:00
void Action : : set_enabled ( bool enabled )
2019-04-12 02:53:27 +02:00
{
if ( m_enabled = = enabled )
return ;
m_enabled = enabled ;
2020-02-02 15:07:41 +01:00
for_each_toolbar_button ( [ enabled ] ( auto & button ) {
2019-04-12 02:53:27 +02:00
button . set_enabled ( enabled ) ;
} ) ;
2020-02-02 15:07:41 +01:00
for_each_menu_item ( [ enabled ] ( auto & item ) {
2019-04-12 02:53:27 +02:00
item . set_enabled ( enabled ) ;
} ) ;
}
2019-04-26 21:09:56 +02:00
2020-02-02 15:07:41 +01:00
void Action : : set_checked ( bool checked )
2019-04-26 21:09:56 +02:00
{
if ( m_checked = = checked )
return ;
m_checked = checked ;
2019-07-09 22:10:03 +02:00
if ( m_checked & & m_action_group ) {
m_action_group - > for_each_action ( [ this ] ( auto & other_action ) {
if ( this = = & other_action )
return IterationDecision : : Continue ;
if ( other_action . is_checkable ( ) )
other_action . set_checked ( false ) ;
return IterationDecision : : Continue ;
} ) ;
}
2020-02-02 15:07:41 +01:00
for_each_toolbar_button ( [ checked ] ( auto & button ) {
2019-04-26 21:09:56 +02:00
button . set_checked ( checked ) ;
} ) ;
2020-02-02 15:07:41 +01:00
for_each_menu_item ( [ checked ] ( MenuItem & item ) {
2019-04-26 21:09:56 +02:00
item . set_checked ( checked ) ;
} ) ;
}
2019-07-09 22:10:03 +02:00
2020-02-02 15:07:41 +01:00
void Action : : set_group ( Badge < ActionGroup > , ActionGroup * group )
2019-07-09 22:10:03 +02:00
{
2021-01-10 16:29:28 -07:00
m_action_group = AK : : try_make_weak_ptr ( group ) ;
2019-07-09 22:10:03 +02:00
}
2020-02-02 15:07:41 +01:00
2020-02-14 23:02:47 +01:00
void Action : : set_icon ( const Gfx : : Bitmap * icon )
{
m_icon = icon ;
}
2020-02-02 15:07:41 +01:00
}