reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

menu.cpp (3877B)


      1 /* ReaPack: Package manager for REAPER
      2  * Copyright (C) 2015-2025  Christian Fillion
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU Lesser General Public License as published by
      6  * the Free Software Foundation, either version 3 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  * GNU Lesser General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Lesser General Public License
     15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16  */
     17 
     18 #include "menu.hpp"
     19 
     20 #include "win32.hpp"
     21 
     22 #ifndef MIIM_FTYPE // for SWELL
     23 #  define MIIM_FTYPE MIIM_TYPE
     24 #endif
     25 
     26 #ifndef _WIN32
     27 #  include <swell/swell.h>
     28 #endif
     29 
     30 #include <reaper_plugin_functions.h>
     31 
     32 Menu::Menu(HMENU handle)
     33   : m_handle(handle), m_ownership(!handle)
     34 {
     35   if(m_ownership)
     36     m_handle = CreatePopupMenu();
     37 
     38   m_size = GetMenuItemCount(m_handle);
     39 }
     40 
     41 Menu::~Menu()
     42 {
     43   if(m_ownership)
     44     DestroyMenu(m_handle);
     45 }
     46 
     47 UINT Menu::addAction(const std::string &label, const int commandId)
     48 {
     49   MENUITEMINFO mii{};
     50   mii.cbSize = sizeof(mii);
     51 
     52   mii.fMask |= MIIM_TYPE;
     53   mii.fType = MFT_STRING;
     54   const auto &&wideLabel = Win32::widen(label);
     55   mii.dwTypeData = const_cast<Win32::char_type *>(wideLabel.c_str());
     56 
     57   mii.fMask |= MIIM_ID;
     58   mii.wID = commandId;
     59 
     60   const UINT index = m_size;
     61   append(mii);
     62   return index;
     63 }
     64 
     65 UINT Menu::addAction(const std::string &label, const char *namedCommand)
     66 {
     67   return addAction(label, NamedCommandLookup(namedCommand));
     68 }
     69 
     70 void Menu::addSeparator()
     71 {
     72   MENUITEMINFO mii{};
     73   mii.cbSize = sizeof(mii);
     74 
     75   mii.fMask = MIIM_TYPE;
     76   mii.fType = MFT_SEPARATOR;
     77 
     78   append(mii);
     79 }
     80 
     81 Menu Menu::addMenu(const std::string &label)
     82 {
     83   MENUITEMINFO mii{};
     84   mii.cbSize = sizeof(mii);
     85 
     86   mii.fMask |= MIIM_TYPE;
     87   mii.fType = MFT_STRING;
     88   const auto &&wideLabel = Win32::widen(label);
     89   mii.dwTypeData = const_cast<Win32::char_type *>(wideLabel.c_str());
     90 
     91   mii.fMask |= MIIM_SUBMENU;
     92   mii.hSubMenu = CreatePopupMenu();
     93 
     94   append(mii);
     95 
     96   return Menu(mii.hSubMenu);
     97 }
     98 
     99 void Menu::append(MENUITEMINFO &mii)
    100 {
    101   InsertMenuItem(m_handle, m_size++, true, &mii);
    102 }
    103 
    104 int Menu::show(const int x, const int y, HWND parent) const
    105 {
    106   const int command = TrackPopupMenu(m_handle,
    107     TPM_TOPALIGN | TPM_LEFTALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
    108     x, y, 0, parent, nullptr);
    109 
    110   // both send the notification and return the command id
    111   SendMessage(parent, WM_COMMAND, command, 0);
    112 
    113   return command;
    114 }
    115 
    116 int Menu::show(HWND control, HWND parent) const
    117 {
    118   RECT rect;
    119   GetWindowRect(control, &rect);
    120 
    121   return show(rect.left, rect.bottom - 1, parent);
    122 }
    123 
    124 void Menu::disable(const UINT index)
    125 {
    126   setEnabled(false, index);
    127 }
    128 
    129 void Menu::enable(const UINT index)
    130 {
    131   setEnabled(true, index);
    132 }
    133 
    134 void Menu::setEnabled(const bool enabled, const UINT index)
    135 {
    136   MENUITEMINFO mii{};
    137   mii.cbSize = sizeof(mii);
    138   mii.fMask |= MIIM_STATE;
    139 
    140   if(!GetMenuItemInfo(m_handle, index, true, &mii))
    141     return;
    142 
    143   mii.fState |= enabled ? MFS_ENABLED : MFS_DISABLED;
    144 
    145   SetMenuItemInfo(m_handle, index, true, &mii);
    146 }
    147 
    148 void Menu::check(const UINT index)
    149 {
    150   MENUITEMINFO mii{};
    151   mii.cbSize = sizeof(mii);
    152   mii.fMask |= MIIM_STATE;
    153 
    154   if(!GetMenuItemInfo(m_handle, index, true, &mii))
    155     return;
    156 
    157   mii.fState |= MFS_CHECKED;
    158 
    159   SetMenuItemInfo(m_handle, index, true, &mii);
    160 }
    161 
    162 void Menu::checkRadio(const UINT index)
    163 {
    164   MENUITEMINFO mii{};
    165   mii.cbSize = sizeof(mii);
    166   mii.fMask |= MIIM_FTYPE;
    167   mii.fMask |= MIIM_STATE;
    168 
    169   if(!GetMenuItemInfo(m_handle, index, true, &mii))
    170     return;
    171 
    172   mii.fType |= MFT_RADIOCHECK;
    173   mii.fState |= MFS_CHECKED;
    174 
    175   SetMenuItemInfo(m_handle, index, true, &mii);
    176 }