aseprite/src/ui/menu.h
2022-04-13 23:01:12 -03:00

207 lines
5.1 KiB
C++

// Aseprite UI Library
// Copyright (C) 2020-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef UI_MENU_H_INCLUDED
#define UI_MENU_H_INCLUDED
#pragma once
#include "obs/signal.h"
#include "ui/register_message.h"
#include "ui/separator.h"
#include "ui/widget.h"
#include "ui/window.h"
#include <memory>
namespace ui {
class MenuBoxWindow;
class MenuItem;
class Timer;
struct MenuBaseData;
class Menu : public Widget {
public:
Menu();
~Menu();
void showPopup(const gfx::Point& pos,
Display* parentDisplay);
Widget* findItemById(const char* id) const;
// Returns the MenuItem that has as submenu this menu.
MenuItem* getOwnerMenuItem() {
return m_menuitem;
}
obs::signal<void()> OpenPopup;
protected:
virtual void onPaint(PaintEvent& ev) override;
virtual void onResize(ResizeEvent& ev) override;
virtual void onSizeHint(SizeHintEvent& ev) override;
virtual void onOpenPopup();
private:
void setOwnerMenuItem(MenuItem* ownerMenuItem) {
m_menuitem = ownerMenuItem;
}
void closeAll();
MenuItem* getHighlightedItem();
void highlightItem(MenuItem* menuitem, bool click, bool open_submenu, bool select_first_child);
void unhighlightItem();
MenuItem* m_menuitem; // From where the menu was open
friend class MenuBox;
friend class MenuItem;
};
class MenuBox : public Widget {
public:
MenuBox(WidgetType type = kMenuBoxWidget);
~MenuBox();
Menu* getMenu();
void setMenu(Menu* menu);
MenuBaseData* getBase() {
return m_base.get();
}
// Closes all menu-boxes and goes back to the normal state of the
// menu-bar.
void cancelMenuLoop();
protected:
virtual bool onProcessMessage(Message* msg) override;
virtual void onResize(ResizeEvent& ev) override;
virtual void onSizeHint(SizeHintEvent& ev) override;
MenuBaseData* createBase();
private:
void closePopup();
void startFilteringMouseDown();
void stopFilteringMouseDown();
std::unique_ptr<MenuBaseData> m_base;
friend class Menu;
friend class MenuItem;
};
class MenuBar : public MenuBox {
public:
enum class ProcessTopLevelShortcuts { kNo, kYes };
MenuBar(ProcessTopLevelShortcuts processShortcuts);
bool processTopLevelShortcuts() const {
return m_processTopLevelShortcuts;
}
static bool expandOnMouseover();
static void setExpandOnMouseover(bool state);
private:
// True if we should open top-level menus with Alt+mnemonic (this
// flag is not used by Aseprite), top-level menus are opened with
// the ShowMenu command now.
bool m_processTopLevelShortcuts;
static bool m_expandOnMouseover;
};
class MenuItem : public Widget {
public:
MenuItem(const std::string& text);
~MenuItem();
Menu* getSubmenu();
void setSubmenu(Menu* submenu);
// Open the submenu of this menu item (the menu item should be
// positioned in a correct position on the screen).
void openSubmenu();
bool isHighlighted() const;
void setHighlighted(bool state);
// Returns true if the MenuItem has a submenu.
bool hasSubmenu() const;
// Returns true if the submenu is opened.
bool hasSubmenuOpened() const {
return (m_submenu_menubox != nullptr);
}
// Returns the menu-box where the sub-menu has been opened, or
// just nullptr if the sub-menu is closed.
MenuBox* getSubmenuContainer() const {
return m_submenu_menubox;
}
void executeClick();
void validateItem();
// Fired when the menu item is clicked.
obs::signal<void()> Click;
protected:
bool onProcessMessage(Message* msg) override;
void onInitTheme(InitThemeEvent& ev) override;
void onPaint(PaintEvent& ev) override;
void onSizeHint(SizeHintEvent& ev) override;
virtual void onClick();
virtual void onValidate();
bool inBar() const;
private:
void openSubmenu(bool select_first);
void closeSubmenu(bool last_of_close_chain);
void startTimer();
void stopTimer();
bool m_highlighted; // Is it highlighted?
Menu* m_submenu; // The sub-menu
MenuBox* m_submenu_menubox; // The opened menubox for this menu-item
std::unique_ptr<Timer> m_submenu_timer; // Timer to open the submenu
friend class Menu;
friend class MenuBox;
friend class MenuBoxWindow;
};
class MenuSeparator : public Separator {
public:
MenuSeparator() : Separator("", HORIZONTAL) {
}
};
class MenuBoxWindow : public Window {
public:
MenuBoxWindow(MenuItem* menuitem = nullptr);
~MenuBoxWindow();
MenuBox* menubox() { return &m_menubox; }
protected:
bool onProcessMessage(Message* msg) override;
private:
MenuBox m_menubox;
MenuItem* m_menuitem;
};
extern RegisterMessage kOpenMenuItemMessage;
extern RegisterMessage kCloseMenuItemMessage;
extern RegisterMessage kClosePopupMessage;
extern RegisterMessage kExecuteMenuItemMessage;
} // namespace ui
#endif