2013-03-15 13:11:33 +00:00
|
|
|
namespace phoenix {
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
void pMenu::append(Action& action) {
|
2011-09-05 03:48:23 +00:00
|
|
|
action.p.parentMenu = &menu;
|
2011-02-24 09:25:20 +00:00
|
|
|
if(parentWindow) parentWindow->p.updateMenu();
|
|
|
|
}
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
void pMenu::remove(Action& action) {
|
2011-09-05 03:48:23 +00:00
|
|
|
if(parentWindow) parentWindow->p.updateMenu();
|
|
|
|
action.p.parentMenu = 0;
|
|
|
|
}
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
void pMenu::setImage(const image& image) {
|
2012-01-26 06:50:09 +00:00
|
|
|
createBitmap();
|
|
|
|
if(parentWindow) parentWindow->p.updateMenu();
|
|
|
|
}
|
|
|
|
|
2013-07-29 09:42:45 +00:00
|
|
|
void pMenu::setText(string text) {
|
2011-02-24 09:25:20 +00:00
|
|
|
if(parentWindow) parentWindow->p.updateMenu();
|
|
|
|
}
|
|
|
|
|
|
|
|
void pMenu::constructor() {
|
|
|
|
hmenu = 0;
|
2012-01-26 06:50:09 +00:00
|
|
|
createBitmap();
|
|
|
|
}
|
|
|
|
|
|
|
|
void pMenu::destructor() {
|
|
|
|
if(hbitmap) { DeleteObject(hbitmap); hbitmap = 0; }
|
|
|
|
if(parentMenu) {
|
|
|
|
parentMenu->remove(menu);
|
|
|
|
} else if(parentWindow) {
|
|
|
|
//belongs to window's main menubar
|
|
|
|
parentWindow->remove(menu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void pMenu::createBitmap() {
|
|
|
|
if(hbitmap) { DeleteObject(hbitmap); hbitmap = 0; }
|
|
|
|
|
|
|
|
if(menu.state.image.width && menu.state.image.height) {
|
|
|
|
nall::image nallImage = menu.state.image;
|
|
|
|
nallImage.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
|
|
|
nallImage.alphaBlend(GetSysColor(COLOR_MENU)); //Windows does not alpha blend menu icons properly (leaves black outline)
|
|
|
|
nallImage.scale(GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK), Interpolation::Linear);
|
|
|
|
hbitmap = CreateBitmap(nallImage);
|
|
|
|
}
|
2011-02-24 09:25:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//Windows actions lack the ability to toggle visibility.
|
|
|
|
//To support this, menus must be destroyed and recreated when toggling any action's visibility.
|
2013-05-02 11:25:45 +00:00
|
|
|
void pMenu::update(Window& parentWindow, Menu* parentMenu) {
|
2011-02-24 09:25:20 +00:00
|
|
|
this->parentMenu = parentMenu;
|
2011-09-05 03:48:23 +00:00
|
|
|
this->parentWindow = &parentWindow;
|
|
|
|
|
2011-02-24 09:25:20 +00:00
|
|
|
if(hmenu) DestroyMenu(hmenu);
|
|
|
|
hmenu = CreatePopupMenu();
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
for(auto& action : menu.state.action) {
|
2011-09-05 03:48:23 +00:00
|
|
|
action.p.parentMenu = &menu;
|
2011-02-24 09:25:20 +00:00
|
|
|
action.p.parentWindow = &parentWindow;
|
|
|
|
|
|
|
|
unsigned enabled = action.state.enabled ? 0 : MF_GRAYED;
|
|
|
|
if(dynamic_cast<Menu*>(&action)) {
|
2013-05-02 11:25:45 +00:00
|
|
|
Menu& item = (Menu&)action;
|
2012-01-26 06:50:09 +00:00
|
|
|
if(action.state.visible) {
|
|
|
|
item.p.update(parentWindow, &menu);
|
|
|
|
AppendMenu(hmenu, MF_STRING | MF_POPUP | enabled, (UINT_PTR)item.p.hmenu, utf16_t(item.state.text));
|
|
|
|
|
|
|
|
if(item.state.image.width && item.state.image.height) {
|
2013-05-02 11:25:45 +00:00
|
|
|
MENUITEMINFO mii = {sizeof(MENUITEMINFO)};
|
2012-01-26 06:50:09 +00:00
|
|
|
//Windows XP and below displays MIIM_BITMAP + hbmpItem in its own column (separate from check/radio marks)
|
|
|
|
//this causes too much spacing, so use a custom checkmark image instead
|
|
|
|
mii.fMask = MIIM_CHECKMARKS;
|
|
|
|
mii.hbmpUnchecked = item.p.hbitmap;
|
|
|
|
SetMenuItemInfo(hmenu, (UINT_PTR)item.p.hmenu, FALSE, &mii);
|
|
|
|
}
|
|
|
|
}
|
2011-02-27 09:05:10 +00:00
|
|
|
} else if(dynamic_cast<Separator*>(&action)) {
|
2013-05-02 11:25:45 +00:00
|
|
|
Separator& item = (Separator&)action;
|
2012-01-26 06:50:09 +00:00
|
|
|
if(action.state.visible) {
|
|
|
|
AppendMenu(hmenu, MF_SEPARATOR | enabled, item.p.id, L"");
|
|
|
|
}
|
2011-02-27 09:05:10 +00:00
|
|
|
} else if(dynamic_cast<Item*>(&action)) {
|
2013-05-02 11:25:45 +00:00
|
|
|
Item& item = (Item&)action;
|
2012-01-15 08:29:57 +00:00
|
|
|
if(action.state.visible) {
|
|
|
|
AppendMenu(hmenu, MF_STRING | enabled, item.p.id, utf16_t(item.state.text));
|
|
|
|
|
|
|
|
if(item.state.image.width && item.state.image.height) {
|
|
|
|
MENUITEMINFO mii = { sizeof(MENUITEMINFO) };
|
|
|
|
//Windows XP and below displays MIIM_BITMAP + hbmpItem in its own column (separate from check/radio marks)
|
|
|
|
//this causes too much spacing, so use a custom checkmark image instead
|
|
|
|
mii.fMask = MIIM_CHECKMARKS;
|
|
|
|
mii.hbmpUnchecked = item.p.hbitmap;
|
|
|
|
SetMenuItemInfo(hmenu, item.p.id, FALSE, &mii);
|
|
|
|
}
|
|
|
|
}
|
2011-02-27 09:05:10 +00:00
|
|
|
} else if(dynamic_cast<CheckItem*>(&action)) {
|
2013-05-02 11:25:45 +00:00
|
|
|
CheckItem& item = (CheckItem&)action;
|
2012-01-26 06:50:09 +00:00
|
|
|
if(action.state.visible) {
|
|
|
|
AppendMenu(hmenu, MF_STRING | enabled, item.p.id, utf16_t(item.state.text));
|
|
|
|
}
|
2011-02-24 09:25:20 +00:00
|
|
|
if(item.state.checked) item.setChecked();
|
2011-02-27 09:05:10 +00:00
|
|
|
} else if(dynamic_cast<RadioItem*>(&action)) {
|
2013-05-02 11:25:45 +00:00
|
|
|
RadioItem& item = (RadioItem&)action;
|
2012-01-26 06:50:09 +00:00
|
|
|
if(action.state.visible) {
|
|
|
|
AppendMenu(hmenu, MF_STRING | enabled, item.p.id, utf16_t(item.state.text));
|
|
|
|
}
|
2011-02-24 09:25:20 +00:00
|
|
|
if(item.state.checked) item.setChecked();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-03-15 13:11:33 +00:00
|
|
|
|
|
|
|
}
|