Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#pragma once
28
29#include <AK/Badge.h>
30#include <AK/Function.h>
31#include <AK/HashTable.h>
32#include <AK/NonnullRefPtr.h>
33#include <AK/RefCounted.h>
34#include <AK/String.h>
35#include <AK/WeakPtr.h>
36#include <AK/Weakable.h>
37#include <LibCore/Object.h>
38#include <LibGUI/Forward.h>
39#include <LibGUI/Shortcut.h>
40#include <LibGfx/Forward.h>
41
42namespace GUI {
43
44namespace CommonActions {
45 NonnullRefPtr<Action> make_open_action(Function<void(Action&)>, Core::Object* parent = nullptr);
46 NonnullRefPtr<Action> make_undo_action(Function<void(Action&)>, Core::Object* parent = nullptr);
47 NonnullRefPtr<Action> make_redo_action(Function<void(Action&)>, Core::Object* parent = nullptr);
48 NonnullRefPtr<Action> make_cut_action(Function<void(Action&)>, Core::Object* parent = nullptr);
49 NonnullRefPtr<Action> make_copy_action(Function<void(Action&)>, Core::Object* parent = nullptr);
50 NonnullRefPtr<Action> make_paste_action(Function<void(Action&)>, Core::Object* parent = nullptr);
51 NonnullRefPtr<Action> make_delete_action(Function<void(Action&)>, Core::Object* parent = nullptr);
52 NonnullRefPtr<Action> make_move_to_front_action(Function<void(Action&)>, Core::Object* parent = nullptr);
53 NonnullRefPtr<Action> make_move_to_back_action(Function<void(Action&)>, Core::Object* parent = nullptr);
54 NonnullRefPtr<Action> make_fullscreen_action(Function<void(Action&)>, Core::Object* parent = nullptr);
55 NonnullRefPtr<Action> make_quit_action(Function<void(Action&)>);
56 NonnullRefPtr<Action> make_go_back_action(Function<void(Action&)>, Core::Object* parent = nullptr);
57 NonnullRefPtr<Action> make_go_forward_action(Function<void(Action&)>, Core::Object* parent = nullptr);
58 NonnullRefPtr<Action> make_go_home_action(Function<void(Action&)> callback, Core::Object* parent = nullptr);
59 NonnullRefPtr<Action> make_reload_action(Function<void(Action&)>, Core::Object* parent = nullptr);
60};
61
62class Action final : public Core::Object {
63 C_OBJECT(Action)
64public:
65 enum class ShortcutScope {
66 None,
67 WidgetLocal,
68 WindowLocal,
69 ApplicationGlobal,
70 };
71 static NonnullRefPtr<Action> create(const StringView& text, Function<void(Action&)> callback, Core::Object* parent = nullptr)
72 {
73 return adopt(*new Action(text, move(callback), parent));
74 }
75 static NonnullRefPtr<Action> create(const StringView& text, RefPtr<Gfx::Bitmap>&& icon, Function<void(Action&)> callback, Core::Object* parent = nullptr)
76 {
77 return adopt(*new Action(text, move(icon), move(callback), parent));
78 }
79 static NonnullRefPtr<Action> create(const StringView& text, const Shortcut& shortcut, Function<void(Action&)> callback, Core::Object* parent = nullptr)
80 {
81 return adopt(*new Action(text, shortcut, move(callback), parent));
82 }
83 static NonnullRefPtr<Action> create(const StringView& text, const Shortcut& shortcut, RefPtr<Gfx::Bitmap>&& icon, Function<void(Action&)> callback, Core::Object* parent = nullptr)
84 {
85 return adopt(*new Action(text, shortcut, move(icon), move(callback), parent));
86 }
87 virtual ~Action() override;
88
89 String text() const { return m_text; }
90 Shortcut shortcut() const { return m_shortcut; }
91 const Gfx::Bitmap* icon() const { return m_icon.ptr(); }
92 void set_icon(const Gfx::Bitmap*);
93
94 const Core::Object* activator() const { return m_activator.ptr(); }
95 Core::Object* activator() { return m_activator.ptr(); }
96
97 Function<void(Action&)> on_activation;
98
99 void activate(Core::Object* activator = nullptr);
100
101 bool is_enabled() const { return m_enabled; }
102 void set_enabled(bool);
103
104 bool is_checkable() const { return m_checkable; }
105 void set_checkable(bool checkable) { m_checkable = checkable; }
106
107 bool is_checked() const
108 {
109 ASSERT(is_checkable());
110 return m_checked;
111 }
112 void set_checked(bool);
113
114 void register_button(Badge<Button>, Button&);
115 void unregister_button(Badge<Button>, Button&);
116 void register_menu_item(Badge<MenuItem>, MenuItem&);
117 void unregister_menu_item(Badge<MenuItem>, MenuItem&);
118
119 const ActionGroup* group() const { return m_action_group.ptr(); }
120 void set_group(Badge<ActionGroup>, ActionGroup*);
121
122private:
123 virtual bool is_action() const override { return true; }
124
125 Action(const StringView& text, Function<void(Action&)> = nullptr, Core::Object* = nullptr);
126 Action(const StringView& text, const Shortcut&, Function<void(Action&)> = nullptr, Core::Object* = nullptr);
127 Action(const StringView& text, const Shortcut&, RefPtr<Gfx::Bitmap>&& icon, Function<void(Action&)> = nullptr, Core::Object* = nullptr);
128 Action(const StringView& text, RefPtr<Gfx::Bitmap>&& icon, Function<void(Action&)> = nullptr, Core::Object* = nullptr);
129
130 template<typename Callback>
131 void for_each_toolbar_button(Callback);
132 template<typename Callback>
133 void for_each_menu_item(Callback);
134
135 String m_text;
136 RefPtr<Gfx::Bitmap> m_icon;
137 Shortcut m_shortcut;
138 bool m_enabled { true };
139 bool m_checkable { false };
140 bool m_checked { false };
141 ShortcutScope m_scope { ShortcutScope::None };
142
143 HashTable<Button*> m_buttons;
144 HashTable<MenuItem*> m_menu_items;
145 WeakPtr<ActionGroup> m_action_group;
146 WeakPtr<Core::Object> m_activator;
147};
148
149}
150
151template<>
152inline bool Core::is<GUI::Action>(const Core::Object& object)
153{
154 return object.is_action();
155}