aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/wnd/contextmenu.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/contextmenu.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/wnd/contextmenu.cpp')
-rw-r--r--Src/Wasabi/api/wnd/contextmenu.cpp170
1 files changed, 170 insertions, 0 deletions
diff --git a/Src/Wasabi/api/wnd/contextmenu.cpp b/Src/Wasabi/api/wnd/contextmenu.cpp
new file mode 100644
index 00000000..25a17aeb
--- /dev/null
+++ b/Src/Wasabi/api/wnd/contextmenu.cpp
@@ -0,0 +1,170 @@
+#include <precomp.h>
+
+#include "contextmenu.h"
+#include <api/service/svcs/svc_contextcmd.h>
+#include <bfc/string/StringW.h>
+
+#define DD_CONTEXTMENUENTRY "ContextMenuEntry v1"
+
+class ContextMenuEntry
+{
+public:
+ ContextMenuEntry(DragItem *_item, svc_contextCmd *_svc, int _pos, const wchar_t *txt, int _sortval, int _addorder) :
+ svc(_svc), item(_item), pos(_pos), text(txt), sortval(_sortval), addorder(_addorder) { }
+
+ svc_contextCmd *svc;
+ DragItem *item;
+ int pos;
+ StringW text, submenu_text;
+ int sortval;
+ int addorder;
+};
+
+class ContextMenuEntryCompare
+{
+public:
+ static int compareItem(void *p1, void* p2)
+ {
+ ContextMenuEntry *e1 = static_cast<ContextMenuEntry*>(p1);
+ ContextMenuEntry *e2 = static_cast<ContextMenuEntry*>(p2);
+ int ret = CMP3(e1->sortval, e2->sortval);
+ if (ret == 0) ret = CMP3(e1->addorder, e2->addorder);
+ return ret;
+ }
+};
+
+ContextMenu::ContextMenu(ifc_window *sourceWnd, DragItem *_item, bool autopop, const wchar_t *_menu_path)
+ : PopupMenu(sourceWnd), item(_item), menu_path(_menu_path)
+{
+ populate();
+ if (autopop) popAtMouse();
+}
+
+ContextMenu::ContextMenu(ifc_window *sourceWnd, int x, int y, DragItem *_item, bool autopop, const wchar_t *_menu_path)
+ : PopupMenu(sourceWnd), item(_item), menu_path(_menu_path)
+{
+ populate();
+ if (autopop) popAtXY(x, y);
+}
+
+ContextMenu::ContextMenu(DragItem *_item, const wchar_t *_menu_path)
+ : item(_item), menu_path(_menu_path)
+{
+ populate();
+}
+
+ContextMenu::~ContextMenu()
+{
+ entries.deleteAll();
+
+ // release all services
+ for (int i = 0; i < svclist.getNumItems(); i++)
+ SvcEnum::release(svclist.enumItem(i));
+}
+
+void ContextMenu::addDragItem(DragItem *_item, const wchar_t *_menu_path)
+{
+ menu_path = _menu_path;
+ item = _item;
+ populate();
+}
+
+void ContextMenu::populate()
+{
+ if (item == NULL) return ;
+
+ ContextCmdEnum cce(item, menu_path);
+ svc_contextCmd *svc;
+ int i, j, addorder = 0;
+
+ // make a list of all context cmd services that match the menu path
+ for (i = 0; (svc = cce.getNext()) != NULL; i++)
+ {
+ for (j = 0; ; j++)
+ {
+ const wchar_t *text = svc->getCommand(item, j);
+ if (text == NULL) break;
+ if (!wcscmp(text, L"~~~SEP~~~")) text = NULL; // sorry, magic value
+ ContextMenuEntry *entry = new ContextMenuEntry(item, svc, j, text, svc->getSortVal(item, j), addorder++);
+ entries.addItem(entry);
+ }
+ // save the service * to release later
+ svclist.addItem(svc);
+ }
+
+ // sorting is implicit but just making sure
+ entries.sort();
+
+ PtrList<StringW> submenu_list;
+
+#ifdef WASABI_COMPILE_COMPONENTS
+ GUID prev = INVALID_GUID;
+#endif
+ // populate the menu from the list
+ int n = entries.getNumItems();
+ for (i = 0; i < n; i++)
+ {
+ ContextMenuEntry *entry = entries.enumItem(i);
+ if (entry->text.isempty())
+ {
+ addSeparator();
+ }
+ else
+ {
+ svc_contextCmd *svc = entry->svc;
+#ifdef WASABI_COMPILE_COMPONENTS
+ GUID g = WASABI_API_SVC->service_getOwningComponent(svc);
+ if (g != prev && prev != INVALID_GUID && i < n - 1)
+ addSeparator();
+ prev = g;
+#endif
+ if (!svc->getSubMenu(item, menu_path))
+ {
+ int checked = entry->svc->getChecked(item, entry->pos);
+ int enabled = entry->svc->getEnabled(item, entry->pos);
+ addCommand(entry->text, reinterpret_cast<intptr_t>(entry), checked, !enabled);
+ }
+ else
+ {
+ entry->submenu_text = svc->getSubMenuText(menu_path);
+ if (!entry->submenu_text.isempty())
+ {
+ for (j = 0; j < submenu_list.getNumItems(); j++)
+ if (!WCSICMP(*submenu_list[j], entry->submenu_text)) break;
+ if (j >= submenu_list.getNumItems())
+ {
+ submenu_list.addItem(new StringW(entry->submenu_text));
+ addSubMenuCallback(entry->submenu_text, this, reinterpret_cast<intptr_t>(entry));
+ }
+ }
+ }
+ }
+ }
+ submenu_list.deleteAll();
+}
+
+void ContextMenu::onPostPop(intptr_t result)
+{
+ //if (result == -1 || result == -2 || result == -3) return; //FUCKO need real enums
+ if (result < 0) return ;
+ ASSERT(result != 0xcccccccc);
+ ContextMenuEntry *entry = reinterpret_cast<ContextMenuEntry*>(result);
+ if (entry == NULL) return ;
+ entry->svc->onCommand(entry->item, entry->pos);
+}
+
+PopupMenu *ContextMenu::popupMenuCallback(PopupMenu *parent, intptr_t param)
+{
+ ContextMenuEntry *entry = reinterpret_cast<ContextMenuEntry*>(param);
+ StringW path = menu_path;
+ if (!path.isempty())
+ path.cat(L"/");
+ path.cat(entry->submenu_text);
+ ContextMenu *ret = new ContextMenu(entry->item, path);
+ if (ret->getNumCommands() <= 0)
+ {
+ delete ret;
+ ret = NULL;
+ }
+ return ret;
+}