diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/api/wnd/popup.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/wnd/popup.cpp')
-rw-r--r-- | Src/Wasabi/api/wnd/popup.cpp | 1720 |
1 files changed, 1720 insertions, 0 deletions
diff --git a/Src/Wasabi/api/wnd/popup.cpp b/Src/Wasabi/api/wnd/popup.cpp new file mode 100644 index 00000000..1019fa91 --- /dev/null +++ b/Src/Wasabi/api/wnd/popup.cpp @@ -0,0 +1,1720 @@ +#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 |