winamp/Src/Wasabi/api/wnd/popup.cpp
2024-09-24 14:54:57 +02:00

1721 lines
38 KiB
C++

#include <precomp.h>
#include <api/wnd/api_window.h>
#include <api/locales/xlatstr.h>
#ifndef WASABI_WANT_FF_POPUP
#include "popup.h"
#ifdef _WIN32
#include "../../../Plugins/General/gen_ff/wa2frontend.h"
extern HINSTANCE hInstance;
#endif
PopupMenu::PopupMenu()
{
hmenu = NULL;
parent = NULL;
}
PopupMenu::PopupMenu(ifc_window *_parent)
{
hmenu = NULL;
parent = _parent;
}
PopupMenu::PopupMenu(PopupMenu *_parent)
{
hmenu = NULL;
parent = _parent->getParent();
}
PopupMenu::~PopupMenu()
{
invalidateMenu();
entries.deleteAll();
sortedentries.removeAll();
}
void PopupMenu::addSubMenu(PopupMenu *menu, const wchar_t *text, int disabled)
{
invalidateMenu();
PopupMenuEntry *e = new PopupMenuEntry(text, -1, menu, 0, disabled);
entries.addItem(e);
sortedentries.addItem(e);
}
void PopupMenu::addSubMenuCallback(const wchar_t *text, PopupMenuCallback *cb, int param)
{
invalidateMenu();
PopupMenuEntry *e = new PopupMenuEntry(text, -1, NULL, 0, 0, cb, param);
entries.addItem(e);
sortedentries.addItem(e);
}
void PopupMenu::addCommand(const wchar_t *text, int command, int checked, int disabled, int addpos)
{
invalidateMenu();
PopupMenuEntry *e = new PopupMenuEntry(text, command, NULL, checked, disabled);
entries.addItem(e);
sortedentries.addItem(e, addpos);
}
void PopupMenu::addSeparator(int addpos)
{
invalidateMenu();
PopupMenuEntry *e = new PopupMenuEntry(NULL, -1, NULL, 0, 0);
entries.addItem(e);
sortedentries.addItem(e, addpos);
};
void PopupMenu::checkCommand(int cmd, int check)
{
invalidateMenu();
PopupMenuEntry *e = sortedentries.findItem((const wchar_t *) & cmd);
if (e) e->setChecked(check);
}
void PopupMenu::disableCommand(int cmd, int disable)
{
invalidateMenu();
PopupMenuEntry *e = sortedentries.findItem((const wchar_t *) & cmd);
if (e) e->setDisabled(disable);
}
int PopupMenu::popAtXY(int x, int y, int native)
{
rebuildMenu();
#ifdef _WIN32
if (!native)
return DoTrackPopup(getOSMenuHandle(), TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, x, y, (parent ? parent->gethWnd() : WASABI_API_WND->main_getRootWnd()->gethWnd())) - 1;
else
return TrackPopupMenuEx(getOSMenuHandle(), TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, x, y, (parent ? parent->gethWnd() : WASABI_API_WND->main_getRootWnd()->gethWnd()), NULL) - 1;
#elif defined(__APPLE__)
return PopUpMenuSelect(getOSMenuHandle(), x, y, 0);
#endif
}
int PopupMenu::popAnchored(int type)
{ // dropped off the sourceWnd given above
#ifdef _WIN32
int flag = 0;
switch (type)
{
case POPUP_ANCHOR_UL: flag |= TPM_LEFTALIGN | TPM_TOPALIGN; break;
case POPUP_ANCHOR_LL: flag |= TPM_LEFTALIGN | TPM_BOTTOMALIGN; break;
case POPUP_ANCHOR_UR: flag |= TPM_RIGHTALIGN | TPM_TOPALIGN; break;
case POPUP_ANCHOR_LR: flag |= TPM_RIGHTALIGN | TPM_BOTTOMALIGN; break;
}
#endif
rebuildMenu();
int x, y;
Wasabi::Std::getMousePos(&x, &y);
#ifdef _WIN32
return DoTrackPopup(getOSMenuHandle(), flag | TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, x, y, (parent ? parent->gethWnd() : WASABI_API_WND->main_getRootWnd()->gethWnd())) - 1;
#elif defined(__APPLE__)
return PopUpMenuSelect(getOSMenuHandle(), x, y, 0);
#endif
}
int PopupMenu::popAtMouse()
{
rebuildMenu();
int x, y;
Wasabi::Std::getMousePos(&x, &y);
#ifdef _WIN32
return DoTrackPopup(getOSMenuHandle(), TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, x, y, (parent ? parent->gethWnd() : WASABI_API_WND->main_getRootWnd()->gethWnd())) - 1;
#elif defined(__APPLE__)
return PopUpMenuSelect(getOSMenuHandle(), x, y, 0);
#endif
}
int PopupMenu::getNumCommands()
{
return entries.getNumItems();
}
const wchar_t *PopupMenu::getCommandText(int command)
{
PopupMenuEntry *e = sortedentries.findItem((const wchar_t *) &command);
if (e) return e->getText();
return NULL;
}
OSMENUHANDLE PopupMenu::getOSMenuHandle()
{
rebuildMenu();
return hmenu;
}
void PopupMenu::rebuildMenu()
{
#ifdef WIN32
if (hmenu != NULL) return ;
hmenu = CreatePopupMenu();
int i = 0;
foreach(entries)
PopupMenuEntry *e = entries.getfor();
OSMENUHANDLE submenu = NULL;
if (e->getCallback())
{
PopupMenu *m = e->getCallback()->popupMenuCallback(this, e->getCallbackParam());
if (m) submenu = m->getOSMenuHandle();
}
else if (e->isSubmenu())
{
submenu = e->getSubmenu()->getOSMenuHandle();
}
InsertMenuW(hmenu, i++, MF_BYPOSITION | (e->getChecked() ? MF_CHECKED : MF_UNCHECKED) | (e->getDisabled() ? MF_GRAYED : 0) | (e->isSeparator() ? MF_SEPARATOR : (e->isSubmenu() ? MF_POPUP : 0) | (e->getText() ? MF_STRING : 0)), e->isSubmenu() ? (UINT_PTR)submenu : e->getCommand() + 1, e->getText());
endfor;
#else
if (hmenu != NULL) return ;
CreateNewMenu(0, 0, &hmenu);
foreach(entries)
PopupMenuEntry *e = entries.getfor();
OSMENUHANDLE submenu = NULL;
if (e->getCallback())
{
PopupMenu *m = e->getCallback()->popupMenuCallback(this, e->getCallbackParam());
if (m) submenu = m->getOSMenuHandle();
}
else if (e->isSubmenu())
{
submenu = e->getSubmenu()->getOSMenuHandle();
}
const wchar_t *name = e->getText();
CFStringRef menuStr = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *)name, wcslen(name)*sizeof(wchar_t), kCFStringEncodingUTF32, false);
MenuItemIndex newMenuItem;
MenuItemAttributes menuAttr = kMenuItemAttrIgnoreMeta;
if (e->getDisabled())
menuAttr|=kMenuItemAttrDisabled;
if (e->isSeparator())
menuAttr|=kMenuItemAttrSeparator;
AppendMenuItemTextWithCFString(hmenu, menuStr, menuAttr, e->getCommand(), &newMenuItem);
if (submenu)
SetMenuItemHierarchicalMenu(hmenu, newMenuItem, submenu);
if (e->getChecked())
CheckMenuItem(hmenu, newMenuItem, true);
CFRelease(menuStr);
endfor;
#endif
}
void PopupMenu::invalidateMenu()
{
#ifdef WIN32
if (hmenu) DestroyMenu(hmenu);
#elif defined(__APPLE__)
if (hmenu) DisposeMenu(hmenu);
#endif
hmenu = NULL;
}
void PopupMenu::abort()
{
#ifdef WIN32
HWND w = (parent ? parent->gethWnd() : WASABI_API_WND->main_getRootWnd()->gethWnd());
PostMessage(w, WM_LBUTTONDOWN, 0, 0xdeadc0de);
PostMessage(w, WM_LBUTTONUP, 0, 0xdeadc0de);
#elif defined(__APPLE__)
CancelMenuTracking(hmenu, true, 0);
#endif
}
#else // WASABI_WANT_FF_POPUP
#include <bfc/api/api_wnd.h>
#include <bfc/api/api_syscb.h>
#include "popup.h"
#include <bfc/notifmsg.h>
#include <studio/assert.h>
#include <studio/api.h>
#include <bfc/wasabi_std.h>
#include <common/xlatstr.h>
#include <bfc/wnds/buttwnd.h>
#include <bfc/util/pathparse.h>
#include <bfc/attribs/cfgitem.h>
#include <common/script/c_script/c_guiobject.h>
#include <common/script/c_script/c_menubutton.h>
#include <common/script/scriptguid.h>
#include <common/menusurface.h>
#ifndef WANT_NEW_POPUPMENU
#define SELMARGIN 1
// todo:
// check marks
// more?
PopupMenu::PopupMenu(ifc_window *sourceWnd)
{
ASSERT(sourceWnd != NULL);
setStartHidden(1);
setRenderRatio(1.0);
parentRootWnd = sourceWnd;
parentWnd = sourceWnd->getOsWindowHandle();
reverse_side = 0;
kbdhooked = 0;
keyctrl = 0;
toplevelmenu = 0;
chainmenu = NULL;
lastxy.x = lastxy.y = -1;
WASABI_API_WND->appdeactivation_push_disallow(this);
init(sourceWnd->getOsModuleHandle(), parentWnd, TRUE);
WASABI_API_WND->appdeactivation_pop_disallow(this);
}
PopupMenu::PopupMenu()
{
setStartHidden(1);
setRenderRatio(1.0);
parentRootWnd = NULL;
parentWnd = INVALIDOSWINDOWHANDLE;
chainmenu = NULL;
reverse_side = 0;
kbdhooked = 0;
toplevelmenu = 0;
keyctrl = 0;
lastxy.x = lastxy.y = -1;
WASABI_API_WND->appdeactivation_push_disallow(this);
init(hInstance, WASABI_API_WND->main_getRootWnd()->gethWnd(), TRUE);
WASABI_API_WND->appdeactivation_pop_disallow(this);
}
PopupMenu::PopupMenu(HWND sourceWnd)
{
parentRootWnd = NULL;
parentWnd = sourceWnd;
setStartHidden(1);
setRenderRatio(1.0);
reverse_side = 0;
kbdhooked = 0;
toplevelmenu = 0;
keyctrl = 0;
chainmenu = NULL;
lastxy.x = lastxy.y = -1;
WASABI_API_WND->appdeactivation_push_disallow(this);
init(hInstance, sourceWnd, TRUE);
WASABI_API_WND->appdeactivation_pop_disallow(this);
}
PopupMenu::PopupMenu(PopupMenu *sourceWnd)
{
parentRootWnd = sourceWnd;
parentWnd = sourceWnd->gethWnd();
setStartHidden(1);
setRenderRatio(1.0);
reverse_side = 0;
kbdhooked = 0;
toplevelmenu = 0;
chainmenu = NULL;
keyctrl = 0;
lastxy.x = lastxy.y = -1;
WASABI_API_WND->appdeactivation_push_disallow(this);
init(sourceWnd, TRUE);
WASABI_API_WND->appdeactivation_pop_disallow(this);
}
int PopupMenu::onInit()
{
POPUPMENU_PARENT::onInit();
bdown = 0;
lastitem = -1;
rcp = 0;
openmenuid = -1;
timerset = 0;
timeritem = -1;
rcode = -1;
toplevelmenu = 0;
disable_autopop = 0;
popupdelay = 250; //TODO: Config
#ifdef WASABI_COMPILE_CONFIG
// {9149C445-3C30-4e04-8433-5A518ED0FDDE}
const GUID uioptions_guid =
{ 0x9149c445, 0x3c30, 0x4e04, { 0x84, 0x33, 0x5a, 0x51, 0x8e, 0xd0, 0xfd, 0xde } };
setTransparency(_intVal(WASABI_API_CONFIG->config_getCfgItemByGuid(uioptions_guid), "Popup menu alpha", 255));
#else
setTransparency(255);
#endif
tex = "wasabi.popup.menu.background";
ful = "wasabi.popup.menu.border.topLeft";
fur = "wasabi.popup.menu.border.topRight";
fll = "wasabi.popup.menu.border.bottomLeft";
flr = "wasabi.popup.menu.border.bottomRight";
fl = "wasabi.popup.menu.border.left";
fr = "wasabi.popup.menu.border.right";
ft = "wasabi.popup.menu.border.top";
fb = "wasabi.popup.menu.border.bottom";
sl = "wasabi.popup.menu.selection.left";
sr = "wasabi.popup.menu.selection.right";
sc = "wasabi.popup.menu.selection.center";
return 1;
}
PopupMenu::~PopupMenu()
{
if (kbdhooked)
{
WASABI_API_WND->unhookKeyboard(this);
kbdhooked = 0;
}
int x, n;
n = items.getNumItems();
for (x = 0; x < n; x ++)
{
if (items[x])
{
if (items[x]->butt) delete items[x]->butt;
if (items[x]->menu) delete items[x]->menu;
delete items[x];
}
}
}
void PopupMenu::addSubMenu(PopupMenu *menu, const wchar_t *text, int disabled)
{
ASSERT(text != NULL);
ButtonWnd *b = new ButtonWnd();
b->init(this);
b->setParent(this);
b->setNotifyId( -1);
b->setButtonText(translateButtonText(text), 14);
// b->setTextJustification(BUTTONJUSTIFY_LEFT);
b->setTextAlign(TEXTALIGN_LEFT);
b->setColors("wasabi.popup.text", "wasabi.popup.hiliteText", "wasabi.button.dimmedText");
if (disabled) b->enableButton(FALSE);
ItemT *t = new ItemT;
t->issep = 0;
t->butt = b;
t->menu = menu;
t->cmd = -1;
t->cb = NULL;
items.addItem(t);
}
void PopupMenu::addSubMenuImage(PopupMenu *menu, const char *bitmap, const char *pushedbitmap, const char *highlightbitmap)
{
ButtonWnd *b = new ButtonWnd();
b->init(this);
b->setParent(this);
b->setBitmaps(bitmap, pushedbitmap, highlightbitmap);
b->setBitmapCenter(1);
b->setNotifyId( -1);
b->setAutoDim(1);
b->setColors("wasabi.popup.text", "wasabi.popup.hiliteText", "wasabi.button.dimmedText");
ItemT *t = new ItemT;
t->issep = 0;
t->butt = b;
t->menu = menu;
t->cb = NULL;
t->cmd = -1;
items.addItem(t);
}
void PopupMenu::addSubMenuCallback(const wchar_t *text, PopupMenuCallback *cb, int param)
{
ASSERT(text != NULL);
ASSERT(cb != NULL);
ButtonWnd *b = new ButtonWnd();
b->init(this);
b->setParent(this);
b->setNotifyId( -1);
b->setButtonText(translateButtonText(text), 14);
// b->setTextJustification(BUTTONJUSTIFY_LEFT);
b->setTextAlign(TEXTALIGN_LEFT);
b->setColors("wasabi.popup.text", "wasabi.popup.hiliteText", "wasabi.button.dimmedText");
ItemT *t = new ItemT;
t->issep = 0;
t->butt = b;
t->menu = 0;
t->cb = cb;
t->cbparam = param;
t->cmd = -1;
items.addItem(t);
}
void PopupMenu::addSeparator(int addpos)
{
ButtonWnd *b = new ButtonWnd();
b->init(this);
b->setParent(this);
b->setNotifyId( -1);
b->setBitmaps("wasabi.popup.menu.seperator");
b->setBitmapCenter(0);
b->enableButton(0);
b->setColors("wasabi.popup.text", "wasabi.popup.hiliteText", "wasabi.button.dimmedText");
ItemT *t = new ItemT;
t->issep = 1;
t->butt = b;
t->menu = 0;
t->cb = NULL;
t->cmd = -1;
items.addItem(t, addpos);
}
void PopupMenu::addCommandImage(const char *bitmap, const char *pushedbitmap, const char *highlightbitmap, int command, int checked, int disabled, int addpos)
{
ButtonWnd *b = new ButtonWnd();
b->init(this);
b->setParent(this);
b->setBitmaps(bitmap, pushedbitmap, highlightbitmap);
b->setBitmapCenter(1);
b->setNotifyId(command);
b->enableButton(disabled ? 0 : 1);
b->setChecked(checked ? 1 : 0);
b->setAutoDim(1);
b->setColors("wasabi.popup.text", "wasabi.popup.hiliteText", "wasabi.button.dimmedText");
ItemT *t = new ItemT;
t->issep = 0;
t->butt = b;
t->menu = 0;
t->cb = NULL;
t->cmd = -1;
items.addItem(t);
}
void PopupMenu::addCommand(const wchar_t *_txt, int command, int checked, int disabled, int addpos)
{
if (!_txt)
{
addSeparator();
return ;
}
String txt = translateButtonText(_txt);
ButtonWnd *b = new ButtonWnd();
b->init(this);
b->setParent(this);
b->setNotifyId(disabled ? -1 : command);
#ifdef WASABI_COMPILE_LOCALES
const wchar_t *bind = (command != 0) ? WASABI_API_LOCALE->locales_getBindFromAction(command) : NULL;
if (bind) txt += StringPrintfW(L"\t%s", bind);
#endif
b->setButtonText(txt);
// b->setTextJustification(BUTTONJUSTIFY_LEFT);
b->setTextAlign(TEXTALIGN_LEFT);
b->enableButton(disabled ? 0 : 1);
b->setChecked(checked);
if (checked == 2) b->setAlpha(128);
b->setColors("wasabi.popup.text", "wasabi.popup.hiliteText", "wasabi.button.dimmedText");
ItemT *t = new ItemT;
t->issep = 0;
t->butt = b;
t->menu = 0;
t->cmd = command;
t->cb = NULL;
ASSERT(PTRLIST_POS_LAST == -1); //BU
items.addItem(t, addpos);
}
void PopupMenu::disableCommand(int cmd, int disable)
{
for (int i = 0;i < items.getNumItems();i++)
if (items.enumItem(i)->cmd == cmd)
{
if (items.enumItem(i)->butt)
items.enumItem(i)->butt->enableButton(!!!disable);
break;
}
}
void PopupMenu::checkCommand(int cmd, int check)
{
for (int i = 0;i < items.getNumItems();i++)
if (items.enumItem(i)->cmd == cmd)
{
if (items.enumItem(i)->butt)
items.enumItem(i)->butt->setChecked(check);
break;
}
}
const wchar_t *PopupMenu::getCommandText(int command)
{
for (int i = 0;i < items.getNumItems();i++)
if (items.enumItem(i)->cmd == command && items.enumItem(i)->butt)
return items.enumItem(i)->butt->getName();
return NULL;
}
int PopupMenu::popAtXY(int x, int y)
{
toplevelmenu = 1;
rcode = -1;
if (items.getNumItems())
{
POINT pt = {x, y};
#ifdef WIN32
HWND oldcw = GetCapture(); // nonportable
ifc_window *oldcrw = (ifc_window*)GetWindowLong(oldcw, GWL_USERDATA);
if (oldcrw != NULL) oldcrw->cancelCapture();
#endif
WASABI_API_SYSCB->syscb_registerCallback(static_cast<SkinCallbackI*>(this));
showAtXY(x, y, &rcode);
beginCapture();
MSG msg;
#ifdef WIN32
SetCursor(LoadCursor(NULL, IDC_ARROW)); // NONPORTABLE
#endif
while (rcode == -1 && GetMessage( &msg, INVALIDOSWINDOWHANDLE, 0, 0 ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
endCapture();
hide();
// if (hadcapture && under) under->beginCapture();
#ifdef WIN32
if (rcode == -2 || rcode == -3)
{
DWORD p = GetMessagePos();
POINT pt;
pt.x = (signed short)LOWORD(p);
pt.y = (signed short)HIWORD(p);
HWND w = WindowFromPoint(pt);
ScreenToClient(w, &pt);
p = (pt.x & 0xFFFF) | (pt.y << 16);
//if (under) under->getRootParent()->wndProc(under->getRootParent()->gethWnd(), WM_MOUSEMOVE, 0, p);
//PostMessage(w, (rcode == -2) ? WM_MOUSEMOVE : WM_RBUTTONDOWN, 0, p);
//PostMessage(w, (rcode == -2) ? WM_LBUTTONDOWN : WM_RBUTTONDOWN, 0, p);
}
#else
DebugString("portme: popup.cpp pass on click");
#endif
}
WASABI_API_SYSCB->syscb_deregisterCallback(static_cast<SkinCallbackI*>(this));
//DebugString("appdeactivation_pop_disallow\n");
WASABI_API_WND->appdeactivation_pop_disallow(this);
onPostPop(rcode);
#ifdef WASABI_COMPILE_SKIN
if (!switchskinto.isempty())
{
WASABI_API_SKIN->skin_switchSkin(switchskinto.getNonConstVal());
switchskinto = "";
}
#endif
return rcode;
}
void PopupMenu::showAtXY(int x, int y, int *rc, int revside, int parentW)
{
int i, n;
int w = 0, h = 0;
lastitem = -1;
rcp = rc;
n = items.getNumItems();
for (i = 0; i < n; i ++)
{
if (items[i]->menu || items[i]->cb)
items[i]->butt->setRightBitmap("wasabi.popup.menu.submenu");
if (!items[i]->butt->getChecked()) items[i]->butt->setChecked( -1);
h += items[i]->butt->getHeight();
items[i]->butt->setUseBaseTexture(0);
items[i]->butt->setBorders(0);
int tw = items[i]->butt->getWidth();
if (w < tw)w = tw;
}
int neww = w + 6 + fl.getWidth() + fr.getWidth();
int newh = h + 6 + ft.getHeight() + fb.getHeight();
POINT p = {x, y};
RECT vp;
Std::getViewport(&vp, &p);
// maintain parent's reversal state
reverse_side = revside;
int savx = x;
if (reverse_side) x -= (neww + parentW);
if (x + neww > vp.right || x < 0)
{
reverse_side = !reverse_side;
x = savx;
if (reverse_side) x -= (neww + parentW);
}
if (y + newh > vp.bottom) y -= newh;
if (x < vp.left) x = vp.left;
if (y < vp.top) y = vp.top;
resize(x, y, neww, newh);
h = 0;
for (i = 0; i < n; i ++)
{
int lh = h;
h += items[i]->butt->getHeight();
items[i]->butt->resize(3 + fl.getWidth(), 3 + lh + ft.getHeight(), w, h - lh);
items[i]->butt->setHilite(0);
items[i]->butt->setPushed(0);
}
WASABI_API_WND->appdeactivation_push_disallow(this);
#ifdef WIN32
SetWindowPos(gethWnd(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
#elif defined(LINUX)
Atom NET_STATE = XInternAtom( Linux::getDisplay(), "_NET_WM_STATE", True );
Atom state[2];
state[0] = XInternAtom( Linux::getDisplay(), "_NET_WM_STATE_SKIP_TASKBAR", True );
state[1] = XInternAtom( Linux::getDisplay(), "_NET_WM_STATE_ABOVE", True );
if ( NET_STATE && state[0] && state[1] )
{
XChangeProperty( Linux::getDisplay(), gethWnd(), NET_STATE, XA_ATOM, 32,
PropModeReplace, (unsigned char *)state, 2 );
}
#endif
WASABI_API_WND->appdeactivation_pop_disallow(this);
setVisible(1);
}
void PopupMenu::onSetVisible(int v)
{
POPUPMENU_PARENT::onSetVisible(v);
if (v && !kbdhooked)
{
WASABI_API_WND->hookKeyboard(this);
kbdhooked = 1;
}
else if (!v && kbdhooked)
{
WASABI_API_WND->unhookKeyboard(this);
kbdhooked = 0;
}
}
void PopupMenu::hide()
{
if (lastitem >= 0 && items[lastitem]->menu)
{
items[lastitem]->menu->hide();
lastitem = -1;
}
setVisible(0);
}
int PopupMenu::popAnchored(int type)
{
RECT wr;
if (parentRootWnd != NULL)
{
parentRootWnd->getWindowRect(&wr);
}
else if (parentWnd != INVALIDOSWINDOWHANDLE)
{
#ifdef WIN32
GetWindowRect(parentWnd, &wr);
#else
DebugString("portme PopupMenu::popAnchored\n");
#endif
}
else
{
ASSERTALWAYS("can't call popAnchored without instantiating with a parent window");
}
switch (type)
{
case POPUP_ANCHOR_UL: return popAtXY(wr.left, wr.top);
case POPUP_ANCHOR_LL: return popAtXY(wr.left, wr.bottom);
case POPUP_ANCHOR_UR: return popAtXY(wr.right, wr.top);
case POPUP_ANCHOR_LR: return popAtXY(wr.right, wr.bottom);
}
return 0;
}
int PopupMenu::popAtMouse()
{
int x, y;
Std::getMousePos(&x, &y);
return popAtXY(x, y);
}
int PopupMenu::childNotify(ifc_window *child, int msg, intptr_t p1, intptr_t p2)
{
if (msg == ChildNotify::BUTTON_LEFTPUSH || msg == ChildNotify::BUTTON_RIGHTPUSH)
{
for (int i = 0;i < items.getNumItems();i++)
{
if (child == items[i]->butt && (items[i]->menu || items[i]->cb))
{
if (!items[i]->butt->getEnabled()) continue;
if (items[i]->cb) initMenuCallback(i);
if (!items[i]->menu) continue;
if (openmenuid == i) continue;
RECT r;
if (openmenuid >= 0)
{
items[openmenuid]->menu->hide();
openmenuid = -1;
}
items[i]->butt->getWindowRect(&r);
PopupMenu *p = items[i]->menu;
p->showAtXY(r.right, r.top, rcp, reverse_side, r.right - r.left);
if (p1)
{
p->selectFirst();
}
openmenuid = i;
}
}
// mig: changed this to call getNotifyId();
// *rcp=p1;
*rcp = child->getNotifyId();
return 0;
}
if (msg == ChildNotify::POPUP_SUBMENUCLOSE)
{
for (int i = 0;i < items.getNumItems();i++)
{
if (child == items[i]->menu)
{
if (openmenuid != i) continue;
items[openmenuid]->menu->hide();
openmenuid = -1;
return 0;
}
}
}
return POPUPMENU_PARENT::childNotify(child, msg, p1, p2);
}
void PopupMenu::selectFirst()
{
ButtonWnd *b = NULL;
int i;
for (i = 0; i < items.getNumItems(); i++)
{
b = items.enumItem(i)->butt;
if (b != NULL) break;
}
if (b == NULL) return ;
lastitem = i;
b->setHilite(1);
invalidate();
}
int PopupMenu::getWhichItem(POINT &p)
{
int x, n;
RECT r2;
getWindowRect(&r2);
n = items.getNumItems();
for (x = 0; x < n; x ++)
{
RECT r;
items[x]->butt->getWindowRect(&r);
r.right = r2.right;
r.left = r2.left;
if (Std::pointInRect(r, p))
{
return x;
}
}
return -1;
}
int PopupMenu::isMine(int x, int y)
{
RECT r;
getWindowRect(&r);
POINT p = {x, y};
if (Std::pointInRect(r, p)) return 1;
if (lastitem >= 0 && items[lastitem]->menu && items[lastitem]->menu->isMine(x, y)) return 1;
return 0;
}
void PopupMenu::setFriendlyId(const char *id)
{
friendid = id;
}
int PopupMenu::onLeftButtonDown(int x, int y)
{
clientToScreen(&x, &y);
onButtonDown(1, x, y);
return 0;
}
int PopupMenu::onRightButtonDown(int x, int y)
{
clientToScreen(&x, &y);
onButtonDown(2, x, y);
return 0;
}
int PopupMenu::onMouseMove(int x, int y)
{
POPUPMENU_PARENT::onMouseMove(x, y);
POINT pnt = {x, y};
clientToScreen(&pnt);
if (keyctrl && lastxy.x == pnt.x && lastxy.y == pnt.y) return 1;
keyctrl = 0;
lastxy = pnt;
if (lastitem >= 0)
{
if (openmenuid >= 0 && items[openmenuid]->menu && items[openmenuid]->menu->isMine(pnt.x, pnt.y))
{
if (lastitem != openmenuid)
{
items[lastitem]->butt->setHilite(0);
items[lastitem]->butt->setPushed(0);
items[openmenuid]->butt->setHilite(1);
items[openmenuid]->butt->setPushed(1);
invalidateItem(lastitem);
lastitem = openmenuid;
invalidateItem(lastitem);
}
resetTimer( -1);
items[openmenuid]->menu->screenToClient(&pnt);
items[openmenuid]->menu->onMouseMove(pnt.x, pnt.y);
return 0;
}
}
int p = getWhichItem(pnt);
if (p >= 0)
{
ItemT *it = items[p];
if (!it->issep)
{
if (p != lastitem)
{
if (lastitem >= 0)
{
/* if (items[lastitem]->menu)
{
items[lastitem]->menu->hide();
}*/
items[lastitem]->butt->setHilite(0);
items[lastitem]->butt->setPushed(0);
invalidateItem(lastitem);
}
invalidateItem(lastitem);
lastitem = p;
invalidateItem(lastitem);
items[p]->butt->setHilite(1);
if (bdown) items[p]->butt->setPushed(1);
/* if (items[p]->menu) {
RECT r;
items[p]->butt->getWindowRect(&r);
items[p]->menu->showAtXY(r.right,r.top,rcp);
}*/
resetTimer(p);
invalidateItem(lastitem);
}
}
else
{
RECT _r;
getClientRect(&_r);
int inside = (x >= 0 && y >= 0 && x <= _r.right - _r.left && y <= _r.bottom - _r.top);
if (lastitem >= 0 && !inside)
{
items[lastitem]->butt->setHilite(0);
items[lastitem]->butt->setPushed(0);
invalidateItem(lastitem);
lastitem = -1;
}
}
}
else
{
if (!friendid.isempty())
{
ifc_window *w = WASABI_API_WND->rootWndFromPoint(&pnt);
if (w != NULL)
{
MenuButtonSurface *s = static_cast<MenuButtonSurface *>(w->getInterface(menuButtonSurfaceGuid));
if (s != NULL)
{
if (s->getParentWnd() != parentRootWnd)
{
const char *str = s->getParentMenuId();
if (STRCASEEQLSAFE(str, friendid))
{
abort();
rcode = -4;
chainmenu = s;
}
}
}
}
}
}
return 0;
}
void PopupMenu::resetTimer(int p)
{
if (timerset)
{
killTimer(POPUP_TIMERID);
timeritem = -1;
}
if (p >= 0 && !disable_autopop)
{
setTimer(POPUP_TIMERID, popupdelay);
timeritem = p;
timerset = 1;
}
}
void PopupMenu::timerCallback(int id)
{
switch (id)
{
case POPUP_TIMERID:
killTimer(POPUP_TIMERID);
timerset = 0;
if (timeritem == openmenuid)
{
timeritem = -1;
break;
}
if (openmenuid >= 0 && items[openmenuid]->menu)
{
items[openmenuid]->menu->hide();
openmenuid = -1;
}
if (timeritem >= 0)
{
if (items[timeritem]->cb) initMenuCallback(timeritem);
if (items[timeritem]->butt->getEnabled() && items[timeritem]->menu)
{
RECT r;
items[timeritem]->butt->getWindowRect(&r);
items[timeritem]->menu->showAtXY(r.right, r.top, rcp, reverse_side, r.right - r.left);
openmenuid = timeritem;
}
timeritem = -1;
}
break;
default:
POPUPMENU_PARENT::timerCallback(id);
break;
}
}
void PopupMenu::initMenuCallback(int item)
{
int a = rcode;
rcode = 0;
PopupMenu *p = items[item]->cb->popupMenuCallback(this, items[item]->cbparam);
rcode = a;
if (p)
{
items[item]->cb = NULL;
items[item]->menu = p;
}
}
int PopupMenu::onLeftButtonUp(int x, int y)
{
clientToScreen(&x, &y);
onButtonUp(1, x, y);
return 0;
}
int PopupMenu::onRightButtonUp(int x, int y)
{
clientToScreen(&x, &y);
onButtonUp(2, x, y);
return 0;
}
void PopupMenu::onButtonDown(int wb, int x, int y)
{
POINT pos = {x, y};
RECT r;
bdown |= wb;
if (lastitem >= 0)
{
if (items[lastitem]->menu && items[lastitem]->menu->isMine(pos.x, pos.y))
{
items[lastitem]->menu->onButtonDown(wb, x, y);
return ;
}
}
getWindowRect(&r);
if (!Std::pointInRect(r, pos))
{
rcode = (wb == 1) ? -2 : -3;
}
else
{
int item = getWhichItem(pos);
if (item >= 0) items[item]->butt->setPushed(1);
}
}
void PopupMenu::onButtonUp(int wb, int x, int y)
{
if (lastitem >= 0)
{
POINT pos = {x, y};
if (items[lastitem]->menu && items[lastitem]->menu->isMine(pos.x, pos.y))
{
items[lastitem]->menu->onButtonUp(wb, x, y);
return ;
}
}
if (bdown & wb)
{
bdown &= ~wb;
POINT pnt = {x, y};
int p = getWhichItem(pnt);
if (p >= 0)
{
items[p]->butt->onLeftPush(x, y);
if (!bdown)
{
items[p]->butt->setPushed(0);
}
}
}
}
int PopupMenu::onKillFocus()
{
#ifndef LINUX
if (rcode == -1) rcode = -2;
#endif
return POPUPMENU_PARENT::onKillFocus();
}
// only translates the text, not the optional accelerator
String PopupMenu::translateButtonText(const wchar_t *text)
{
PathParser pp(text, "\t");
String ret;
for (int i = 0; i < pp.getNumStrings(); i++)
{
if (i == 0) ret += _(pp.enumString(i)); // translate first
else ret += pp.enumString(i);
if (i != pp.getNumStrings() - 1) ret += "\t";
}
return ret;
}
int PopupMenu::onPaint(Canvas *canvas)
{
PaintBltCanvas paintcanvas;
if (canvas == NULL)
{
if (!paintcanvas.beginPaint(this)) return 0;
canvas = &paintcanvas;
}
POPUPMENU_PARENT::onPaint(canvas);
RECT r, r2;
getClientRect(&r);
tex.getBitmap()->blitTile(canvas, &r);
// left side
ful.getBitmap()->blitAlpha(canvas, 0, 0);
r2.left = 0;
r2.right = fl.getWidth();
r2.top = ful.getHeight();
r2.bottom = r.bottom - fll.getHeight();
fl.getBitmap()->stretchToRectAlpha(canvas, &r2);
fll.getBitmap()->blitAlpha(canvas, 0, r.bottom - fll.getHeight());
// right side
fur.getBitmap()->blitAlpha(canvas, r.right - fur.getWidth(), 0);
r2.left = r.right - fr.getWidth();
r2.right = r.right;
r2.top = fur.getHeight();
r2.bottom = r.bottom - flr.getHeight();
fr.getBitmap()->stretchToRectAlpha(canvas, &r2);
flr.getBitmap()->blitAlpha(canvas, r.right - flr.getWidth(), r.bottom - flr.getHeight());
// top
r2.left = ful.getWidth();
r2.right = r.right - fur.getWidth();
r2.top = 0;
r2.bottom = ft.getHeight();
ft.getBitmap()->stretchToRectAlpha(canvas, &r2);
// bottom
r2.left = fll.getWidth();
r2.right = r.right - flr.getWidth();
r2.top = r.bottom - fb.getHeight();
r2.bottom = r.bottom;
fb.getBitmap()->stretchToRectAlpha(canvas, &r2);
// selection bar
if (lastitem != -1)
{
ItemT *it = items[lastitem];
RECT r3, c;
it->butt->getClientRect(&r3);
// left
r2.left = r.left + fl.getWidth() + SELMARGIN;
r2.top = r.top + r3.top;
r2.right = r2.left + sl.getWidth();
r2.bottom = r2.top + (r3.bottom - r3.top);
sl.getBitmap()->stretchToRectAlpha(canvas, &r2);
c = r2;
c.left = c.right - 1;
// right
r2.right = r.right - fr.getWidth() - SELMARGIN;
r2.left = r2.right - sr.getWidth();
sr.getBitmap()->stretchToRectAlpha(canvas, &r2);
c.right = r2.left;
// center
sc.getBitmap()->stretchToRectAlpha(canvas, &c);
}
return 1;
}
void PopupMenu::invalidateItem(int i)
{
if (i < 0 || i >= items.getNumItems()) return ;
RECT r, r2, r3;
getClientRect(&r);
ItemT *it = items[i];
it->butt->getClientRect(&r3);
r2.left = r.left + fl.getWidth();
r2.top = r.top + r3.top;
r2.right = r.right - fl.getWidth();
r2.bottom = r2.top + (r3.bottom - r3.top);
invalidateRect(&r2);
}
int PopupMenu::getNumCommands()
{
return items.getNumItems();
}
#ifdef WASABI_COMPILE_SKIN
int PopupMenu::skincb_onCheckPreventSwitch(const char *skinname)
{
switchskinto = skinname;
rcode = -2;
return 1;
}
#endif
int PopupMenu::onSysKeyDown(int code, int d)
{
int a = POPUPMENU_PARENT::onSysKeyDown(code, d);
/* if (d & (1<<29)) {
//ALT key pressed, abort menu (mimics win32 popup behavior)
abort();
if(getParent()) SendMessageW(getParent()->gethWnd(),WM_SYSKEYDOWN,code,d);
return 0;
}*/
if (a == 0)
return onKeyDown(code);
return 0;
}
int PopupMenu::onKeyDown(int code)
{
if (POPUPMENU_PARENT::onKeyDown(code)) return 1;
switch (code)
{
case STDKEY_DOWN:
navigate(1);
return 1;
case STDKEY_UP:
navigate( -1);
return 1;
case STDKEY_RETURN:
navigate(0, 1);
return 1;
case STDKEY_RIGHT:
navigate(0, 0);
return 1;
case VK_LEFT:
if (!toplevelmenu)
notifyParent(ChildNotify::POPUP_SUBMENUCLOSE);
return 1;
case VK_ESCAPE:
abort();
return 1;
}
return 0;
}
void PopupMenu::abort()
{
if (toplevelmenu)
rcode = -2;
else
notifyParent(ChildNotify::POPUP_SUBMENUCLOSE);
}
void PopupMenu::navigate(int p, int f)
{
keyctrl = 1;
int i = lastitem;
ItemT *t = NULL;
if (p == 0)
{
if (lastitem >= 0)
{
ItemT *t = items.enumItem(lastitem);
if (f || t->menu || t->cb)
{
t->butt->setHilite(1);
t->butt->setPushed(1);
childNotify(t->butt, ChildNotify::BUTTON_LEFTPUSH, 1, 0);
}
}
return ;
}
while (!t || t->issep)
{
i += p;
i %= items.getNumItems();
if (i == -1) i = items.getNumItems() - 1;
if (i >= items.getNumItems()) return ;
t = items.enumItem(i);
}
if (t->butt)
{
int i;
i = items.searchItem(t);
t->butt->setHilite(1);
if (lastitem != -1)
{
ItemT *s = items.enumItem(lastitem);
if (s->butt)
{
s->butt->setPushed(0);
s->butt->setHilite(0);
}
}
lastitem = i;
invalidate();
}
}
#else
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
// 3rd level popup menu, yay
#include "script/c_script/c_text.h"
#include "script/c_script/c_rootobj.h"
#include "script/c_script/c_button.h"
#include "script/c_script/c_group.h"
PopupMenu::PopupMenu(ifc_window *sourceWnd)
{
ASSERT(sourceWnd != NULL);
myInit();
setParent(sourceWnd);
sourceWnd->setAllowDeactivation(0);
init(HINSTANCEfromHWND(getParent()->gethWnd()), sourceWnd->gethWnd(), TRUE);
sourceWnd->setAllowDeactivation(1);
}
PopupMenu::PopupMenu()
{
myInit();
setParent(WASABI_API_WND->main_getRootWnd());
WASABI_API_WND->main_getRootWnd()->setAllowDeactivation(0);
init(hInstance, WASABI_API_WND->main_getRootWnd()->gethWnd(), TRUE);
WASABI_API_WND->main_getRootWnd()->setAllowDeactivation(1);
}
PopupMenu::PopupMenu(PopupMenu *sourceWnd)
{
myInit();
setParent(sourceWnd);
sourceWnd->setAllowDeactivation(0);
init(GetModuleHandle(NULL), sourceWnd->gethWnd(), TRUE);
sourceWnd->setAllowDeactivation(1);
}
void PopupMenu::myInit()
{
setVirtual(0);
setStartHidden(1);
setRenderRatio(1.0);
reverse_side = 0;
rcode = 0;
submenus = 0;
c_grouplist = NULL;
WASABI_API_WND->popupexit_register(this, this);
}
PopupMenu::~PopupMenu()
{
WASABI_API_WND->popupexit_deregister(this);
delete c_grouplist;
}
int PopupMenu::onInit()
{
POPUPMENU_PARENT::onInit();
#ifdef WASABI_COMPILE_CONFIG
// {9149C445-3C30-4e04-8433-5A518ED0FDDE}
const GUID uioptions_guid =
{ 0x9149c445, 0x3c30, 0x4e04, { 0x84, 0x33, 0x5a, 0x51, 0x8e, 0xd0, 0xfd, 0xde } };
setTransparency(_intVal(WASABI_API_CONFIG->config_getCfgItemByGuid(uioptions_guid), "Popup menu alpha", 255));
#else
setTransparency(255);
#endif
setContent("wasabi.popup.main.group");
return 1;
}
int PopupMenu::popAtXY(int x, int y)
{
rcode = -1;
if (1 /*items.getNumItems()*/)
{
POINT pt = {x, y};
//DebugString("appdeactivation_push_disallow\n");
WASABI_API_WND->appdeactivation_push_disallow(this);
showAtXY(x, y, &rcode);
//MSG msg;
/*while (rcode == -1 && GetMessage( &msg, NULL, 0, 0 )) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}*/
SetCursor(LoadCursor(NULL, IDC_ARROW)); // NONPORTABLE
int quit = 0;
while (!quit)
{
rcode = getGuiObject()->guiobject_runModal();
if (rcode & 0x40000000 && rcode != -2 && rcode != -1)
{
int submenuentry = rcode & ~0x40000000;
ItemT *t = items.enumItem(submenuentry);
if (t->cb != NULL)
initMenuCallback(submenuentry);
if (t->menu != NULL)
{
setAllowDeactivation(0);
t->menu->showAtXY(0, 0, NULL, 0, 0);
setAllowDeactivation(1);
}
}
else
quit = 1;
}
setVisible(0);
}
//DebugString("appdeactivation_pop_disallow\n");
WASABI_API_WND->appdeactivation_pop_disallow(this);
onPostPop(rcode);
return rcode;
}
void PopupMenu::showAtXY(int x, int y, int *rc, int revside /* =0 */, int parentW /* =0 */)
{
fillContent();
int neww = getPreferences(SUGGESTED_W);
int newh = getPreferences(SUGGESTED_H);;
POINT p = {x, y};
RECT vp;
Std::getViewport(&vp, &p);
// maintain parent's reversal state
reverse_side = revside;
int savx = x;
if (reverse_side) x -= (neww + parentW);
if (x + neww > vp.right || x < 0)
{
reverse_side = !reverse_side;
x = savx;
if (reverse_side) x -= (neww + parentW);
}
if (y + newh > vp.bottom) y -= newh;
if (x < vp.left) x = vp.left;
if (y < vp.top) y = vp.top;
resize(x, y, neww, newh);
WASABI_API_WND->appdeactivation_push_disallow(this);
#ifdef WIN32
SetWindowPos(gethWnd(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
#else
Atom NET_STATE = XInternAtom( Linux::getDisplay(), "_NET_WM_STATE", True );
Atom state[2];
state[0] = XInternAtom( Linux::getDisplay(), "_NET_WM_STATE_SKIP_TASKBAR", True );
state[1] = XInternAtom( Linux::getDisplay(), "_NET_WM_STATE_ABOVE", True );
if ( NET_STATE && state[0] && state[1] )
{
XChangeProperty( Linux::getDisplay(), gethWnd(), NET_STATE, XA_ATOM, 32,
PropModeReplace, (unsigned char *)state, 2 );
}
#endif
WASABI_API_WND->appdeactivation_pop_disallow(this);
setVisible(1);
}
int PopupMenu::popAnchored(int type)
{
RECT wr;
getParent()->getWindowRect(&wr);
switch (type)
{
case POPUP_ANCHOR_UL: return popAtXY(wr.left, wr.top);
case POPUP_ANCHOR_LL: return popAtXY(wr.left, wr.bottom);
case POPUP_ANCHOR_UR: return popAtXY(wr.right, wr.top);
case POPUP_ANCHOR_LR: return popAtXY(wr.right, wr.bottom);
}
return 0;
}
int PopupMenu::popAtMouse()
{
int x, y;
Std::getMousePos(&x, &y);
return popAtXY(x, y);
}
void PopupMenu::onNewContent()
{
POPUPMENU_PARENT::onNewContent();
if (isVisible())
fillContent();
}
void PopupMenu::fillContent()
{
GuiObject *grouplist = findObject("popup.content");
if (grouplist != NULL)
{
delete c_grouplist;
c_grouplist = new C_GroupList(*grouplist);
c_grouplist->removeAll();
c_grouplist->setRedraw(0);
for (int i = 0;i < items.getNumItems();i++)
{
addItem(items.enumItem(i));
}
c_grouplist->setRedraw(1);
}
}
void PopupMenu::addItem(ItemT *i)
{
if (c_grouplist == NULL) return ;
switch (i->type)
{
case POPUPITEM_TYPE_TEXT:
{
c_grouplist->instantiate("wasabi.popup.text.item", 1);
ScriptObject *o = c_grouplist->enumItem(c_grouplist->getNumItems() - 1);
if (o != NULL)
{
C_Group grp(o);
C_RootObject g(o);
g.notify("arrow", StringPrintfW(L"%d", (submenus) ? 1 : 0), 0, 0);
g.notify("checkmark", StringPrintfW(L"%d", menuchecks ? 1 : 0), 0, 0);
g.notify("id", StringPrintfW(L"%d", i->cmd), 0, 0);
ScriptObject *check = grp.getObject("popup.item.checkmark");
if (check != NULL)
{
C_Button toggle(check);
toggle.setActivated(i->checked);
}
ScriptObject *arrow = grp.getObject("popup.item.submenuarrow");
if (check != NULL)
{
C_Button sub(arrow);
sub.setActivated((i->menu != NULL || i->cb != NULL));
}
ScriptObject *txt = grp.getObject("popup.item.text");
if (txt != NULL)
{
C_Text itemtxt(txt);
itemtxt.setText(i->txt);
}
}
break;
}
case POPUPITEM_TYPE_IMAGE:
c_grouplist->instantiate("wasabi.popup.image.item", 1);
break;
case POPUPITEM_TYPE_SEPARATOR:
c_grouplist->instantiate("wasabi.popup.separator.item", 1);
break;
}
}
String PopupMenu::translateButtonText(const wchar_t *text)
{
PathParser pp(text, "\t");
String ret;
for (int i = 0; i < pp.getNumStrings(); i++)
{
if (i == 0) ret += _(pp.enumString(i)); // translate first
else ret += pp.enumString(i);
if (i != pp.getNumStrings() - 1) ret += "\t";
}
return ret;
}
void PopupMenu::addCommand(const wchar_t *_txt, int command, int checked, int disabled, int addpos)
{
if (!_txt)
{
addSeparator();
return ;
}
String txt = translateButtonText(_txt);
#ifdef WASABI_COMPILE_LOCALES
const char *bind = WASABI_API_LOCALE->locales_getBindFromAction(command);
if (bind) txt += StringPrintfW(L"\t%s", bind);
#endif
ItemT *t = new ItemT;
t->type = POPUPITEM_TYPE_TEXT;
t->cmd = command;
t->txt = txt;
t->checked = checked;
t->menu = NULL;
t->cb = NULL;
t->cmd = -1;
ASSERT(PTRLIST_POS_LAST == -1); //BU
items.addItem(t, addpos);
}
int PopupMenu::popupexitcb_onExitPopup()
{
getGuiObject()->guiobject_endModal( -2);
return 1;
}
void PopupMenu::addSubMenu(PopupMenu *menu, const wchar_t *text)
{
ASSERT(text != NULL);
submenus = 1;
ItemT *t = new ItemT;
t->type = POPUPITEM_TYPE_TEXT;
t->cmd = items.getNumItems() | 0x40000000;
t->txt = translateButtonText(text);
t->checked = 0;
t->menu = menu;
t->cb = NULL;
t->cmd = -1;
t->cmd = -1;
items.addItem(t);
}
void PopupMenu::addSubMenuCallback(const wchar_t *text, PopupMenuCallback *cb, int param)
{
ASSERT(text != NULL);
ASSERT(cb != NULL);
ItemT *t = new ItemT;
submenus = 1;
t->type = POPUPITEM_TYPE_TEXT;
t->checked = 0;
t->cmd = items.getNumItems() | 0x40000000;
t->menu = NULL;
t->cb = cb;
t->cbparam = param;
t->txt = translateButtonText(text);
t->cmd = -1;
items.addItem(t);
}
void PopupMenu::initMenuCallback(int item)
{
int a = rcode;
rcode = 0;
PopupMenu *p = items[item]->cb->popupMenuCallback(this, items[item]->cbparam);
rcode = a;
if (p)
{
items[item]->cb = NULL;
items[item]->menu = p;
}
}
#endif
#endif //WASABI_WANT_FF_POPUP