aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/wnd/popup.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/api/wnd/popup.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/wnd/popup.cpp')
-rw-r--r--Src/Wasabi/api/wnd/popup.cpp1720
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