summaryrefslogtreecommitdiff
path: root/plugins/ModernOpt/mopt_selector.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/ModernOpt/mopt_selector.cpp')
-rw-r--r--plugins/ModernOpt/mopt_selector.cpp385
1 files changed, 385 insertions, 0 deletions
diff --git a/plugins/ModernOpt/mopt_selector.cpp b/plugins/ModernOpt/mopt_selector.cpp
new file mode 100644
index 0000000000..42b15f51bb
--- /dev/null
+++ b/plugins/ModernOpt/mopt_selector.cpp
@@ -0,0 +1,385 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2007 Artem Shpynov
+Copyright 2000-2007 Miranda ICQ/IM project,
+
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "commonheaders.h"
+#include "modernopt.h"
+
+static void sttApplySkin(MODERNOPTOBJECT *obj, TCHAR *fn)
+{
+ char svc[128];
+ mir_snprintf(svc, SIZEOF(svc), "%s%s", obj->lpzThemeModuleName, TS_SKIN_APPLY);
+ CallService(svc, NULL, (LPARAM)fn);
+}
+
+static TCHAR *sttGetActiveSkin(MODERNOPTOBJECT *obj)
+{
+ char svc[128];
+ mir_snprintf(svc, SIZEOF(svc), "%s%s", obj->lpzThemeModuleName, TS_SKIN_ACTIVE);
+ return ServiceExists(svc) ? (TCHAR *)CallService(svc, 0, 0) : 0;
+}
+
+static void sttPreviewSkin(MODERNOPTOBJECT *obj, TCHAR *fn, LPDRAWITEMSTRUCT lps)
+{
+ if (!fn) return;
+
+ char svc[128];
+ mir_snprintf(svc, SIZEOF(svc), "%s%s", obj->lpzThemeModuleName, TS_SKIN_PREVIEW);
+ if (ServiceExists(svc))
+ CallService(svc, (WPARAM)lps, (LPARAM)fn);
+ else {
+ char *afn = mir_t2a(fn);
+ char *fnpreview = (char *)mir_alloc(lstrlenA(afn) + 10);
+ lstrcpyA(fnpreview, afn);
+ lstrcatA(fnpreview, ".png");
+ HBITMAP hbmPreview = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (LPARAM)fnpreview);
+ mir_free(afn);
+ mir_free(fnpreview);
+
+ if (!hbmPreview) return;
+
+ BITMAP bmp;
+ GetObject(hbmPreview, sizeof(bmp), &bmp);
+
+ SIZE szDst = { abs(bmp.bmWidth), abs(bmp.bmHeight) };
+ if ((szDst.cx > lps->rcItem.right-lps->rcItem.left) || (szDst.cy > lps->rcItem.bottom-lps->rcItem.top)) {
+ float q = min(
+ float(lps->rcItem.right-lps->rcItem.left) / szDst.cx,
+ float(lps->rcItem.bottom-lps->rcItem.top) / szDst.cy);
+ szDst.cx *= q;
+ szDst.cy *= q;
+ }
+ POINT ptDst = {
+ (lps->rcItem.left+lps->rcItem.right-szDst.cx) / 2,
+ (lps->rcItem.top+lps->rcItem.bottom-szDst.cy) / 2 };
+
+ HDC hdc = CreateCompatibleDC(lps->hDC);
+ SelectObject(hdc, hbmPreview);
+ SetStretchBltMode(hdc, HALFTONE);
+ StretchBlt(lps->hDC, ptDst.x, ptDst.y, szDst.cx, szDst.cy, hdc, 0, 0, abs(bmp.bmWidth), abs(bmp.bmHeight), SRCCOPY);
+ DeleteDC(hdc);
+ DeleteObject(hbmPreview);
+ }
+}
+
+struct TSkinListItem
+{
+ TCHAR *path;
+ TCHAR *title;
+ TCHAR *filename;
+
+ TSkinListItem(TCHAR *fn)
+ {
+ title = mir_tstrdup(fn);
+ if (TCHAR *p = _tcsrchr(title, _T('.'))) *p = 0;
+
+ TCHAR curPath[MAX_PATH];
+ GetCurrentDirectory(SIZEOF(curPath), curPath);
+
+ path = (TCHAR *)mir_alloc(MAX_PATH * sizeof(TCHAR));
+ CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)curPath, (LPARAM)path);
+
+ int length = lstrlen(curPath)+lstrlen(fn)+2;
+ filename = (TCHAR *)mir_alloc(length * sizeof(TCHAR));
+ mir_sntprintf(filename, length, _T("%s\\%s"), curPath, fn);
+ }
+
+ ~TSkinListItem()
+ {
+ mir_free(path);
+ mir_free(title);
+ mir_free(filename);
+ }
+};
+
+struct TSelectorData
+{
+ MODERNOPTOBJECT *obj;
+ TCHAR *active;
+ HBITMAP hbmpPreview;
+
+ TSelectorData()
+ {
+ ZeroMemory(this, sizeof(*this));
+ }
+ ~TSelectorData()
+ {
+ mir_free(active);
+ DeleteObject(hbmpPreview);
+ }
+};
+
+static bool CheckExt(TCHAR *fn, TCHAR *ext, int n)
+{
+ int l = lstrlen(fn);
+ return (l > n) && !lstrcmp(fn + l - n, ext);
+}
+
+static void BuildSkinList(HWND hwndList, TCHAR *szExt, int nExtLength = -1, bool start = true)
+{
+ if (start) {
+ static TCHAR mirPath[MAX_PATH];
+ GetModuleFileName(NULL, mirPath, SIZEOF(mirPath));
+ if (TCHAR *p = _tcsrchr(mirPath, _T('\\'))) *p = 0;
+ SetCurrentDirectory(mirPath);
+ SendMessage(hwndList, LB_RESETCONTENT, 0, 0);
+ nExtLength = lstrlen(szExt);
+ SendMessage(hwndList, WM_SETREDRAW, FALSE, 0);
+ }
+
+ WIN32_FIND_DATA ffd = {0};
+ HANDLE h = FindFirstFile(_T("*.*"), &ffd);
+ if (h != INVALID_HANDLE_VALUE) {
+ do {
+ if (!lstrcmp(ffd.cFileName, _T("")) || !lstrcmp(ffd.cFileName, _T(".")) || !lstrcmp(ffd.cFileName, _T("..")))
+ continue;
+
+ if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ SetCurrentDirectory(ffd.cFileName);
+ BuildSkinList(hwndList, szExt, nExtLength, false);
+ SetCurrentDirectory(_T(".."));
+ }
+ else {
+ if (CheckExt(ffd.cFileName, szExt, nExtLength)) {
+ TSkinListItem *dat = new TSkinListItem(ffd.cFileName);
+ DWORD dwItem = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)ffd.cFileName);
+ SendMessage(hwndList, LB_SETITEMDATA, dwItem, (LPARAM)dat);
+ } }
+ }
+ while (FindNextFile(h, &ffd));
+ FindClose(h);
+ }
+
+ if (start) {
+ SendMessage(hwndList, WM_SETREDRAW, TRUE, 0);
+ RedrawWindow(hwndList, NULL, NULL, RDW_INVALIDATE);
+ }
+}
+
+static void CreatePreview(TSelectorData *sd, TCHAR *fn, LPDRAWITEMSTRUCT lps)
+{
+ HDC hdc = CreateCompatibleDC(lps->hDC);
+ sd->hbmpPreview = CreateCompatibleBitmap(lps->hDC, lps->rcItem.right - lps->rcItem.left, lps->rcItem.bottom - lps->rcItem.top);
+ SelectObject(hdc, sd->hbmpPreview);
+
+ RECT rc;
+ HBRUSH hbr;
+
+ BITMAPINFO bi = {0};
+ bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
+ bi.bmiHeader.biWidth = 8;
+ bi.bmiHeader.biHeight = -8;
+ bi.bmiHeader.biPlanes = 1;
+ bi.bmiHeader.biBitCount = 32;
+ bi.bmiHeader.biCompression = BI_RGB;
+
+ HBITMAP hBmpBrush = (HBITMAP)CreateDIBSection(0, &bi, DIB_RGB_COLORS, 0, 0, 0);
+ HDC dcBmp = CreateCompatibleDC(0);
+ HBITMAP hBmpSave = (HBITMAP)SelectObject(dcBmp, hBmpBrush);
+ hbr = CreateSolidBrush(RGB(0xcc, 0xcc, 0xcc));
+ SetRect(&rc, 0, 0, 8, 8);
+ FillRect(dcBmp, &rc, hbr);
+ DeleteObject(hbr);
+ hbr = CreateSolidBrush(RGB(0xff, 0xff, 0xff));
+ SetRect(&rc, 4, 0, 8, 4);
+ FillRect(dcBmp, &rc, hbr);
+ SetRect(&rc, 0, 4, 4, 8);
+ FillRect(dcBmp, &rc, hbr);
+ DeleteObject(hbr);
+ SelectObject(dcBmp, hBmpSave);
+ DeleteDC(dcBmp);
+
+ rc = lps->rcItem;
+ OffsetRect(&rc, -rc.left, -rc.top);
+ hbr = CreatePatternBrush(hBmpBrush);
+ SetBrushOrgEx(hdc, 1, 1, 0);
+ FillRect(hdc, &rc, hbr);
+ DeleteObject(hbr);
+ DeleteObject(hBmpBrush);
+
+ HDC hdcSave = lps->hDC;
+ lps->hDC = hdc;
+ sttPreviewSkin(sd->obj, fn, lps);
+ lps->hDC = hdcSave;
+
+ FrameRect(hdc, &rc, GetStockBrush(LTGRAY_BRUSH));
+ DeleteDC(hdc);
+}
+
+INT_PTR CALLBACK ModernOptSelector_DlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TSelectorData *sd = (TSelectorData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ MODERNOPTOBJECT *&obj = sd->obj;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ sd = new TSelectorData;
+ MODERNOPTOBJECT *&obj = sd->obj;
+
+ sd->obj = (MODERNOPTOBJECT *)lParam;
+ sd->active = sttGetActiveSkin(obj);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)sd);
+
+ TCHAR *s = mir_a2t(obj->lpzThemeExtension);
+ BuildSkinList(GetDlgItem(hwndDlg, IDC_SKINLIST), s);
+ mir_free(s);
+ }
+ return FALSE;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_SKINLIST) {
+ switch (HIWORD(wParam)) {
+ case LBN_SELCHANGE:
+ DeleteObject(sd->hbmpPreview);
+ sd->hbmpPreview = 0;
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_PREVIEW1), NULL, NULL, RDW_INVALIDATE);
+ break;
+
+ case LBN_DBLCLK:
+ {
+ int idx = SendDlgItemMessage(hwndDlg, IDC_SKINLIST, LB_GETCURSEL, 0, 0);
+ if (idx >= 0)
+ {
+ TSkinListItem *dat = (TSkinListItem *)SendDlgItemMessage(hwndDlg, IDC_SKINLIST, LB_GETITEMDATA, idx, 0);
+ sttApplySkin(obj, dat->filename);
+ mir_free(sd->active);
+ sd->active = sttGetActiveSkin(obj);
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_SKINLIST), NULL, NULL, RDW_INVALIDATE);
+ }
+ break;
+ } }
+ break;
+ }
+ return FALSE;
+
+ case WM_MEASUREITEM:
+ {
+ LPMEASUREITEMSTRUCT lps = (LPMEASUREITEMSTRUCT)lParam;
+ if (lps->CtlID != IDC_SKINLIST)
+ break;
+ TSkinListItem *dat = (TSkinListItem *)lps->itemData;
+ if (!dat) break;
+
+ lps->itemWidth = 10;
+ lps->itemHeight = 30;
+
+ return FALSE;
+ }
+
+ case WM_DRAWITEM:
+ {
+ LPDRAWITEMSTRUCT lps = (LPDRAWITEMSTRUCT)lParam;
+ if (lps->CtlID == IDC_SKINLIST) {
+ TSkinListItem *dat = (TSkinListItem *)lps->itemData;
+ if (!dat) break;
+
+ SetBkMode(lps->hDC, TRANSPARENT);
+ COLORREF clLine1, clLine2, clBack;
+ if (lps->itemState & ODS_SELECTED) {
+ FillRect(lps->hDC, &lps->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT));
+ clBack = GetSysColor(COLOR_HIGHLIGHT);
+ clLine1 = GetSysColor(COLOR_HIGHLIGHTTEXT);
+ }
+ else {
+ FillRect(lps->hDC, &lps->rcItem, GetSysColorBrush(COLOR_WINDOW));
+ clBack = GetSysColor(COLOR_WINDOW);
+ clLine1 = GetSysColor(COLOR_WINDOWTEXT);
+ }
+ clLine2 = RGB(
+ GetRValue(clLine1) * 0.66 + GetRValue(clBack) * 0.34,
+ GetGValue(clLine1) * 0.66 + GetGValue(clBack) * 0.34,
+ GetBValue(clLine1) * 0.66 + GetBValue(clBack) * 0.34
+ );
+
+ lps->rcItem.left += 2;
+ lps->rcItem.top += 2;
+ lps->rcItem.bottom -= 2;
+ lps->rcItem.right -= 5;
+
+ int cxIcon = GetSystemMetrics(SM_CXSMICON);
+ int cyIcon = GetSystemMetrics(SM_CYSMICON);
+
+ if (sd->active && !lstrcmp(sd->active, dat->filename)) {
+ DrawIconEx(lps->hDC, lps->rcItem.left, (lps->rcItem.top+lps->rcItem.bottom-cyIcon)/2,
+ LoadSkinnedIcon(SKINICON_OTHER_EMPTYBLOB),
+ cxIcon, cyIcon, 0, NULL, DI_NORMAL);
+ }
+ else {
+ DrawIconEx(lps->hDC, lps->rcItem.left, (lps->rcItem.top+lps->rcItem.bottom-cyIcon)/2,
+ LoadSkinnedIcon(SKINICON_OTHER_SMALLDOT),
+ cxIcon, cyIcon, 0, NULL, DI_NORMAL);
+ }
+ lps->rcItem.left += cxIcon;
+ lps->rcItem.left += 5;
+
+// SelectObject(lps->hDC, dat->hfntTitle);
+ SetTextColor(lps->hDC, clLine1);
+ DrawText(lps->hDC, dat->title, -1, &lps->rcItem, DT_LEFT|DT_NOPREFIX|DT_SINGLELINE|DT_END_ELLIPSIS|DT_TOP);
+ lps->rcItem.left += cxIcon;
+
+ SetTextColor(lps->hDC, clLine2);
+ DrawText(lps->hDC, dat->path, -1, &lps->rcItem, DT_LEFT|DT_NOPREFIX|DT_SINGLELINE|DT_PATH_ELLIPSIS|DT_BOTTOM);
+ }
+ else if (lps->CtlID == IDC_PREVIEW1) {
+ int idx = SendDlgItemMessage(hwndDlg, IDC_SKINLIST, LB_GETCURSEL, 0, 0);
+
+ if (!sd->hbmpPreview) {
+ if (idx >= 0) {
+ TSkinListItem *dat = (TSkinListItem *)SendDlgItemMessage(hwndDlg, IDC_SKINLIST, LB_GETITEMDATA, idx, 0);
+ CreatePreview(sd, dat->filename, lps);
+ //sttPreviewSkin(obj, dat->filename, lps);
+ }
+ else CreatePreview(sd, NULL, lps);
+ }
+
+ if (sd->hbmpPreview) {
+ HDC hdc = CreateCompatibleDC(lps->hDC);
+ SelectObject(hdc, sd->hbmpPreview);
+ BitBlt(lps->hDC,
+ lps->rcItem.left, lps->rcItem.top,
+ lps->rcItem.right - lps->rcItem.left, lps->rcItem.bottom - lps->rcItem.top,
+ hdc, 0, 0, SRCCOPY);
+ DeleteDC(hdc);
+ }
+ }
+
+ return TRUE;
+ }
+
+ case WM_DELETEITEM:
+ {
+ LPDELETEITEMSTRUCT lps = (LPDELETEITEMSTRUCT)lParam;
+ if (lps->CtlID != IDC_SKINLIST) break;
+ TSkinListItem *dat = (TSkinListItem *)lps->itemData;
+ if (dat) delete dat;
+ return FALSE;
+ }
+
+ case WM_DESTROY:
+ delete sd;
+ return FALSE;
+ }
+ return FALSE;
+}