1 #include "menu.hpp"
2 #include "config.hpp"
3 #include <iostream>
4 #include <string>
5
6 const Glib::ustring menu_xml = R"RAW(<interface>
7 <menu id='right-click-line-menu'>
8 <section>
9 <item>
10 <attribute name='label' translatable='yes'>_Undo</attribute>
11 <attribute name='action'>app.edit_undo</attribute>
12 </item>
13 <item>
14 <attribute name='label' translatable='yes'>_Redo</attribute>
15 <attribute name='action'>app.edit_redo</attribute>
16 </item>
17 </section>
18 <section>
19 <item>
20 <attribute name='label' translatable='yes'>_Paste</attribute>
21 <attribute name='action'>app.edit_paste</attribute>
22 </item>
23 </section>
24 <section>
25 <item>
26 <attribute name='label' translatable='yes'>_Toggle _Comments</attribute>
27 <attribute name='action'>app.source_comments_toggle</attribute>
28 </item>
29 </section>
30 <section>
31 <item>
32 <attribute name='label' translatable='yes'>_Go _to _Declaration</attribute>
33 <attribute name='action'>app.source_goto_declaration</attribute>
34 </item>
35 <item>
36 <attribute name='label' translatable='yes'>_Go _to _Type _Declaration</attribute>
37 <attribute name='action'>app.source_goto_type_declaration</attribute>
38 </item>
39 <item>
40 <attribute name='label' translatable='yes'>_Go _to _Implementation</attribute>
41 <attribute name='action'>app.source_goto_implementation</attribute>
42 </item>
43 <item>
44 <attribute name='label' translatable='yes'>_Go _to _Usage</attribute>
45 <attribute name='action'>app.source_goto_usage</attribute>
46 </item>
47 <item>
48 <attribute name='label' translatable='yes'>_Go _to _Method</attribute>
49 <attribute name='action'>app.source_goto_method</attribute>
50 </item>
51 <item>
52 <attribute name='label' translatable='yes'>_Rename</attribute>
53 <attribute name='action'>app.source_rename</attribute>
54 </item>
55 </section>
56 </menu>
57 <menu id='right-click-selected-menu'>
58 <section>
59 <item>
60 <attribute name='label' translatable='yes'>_Undo</attribute>
61 <attribute name='action'>app.edit_undo</attribute>
62 </item>
63 <item>
64 <attribute name='label' translatable='yes'>_Redo</attribute>
65 <attribute name='action'>app.edit_redo</attribute>
66 </item>
67 </section>
68 <section>
69 <item>
70 <attribute name='label' translatable='yes'>_Cut</attribute>
71 <attribute name='action'>app.edit_cut</attribute>
72 </item>
73 <item>
74 <attribute name='label' translatable='yes'>_Copy</attribute>
75 <attribute name='action'>app.edit_copy</attribute>
76 </item>
77 <item>
78 <attribute name='label' translatable='yes'>_Paste</attribute>
79 <attribute name='action'>app.edit_paste</attribute>
80 </item>
81 </section>
82 <section>
83 <item>
84 <attribute name='label' translatable='yes'>_Toggle _Comments</attribute>
85 <attribute name='action'>app.source_comments_toggle</attribute>
86 </item>
87 </section>
88 </menu>
89 <menu id='juci-menu'>
90 <section>
91 <item>
92 <attribute name='label' translatable='yes'>_About</attribute>
93 <attribute name='action'>app.about</attribute>
94 </item>
95 </section>
96 <section>
97 <item>
98 <attribute name='label' translatable='yes'>_Preferences</attribute>
99 <attribute name='action'>app.preferences</attribute>
100 </item>
101 </section>
102 <section>
103 <item>
104 <attribute name='label' translatable='yes'>_Snippets</attribute>
105 <attribute name='action'>app.snippets</attribute>
106 </item>
107 <item>
108 <attribute name='label' translatable='yes'>_Commands</attribute>
109 <attribute name='action'>app.commands</attribute>
110 </item>
111 </section>
112 <section>
113 <item>
114 <attribute name='label' translatable='yes'>_Quit</attribute>
115 <attribute name='action'>app.quit</attribute>
116 </item>
117 </section>
118 </menu>
119
120 <menu id='window-menu'>
121 <submenu>
122 <attribute name='label' translatable='yes'>_File</attribute>
123 <section>
124 <item>
125 <attribute name='label' translatable='yes'>_New _File</attribute>
126 <attribute name='action'>app.file_new_file</attribute>
127 </item>
128 <item>
129 <attribute name='label' translatable='yes'>_New _Folder</attribute>
130 <attribute name='action'>app.file_new_folder</attribute>
131 </item>
132 <submenu>
133 <attribute name='label' translatable='yes'>_New _Project</attribute>
134 <item>
135 <attribute name='label' translatable='no'>C</attribute>
136 <attribute name='action'>app.file_new_project_c</attribute>
137 </item>
138 <item>
139 <attribute name='label' translatable='no'>C++</attribute>
140 <attribute name='action'>app.file_new_project_cpp</attribute>
141 </item>
142 <item>
143 <attribute name='label' translatable='no'>Rust</attribute>
144 <attribute name='action'>app.file_new_project_rust</attribute>
145 </item>
146 </submenu>
147 </section>
148 <section>
149 <item>
150 <attribute name='label' translatable='yes'>_Open _File</attribute>
151 <attribute name='action'>app.file_open_file</attribute>
152 </item>
153 <item>
154 <attribute name='label' translatable='yes'>_Open _Folder</attribute>
155 <attribute name='action'>app.file_open_folder</attribute>
156 </item>
157 </section>
158 <section>
159 <item>
160 <attribute name='label' translatable='yes'>_Find _File</attribute>
161 <attribute name='action'>app.file_find_file</attribute>
162 </item>
163 <item>
164 <attribute name='label' translatable='yes'>_Switch _File _Type</attribute>
165 <attribute name='action'>app.file_switch_file_type</attribute>
166 </item>
167 </section>
168 <section>
169 <item>
170 <attribute name='label' translatable='yes'>_Reload _File</attribute>
171 <attribute name='action'>app.file_reload_file</attribute>
172 </item>
173 </section>
174 <section>
175 <item>
176 <attribute name='label' translatable='yes'>_Save</attribute>
177 <attribute name='action'>app.file_save</attribute>
178 </item>
179 <item>
180 <attribute name='label' translatable='yes'>_Save _As</attribute>
181 <attribute name='action'>app.file_save_as</attribute>
182 </item>
183 </section>
184 <section>
185 <item>
186 <attribute name='label' translatable='yes'>_Close _File</attribute>
187 <attribute name='action'>app.file_close_file</attribute>
188 </item>
189 <item>
190 <attribute name='label' translatable='yes'>_Close _Folder</attribute>
191 <attribute name='action'>app.file_close_folder</attribute>
192 </item>
193 <item>
194 <attribute name='label' translatable='yes'>_Close _Project</attribute>
195 <attribute name='action'>app.file_close_project</attribute>
196 </item>
197 <item>
198 <attribute name='label' translatable='yes'>_Close _Other _Files</attribute>
199 <attribute name='action'>app.file_close_other_files</attribute>
200 </item>
201 </section>
202 <section>
203 <item>
204 <attribute name='label' translatable='yes'>_Print</attribute>
205 <attribute name='action'>app.file_print</attribute>
206 </item>
207 </section>
208 </submenu>
209
210 <submenu>
211 <attribute name='label' translatable='yes'>_Edit</attribute>
212 <section>
213 <item>
214 <attribute name='label' translatable='yes'>_Undo</attribute>
215 <attribute name='action'>app.edit_undo</attribute>
216 </item>
217 <item>
218 <attribute name='label' translatable='yes'>_Redo</attribute>
219 <attribute name='action'>app.edit_redo</attribute>
220 </item>
221 </section>
222 <section>
223 <item>
224 <attribute name='label' translatable='yes'>_Cut</attribute>
225 <attribute name='action'>app.edit_cut</attribute>
226 </item>
227 <item>
228 <attribute name='label' translatable='yes'>_Cut _Lines</attribute>
229 <attribute name='action'>app.edit_cut_lines</attribute>
230 </item>
231 <item>
232 <attribute name='label' translatable='yes'>_Copy</attribute>
233 <attribute name='action'>app.edit_copy</attribute>
234 </item>
235 <item>
236 <attribute name='label' translatable='yes'>_Copy _Lines</attribute>
237 <attribute name='action'>app.edit_copy_lines</attribute>
238 </item>
239 <item>
240 <attribute name='label' translatable='yes'>_Paste</attribute>
241 <attribute name='action'>app.edit_paste</attribute>
242 </item>
243 </section>
244 <section>
245 <item>
246 <attribute name='label' translatable='yes'>_Extend _Selection</attribute>
247 <attribute name='action'>app.edit_extend_selection</attribute>
248 </item>
249 <item>
250 <attribute name='label' translatable='yes'>_Shrink _Selection</attribute>
251 <attribute name='action'>app.edit_shrink_selection</attribute>
252 </item>
253 </section>
254 <section>
255 <item>
256 <attribute name='label' translatable='yes'>_Show/_Hide</attribute>
257 <attribute name='action'>app.edit_show_or_hide</attribute>
258 </item>
259 </section>
260 <section>
261 <item>
262 <attribute name='label' translatable='yes'>_Find</attribute>
263 <attribute name='action'>app.edit_find</attribute>
264 </item>
265 </section>
266 </submenu>
267
268 <submenu>
269 <attribute name='label' translatable='yes'>_Source</attribute>
270 <section>
271 <submenu>
272 <attribute name='label' translatable='yes'>_Spell _Check</attribute>
273 <item>
274 <attribute name='label' translatable='yes'>_Spell _Check _Buffer</attribute>
275 <attribute name='action'>app.source_spellcheck</attribute>
276 </item>
277 <item>
278 <attribute name='label' translatable='yes'>_Clear _Spelling _Errors</attribute>
279 <attribute name='action'>app.source_spellcheck_clear</attribute>
280 </item>
281 <item>
282 <attribute name='label' translatable='yes'>_Go _to _Next _Spelling _Error</attribute>
283 <attribute name='action'>app.source_spellcheck_next_error</attribute>
284 </item>
285 </submenu>
286 </section>
287 <section>
288 <submenu>
289 <attribute name='label' translatable='yes'>_Git</attribute>
290 <item>
291 <attribute name='label' translatable='yes'>_Go _to _Next _Diff</attribute>
292 <attribute name='action'>app.source_git_next_diff</attribute>
293 </item>
294 <item>
295 <attribute name='label' translatable='yes'>_Show _Diff</attribute>
296 <attribute name='action'>app.source_git_show_diff</attribute>
297 </item>
298 </submenu>
299 </section>
300 <section>
301 <submenu>
302 <attribute name='label' translatable='yes'>_Indentation</attribute>
303 <item>
304 <attribute name='label' translatable='yes'>_Set _Current _Buffer _Tab</attribute>
305 <attribute name='action'>app.source_indentation_set_buffer_tab</attribute>
306 </item>
307 <item>
308 <attribute name='label' translatable='yes'>_Auto-Indent _Current _Buffer</attribute>
309 <attribute name='action'>app.source_indentation_auto_indent_buffer</attribute>
310 </item>
311 </submenu>
312 </section>
313 <section>
314 <item>
315 <attribute name='label' translatable='yes'>_Go _to _Line</attribute>
316 <attribute name='action'>app.source_goto_line</attribute>
317 </item>
318 <item>
319 <attribute name='label' translatable='yes'>_Center _Cursor</attribute>
320 <attribute name='action'>app.source_center_cursor</attribute>
321 </item>
322 <submenu>
323 <attribute name='label' translatable='yes'>_Cursor _History</attribute>
324 <item>
325 <attribute name='label' translatable='yes'>_Back</attribute>
326 <attribute name='action'>app.source_cursor_history_back</attribute>
327 </item>
328 <item>
329 <attribute name='label' translatable='yes'>_Forward</attribute>
330 <attribute name='action'>app.source_cursor_history_forward</attribute>
331 </item>
332 </submenu>
333 </section>
334 <section>
335 <item>
336 <attribute name='label' translatable='yes'>_Find _Symbol</attribute>
337 <attribute name='action'>app.source_find_symbol</attribute>
338 </item>
339 <item>
340 <attribute name='label' translatable='yes'>_Find _Pattern</attribute>
341 <attribute name='action'>app.source_find_pattern</attribute>
342 </item>
343 </section>
344 <section>
345 <submenu>
346 <attribute name='label' translatable='yes'>_Comments</attribute>
347 <item>
348 <attribute name='label' translatable='yes'>_Toggle _Comments</attribute>
349 <attribute name='action'>app.source_comments_toggle</attribute>
350 </item>
351 <item>
352 <attribute name='label' translatable='yes'>_Add _Documentation</attribute>
353 <attribute name='action'>app.source_comments_add_documentation</attribute>
354 </item>
355 </submenu>
356 <item>
357 <attribute name='label' translatable='yes'>_Find _Documentation</attribute>
358 <attribute name='action'>app.source_find_documentation</attribute>
359 </item>
360 </section>
361 <section>
362 <item>
363 <attribute name='label' translatable='yes'>_Go to Declaration</attribute>
364 <attribute name='action'>app.source_goto_declaration</attribute>
365 </item>
366 <item>
367 <attribute name='label' translatable='yes'>_Go to _Type _Declaration</attribute>
368 <attribute name='action'>app.source_goto_type_declaration</attribute>
369 </item>
370 <item>
371 <attribute name='label' translatable='yes'>_Go to Implementation</attribute>
372 <attribute name='action'>app.source_goto_implementation</attribute>
373 </item>
374 <item>
375 <attribute name='label' translatable='yes'>_Go to Usage</attribute>
376 <attribute name='action'>app.source_goto_usage</attribute>
377 </item>
378 <item>
379 <attribute name='label' translatable='yes'>_Go to Method</attribute>
380 <attribute name='action'>app.source_goto_method</attribute>
381 </item>
382 <item>
383 <attribute name='label' translatable='yes'>_Rename</attribute>
384 <attribute name='action'>app.source_rename</attribute>
385 </item>
386 <item>
387 <attribute name='label' translatable='yes'>_Implement _Method</attribute>
388 <attribute name='action'>app.source_implement_method</attribute>
389 </item>
390 </section>
391 <section>
392 <item>
393 <attribute name='label' translatable='yes'>_Go to Next Diagnostic</attribute>
394 <attribute name='action'>app.source_goto_next_diagnostic</attribute>
395 </item>
396 <item>
397 <attribute name='label' translatable='yes'>_Apply Fix-Its</attribute>
398 <attribute name='action'>app.source_apply_fix_its</attribute>
399 </item>
400 </section>
401 </submenu>
402
403 <submenu>
404 <attribute name='label' translatable='yes'>_Project</attribute>
405 <section>
406 <item>
407 <attribute name='label' translatable='yes'>_Set _Run _Arguments</attribute>
408 <attribute name='action'>app.project_set_run_arguments</attribute>
409 </item>
410 <item>
411 <attribute name='label' translatable='yes'>_Compile _and _Run</attribute>
412 <attribute name='action'>app.project_compile_and_run</attribute>
413 </item>
414 <item>
415 <attribute name='label' translatable='yes'>_Compile</attribute>
416 <attribute name='action'>app.project_compile</attribute>
417 </item>
418 <item>
419 <attribute name='label' translatable='yes'>_Recreate _Build</attribute>
420 <attribute name='action'>app.project_recreate_build</attribute>
421 </item>
422 </section>
423 <section>
424 <item>
425 <attribute name='label' translatable='yes'>_Run _Command</attribute>
426 <attribute name='action'>app.project_run_command</attribute>
427 </item>
428 <item>
429 <attribute name='label' translatable='yes'>_Kill _Last _Process</attribute>
430 <attribute name='action'>app.project_kill_last_running</attribute>
431 </item>
432 <item>
433 <attribute name='label' translatable='yes'>_Force _Kill _Last _Process</attribute>
434 <attribute name='action'>app.project_force_kill_last_running</attribute>
435 </item>
436 </section>
437 </submenu>
438
439 <submenu>
440 <attribute name='label' translatable='yes'>_Debug</attribute>
441 <section>
442 <item>
443 <attribute name='label' translatable='yes'>_Set _Run _Arguments</attribute>
444 <attribute name='action'>app.debug_set_run_arguments</attribute>
445 </item>
446 <item>
447 <attribute name='label' translatable='yes'>_Start/_Continue</attribute>
448 <attribute name='action'>app.debug_start_continue</attribute>
449 </item>
450 <item>
451 <attribute name='label' translatable='yes'>_Stop</attribute>
452 <attribute name='action'>app.debug_stop</attribute>
453 </item>
454 <item>
455 <attribute name='label' translatable='yes'>_Kill</attribute>
456 <attribute name='action'>app.debug_kill</attribute>
457 </item>
458 </section>
459 <section>
460 <item>
461 <attribute name='label' translatable='yes'>_Step _Over</attribute>
462 <attribute name='action'>app.debug_step_over</attribute>
463 </item>
464 <item>
465 <attribute name='label' translatable='yes'>_Step _Into</attribute>
466 <attribute name='action'>app.debug_step_into</attribute>
467 </item>
468 <item>
469 <attribute name='label' translatable='yes'>_Step _Out</attribute>
470 <attribute name='action'>app.debug_step_out</attribute>
471 </item>
472 </section>
473 <section>
474 <item>
475 <attribute name='label' translatable='yes'>_Backtrace</attribute>
476 <attribute name='action'>app.debug_backtrace</attribute>
477 </item>
478 <item>
479 <attribute name='label' translatable='yes'>_Show _Variables</attribute>
480 <attribute name='action'>app.debug_show_variables</attribute>
481 </item>
482 </section>
483 <section>
484 <item>
485 <attribute name='label' translatable='yes'>_Run Command</attribute>
486 <attribute name='action'>app.debug_run_command</attribute>
487 </item>
488 </section>
489 <section>
490 <item>
491 <attribute name='label' translatable='yes'>_Toggle _Breakpoint</attribute>
492 <attribute name='action'>app.debug_toggle_breakpoint</attribute>
493 </item>
494 <item>
495 <attribute name='label' translatable='yes'>_Show _Breakpoints</attribute>
496 <attribute name='action'>app.debug_show_breakpoints</attribute>
497 </item>
498 </section>
499 <section>
500 <item>
501 <attribute name='label' translatable='yes'>_Go _to _Stop</attribute>
502 <attribute name='action'>app.debug_goto_stop</attribute>
503 </item>
504 </section>
505 </submenu>
506
507 <submenu>
508 <attribute name='label' translatable='yes'>_Window</attribute>
509 <section>
510 <item>
511 <attribute name='label' translatable='yes'>_Next _Tab</attribute>
512 <attribute name='action'>app.window_next_tab</attribute>
513 </item>
514 <item>
515 <attribute name='label' translatable='yes'>_Previous _Tab</attribute>
516 <attribute name='action'>app.window_previous_tab</attribute>
517 </item>
518 <item>
519 <attribute name='label' translatable='yes'>_Go _to _Tab</attribute>
520 <attribute name='action'>app.window_goto_tab</attribute>
521 </item>
522 </section>
523 <section>
524 <item>
525 <attribute name='label' translatable='yes'>_Toggle _Split</attribute>
526 <attribute name='action'>app.window_toggle_split</attribute>
527 </item>
528 <item>
529 <attribute name='label' translatable='yes'>_Split _Source _Buffer</attribute>
530 <attribute name='action'>app.window_split_source_buffer</attribute>
531 </item>
532 </section>
533 <section>
534 <item>
535 <attribute name='label' translatable='yes'>_Toggle _Full _Screen</attribute>
536 <attribute name='action'>app.window_toggle_full_screen</attribute>
537 </item>
538 <item>
539 <attribute name='label' translatable='yes'>_Toggle _Directories</attribute>
540 <attribute name='action'>app.window_toggle_directories</attribute>
541 </item>
542 <item>
543 <attribute name='label' translatable='yes'>_Toggle _Terminal</attribute>
544 <attribute name='action'>app.window_toggle_terminal</attribute>
545 </item>
546 <item>
547 <attribute name='label' translatable='yes'>_Toggle _Status</attribute>
548 <attribute name='action'>app.window_toggle_status</attribute>
549 </item>
550 <item>
551 <attribute name='label' translatable='yes'>_Toggle _Menu</attribute>
552 <attribute name='action'>app.window_toggle_menu</attribute>
553 </item>
554 <item>
555 <attribute name='label' translatable='yes'>_Toggle _Tabs</attribute>
556 <attribute name='action'>app.window_toggle_tabs</attribute>
557 </item>
558 <item>
559 <attribute name='label' translatable='yes'>_Toggle _Zen _Mode</attribute>
560 <attribute name='action'>app.window_toggle_zen_mode</attribute>
561 </item>
562 </section>
563 <section>
564 <item>
565 <attribute name='label' translatable='yes'>_Clear _Terminal</attribute>
566 <attribute name='action'>app.window_clear_terminal</attribute>
567 </item>
568 </section>
569 </submenu>
570 </menu>
571 </interface>
572 )RAW";
573
add_action(const std::string & name,const std::function<void ()> & action)574 void Menu::add_action(const std::string &name, const std::function<void()> &action) {
575 auto g_application = g_application_get_default();
576 auto gio_application = Glib::wrap(g_application, true);
577 auto application = Glib::RefPtr<Gtk::Application>::cast_static(gio_application);
578
579 actions[name] = application->add_action(name, action);
580 }
581
set_keys()582 void Menu::set_keys() {
583 auto g_application = g_application_get_default();
584 auto gio_application = Glib::wrap(g_application, true);
585 auto application = Glib::RefPtr<Gtk::Application>::cast_static(gio_application);
586
587 for(auto &key : Config::get().menu.keys) {
588 if(actions.find(key.first) != actions.end()) {
589 if(!key.second.empty())
590 application->set_accel_for_action("app." + key.first, key.second);
591 else
592 application->unset_accels_for_action("app." + key.first);
593 }
594 }
595 }
596
build()597 void Menu::build() {
598 try {
599 builder = Gtk::Builder::create_from_string(menu_xml);
600 auto object = builder->get_object("juci-menu");
601 juci_menu = Glib::RefPtr<Gio::Menu>::cast_dynamic(object);
602 object = builder->get_object("window-menu");
603 window_menu = Glib::RefPtr<Gio::Menu>::cast_dynamic(object);
604 object = builder->get_object("right-click-line-menu");
605 auto ptr = Glib::RefPtr<Gio::Menu>::cast_dynamic(object);
606 right_click_line_menu = std::make_unique<Gtk::Menu>(ptr);
607 object = builder->get_object("right-click-selected-menu");
608 ptr = Glib::RefPtr<Gio::Menu>::cast_dynamic(object);
609 right_click_selected_menu = std::make_unique<Gtk::Menu>(ptr);
610 }
611 catch(const Glib::Error &ex) {
612 std::cerr << "building menu failed: " << ex.what();
613 }
614 }
615