diff options
author | Jean-Francois Mauguit <jfmauguit@mac.com> | 2024-09-24 09:03:25 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-24 09:03:25 -0400 |
commit | bab614c421ed7ae329d26bf028c4a3b1d2450f5a (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/Library/ml_devices/navigation.cpp | |
parent | 4bde6044fddf053f31795b9eaccdd2a5a527d21f (diff) | |
parent | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (diff) | |
download | winamp-bab614c421ed7ae329d26bf028c4a3b1d2450f5a.tar.gz |
Merge pull request #5 from WinampDesktop/community
Merge to main
Diffstat (limited to 'Src/Plugins/Library/ml_devices/navigation.cpp')
-rw-r--r-- | Src/Plugins/Library/ml_devices/navigation.cpp | 1073 |
1 files changed, 1073 insertions, 0 deletions
diff --git a/Src/Plugins/Library/ml_devices/navigation.cpp b/Src/Plugins/Library/ml_devices/navigation.cpp new file mode 100644 index 00000000..25fade94 --- /dev/null +++ b/Src/Plugins/Library/ml_devices/navigation.cpp @@ -0,0 +1,1073 @@ +#include "main.h" +#include "./navigation.h" + +#include <strsafe.h> + +#define DEVICES_NAVITEM_PREFIX L"ml_devices_" + +static HNAVITEM navigationRoot = NULL; +static size_t deviceHandler = 0; + +static HNAVITEM +NavigationItem_Insert(HNAVITEM parent, + HNAVITEM insertAfter, + unsigned int mask, + int itemId, + const wchar_t *name, + const wchar_t *displayName, + unsigned int style, + int image, + LPARAM param) +{ + NAVITEM *item; + NAVINSERTSTRUCT nis = {0}; + + nis.hInsertAfter = insertAfter; + nis.hParent = parent; + item = &nis.item; + + item->cbSize = sizeof(NAVITEM); + item->id = itemId; + + if (0 != (NIMF_IMAGE & mask)) + mask |= NIMF_IMAGESEL; + + item->mask = mask; + item->pszText = (wchar_t*)displayName; + item->pszInvariant = (wchar_t*)name; + item->style = style; + item->styleMask = style; + item->iImage = image; + item->iSelectedImage = image; + item->lParam = param; + + if (!wcsnicmp(L"ml_devices_all_sources", item->pszInvariant, 22)) + { + // and this will allow us to make the cloud library + // root do a web page or a sources view as needed... + return NULL; + } + + return MLNavCtrl_InsertItem(Plugin_GetLibraryWindow(), &nis); +} + +static BOOL +NavigationItem_Delete(HNAVITEM item) +{ + return MLNavCtrl_DeleteItem(Plugin_GetLibraryWindow(), item); +} + +static HNAVITEM +NavigationItem_GetFromMessage(INT msg, INT_PTR param) +{ + return (msg < ML_MSG_NAVIGATION_FIRST) ? + MLNavCtrl_FindItemById(Plugin_GetLibraryWindow(), param) : + (HNAVITEM)param; +} + +static HNAVITEM +NavigationItem_Find(HNAVITEM root, const wchar_t *name, BOOL allow_root = 0) +{ + NAVCTRLFINDPARAMS find = {0}; + HNAVITEM item; + HWND libraryWindow; + + if (NULL == name) + return NULL; + + libraryWindow = Plugin_GetLibraryWindow(); + if (NULL == libraryWindow) + return NULL; + + find.pszName = (wchar_t*)name; + find.cchLength = -1; + find.compFlags = NICF_INVARIANT; + find.fFullNameSearch = FALSE; + + item = MLNavCtrl_FindItemByName(libraryWindow, &find); + if (NULL == item) + return NULL; + + if (!allow_root) + { + // if allowed then we can look for root level items which + // is really for getting 'cloud' devices to another group + if (NULL != root && + root != MLNavItem_GetParent(libraryWindow, item)) + { + item = NULL; + } + } + + return item; +} + +static wchar_t * +NavigationItem_GetNameFromDeviceName(wchar_t *buffer, size_t bufferMax, const char *name) +{ + wchar_t *cursor; + size_t length; + BOOL allocated; + + if (NULL == name || '\0' == *name) + return NULL; + + length = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0); + if (ARRAYSIZE(DEVICES_NAVITEM_PREFIX) > bufferMax || + length > (bufferMax - (ARRAYSIZE(DEVICES_NAVITEM_PREFIX) - 1))) + { + bufferMax = length + ARRAYSIZE(DEVICES_NAVITEM_PREFIX) - 1; + buffer = String_Malloc(bufferMax); + if (NULL == buffer) + return NULL; + + allocated = TRUE; + } + else + allocated = FALSE; + + if (FAILED(StringCchCopyEx(buffer, bufferMax, DEVICES_NAVITEM_PREFIX, &cursor, &length, 0)) || + 0 == MultiByteToWideChar(CP_UTF8, 0, name, -1, cursor, (int)length)) + { + if (FALSE != allocated) + String_Free(buffer); + + return NULL; + } + + return buffer; +} + +static HNAVITEM +NavigationItem_FindFromDeviceName(HNAVITEM root, const char *name) +{ + wchar_t buffer[1], *itemName; + HNAVITEM item; + + if (NULL == root) + return NULL; + + itemName = NavigationItem_GetNameFromDeviceName(buffer, ARRAYSIZE(buffer), name); + if (NULL == itemName) + return NULL; + + item = NavigationItem_Find(root, itemName); + + if (itemName != buffer) + String_Free(itemName); + + return item; +} + +static HNAVITEM +NavigationItem_FindFromDevice(HNAVITEM root, ifc_device *device) +{ + if (NULL == device) + return NULL; + + return NavigationItem_FindFromDeviceName(root, device->GetName()); +} + +static BOOL +NavigationItem_DisplayDeviceMenu(HNAVITEM item, const char *deviceName, HWND hostWindow, POINT pt) +{ + HMENU menu; + ifc_device *device; + unsigned int commandId; + BOOL succeeded; + HWND libraryWindow; + + libraryWindow = Plugin_GetLibraryWindow(); + + if (NULL == item|| NULL == deviceName) + return FALSE; + + if (NULL == WASABI_API_DEVICES || + S_OK != WASABI_API_DEVICES->DeviceFind(deviceName, &device)) + { + return FALSE; + } + + menu = CreatePopupMenu(); + if (NULL != menu) + { + if (0 == Menu_InsertDeviceItems(menu, 0, 100, device, DeviceCommandContext_NavigationMenu)) + { + DestroyMenu(menu); + menu = NULL; + } + } + + device->Release(); + + if (NULL == menu) + return FALSE; + + succeeded = FALSE; + + if (item == MLNavCtrl_GetSelection(libraryWindow)) + { + commandId = Menu_FindItemByAnsiStringData(menu, "view_open"); + if ((unsigned int)-1 != commandId) + EnableMenuItem(menu, commandId, MF_BYCOMMAND | MF_DISABLED); + } + + commandId = Menu_TrackPopup(Plugin_GetLibraryWindow(), menu, + TPM_LEFTALIGN | TPM_TOPALIGN | TPM_VERPOSANIMATION | TPM_VERTICAL | TPM_RETURNCMD, + pt.x, pt.y, hostWindow, NULL); + + if (0 != commandId) + { + const char *command; + + command = (const char*)Menu_GetItemData(menu, commandId, FALSE); + if (NULL != command) + { + if (NULL != WASABI_API_DEVICES && + S_OK == WASABI_API_DEVICES->DeviceFind(deviceName, &device)) + { + BOOL commandProcessed; + + commandProcessed = FALSE; + + if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, 0, command, -1, "view_open", -1)) + { + succeeded = MLNavItem_Select(libraryWindow, item); + commandProcessed = succeeded; + } + else if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, 0, command, -1, "rename", -1)) + { + succeeded = MLNavItem_EditTitle(libraryWindow, item); + commandProcessed = succeeded; + } + + if (FALSE == commandProcessed && + SUCCEEDED(device->SendCommand(command, hostWindow, 0))) + { + succeeded = TRUE; + } + + device->Release(); + } + } + } + else + { + if (ERROR_SUCCESS == GetLastError()) + succeeded = TRUE; + } + + Menu_FreeItemData(menu, 0, -1); + + return succeeded; +} + +static BOOL +NavigationItem_DisplayRootMenu(HNAVITEM item, HWND hostWindow, POINT pt) +{ + HMENU pluginMenu, menu; + BOOL succeeded; + + if (NULL == item) + return FALSE; + + pluginMenu = Plugin_LoadMenu(); + if (NULL == pluginMenu) + return FALSE; + + succeeded = FALSE; + + menu = GetSubMenu(pluginMenu, 0); + if (NULL != menu) + { + HWND libraryWindow; + HNAVITEM selectedItem; + + libraryWindow = Plugin_GetLibraryWindow(); + + selectedItem = MLNavCtrl_GetSelection(libraryWindow); + + EnableMenuItem(menu, ID_VIEW_OPEN, MF_BYCOMMAND | ((item != selectedItem) ? MF_ENABLED : MF_DISABLED)); + SetMenuDefaultItem(menu, ID_VIEW_OPEN, FALSE); + + unsigned int commandId = Menu_TrackPopup(Plugin_GetLibraryWindow(), menu, + TPM_LEFTALIGN | TPM_TOPALIGN | TPM_VERPOSANIMATION | TPM_VERTICAL | TPM_RETURNCMD, + pt.x, pt.y, hostWindow, NULL); + + if (0 != commandId) + { + switch(commandId) + { + case ID_VIEW_OPEN: + MLNavItem_Select(libraryWindow, item); + break; + case ID_DISCOVERY_BEGIN: + Plugin_BeginDiscovery(); + break; + case ID_PLUGIN_HELP: + Plugin_ShowHelp(); + break; + } + } + else + { + if (ERROR_SUCCESS == GetLastError()) + succeeded = TRUE; + } + } + + DestroyMenu(pluginMenu); + + return succeeded; +} + +static BOOL +Navigation_GetDeviceTitle(ifc_device *device, wchar_t *buffer, size_t bufferMax) +{ + size_t read, write; + + if (NULL == device || + FAILED(device->GetDisplayName(buffer, bufferMax))) + { + return FALSE; + } + + for(read = 0, write = 0;; read++) + { + if (read == bufferMax) + return FALSE; + + if (L'\r' == buffer[read]) + continue; + + if (L'\n' == buffer[read] || + L'\t' == buffer[read] || + L'\b' == buffer[read]) + { + buffer[write] = L' '; + } + + buffer[write] = buffer[read]; + if (L'\0' == buffer[read]) + break; + + write++; + } + + return TRUE; +} + +static BOOL +Navigation_DeviceAdd(HNAVITEM root, ifc_device *device) +{ + HNAVITEM item, insertAfter = NCI_LAST; + wchar_t nameBuffer[256] = {0}, *itemName; + wchar_t title[512] = {0}; + int iconIndex; + + if (NULL == device) + return FALSE; + + itemName = NavigationItem_GetNameFromDeviceName(nameBuffer, ARRAYSIZE(nameBuffer), device->GetName()); + if (NULL == itemName) + return FALSE; + + if (NULL != NavigationItem_Find(root, itemName)) + { + if (itemName != nameBuffer) + String_Free(itemName); + + return FALSE; + } + + if (FALSE == Navigation_GetDeviceTitle(device, title, ARRAYSIZE(title))) + title[0] = L'\0'; + + iconIndex = NavigationIcons_GetDeviceIconIndex(device); + + // filter the cloud devices to their own group + if (!lstrcmpiA(device->GetConnection(), "cloud")) + { + HNAVITEM cloud = NavigationItem_Find(navigationRoot, L"cloud_sources", TRUE); + if (cloud != NULL) + { + root = cloud; + HNAVITEM transfers = NavigationItem_Find(0, L"cloud_transfers", TRUE); + + // to maintain some specific orders, we need to alter the insert position + if (!wcsnicmp(L"ml_devices_hss", itemName, 14)) + { + insertAfter = transfers; + if (!insertAfter) insertAfter = NCI_LAST; + } + else if (!wcsnicmp(L"ml_devices_local_desktop", itemName, 24)) + { + insertAfter = NavigationItem_Find(0, L"ml_devices_hss", TRUE); + if (!insertAfter) insertAfter = NCI_LAST; + } + + // when adding children, change from the cloud source to the open/closed arrow + HWND libraryWindow = Plugin_GetLibraryWindow(); + if (NULL != libraryWindow && transfers) + { + NAVITEM itemInfo = {0}; + itemInfo.hItem = cloud; + itemInfo.cbSize = sizeof(itemInfo); + itemInfo.mask = NIMF_IMAGE | NIMF_IMAGESEL; + itemInfo.iImage = itemInfo.iSelectedImage = -1; + MLNavItem_SetInfo(libraryWindow, &itemInfo); + } + } + } + + item = NavigationItem_Insert(root, insertAfter, + NIMF_TEXT | NIMF_TEXTINVARIANT | NIMF_IMAGE | NIMF_IMAGESEL | NIMF_STYLE, + 0, itemName, title, NIS_ALLOWEDIT, iconIndex, 0L); + + if (NULL == item) + NavigationIcons_ReleaseIconIndex(iconIndex); + + if (itemName != nameBuffer) + String_Free(itemName); + + if (NULL == item) + return FALSE; + + device->SetNavigationItem(item); + + return TRUE; +} + +static BOOL +Navigation_DeviceRemove(HNAVITEM root, ifc_device *device) +{ + HNAVITEM item; + + item = NavigationItem_FindFromDevice(root, device); + if (NULL == item) + return FALSE; + + return NavigationItem_Delete(item); +} + +static BOOL +Navigation_DeviceTitleChanged(HNAVITEM root, ifc_device *device) +{ + NAVITEM itemInfo; + wchar_t buffer[1024] = {0}; + + itemInfo.hItem = NavigationItem_FindFromDevice(root, device); + if (NULL == itemInfo.hItem) + return FALSE; + + if (FALSE == Navigation_GetDeviceTitle(device, buffer, ARRAYSIZE(buffer))) + return FALSE; + + itemInfo.cbSize = sizeof(itemInfo); + itemInfo.pszText = buffer; + itemInfo.cchTextMax = -1; + itemInfo.mask = NIMF_TEXT; + + return MLNavItem_SetInfo(Plugin_GetLibraryWindow(), &itemInfo); +} + +static BOOL +Navigation_DeviceIconChanged(HNAVITEM root, ifc_device *device) +{ + NAVITEM itemInfo; + int iconIndex; + HWND libraryWindow; + + if (NULL == root || NULL == device) + return FALSE; + + libraryWindow = Plugin_GetLibraryWindow(); + + itemInfo.hItem = NavigationItem_FindFromDevice(root, device); + if (NULL == itemInfo.hItem) + return FALSE; + + iconIndex = NavigationIcons_GetDeviceIconIndex(device); + + itemInfo.cbSize = sizeof(itemInfo); + itemInfo.mask = NIMF_IMAGE; + + if (FALSE == MLNavItem_GetInfo(libraryWindow, &itemInfo)) + { + NavigationIcons_ReleaseIconIndex(iconIndex); + return FALSE; + } + + if (itemInfo.iImage == iconIndex) + { + NavigationIcons_ReleaseIconIndex(iconIndex); + return TRUE; + } + + NavigationIcons_ReleaseIconIndex(itemInfo.iImage); + itemInfo.mask = NIMF_IMAGE | NIMF_IMAGESEL; + itemInfo.iImage = iconIndex; + itemInfo.iSelectedImage = iconIndex; + + if (FALSE == MLNavItem_SetInfo(libraryWindow, &itemInfo)) + { + NavigationIcons_ReleaseIconIndex(iconIndex); + return FALSE; + } + + return TRUE; +} + +static void +Navigation_AddExistingDevices(HNAVITEM root) +{ + ifc_device *device; + ifc_deviceobject *object; + ifc_deviceobjectenum *enumerator; + + if (NULL == WASABI_API_DEVICES) + return; + + if (FAILED(WASABI_API_DEVICES->DeviceEnumerate(&enumerator))) + return; + + while(S_OK == enumerator->Next(&object, 1, NULL)) + { + if (SUCCEEDED(object->QueryInterface(IFC_Device, (void**)&device))) + { + if (FALSE == device->GetHidden() && + FALSE != device->GetAttached()) + { + Navigation_DeviceAdd(root, device); + } + device->Release(); + } + object->Release(); + } + enumerator->Release(); +} + +static void +Navigation_DeviceCb(ifc_device *device, DeviceEvent eventId, void *user) +{ + HNAVITEM rootItem; + rootItem = (HNAVITEM)user; + + switch(eventId) + { + case Event_DeviceAdded: + if (FALSE != device->GetAttached()) + Navigation_DeviceAdd(rootItem, device); + break; + case Event_DeviceRemoved: + if (FALSE != device->GetAttached()) + Navigation_DeviceRemove(rootItem, device); + break; + case Event_DeviceHidden: + if (FALSE != device->GetAttached()) + Navigation_DeviceRemove(rootItem, device); + break; + case Event_DeviceShown: + if (FALSE != device->GetAttached()) + Navigation_DeviceAdd(rootItem, device); + break; + case Event_DeviceAttached: + Navigation_DeviceAdd(rootItem, device); + break; + case Event_DeviceDetached: + Navigation_DeviceRemove(rootItem, device); + break; + case Event_DeviceDisplayNameChanged: + Navigation_DeviceTitleChanged(rootItem, device); + break; + case Event_DeviceIconChanged: + Navigation_DeviceIconChanged(rootItem, device); + break; + } +} + +static BOOL +Navigation_RegisterDeviceHandler(HNAVITEM root) +{ + HWND eventRelay; + DeviceEventCallbacks callbacks; + + if (0 != deviceHandler) + return FALSE; + + eventRelay = Plugin_GetEventRelayWindow(); + if (NULL == eventRelay) + return FALSE; + + ZeroMemory(&callbacks, sizeof(callbacks)); + callbacks.deviceCb = Navigation_DeviceCb; + + deviceHandler = EVENTRELAY_REGISTER_HANDLER(eventRelay, &callbacks, root); + return (0 != deviceHandler); +} + +BOOL +Navigation_Initialize(void) +{ + HWND libraryWindow; + wchar_t buffer[128] = {0}; + + if (NULL != navigationRoot) + return FALSE; + + libraryWindow = Plugin_GetLibraryWindow(); + + MLNavCtrl_BeginUpdate(libraryWindow, NUF_LOCK_TOP); + + WASABI_API_LNGSTRINGW_BUF(IDS_DEVICES_NAVIGATION_NODE, buffer, ARRAYSIZE(buffer)); + + navigationRoot = NavigationItem_Insert(NULL, NULL, + NIMF_ITEMID | NIMF_TEXT | NIMF_STYLE | NIMF_TEXTINVARIANT | + NIMF_PARAM | NIMF_IMAGE | NIMF_IMAGESEL, + ML_TREEVIEW_ID_DEVICES, + DEVICES_NAVITEM_PREFIX L"root", + buffer, + NIS_HASCHILDREN | NIS_ALLOWCHILDMOVE | NIS_DEFAULTIMAGE, + -1, + -1L); + + if (NULL == navigationRoot) + return FALSE; + + Navigation_AddExistingDevices(navigationRoot); + Navigation_RegisterDeviceHandler(navigationRoot); + + MLNavCtrl_EndUpdate(libraryWindow); + + return TRUE; +} + +void +Navigation_Uninitialize(void) +{ + if (0 != deviceHandler) + { + HWND eventRelay; + eventRelay = Plugin_GetEventRelayWindow(); + if (NULL != eventRelay) + { + EVENTRELAY_UNREGISTER_HANDLER(eventRelay, deviceHandler); + } + deviceHandler = NULL; + } + + if (NULL != navigationRoot) + { + NavigationItem_Delete(navigationRoot); + navigationRoot = FALSE; + } + + NavigationIcons_ClearCache(); +} + +BOOL +Navigation_SelectDevice(const char *name) +{ + HNAVITEM item; + + item = NavigationItem_FindFromDeviceName(navigationRoot, name); + if (NULL == item) + return FALSE; + + return MLNavItem_Select(Plugin_GetLibraryWindow(), item); +} + +BOOL +Navigation_EditDeviceTitle(const char *name) +{ + HNAVITEM item; + + item = NavigationItem_FindFromDeviceName(navigationRoot, name); + if (NULL == item) + return FALSE; + + return MLNavItem_EditTitle(Plugin_GetLibraryWindow(), item); +} + +static void +Navigation_DestroyCb() +{ +} + +static BOOL +NavigationItem_IsMine(HNAVITEM item, ifc_device **device) +{ + NAVITEM info; + wchar_t buffer[128] = {0}; + INT nameLength; + INT prefixLength; + + if (NULL == item) + return FALSE; + + if (item == navigationRoot) + { + if (NULL != device) + *device = NULL; + return TRUE; + } + + info.cbSize = sizeof(NAVITEM); + info.hItem = item; + info.mask = NIMF_TEXTINVARIANT; + info.cchInvariantMax = ARRAYSIZE(buffer); + info.pszInvariant = buffer; + + if (FALSE == MLNavItem_GetInfo(Plugin_GetLibraryWindow(), &info)) + return FALSE; + + // to maintain some specific orders, we need to alter the insert position + BOOL swappped = FALSE; + if (!wcsnicmp(L"cloud_sources", info.pszInvariant, 13)) + { + // and this will allow us to make the cloud library + // root do a web page or a sources view as needed... + lstrcpynW(info.pszInvariant, L"ml_devices_all_sources", ARRAYSIZE(buffer)); + swappped = TRUE; + } + + nameLength = (NULL != info.pszInvariant) ? lstrlen(info.pszInvariant) : 0; + prefixLength = ARRAYSIZE(DEVICES_NAVITEM_PREFIX) - 1; + + if (nameLength <= prefixLength) + return FALSE; + + if (CSTR_EQUAL != CompareString(CSTR_INVARIANT, 0, + DEVICES_NAVITEM_PREFIX, prefixLength, info.pszInvariant, prefixLength)) + { + return FALSE; + } + + if (NULL != device) + { + char name[ARRAYSIZE(buffer)] = {0}; + nameLength = WideCharToMultiByte(CP_UTF8, 0, + info.pszInvariant + prefixLength, nameLength - prefixLength, + name, ARRAYSIZE(name), NULL, NULL); + name[nameLength] = '\0'; + + if (0 == nameLength || + NULL == WASABI_API_DEVICES || + S_OK != WASABI_API_DEVICES->DeviceFind(name, device)) + { + *device = NULL; + if (swappped) return FALSE; + } + } + return TRUE; +} + +static HWND +Navigation_CreateViewErrorWidget(HWND hostWindow, void *user) +{ + return InfoWidget_CreateWindow(WIDGET_TYPE_VIEW_ERROR, + MAKEINTRESOURCE(IDS_INFOWIDGET_TITLE), + MAKEINTRESOURCE(IDS_CREATE_DEVICE_VIEW_FAILED), + NULL, + hostWindow, 0, 0, 0, 0, FALSE, 0); +} + +static HWND +NavigationItem_CreateViewCb(HNAVITEM item, HWND parentWindow) +{ + HWND hwnd; + ifc_device *device; + + if (NULL == item || + FALSE == NavigationItem_IsMine(item, &device)) + return NULL; + + if (NULL != device) + { + hwnd = device->CreateView(parentWindow); + device->Release(); + + if (NULL == hwnd) + { + hwnd = WidgetHost_Create(0, 0, 0, 0, 0, parentWindow, Navigation_CreateViewErrorWidget, NULL); + } + } + else + { + hwnd = ManagerView_CreateWindow(parentWindow); + } + return hwnd; +} + +static BOOL +NavigationItem_ShowContextMenuCb(HNAVITEM item, HWND hostWindow, POINTS pts) +{ + POINT pt; + ifc_device *device; + + if (NULL == item || + FALSE == NavigationItem_IsMine(item, &device)) + return FALSE; + + POINTSTOPOINT(pt, pts); + + if (item != navigationRoot) + { + if (NULL != device) + { + char *deviceName = AnsiString_Duplicate(device->GetName()); + device->Release(); + device = NULL; + + if (NULL != deviceName) + { + NavigationItem_DisplayDeviceMenu(item, deviceName, hostWindow, pt); + AnsiString_Free(deviceName); + } + } + } + else + { + NavigationItem_DisplayRootMenu(item, hostWindow, pt); + } + + if (NULL != device) + device->Release(); + + return TRUE; +} + +static BOOL +NavigationItem_ShowHelpCb(HNAVITEM item, HWND hostWindow, POINTS pts) +{ + if (NULL == item || + FALSE == NavigationItem_IsMine(item, NULL)) + { + return FALSE; + } + + Plugin_ShowHelp(); + return TRUE; +} + +static BOOL +NavigationItem_DeleteCb(HNAVITEM item) +{ + ifc_device *device; + + if (NULL == item || + FALSE == NavigationItem_IsMine(item, &device)) + return FALSE; + + if (NULL != device) + { + device->SetNavigationItem(NULL); + device->Release(); + } + + if (item != navigationRoot) + { + NAVITEM itemInfo; + HWND libraryWindow; + + libraryWindow = Plugin_GetLibraryWindow(); + + itemInfo.cbSize = sizeof(itemInfo); + itemInfo.mask = NIMF_IMAGE; + itemInfo.hItem = item; + + if (FALSE != MLNavItem_GetInfo(libraryWindow, &itemInfo) && + -1 != itemInfo.iImage) + { + NavigationIcons_ReleaseIconIndex(itemInfo.iImage); + } + } + + return TRUE; +} + +static BOOL +NavigationItem_KeyDownCb(HNAVITEM item, NMTVKEYDOWN *keyData) +{ + ifc_device *device; + + if (NULL == keyData || + NULL == item || + FALSE == NavigationItem_IsMine(item, &device)) + { + return FALSE; + } + + if (NULL == device) + return TRUE; + + switch(keyData->wVKey) + { + case VK_F2: + MLNavItem_EditTitle(Plugin_GetLibraryWindow(), item); + break; + } + + device->Release(); + return TRUE; +} + +static int +NavigationItem_DropTargetCb(HNAVITEM item, unsigned int dataType, void *data) +{ + ifc_device *device; + int result; + + if (NULL == item || + FALSE == NavigationItem_IsMine(item, &device)) + { + return 0; + } + + if (NULL == device) + return -1; + + result = -1; + + if (NULL == data) + { + if (S_OK == device->GetDropSupported(dataType)) + result = 1; + } + else + { + if (SUCCEEDED(device->Drop(data, dataType))) + result = 1; + } + + device->Release(); + + return result; +} + +static BOOL +NavigationItem_TitleEditBeginCb(HNAVITEM item) +{ // return TRUE to cancel ediging (only on own items!!!); + + ifc_device *device; + + BOOL blockEditor; + + if (NULL == item || + FALSE == NavigationItem_IsMine(item, &device)) + { + return FALSE; + } + + if (NULL == device) + return TRUE; + + blockEditor = (FALSE == DeviceCommand_GetEnabled(device, "rename", + DeviceCommandContext_NavigationMenu)); + + device->Release(); + + return blockEditor; +} + + +static BOOL +NavigationItem_TitleEditEndCb(HNAVITEM item, const wchar_t *title) +{ + HRESULT hr; + ifc_device *device; + + if (NULL == title) + return FALSE; + + if (NULL == item || + FALSE == NavigationItem_IsMine(item, &device) || + NULL == device) + { + return FALSE; + } + + hr = device->SetDisplayName(title); + device->Release(); + + if (FAILED(hr)) + { + HWND libraryWindow; + wchar_t title[256] = {0}, message[1024] = {0}; + + libraryWindow = Plugin_GetLibraryWindow(); + + WASABI_API_LNGSTRINGW_BUF(IDS_MESSAGEBOX_TITLE, title, ARRAYSIZE(title)); + WASABI_API_LNGSTRINGW_BUF(IDS_MESSAGE_UNABLE_TO_RENAME, message, ARRAYSIZE(message)); + + MessageBox(libraryWindow, message, title, MB_OK | MB_ICONERROR); + return FALSE; + } + + return FALSE; +} + + +BOOL +Navigation_ProcessMessage(INT msg, INT_PTR param1, INT_PTR param2, INT_PTR param3, INT_PTR *result) +{ + if (msg == ML_MSG_NO_CONFIG) + { + *result = TRUE; + return TRUE; + } + + if (msg < ML_MSG_TREE_BEGIN || msg > ML_MSG_TREE_END) + return FALSE; + + HNAVITEM item; + switch(msg) + { + case ML_MSG_TREE_ONCREATEVIEW: + item = NavigationItem_GetFromMessage(msg, param1); + *result = (INT_PTR)NavigationItem_CreateViewCb(item, (HWND)param2); + return TRUE; + + case ML_MSG_NAVIGATION_CONTEXTMENU: + item = NavigationItem_GetFromMessage(msg, param1); + *result = (INT_PTR)NavigationItem_ShowContextMenuCb(item, (HWND)param2, MAKEPOINTS(param3)); + return TRUE; + + case ML_MSG_NAVIGATION_HELP: + item = NavigationItem_GetFromMessage(msg, param1); + *result = (INT_PTR)NavigationItem_ShowHelpCb(item, (HWND)param2, MAKEPOINTS(param3)); + return TRUE; + + case ML_MSG_NAVIGATION_ONDELETE: + item = NavigationItem_GetFromMessage(msg, param1); + *result = (INT_PTR)NavigationItem_DeleteCb(item); + return TRUE; + + case ML_MSG_TREE_ONKEYDOWN: + item = NavigationItem_GetFromMessage(msg, param1); + *result = (INT_PTR)NavigationItem_KeyDownCb(item, (NMTVKEYDOWN*)param2); + return TRUE; + + case ML_MSG_TREE_ONDROPTARGET: + item = NavigationItem_GetFromMessage(msg, param1); + *result = (INT_PTR)NavigationItem_DropTargetCb(item, (unsigned int)param2, (void*)param3); + return TRUE; + + case ML_MSG_NAVIGATION_ONBEGINTITLEEDIT: + item = NavigationItem_GetFromMessage(msg, param1); + *result = (INT_PTR)NavigationItem_TitleEditBeginCb(item); + return TRUE; + + case ML_MSG_NAVIGATION_ONENDTITLEEDIT: + item = NavigationItem_GetFromMessage(msg, param1); + *result = (INT_PTR)NavigationItem_TitleEditEndCb(item, (const wchar_t*)param2); + return TRUE; + + case ML_MSG_NAVIGATION_ONDESTROY: + Navigation_DestroyCb(); + *result = 0L; + return TRUE; + + } + return FALSE; +}
\ No newline at end of file |