GMenu.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #include <LibGUI/GAction.h>
  2. #include <LibGUI/GMenu.h>
  3. #include <LibGUI/GEventLoop.h>
  4. #include <LibC/gui.h>
  5. #include <AK/HashMap.h>
  6. static HashMap<int, GMenu*>& all_menus()
  7. {
  8. static HashMap<int, GMenu*>* map;
  9. if (!map)
  10. map = new HashMap<int, GMenu*>();
  11. return *map;
  12. }
  13. GMenu* GMenu::from_menu_id(int menu_id)
  14. {
  15. auto it = all_menus().find(menu_id);
  16. if (it == all_menus().end())
  17. return nullptr;
  18. return (*it).value;
  19. }
  20. GMenu::GMenu(const String& name)
  21. : m_name(name)
  22. {
  23. }
  24. GMenu::~GMenu()
  25. {
  26. unrealize_menu();
  27. }
  28. void GMenu::add_action(OwnPtr<GAction>&& action)
  29. {
  30. m_items.append(make<GMenuItem>(move(action)));
  31. }
  32. void GMenu::add_separator()
  33. {
  34. m_items.append(make<GMenuItem>(GMenuItem::Separator));
  35. }
  36. int GMenu::realize_menu()
  37. {
  38. GUI_ClientMessage request;
  39. request.type = GUI_ClientMessage::Type::CreateMenu;
  40. ASSERT(m_name.length() < sizeof(request.menu.text));
  41. strcpy(request.menu.text, m_name.characters());
  42. request.menu.text_length = m_name.length();
  43. auto response = GEventLoop::main().sync_request(request, GUI_ServerMessage::Type::DidCreateMenu);
  44. m_menu_id = response.menu.menu_id;
  45. ASSERT(m_menu_id > 0);
  46. for (size_t i = 0; i < m_items.size(); ++i) {
  47. auto& item = *m_items[i];
  48. if (item.type() == GMenuItem::Separator) {
  49. GUI_ClientMessage request;
  50. request.type = GUI_ClientMessage::Type::AddMenuSeparator;
  51. request.menu.menu_id = m_menu_id;
  52. GEventLoop::main().sync_request(request, GUI_ServerMessage::Type::DidAddMenuSeparator);
  53. continue;
  54. }
  55. if (item.type() == GMenuItem::Action) {
  56. auto& action = *item.action();
  57. GUI_ClientMessage request;
  58. request.type = GUI_ClientMessage::Type::AddMenuItem;
  59. request.menu.menu_id = m_menu_id;
  60. request.menu.identifier = i;
  61. ASSERT(action.text().length() < sizeof(request.menu.text));
  62. strcpy(request.menu.text, action.text().characters());
  63. request.menu.text_length = action.text().length();
  64. GEventLoop::main().sync_request(request, GUI_ServerMessage::Type::DidAddMenuItem);
  65. }
  66. }
  67. all_menus().set(m_menu_id, this);
  68. return m_menu_id;
  69. }
  70. void GMenu::unrealize_menu()
  71. {
  72. if (!m_menu_id)
  73. return;
  74. all_menus().remove(m_menu_id);
  75. GUI_ClientMessage request;
  76. request.type = GUI_ClientMessage::Type::DestroyMenu;
  77. request.menu.menu_id = m_menu_id;
  78. GEventLoop::main().sync_request(request, GUI_ServerMessage::Type::DidDestroyMenu);
  79. m_menu_id = 0;
  80. }
  81. GAction* GMenu::action_at(size_t index)
  82. {
  83. if (index >= m_items.size())
  84. return nullptr;
  85. return m_items[index]->action();
  86. }