1 | // Aseprite |
2 | // Copyright (C) 2019-2022 Igara Studio S.A. |
3 | // Copyright (C) 2001-2017 David Capello |
4 | // |
5 | // This program is distributed under the terms of |
6 | // the End-User License Agreement for Aseprite. |
7 | |
8 | #ifdef HAVE_CONFIG_H |
9 | #include "config.h" |
10 | #endif |
11 | |
12 | #include "app/ui/app_menuitem.h" |
13 | |
14 | #include "app/app_menus.h" |
15 | #include "app/commands/command.h" |
16 | #include "app/commands/commands.h" |
17 | #include "app/commands/params.h" |
18 | #include "app/modules/gui.h" |
19 | #include "app/ui/keyboard_shortcuts.h" |
20 | #include "app/ui_context.h" |
21 | #include "os/menus.h" |
22 | #include "ui/accelerator.h" |
23 | #include "ui/menu.h" |
24 | #include "ui/message.h" |
25 | #include "ui/size_hint_event.h" |
26 | #include "ui/widget.h" |
27 | |
28 | #include <cstdarg> |
29 | #include <string> |
30 | |
31 | namespace app { |
32 | |
33 | using namespace ui; |
34 | |
35 | // static |
36 | Params AppMenuItem::; |
37 | |
38 | AppMenuItem::(const std::string& text, |
39 | const std::string& commandId, |
40 | const Params& params) |
41 | : MenuItem(text) |
42 | , m_key(nullptr) |
43 | , m_commandId(commandId) |
44 | , m_params(params) |
45 | , m_isRecentFileItem(false) |
46 | , m_native(nullptr) |
47 | { |
48 | } |
49 | |
50 | Command* AppMenuItem::getCommand() const |
51 | { |
52 | if (!m_commandId.empty()) |
53 | return Commands::instance()->byId(m_commandId.c_str()); |
54 | else |
55 | return nullptr; |
56 | } |
57 | |
58 | void AppMenuItem::(const KeyPtr& key) |
59 | { |
60 | m_key = key; |
61 | syncNativeMenuItemKeyShortcut(); |
62 | } |
63 | |
64 | void AppMenuItem::(const Native& native) |
65 | { |
66 | if (!m_native) |
67 | m_native.reset(new Native(native)); |
68 | else |
69 | *m_native = native; |
70 | } |
71 | |
72 | void AppMenuItem::() |
73 | { |
74 | m_native.reset(); |
75 | } |
76 | |
77 | void AppMenuItem::() |
78 | { |
79 | if (m_native) { |
80 | os::Shortcut shortcut = get_os_shortcut_from_key(m_key.get()); |
81 | |
82 | m_native->shortcut = shortcut; |
83 | m_native->menuItem->setShortcut(shortcut); |
84 | m_native->keyContext = (m_key ? m_key->keycontext(): KeyContext::Any); |
85 | } |
86 | } |
87 | |
88 | // static |
89 | void AppMenuItem::(const Params& params) |
90 | { |
91 | s_contextParams = params; |
92 | } |
93 | |
94 | bool AppMenuItem::(Message* msg) |
95 | { |
96 | switch (msg->type()) { |
97 | |
98 | case kCloseMessage: |
99 | // Don't disable items with submenus |
100 | if (!hasSubmenu()) { |
101 | // Disable the menu item (the keyboard shortcuts are processed |
102 | // by "manager_msg_proc") |
103 | setEnabled(false); |
104 | } |
105 | break; |
106 | } |
107 | |
108 | return MenuItem::onProcessMessage(msg); |
109 | } |
110 | |
111 | void AppMenuItem::(SizeHintEvent& ev) |
112 | { |
113 | gfx::Size size(0, 0); |
114 | |
115 | if (hasText()) { |
116 | size.w = |
117 | + textWidth() |
118 | + (inBar() ? childSpacing()/4: childSpacing()) |
119 | + border().width(); |
120 | |
121 | size.h = |
122 | + textHeight() |
123 | + border().height(); |
124 | |
125 | if (m_key && !m_key->accels().empty()) { |
126 | size.w += Graphics::measureUITextLength( |
127 | m_key->accels().front().toString().c_str(), font()); |
128 | } |
129 | } |
130 | |
131 | ev.setSizeHint(size); |
132 | } |
133 | |
134 | void AppMenuItem::() |
135 | { |
136 | MenuItem::onClick(); |
137 | |
138 | if (!m_commandId.empty()) { |
139 | Params params = m_params; |
140 | if (!s_contextParams.empty()) |
141 | params |= s_contextParams; |
142 | |
143 | // Load parameters to call Command::isEnabled, so we can check if |
144 | // the command is enabled with this parameters. |
145 | if (auto command = getCommand()) { |
146 | command->loadParams(params); |
147 | |
148 | UIContext* context = UIContext::instance(); |
149 | if (command->isEnabled(context)) |
150 | context->executeCommandFromMenuOrShortcut(command, params); |
151 | |
152 | // TODO At this point, the "this" pointer might be deleted if |
153 | // the command reloaded the App main menu |
154 | } |
155 | } |
156 | } |
157 | |
158 | void AppMenuItem::() |
159 | { |
160 | // Update the context flags after opening the menuitem's |
161 | // submenu to update the "enabled" flag of each command |
162 | // correctly. |
163 | Context* context = UIContext::instance(); |
164 | context->updateFlags(); |
165 | |
166 | if (auto command = getCommand()) { |
167 | Params params = m_params; |
168 | if (!s_contextParams.empty()) |
169 | params |= s_contextParams; |
170 | |
171 | command->loadParams(params); |
172 | |
173 | setEnabled(command->isEnabled(context)); |
174 | setSelected(command->isChecked(context)); |
175 | } |
176 | } |
177 | |
178 | } // namespace app |
179 | |