diff options
Diffstat (limited to 'Src/omBrowser/travelLogHelper.cpp')
-rw-r--r-- | Src/omBrowser/travelLogHelper.cpp | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/Src/omBrowser/travelLogHelper.cpp b/Src/omBrowser/travelLogHelper.cpp new file mode 100644 index 00000000..bbbbbf48 --- /dev/null +++ b/Src/omBrowser/travelLogHelper.cpp @@ -0,0 +1,331 @@ +#include "main.h" +#include "./travelLogHelper.h" +#include "./graphics.h" +#include "./resource.h" +#include "./ifc_skinhelper.h" +#include "./ifc_imageloader.h" +#include "./menu.h" +#include "../Plugins/General/gen_ml/ml_ipc_0313.h" + +#include <exdisp.h> +#include <tlogstg.h> + +#define TRAVELLOGPOPUP_MAXCHARWIDTH 42 + +TravelLogHelper::TravelLogHelper(IWebBrowser2 *pWeb) + : ref(1), pWeb2(pWeb), bitmap(NULL), pixelData(NULL), firstFwd(FALSE), entriesCount(0), backEntry(-1) +{ + if (NULL != pWeb2) + pWeb2->AddRef(); +} + +TravelLogHelper::~TravelLogHelper() +{ + if (NULL != pWeb2) + pWeb2->Release(); + + if (NULL != bitmap) + DeleteObject(bitmap); +} + +HRESULT TravelLogHelper::CreateInstance(IWebBrowser2 *pWeb2, TravelLogHelper **instance) +{ + if (NULL == instance) return E_POINTER; + *instance = NULL; + + if (NULL == pWeb2) + return E_INVALIDARG; + + *instance = new TravelLogHelper(pWeb2); + if (NULL == *instance) return E_OUTOFMEMORY; + + return S_OK; +} + +size_t TravelLogHelper::AddRef() +{ + return InterlockedIncrement((LONG*)&ref); +} + +size_t TravelLogHelper::Release() +{ + if (0 == ref) + return ref; + + LONG r = InterlockedDecrement((LONG*)&ref); + if (0 == r) + delete(this); + + return r; +} + +int TravelLogHelper::QueryInterface(GUID interface_guid, void **object) +{ + if (NULL == object) return E_POINTER; + + if (IsEqualIID(interface_guid, IFC_TravelLogHelper)) + *object = static_cast<ifc_travelloghelper*>(this); + else if (IsEqualIID(interface_guid, IFC_MenuCustomizer)) + *object = static_cast<ifc_menucustomizer*>(this); + else + { + *object = NULL; + return E_NOINTERFACE; + } + + if (NULL == *object) + return E_UNEXPECTED; + + AddRef(); + return S_OK; +} + +HRESULT TravelLogHelper::QueryStorage(ITravelLogStg **ppLog) +{ + HRESULT hr; + + if (NULL == ppLog) + return E_POINTER; + + *ppLog = NULL; + + if (NULL == pWeb2) return E_UNEXPECTED; + + IServiceProvider *pProvider; + hr = pWeb2->QueryInterface(IID_IServiceProvider, (void**)&pProvider); + if (SUCCEEDED(hr)) + { + hr = pProvider->QueryService(SID_STravelLogCursor, ppLog); + pProvider->Release(); + } + return hr; +} + +BOOL TravelLogHelper::DrawIcon(HMENU menuInstance, HDC hdc, DRAWITEMSTRUCT *pdis) +{ + if (0 == (ODS_SELECTED & pdis->itemState)) + return FALSE; + + LONG entry = pdis->itemID - 101; + if (entry < 0 || ((ULONG)entry) > entriesCount) + return FALSE; + + BOOL fForward = (FALSE != firstFwd) ? TRUE : FALSE; + if (-1 != backEntry && entry >= backEntry) + fForward = !fForward; + + if (NULL == bitmap) + { + ifc_omimageloader *imageLoader; + if (SUCCEEDED(Plugin_QueryImageLoader(Plugin_GetInstance(), MAKEINTRESOURCE(IDR_MENUARROW_IMAGE), FALSE, &imageLoader))) + { + if (SUCCEEDED(imageLoader->LoadBitmapEx(&bitmap, &header, &pixelData))) + { + if (header.biHeight < 0) header.biHeight = -header.biHeight; + + Image_Colorize((BYTE*)pixelData, header.biWidth, header.biHeight, + header.biBitCount, GetBkColor(hdc), GetTextColor(hdc), TRUE); + } + imageLoader->Release(); + } + } + + BOOL resultOk = FALSE; + if (NULL != bitmap) + { + INT cx = header.biWidth/2; + INT cy = header.biHeight; + if (cy < 0) cy = -cy; + + INT side = (pdis->rcItem.bottom - pdis->rcItem.top - 2); + if (cy < side) side = cy; + + INT top = pdis->rcItem.top + ((pdis->rcItem.bottom - pdis->rcItem.top) - side)/2; + INT left = pdis->rcItem.left + (GetSystemMetrics(SM_CXMENUCHECK) - side)/2 + 3; + + resultOk = StretchDIBits(hdc, left, top, side, side, + ((FALSE != fForward) ? cx : 0), 0, cx, cy, pixelData, (BITMAPINFO*)&header, DIB_RGB_COLORS, SRCCOPY); + + } + return resultOk; +} + +INT TravelLogHelper::CustomDraw(HMENU menuInstance, INT action, HDC hdc, LPARAM param) +{ + switch(action) + { + case MLMENU_ACTION_DRAWITEM: + return MLMENU_WANT_DRAWPART; + case MLMENU_ACTION_DRAWICON: + return DrawIcon(menuInstance, hdc, (DRAWITEMSTRUCT*)param); + } + return FALSE; +} + + +HRESULT TravelLogHelper::ShowPopup(UINT fuFlags, INT x, INT y, HWND hwnd, LPTPMPARAMS lptpm) +{ + HRESULT hr; + ITravelLogStg *pLog; + hr = QueryStorage(&pLog); + if (FAILED(hr) || NULL == pLog) return hr; + + DWORD entriesMax; + if (FAILED(pLog->GetCount(TLEF_RELATIVE_FORE | TLEF_RELATIVE_BACK, &entriesMax))) + entriesMax = 0; + + ITravelLogEntry **entries = NULL; + + INT selectedEntry = -1; + firstFwd = (0 == (TPM_BOTTOMALIGN & fuFlags)); + entriesCount = 0; + backEntry = -1; + + if (0 != entriesMax) + { + entries = (ITravelLogEntry**)calloc(entriesMax, sizeof(ITravelLogEntry*)); + if (NULL != entries) + { + IEnumTravelLogEntry *pEnum = NULL; + TLENUMF tlenum = (0 != (TPM_BOTTOMALIGN & fuFlags)) ? TLEF_RELATIVE_BACK : TLEF_RELATIVE_FORE; + if (SUCCEEDED(pLog->EnumEntries(tlenum, &pEnum))) + { + ULONG fetched; + pEnum->Reset(); + pEnum->Next(entriesMax - entriesCount, &entries[entriesCount], &fetched); + if (0 != fetched) + { + ITravelLogEntry *t, **l, **r; + for (l = &entries[entriesCount], r = &entries[entriesCount + fetched - 1]; l < r; l++, r--) + { + t = *l; + *l = *r; + *r = t; + } + entriesCount += fetched; + } + pEnum->Release(); + } + + tlenum = (0 != (TLEF_RELATIVE_FORE & tlenum)) ? + ((tlenum & ~TLEF_RELATIVE_FORE) | TLEF_RELATIVE_BACK) : + tlenum = ((tlenum & ~TLEF_RELATIVE_BACK) | TLEF_RELATIVE_FORE); + + if (SUCCEEDED(pLog->EnumEntries(tlenum, &pEnum))) + { + + ULONG fetched; + pEnum->Reset(); + pEnum->Next(entriesMax - entriesCount, &entries[entriesCount], &fetched); + if (0 != fetched) + { + backEntry = entriesCount; + entriesCount += fetched; + } + pEnum->Release(); + } + } + + if (entriesCount > 0) + { + HMENU hMenu = CreatePopupMenu(); + if (NULL != hMenu) + { + MENUITEMINFOW mii = {0}; + mii.cbSize = sizeof(MENUITEMINFOW); + mii.fMask = MIIM_STRING | MIIM_ID | MIIM_STATE; + mii.fState = MFS_ENABLED | MFS_UNCHECKED; + + for (ULONG i = 0; i < entriesCount; i++) + { + if (NULL != entries[i]) + { + LPWSTR pszTitle; + if (SUCCEEDED(entries[i]->GetTitle(&pszTitle)) && NULL != pszTitle) + { + INT cchTitle = lstrlen(pszTitle); + + if (cchTitle > TRAVELLOGPOPUP_MAXCHARWIDTH) + { + pszTitle[TRAVELLOGPOPUP_MAXCHARWIDTH] = L'\0'; + for (INT k = 0; k < 3; k++) + pszTitle[TRAVELLOGPOPUP_MAXCHARWIDTH - 1 - k] = L'.'; + + } + mii.dwTypeData = pszTitle; + mii.wID = 101 + i; + InsertMenuItem(hMenu, i, TRUE, &mii); + CoTaskMemFree(pszTitle); + } + } + } + + + { // insert current page + WCHAR szBuffer[256] = {0}; + + Plugin_LoadString(IDS_CURRENT_PAGE, szBuffer, ARRAYSIZE(szBuffer)); + + mii.dwTypeData = szBuffer; + mii.fMask = MIIM_STRING | MIIM_ID | MIIM_STATE | MIIM_FTYPE; + mii.fState = MFS_ENABLED | MFS_DEFAULT | MFS_CHECKED; + mii.fType = MFT_STRING | MFT_RADIOCHECK; + mii.wID = 100; + + if (-1 == backEntry) + InsertMenuItem(hMenu, GetMenuItemCount(hMenu), TRUE, &mii); + else + InsertMenuItem(hMenu, 101 + backEntry, FALSE, &mii); + } + + + + HANDLE hHook = Menu_InitializeHook(hwnd, this); + + UINT commandId = TrackPopupMenuEx(hMenu, fuFlags | TPM_RETURNCMD, x, y, hwnd, lptpm); + + if (NULL != hHook) Menu_RemoveHook(hHook); + + if (commandId > 100 && commandId <= (100 + entriesCount)) + selectedEntry = commandId - 101; + + DestroyMenu(hMenu); + } + } + + } + + if (-1 != selectedEntry && NULL != entries[selectedEntry]) + { + pLog->TravelTo(entries[selectedEntry]); + } + + if (NULL != entries) + { + for (ULONG i = 0; i < entriesCount; i++) + { + if (NULL != entries[i]) entries[i]->Release(); + } + free(entries); + + } + pLog->Release(); + return hr; +} + +#define CBCLASS TravelLogHelper +START_MULTIPATCH; + START_PATCH(MPIID_TRAVELLOGHELPER) + M_CB(MPIID_TRAVELLOGHELPER, ifc_travelloghelper, ADDREF, AddRef); + M_CB(MPIID_TRAVELLOGHELPER, ifc_travelloghelper, RELEASE, Release); + M_CB(MPIID_TRAVELLOGHELPER, ifc_travelloghelper, QUERYINTERFACE, QueryInterface); + M_CB(MPIID_TRAVELLOGHELPER, ifc_travelloghelper, API_QUERYSTORAGE, QueryStorage); + M_CB(MPIID_TRAVELLOGHELPER, ifc_travelloghelper, API_SHOWPOPUP, ShowPopup); + NEXT_PATCH(MPIID_MENUCUSTOMIZER) + M_CB(MPIID_MENUCUSTOMIZER, ifc_menucustomizer, ADDREF, AddRef); + M_CB(MPIID_MENUCUSTOMIZER, ifc_menucustomizer, RELEASE, Release); + M_CB(MPIID_MENUCUSTOMIZER, ifc_menucustomizer, QUERYINTERFACE, QueryInterface); + M_CB(MPIID_MENUCUSTOMIZER, ifc_menucustomizer, API_CUSTOMDRAW, CustomDraw); + END_PATCH +END_MULTIPATCH; +#undef CBCLASS
\ No newline at end of file |