winamp/Src/omBrowser/toolbarRating.cpp

461 lines
11 KiB
C++

#include "main.h"
#include "./toolbarRating.h"
#include "./toolbar.h"
#include "./graphics.h"
#include "./resource.h"
#include "./ifc_skinhelper.h"
#include "./ifc_skinnedrating.h"
#include "./menu.h"
#include "../Plugins/General/gen_ml/ml_ipc_0313.h"
#include <strsafe.h>
#define RATING_SPACECX_PX 4
#define RATING_SPACECX_UNIT 2
#define RATING_STARSTYLE (RDS_LEFT | RDS_TOP)
BYTE rating;
BYTE highlighted;
BYTE focused;
RECT ratingRect;
RECT textRect;
INT baseLine;
ifc_skinnedrating *skinnedRating;
ToolbarRating::ToolbarRating(LPCSTR pszName, UINT nStyle, LPCWSTR pszText, LPCWSTR pszDescription) :
ToolbarItem(pszName, nStyle, ICON_NONE, pszText, pszDescription),
rating(0), highlighted(0), focused(0), baseLine(0), skinnedRating(NULL)
{
ifc_skinhelper *skinHelper;
if (SUCCEEDED(Plugin_GetSkinHelper(&skinHelper)))
{
if (FAILED(skinHelper->QueryInterface(IFC_SkinnedRating, (void**)&skinnedRating)))
skinnedRating = NULL;
skinHelper->Release();
}
}
ToolbarRating::~ToolbarRating()
{
if (NULL != skinnedRating)
skinnedRating->Release();
}
ToolbarItem* CALLBACK ToolbarRating::CreateInstance(ToolbarItem::Template *item)
{
if (NULL == item)
return NULL;
return new ToolbarRating( (NULL != item->name) ? item->name : TOOLCLS_RATING,
item->style,
item->text,
item->description);
}
static BOOL ToolbarRating_GetTextSize(LPCWSTR pszText, HWND hToolbar, SIZE *textSize)
{
BOOL result = FALSE;
WCHAR szText[64] = {0};
if (IS_INTRESOURCE(pszText))
{
Plugin_LoadString((INT)(INT_PTR)pszText, szText, ARRAYSIZE(szText));
pszText = szText;
}
INT cchText = (NULL != pszText) ? lstrlenW(pszText) : 0;
if (0 != cchText)
{
HDC hdc = GetDCEx(hToolbar, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL != hdc)
{
HFONT font = (HFONT)SendMessage(hToolbar, WM_GETFONT, 0, 0L);
HFONT originalFont = (HFONT)SelectObject(hdc, font);
result = GetTextExtentPoint32(hdc, pszText, cchText, textSize);
SelectObject(hdc, originalFont);
ReleaseDC(hToolbar, hdc);
}
}
return result;
}
BOOL ToolbarRating::AdjustRect(HWND hToolbar, RECT *proposedRect)
{
TOOLBARTEXTMETRIC ttm;
if (NULL == skinnedRating || FAILED(skinnedRating->CalcMinRect(5, &ratingRect)))
::SetRectEmpty(&ratingRect);
if (!Toolbar_GetTextMetrics(hToolbar, &ttm))
ZeroMemory(&ttm, sizeof(TOOLBARTEXTMETRIC));
::SetRectEmpty(&textRect);
ToolbarRating_GetTextSize(text, hToolbar, ((SIZE*)&textRect) + 1);
INT spaceCX = MulDiv(RATING_SPACECX_UNIT, ttm.aveCharWidth, 4);
LONG cx = (ratingRect.right - ratingRect.left) + 2*spaceCX + (textRect.right - textRect.left) + 4;
::OffsetRect(&textRect, spaceCX, ttm.origY - proposedRect->top);
baseLine = ttm.baseY;
::OffsetRect(&ratingRect,
spaceCX + (textRect.right - textRect.left) + 4,
(ttm.origY - proposedRect->top) + baseLine - (ratingRect.bottom - ratingRect.top) + 1);
proposedRect->right = proposedRect->left + cx;
return TRUE;
}
BOOL ToolbarRating::Paint(HWND hToolbar, HDC hdc, const RECT *paintRect, UINT state)
{
RECT cotrolRect;
CopyRect(&cotrolRect, &ratingRect);
::OffsetRect(&cotrolRect, rect.left, rect.top);
INT trackingVal = (0 != (stateHighlighted & style)) ? highlighted : rating;
UINT fStyle = RATING_STARSTYLE | RDS_OPAQUE;
if (0 == rating || 0 != ((stateFocused | stateHighlighted) & state))
fStyle |= RDS_SHOWEMPTY;
if (0 == (stateDisabled & style))
fStyle |= RDS_HOT;
HRGN rgn = CreateRectRgnIndirect(&rect);
HRGN rgn2 = CreateRectRgnIndirect(&textRect);
OffsetRgn(rgn2, rect.left, rect.top);
CombineRgn(rgn, rgn, rgn2, RGN_DIFF);
SetRectRgn(rgn2, cotrolRect.left, cotrolRect.top, cotrolRect.right, cotrolRect.bottom);
CombineRgn(rgn, rgn, rgn2, RGN_DIFF);
HBRUSH hb = Toolbar_GetBkBrush(hToolbar);
FillRgn(hdc, rgn, hb);
DeleteObject(rgn);
DeleteObject(rgn2);
if (!::IsRectEmpty(&textRect))
{
WCHAR szText[64], *pszText(text);
if (IS_INTRESOURCE(pszText))
{
Plugin_LoadString((INT)(INT_PTR)pszText, szText, ARRAYSIZE(szText));
pszText = szText;
}
INT cchText = lstrlenW(pszText);
if (0 != cchText)
{
UINT originalAlign = SetTextAlign(hdc, TA_LEFT | TA_BASELINE);
RECT rc;
CopyRect(&rc, &textRect);
::OffsetRect(&rc, rect.left, rect.top);
ExtTextOut(hdc, rc.left, rc.top + baseLine, ETO_OPAQUE, &rc, pszText, cchText, NULL);
if ((TA_LEFT | TA_BASELINE) != originalAlign) SetTextAlign(hdc, originalAlign);
}
}
if (NULL == skinnedRating || FAILED(skinnedRating->Draw(hdc, 5, rating, trackingVal, &cotrolRect, fStyle)))
{
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &cotrolRect, NULL, 0, NULL);
}
else
{
if (stateFocused == ((stateFocused | stateNoFocusRect) & state) && focused > 0 && focused < 6)
{
RECT focusRect;
CopyRect(&focusRect, &cotrolRect);
INT starWidth = (cotrolRect.right - cotrolRect.left)/5;
focusRect.left += starWidth * (focused - 1);
focusRect.right = focusRect.left + starWidth;
InflateRect(&focusRect, 1, 1);
COLORREF origBk = SetBkColor(hdc, 0x00000000);
COLORREF origFg = SetTextColor(hdc, 0x00FFFFFF);
DrawFocusRect(hdc, &focusRect);
if (origBk != 0x00000000) SetBkColor(hdc, origBk);
if (origFg != 0x00FFFFFF) SetTextColor(hdc, origFg);
}
}
return TRUE;
}
void ToolbarRating::MouseMove(HWND hToolbar, UINT mouseFlags, POINT pt)
{
BYTE tracking = 0;
UINT state = 0;
if (PtInItem(pt))
{
state = stateHighlighted;
RECT controlRect;
CopyRect(&controlRect, &ratingRect);
::OffsetRect(&controlRect, rect.left, rect.top);
POINT ptTest = pt;
ptTest.y = controlRect.top;
LONG result;
if (NULL == skinnedRating || FAILED(skinnedRating->HitTest(pt, 5, &controlRect, RATING_STARSTYLE, &result)))
result = 0;
UINT hitTest = HIWORD(result);
if (0 != ((RHT_ONVALUE | RHT_ONVALUEABOVE | RHT_ONVALUEBELOW) & hitTest))
tracking = (BYTE)LOWORD(result);
}
BOOL invalidate = FALSE;
if (tracking != highlighted)
{
highlighted = tracking;
invalidate = TRUE;
}
if ((stateHighlighted & style) != (stateHighlighted & state))
{
style |= ((style & ~stateHighlighted) | state);
invalidate = TRUE;
}
if (FALSE != invalidate)
{
RECT invalidRect;
CopyRect(&invalidRect, &ratingRect);
::OffsetRect(&invalidRect, rect.left, rect.top);
InvalidateRect(hToolbar, &invalidRect, FALSE);
Toolbar_UpdateTip(hToolbar);
}
}
void ToolbarRating::MouseLeave(HWND hToolbar)
{
BOOL invalidate = FALSE;
if (highlighted != 0)
{
highlighted = 0;
invalidate = TRUE;
}
if (0 != (stateHighlighted & style))
{
style &= ~stateHighlighted;
invalidate = TRUE;
}
if (FALSE != invalidate)
{
RECT invalidRect;
CopyRect(&invalidRect, &ratingRect);
::OffsetRect(&invalidRect, rect.left, rect.top);
InvalidateRect(hToolbar, &invalidRect, FALSE);
}
}
void ToolbarRating::LButtonDown(HWND hToolbar, UINT mouseFlags, POINT pt)
{
style |= statePressed;
}
void ToolbarRating::LButtonUp(HWND hToolbar, UINT mouseFlags, POINT pt)
{
style &= ~statePressed;
}
void ToolbarRating::Click(HWND hToolbar, UINT mouseFlags, POINT pt)
{
if (0 == (ToolbarItem::statePressed & style))
return;
RECT controlRect;
CopyRect(&controlRect, &ratingRect);
::OffsetRect(&controlRect, rect.left, rect.top);
POINT ptTest = pt;
ptTest.y = controlRect.top;
LONG result;
if (NULL == skinnedRating || FAILED(skinnedRating->HitTest(pt, 5, &controlRect, RATING_STARSTYLE, &result)))
result = 0;
if (0 != ((RHT_ONVALUE | RHT_ONVALUEABOVE | RHT_ONVALUEBELOW) & HIWORD(result)) && LOWORD(result) > 0)
{
SendRating(hToolbar, LOWORD(result));
}
}
void ToolbarRating::SendRating(HWND hToolbar, INT ratingValue)
{
INT commandId = 0;
switch(ratingValue)
{
case 1: commandId = ID_RATING_VALUE_1; break;
case 2: commandId = ID_RATING_VALUE_2; break;
case 3: commandId = ID_RATING_VALUE_3; break;
case 4: commandId = ID_RATING_VALUE_4; break;
case 5: commandId = ID_RATING_VALUE_5; break;
}
if (0 != commandId)
Toolbar_SendCommand(hToolbar, commandId);
}
void ToolbarRating::UpdateSkin(HWND hToolbar)
{
}
BOOL ToolbarRating::PtInItem(POINT pt)
{
return (pt.x >= (rect.left + textRect.left) && pt.x < (rect.left + ratingRect.right) && rect.bottom != rect.top);
}
BOOL ToolbarRating::SetValueInt(HWND hToolbar, INT value)
{
if (value < 0) value = 0;
if (value > 5) value = 5;
if (rating != value)
{
rating = value;
RECT invalidRect;
CopyRect(&invalidRect, &ratingRect);
::OffsetRect(&invalidRect, rect.left, rect.top);
InvalidateRect(hToolbar, &invalidRect, FALSE);
}
return TRUE;
}
static LPCWSTR ToolbarRating_FormatRating(INT ratingValue, LPWSTR pszBuffer, INT cchBufferMax)
{
INT stringId;
switch(ratingValue)
{
case 5: stringId = IDS_RATING_5; break;
case 4: stringId = IDS_RATING_4; break;
case 3: stringId = IDS_RATING_3; break;
case 2: stringId = IDS_RATING_2; break;
case 1: stringId = IDS_RATING_1; break;
default: stringId = IDS_RATING_0; break;
}
Plugin_LoadString(stringId, pszBuffer, cchBufferMax);
return pszBuffer;
}
INT ToolbarRating::GetTip(LPTSTR pszBuffer, INT cchBufferMax)
{
WCHAR szText[64] = {0}, szRated[32] = {0};
size_t remaining = 0;
LPWSTR cursor;
Plugin_LoadString(IDS_RATING_CURRENT, szText, ARRAYSIZE(szText));
ToolbarRating_FormatRating(rating, szRated, ARRAYSIZE(szRated));
HRESULT hr = StringCchPrintfEx(pszBuffer, cchBufferMax, &cursor, &remaining, STRSAFE_IGNORE_NULLS, TEXT("%s %s "), szText, szRated);
if (FAILED(hr)) return 0;
if (NULL != highlighted)
{
Plugin_LoadString(IDS_RATING_CHANGETO, szText, ARRAYSIZE(szText));
ToolbarRating_FormatRating(highlighted, szRated, ARRAYSIZE(szRated));
hr = StringCchPrintfEx(cursor, remaining, &cursor, &remaining, STRSAFE_IGNORE_NULLS, TEXT("\r\n%s %s "), szText, szRated);
if (FAILED(hr)) return 0;
}
return cchBufferMax - (INT)remaining;
}
BOOL ToolbarRating::FillMenuInfo(HWND hToolbar, MENUITEMINFO *pmii, LPWSTR pszBuffer, INT cchBufferMax)
{
pmii->fMask = MIIM_STRING | MIIM_ID | MIIM_STATE | MIIM_SUBMENU;
pmii->wID = 0;
pmii->fState = MFS_ENABLED;
pmii->dwTypeData = pszBuffer;
pmii->hSubMenu = Menu_GetMenu(MENU_RATING, RATINGTOMCF(rating));
if (IS_INTRESOURCE(text))
{
Plugin_LoadString((INT)(INT_PTR)text, pszBuffer, cchBufferMax);
}
else
{
if (FAILED(StringCchCopyEx(pszBuffer, cchBufferMax, text, NULL, NULL, STRSAFE_IGNORE_NULLS)))
pszBuffer[0] = L'\0';
}
return TRUE;
}
void ToolbarRating::SetFocus(HWND hToolbar, ToolbarItem *focusItem, BOOL fSet)
{
if (FALSE != fSet)
{
focused = 1;
if (NULL != focusItem)
{
INT mineIndex = Toolbar_FindItem(hToolbar, name);
INT otherIndex = Toolbar_FindItem(hToolbar, focusItem->GetName());
if (ITEM_ERR != mineIndex &&
ITEM_ERR != otherIndex &&
otherIndex > mineIndex)
{
focused = 5;
}
}
}
else
{
focused = 0;
}
InvalidateRect(hToolbar, &rect, FALSE);
}
BOOL ToolbarRating::KeyDown(HWND hToolbar, INT vKey, UINT flags)
{
switch(vKey)
{
case VK_LEFT:
if (focused > 1)
{
focused--;
InvalidateRect(hToolbar, &rect, FALSE);
return TRUE;
}
break;
case VK_RIGHT:
if (focused < 5)
{
focused++;
InvalidateRect(hToolbar, &rect, FALSE);
return TRUE;
}
break;
case VK_SPACE:
case VK_RETURN:
SetStyle(hToolbar, statePressed, statePressed);
return TRUE;
}
return FALSE;
}
BOOL ToolbarRating::KeyUp(HWND hToolbar, INT vKey, UINT flags)
{
switch(vKey)
{
case VK_SPACE:
case VK_RETURN:
if (0 != (statePressed & style) && 0 != focused)
{
SetStyle(hToolbar, 0, statePressed);
SendRating(hToolbar, focused);
}
return TRUE;
}
return FALSE;
}