diff options
author | George Hazan <george.hazan@gmail.com> | 2014-03-04 23:23:45 +0000 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2014-03-04 23:23:45 +0000 |
commit | 15855fa84a09fd1fd486d357c38db0f2bd181e74 (patch) | |
tree | c98d1ae74abca41c776522059343eda13a7e0a31 /plugins/HistoryStats/src/optionsctrlimpl.cpp | |
parent | 819f8efabea6b0d7d971f9e6e4b21bbc18838874 (diff) |
HistoryStats compiles ok now
git-svn-id: http://svn.miranda-ng.org/main/trunk@8399 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/HistoryStats/src/optionsctrlimpl.cpp')
-rw-r--r-- | plugins/HistoryStats/src/optionsctrlimpl.cpp | 1428 |
1 files changed, 1428 insertions, 0 deletions
diff --git a/plugins/HistoryStats/src/optionsctrlimpl.cpp b/plugins/HistoryStats/src/optionsctrlimpl.cpp new file mode 100644 index 0000000000..46d63e8c58 --- /dev/null +++ b/plugins/HistoryStats/src/optionsctrlimpl.cpp @@ -0,0 +1,1428 @@ +#include "_globals.h"
+#include "optionsctrlimpl.h"
+
+#include "main.h"
+#include "iconlib.h"
+
+/*
+ * OptionsCtrlImpl
+ */
+
+const mu_text* OptionsCtrlImpl::m_ClassName = muT("HistoryStatsOptions");
+HIMAGELIST OptionsCtrlImpl::m_hStateIcons = NULL;
+int OptionsCtrlImpl::m_nStateIconsRef = 0;
+
+LRESULT CALLBACK OptionsCtrlImpl::staticWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ OptionsCtrlImpl* pCtrl = reinterpret_cast<OptionsCtrlImpl*>(GetWindowLong(hWnd, 0));
+
+ switch (msg)
+ {
+ case WM_NCCREATE:
+ {
+ CREATESTRUCT* pCS = reinterpret_cast<CREATESTRUCT*>(lParam);
+
+ pCS->style &= ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL);
+ pCS->style |= WS_CHILD;
+ pCS->dwExStyle &= ~(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE | WS_EX_WINDOWEDGE);
+
+ pCtrl = new OptionsCtrlImpl(hWnd, reinterpret_cast<int>(pCS->hMenu));
+ SetWindowLong(hWnd, 0, reinterpret_cast<LONG>(pCtrl));
+
+ return pCtrl ? TRUE : FALSE;
+ }
+
+ case WM_CREATE:
+ return pCtrl->onWMCreate(reinterpret_cast<CREATESTRUCT*>(lParam));
+
+ case WM_DESTROY:
+ pCtrl->onWMDestroy();
+ delete pCtrl;
+ SetWindowLong(hWnd, 0, 0);
+ return 0;
+
+ case WM_SETFOCUS:
+ SetFocus(pCtrl->m_hTree);
+ return 0;
+
+ case WM_ENABLE:
+ EnableWindow(pCtrl->m_hTree, wParam);
+ return 0;
+
+ case WM_GETFONT:
+ return SendMessage(pCtrl->m_hTree, WM_GETFONT, wParam, lParam);
+
+ case WM_SETFONT:
+ return SendMessage(pCtrl->m_hTree, WM_SETFONT, wParam, lParam);
+
+ case WM_WINDOWPOSCHANGED:
+ {
+ WINDOWPOS* pWP = reinterpret_cast<WINDOWPOS*>(lParam);
+
+ SetWindowPos(pCtrl->m_hTree, NULL, 0, 0, pWP->cx, pWP->cy, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+
+ return 0;
+ }
+
+ case WM_SETREDRAW:
+ return SendMessage(pCtrl->m_hTree, WM_SETREDRAW, wParam, lParam);
+
+ case WM_NOTIFY:
+ {
+ NMHDR* pNM = reinterpret_cast<NMHDR*>(lParam);
+
+ if (pNM->hwndFrom == pCtrl->m_hTree)
+ {
+ switch (pNM->code)
+ {
+ case NM_CLICK:
+ pCtrl->onNMClick();
+ return 0;
+
+ case NM_CUSTOMDRAW:
+ return pCtrl->onNMCustomDraw(reinterpret_cast<NMTVCUSTOMDRAW*>(pNM));
+
+ case NM_KILLFOCUS:
+ pCtrl->onNMKillFocus();
+ return 0;
+
+ case TVN_ITEMEXPANDING:
+ return pCtrl->onTVNItemExpanding(reinterpret_cast<NMTREEVIEW*>(pNM));
+
+ case TVN_DELETEITEM:
+ pCtrl->onTVNDeleteItem(reinterpret_cast<NMTREEVIEW*>(pNM));
+ return 0;
+
+ case TVN_SELCHANGING:
+ pCtrl->onTVNSelChanging(reinterpret_cast<NMTREEVIEW*>(pNM));
+ return 0;
+
+ case TVN_SELCHANGED:
+ pCtrl->onTVNSelChanged(reinterpret_cast<NMTREEVIEW*>(pNM));
+ return 0;
+
+ case TVN_BEGINDRAG:
+ pCtrl->onTVNBeginDrag(reinterpret_cast<NMTREEVIEW*>(pNM));
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ {
+ POINTS pts = MAKEPOINTS(lParam);
+ POINT pt = { pts.x, pts.y };
+
+ pCtrl->onWMMouseMove(pt);
+
+ return 0;
+ }
+
+ case WM_LBUTTONUP:
+ {
+ POINTS pts = MAKEPOINTS(lParam);
+ POINT pt = { pts.x, pts.y };
+
+ pCtrl->onWMLButtonUp(pt);
+
+ return 0;
+ }
+
+ case OCM_INSERTGROUP:
+ return reinterpret_cast<LRESULT>(pCtrl->onOCMInsertGroup(reinterpret_cast<HTREEITEM>(wParam), reinterpret_cast<OCGROUP*>(lParam)));
+
+ case OCM_INSERTCHECK:
+ return reinterpret_cast<LRESULT>(pCtrl->onOCMInsertCheck(reinterpret_cast<HTREEITEM>(wParam), reinterpret_cast<OCCHECK*>(lParam)));
+
+ case OCM_INSERTRADIO:
+ return reinterpret_cast<LRESULT>(pCtrl->onOCMInsertRadio(reinterpret_cast<HTREEITEM>(wParam), reinterpret_cast<OCRADIO*>(lParam)));
+
+ case OCM_INSERTEDIT:
+ return reinterpret_cast<LRESULT>(pCtrl->onOCMInsertEdit(reinterpret_cast<HTREEITEM>(wParam), reinterpret_cast<OCEDIT*>(lParam)));
+
+ case OCM_INSERTCOMBO:
+ return reinterpret_cast<LRESULT>(pCtrl->onOCMInsertCombo(reinterpret_cast<HTREEITEM>(wParam), reinterpret_cast<OCCOMBO*>(lParam)));
+
+ case OCM_INSERTBUTTON:
+ return reinterpret_cast<LRESULT>(pCtrl->onOCMInsertButton(reinterpret_cast<HTREEITEM>(wParam), reinterpret_cast<OCBUTTON*>(lParam)));
+
+ case OCM_GETITEMLABEL:
+ return reinterpret_cast<LRESULT>(pCtrl->onOCMGetItemLabel(reinterpret_cast<HTREEITEM>(wParam)));
+
+ case OCM_SETITEMLABEL:
+ pCtrl->onOCMSetItemLabel(reinterpret_cast<HTREEITEM>(wParam), reinterpret_cast<const mu_text*>(lParam));
+ return 0;
+
+ case OCM_ISITEMENABLED:
+ return BOOL_(pCtrl->onOCMIsItemEnabled(reinterpret_cast<HTREEITEM>(wParam)));
+
+ case OCM_ENABLEITEM:
+ pCtrl->onOCMEnableItem(reinterpret_cast<HTREEITEM>(wParam), bool_(lParam));
+ return 0;
+
+ case OCM_GETITEMDATA:
+ return pCtrl->onOCMGetItemData(reinterpret_cast<HTREEITEM>(wParam));
+
+ case OCM_SETITEMDATA:
+ pCtrl->onOCMSetItemData(reinterpret_cast<HTREEITEM>(wParam), lParam);
+ return 0;
+
+ case OCM_ISITEMCHECKED:
+ return BOOL_(pCtrl->onOCMIsItemChecked(reinterpret_cast<HTREEITEM>(wParam)));
+
+ case OCM_CHECKITEM:
+ pCtrl->onOCMCheckItem(reinterpret_cast<HTREEITEM>(wParam), bool_(lParam));
+ return 0;
+
+ case OCM_GETRADIOCHECKED:
+ return pCtrl->onOCMGetRadioChecked(reinterpret_cast<HTREEITEM>(wParam));
+
+ case OCM_SETRADIOCHECKED:
+ pCtrl->onOCMSetRadioChecked(reinterpret_cast<HTREEITEM>(wParam), lParam);
+ return 0;
+
+ case OCM_GETEDITNUMBER:
+ return pCtrl->onOCMGetEditNumber(reinterpret_cast<HTREEITEM>(wParam));
+
+ case OCM_SETEDITNUMBER:
+ pCtrl->onOCMSetEditNumber(reinterpret_cast<HTREEITEM>(wParam), lParam);
+ return 0;
+
+ case OCM_GETEDITSTRING:
+ return reinterpret_cast<LPARAM>(pCtrl->onOCMGetEditString(reinterpret_cast<HTREEITEM>(wParam)));
+
+ case OCM_SETEDITSTRING:
+ pCtrl->onOCMSetEditString(reinterpret_cast<HTREEITEM>(wParam), reinterpret_cast<const mu_text*>(lParam));
+ return 0;
+
+ case OCM_ADDCOMBOITEM:
+ pCtrl->onOCMAddComboItem(reinterpret_cast<HTREEITEM>(wParam), reinterpret_cast<const mu_text*>(lParam));
+ return 0;
+
+ case OCM_GETCOMBOSELECTED:
+ return pCtrl->onOCMGetComboSelected(reinterpret_cast<HTREEITEM>(wParam));
+
+ case OCM_SETCOMBOSELECTED:
+ pCtrl->onOCMSetComboSelected(reinterpret_cast<HTREEITEM>(wParam), lParam);
+ return 0;
+
+ case OCM_ENSUREVISIBLE:
+ pCtrl->onOCMEnsureVisible(reinterpret_cast<HTREEITEM>(wParam));
+ return 0;
+
+ case OCM_DELETEALLITEMS:
+ pCtrl->onOCMDeleteAllItems();
+ return 0;
+
+ case OCM_GETSELECTION:
+ return reinterpret_cast<LRESULT>(pCtrl->onOCMGetSelection());
+
+ case OCM_SELECTITEM:
+ pCtrl->onOCMSelectItem(reinterpret_cast<HTREEITEM>(wParam));
+ return 0;
+
+ case OCM_GETITEM:
+ return reinterpret_cast<LRESULT>(pCtrl->onOCMGetItem(reinterpret_cast<HTREEITEM>(wParam), lParam));
+
+ case OCM_DELETEITEM:
+ pCtrl->onOCMDeleteItem(reinterpret_cast<HTREEITEM>(wParam));
+ return 0;
+
+ case OCM_MOVEITEM:
+ pCtrl->onOCMMoveItem(*reinterpret_cast<HTREEITEM*>(wParam), reinterpret_cast<HTREEITEM>(lParam));
+ return 0;
+
+ case OCM_GETSCROLLPOS:
+ return GetScrollPos(pCtrl->m_hTree, wParam);
+
+ case OCM_SETSCROLLPOS:
+ SetScrollPos(pCtrl->m_hTree, wParam, lParam, TRUE);
+ return 0;
+
+ case OCM_INSERTDATETIME:
+ return reinterpret_cast<LRESULT>(pCtrl->onOCMInsertDateTime(reinterpret_cast<HTREEITEM>(wParam), reinterpret_cast<OCDATETIME*>(lParam)));
+
+ case OCM_ISDATETIMENONE:
+ return BOOL_(pCtrl->onOCMIsDateTimeNone(reinterpret_cast<HTREEITEM>(wParam)));
+
+ case OCM_SETDATETIMENONE:
+ pCtrl->onOCMSetDateTimeNone(reinterpret_cast<HTREEITEM>(wParam));
+ return 0;
+
+ case OCM_GETDATETIME:
+ return pCtrl->onOCMGetDateTime(reinterpret_cast<HTREEITEM>(wParam), reinterpret_cast<BOOL*>(lParam));
+
+ case OCM_SETDATETIME:
+ pCtrl->onOCMSetDateTime(reinterpret_cast<HTREEITEM>(wParam), lParam);
+ return 0;
+
+ case OCM_INSERTCOLOR:
+ return reinterpret_cast<LRESULT>(pCtrl->onOCMInsertColor(reinterpret_cast<HTREEITEM>(wParam), reinterpret_cast<OCCOLOR*>(lParam)));
+
+ case OCM_GETITEMCOLOR:
+ return pCtrl->onOCMGetItemColor(reinterpret_cast<HTREEITEM>(wParam));
+
+ case OCM_SETITEMCOLOR:
+ pCtrl->onOCMSetItemColor(reinterpret_cast<HTREEITEM>(wParam), lParam);
+ return 0;
+ }
+
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+}
+
+LRESULT CALLBACK OptionsCtrlImpl::staticTreeProc(HWND hTree, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ OptionsCtrlImpl* pCtrl = reinterpret_cast<OptionsCtrlImpl*>(GetWindowLong(GetParent(hTree), 0));
+
+ switch (msg)
+ {
+ case WM_LBUTTONDOWN:
+ pCtrl->onTreeWMLButtonDown(wParam, MAKEPOINTS(lParam));
+
+ case WM_CHAR:
+ pCtrl->onTreeWMChar(wParam, LOWORD(lParam), HIWORD(lParam));
+ break;
+
+ case WM_KEYDOWN:
+ pCtrl->onTreeWMKeyDown(wParam, LOWORD(lParam), HIWORD(lParam));
+ break;
+
+ case WM_VSCROLL:
+ case WM_HSCROLL:
+ case WM_MOUSEWHEEL:
+ case WM_WINDOWPOSCHANGED:
+ pCtrl->onTreeXScroll(); // stops editing
+ break;
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case ccEdit:
+ if (HIWORD(wParam) == EN_CHANGE)
+ {
+ pCtrl->onENChange();
+ }
+ else if (HIWORD(wParam) == EN_KILLFOCUS)
+ {
+ pCtrl->onNMKillFocus();
+ }
+ return 0;
+
+ case ccCombo:
+ if (HIWORD(wParam) == CBN_SELCHANGE)
+ {
+ pCtrl->onCBNSelChange();
+ }
+ else if (HIWORD(wParam) == CBN_KILLFOCUS)
+ {
+ pCtrl->onNMKillFocus();
+ }
+ return 0;
+
+ case ccButton:
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ pCtrl->onBNClicked();
+ }
+ else if (HIWORD(wParam) == BN_KILLFOCUS)
+ {
+ pCtrl->onNMKillFocus();
+ }
+ return 0;
+
+ case ccColor:
+ if (HIWORD(wParam) == CPN_COLOURCHANGED)
+ {
+ pCtrl->onCPNColorChanged();
+ }
+ return 0;
+ }
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ NMHDR* pNM = reinterpret_cast<NMHDR*>(lParam);
+
+ if (pNM->idFrom == ccDateTime)
+ {
+ if (pNM->code == DTN_DATETIMECHANGE)
+ {
+ pCtrl->onDTNDateTimeChange();
+ }
+ else if (pNM->code == NM_KILLFOCUS)
+ {
+ pCtrl->onNMKillFocus();
+ }
+ return 0;
+ }
+ }
+ break;
+ }
+
+ return CallWindowProc(pCtrl->m_pfnOldTreeProc, hTree, msg, wParam, lParam);
+}
+
+void OptionsCtrlImpl::staticInitStateImages()
+{
+ if (m_nStateIconsRef++ == 0 && !m_hStateIcons)
+ {
+ m_hStateIcons = ImageList_Create(OS::smIconCX(), OS::smIconCY(), OS::imageListColor() | ILC_MASK, 16, 0);
+
+ staticUpdateStateImages(0);
+ IconLib::registerCallback(staticUpdateStateImages, 0);
+ }
+}
+
+void OptionsCtrlImpl::staticFreeStateImages()
+{
+ if (m_hStateIcons && --m_nStateIconsRef == 0)
+ {
+ IconLib::unregisterCallback(staticUpdateStateImages, 0);
+ ImageList_Destroy(m_hStateIcons);
+
+ m_hStateIcons = NULL;
+ }
+}
+
+void OptionsCtrlImpl::staticUpdateStateImages(LPARAM lParam)
+{
+ static const IconLib::IconIndex StateIcons[18] = {
+ IconLib::iiTreeCheck1,
+ IconLib::iiTreeCheck2,
+ IconLib::iiTreeCheck3,
+ IconLib::iiTreeCheck4,
+ IconLib::iiTreeRadio1,
+ IconLib::iiTreeRadio2,
+ IconLib::iiTreeRadio3,
+ IconLib::iiTreeRadio4,
+ IconLib::iiTreeEdit1,
+ IconLib::iiTreeEdit2,
+ IconLib::iiTreeCombo1,
+ IconLib::iiTreeCombo2,
+ IconLib::iiTreeFolder1,
+ IconLib::iiTreeFolder2,
+ IconLib::iiTreeButton1,
+ IconLib::iiTreeButton2,
+ IconLib::iiTreeDateTime1,
+ IconLib::iiTreeDateTime2,
+ };
+
+ ImageList_RemoveAll(m_hStateIcons);
+
+ array_each_(i, StateIcons)
+ {
+ ImageList_AddIcon(m_hStateIcons, IconLib::getIcon(StateIcons[i]));
+ }
+}
+
+bool OptionsCtrlImpl::registerClass()
+{
+ const WNDCLASSEX wcx = {
+ sizeof(wcx), // cbSize
+ 0, // style
+ staticWndProc, // lpfnWndProc
+ 0, // cbClsExtra
+ sizeof(OptionsCtrlImpl*), // cbWndExtra
+ g_hInst, // hInstance
+ NULL, // hIcon
+ NULL, // hCursor
+ NULL, // hbrBackground
+ NULL, // lpszMenuName
+ m_ClassName, // lpszClassName
+ NULL // hIconSm
+ };
+
+ if (!RegisterClassEx(&wcx))
+ {
+ return false;
+ }
+
+ INITCOMMONCONTROLSEX icc;
+
+ icc.dwSize = sizeof(icc);
+ icc.dwICC = ICC_DATE_CLASSES;
+
+ if (!InitCommonControlsEx(&icc))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void OptionsCtrlImpl::unregisterClass()
+{
+ UnregisterClass(m_ClassName, g_hInst);
+}
+
+OptionsCtrlImpl::OptionsCtrlImpl(HWND hWnd, int nOwnId)
+ : m_hWnd(hWnd), m_nOwnId(nOwnId), m_hTree(NULL), m_pfnOldTreeProc(NULL), m_bModified(true), m_hDragItem(NULL)
+{
+}
+
+OptionsCtrlImpl::~OptionsCtrlImpl()
+{
+}
+
+LRESULT OptionsCtrlImpl::onWMCreate(CREATESTRUCT* pCS)
+{
+ DWORD dwStyle = 0;
+
+ if (!(pCS->style & OCS_ALLOWDRAGDROP))
+ {
+ dwStyle |= TVS_DISABLEDRAGDROP;
+ }
+
+ m_hTree = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ WC_TREEVIEW,
+ muT(""),
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | TVS_HASLINES | TVS_NOHSCROLL | TVS_SHOWSELALWAYS | dwStyle,
+ 0,
+ 0,
+ pCS->cx,
+ pCS->cy,
+ m_hWnd,
+ reinterpret_cast<HMENU>(ccTree),
+ g_hInst,
+ NULL);
+
+ if (!m_hTree)
+ {
+ return -1;
+ }
+
+ // subclass tree view
+ m_pfnOldTreeProc = reinterpret_cast<WNDPROC>(SetWindowLong(m_hTree, GWLP_WNDPROC, reinterpret_cast<LONG>(staticTreeProc)));
+
+ // create/set state icons
+ staticInitStateImages();
+ TreeView_SetImageList(m_hTree, m_hStateIcons, TVSIL_NORMAL);
+
+ return 0;
+}
+
+void OptionsCtrlImpl::onWMDestroy()
+{
+ // empty tree just to be sure
+ onOCMDeleteAllItems();
+
+ // unset/free state icons
+ if (TreeView_GetImageList(m_hTree, TVSIL_NORMAL))
+ {
+ staticFreeStateImages();
+ }
+
+ // undo subclassing of tree view
+ SetWindowLong(m_hTree, GWLP_WNDPROC, reinterpret_cast<LONG>(m_pfnOldTreeProc));
+ m_pfnOldTreeProc = NULL;
+
+ // destroy tree view before invalidating 'this'
+ DestroyWindow(m_hTree);
+ m_hTree = NULL;
+}
+
+void OptionsCtrlImpl::onNMClick()
+{
+ DWORD dwPoint = GetMessagePos();
+ POINTS pts = MAKEPOINTS(dwPoint);
+ TVHITTESTINFO hti = { { pts.x, pts.y } };
+
+ ScreenToClient(m_hTree, &hti.pt);
+
+ HTREEITEM hSelItem = TreeView_GetSelection(m_hTree);
+ HTREEITEM hItem = TreeView_HitTest(m_hTree, &hti);
+
+ if (hItem == hSelItem && hti.flags & TVHT_ONITEM)
+ {
+ getItem(hItem)->onSelect();
+ }
+}
+
+LRESULT OptionsCtrlImpl::onNMCustomDraw(NMTVCUSTOMDRAW* pNMCustomDraw)
+{
+ switch (pNMCustomDraw->nmcd.dwDrawStage)
+ {
+ case CDDS_PREPAINT:
+ return CDRF_NOTIFYITEMDRAW;
+
+ case CDDS_ITEMPREPAINT:
+ {
+ Item* pItem = reinterpret_cast<Item*>(pNMCustomDraw->nmcd.lItemlParam);
+
+ if (pItem)
+ {
+ /*
+ if (pItem->m_ItemType == itGroup && reinterpret_cast<Group*>(pItem)->m_bDrawLine)
+ {
+ COLORREF crNewBk = GetSysColor(COLOR_HIGHLIGHT);
+ COLORREF crOldBk = SetBkColor(pNMCustomDraw->nmcd.hdc, crNewBk);
+
+ RECT rLine = pNMCustomDraw->nmcd.rc;
+ RECT rText;
+
+ TreeView_GetItemRect(m_hTree, reinterpret_cast<HTREEITEM>(pNMCustomDraw->nmcd.dwItemSpec), &rText, TRUE);
+
+ rLine.top = (rLine.bottom = (rLine.bottom + rLine.top) / 2) - 1;
+ rLine.left = rText.right;
+ rLine.right -= 2;
+
+ ExtTextOut(pNMCustomDraw->nmcd.hdc, 0, 0, ETO_OPAQUE, &rLine, NULL, 0, NULL);
+
+ OffsetRect(&rLine, 0, 2);
+ ExtTextOut(pNMCustomDraw->nmcd.hdc, 0, 0, ETO_OPAQUE, &rLine, NULL, 0, NULL);
+
+ SetBkColor(pNMCustomDraw->nmcd.hdc, crOldBk);
+ }
+ */
+
+ /*
+ if (pItem->m_ItemType == itColor)
+ {
+ COLORREF crColor = reinterpret_cast<Color*>(pItem)->m_crColor;
+
+ COLORREF crNewBk = GetSysColor(COLOR_HIGHLIGHT);
+ COLORREF crOldBk = SetBkColor(pNMCustomDraw->nmcd.hdc, crNewBk);
+
+ RECT rColor = pNMCustomDraw->nmcd.rc;
+ RECT rText;
+
+ TreeView_GetItemRect(m_hTree, reinterpret_cast<HTREEITEM>(pNMCustomDraw->nmcd.dwItemSpec), &rText, TRUE);
+
+ ++rColor.top;
+ --rColor.bottom;
+ rColor.left = rText.right;
+ rColor.right -= 2;
+
+ if (rColor.right - 40 > rColor.left)
+ {
+ rColor.right = rColor.left + 40;
+ }
+
+ ExtTextOut(pNMCustomDraw->nmcd.hdc, 0, 0, ETO_OPAQUE, &rColor, NULL, 0, NULL);
+
+ SetBkColor(pNMCustomDraw->nmcd.hdc, crColor);
+
+ InflateRect(&rColor, -1, -1);
+ ExtTextOut(pNMCustomDraw->nmcd.hdc, 0, 0, ETO_OPAQUE, &rColor, NULL, 0, NULL);
+
+ SetBkColor(pNMCustomDraw->nmcd.hdc, crOldBk);
+ }
+ */
+
+ if (!pItem->m_bEnabled)
+ {
+ pNMCustomDraw->clrText = GetSysColor(COLOR_GRAYTEXT);
+ }
+ }
+ }
+ return CDRF_NEWFONT;
+ }
+
+ return 0;
+}
+
+void OptionsCtrlImpl::onNMKillFocus()
+{
+ HWND hWndFocused = GetFocus();
+
+ if (hWndFocused != m_hTree && !IsChild(m_hTree, hWndFocused))
+ {
+ HTREEITEM hSelected = TreeView_GetSelection(m_hTree);
+
+ if (hSelected)
+ {
+ Item* pItem = getItem(hSelected);
+
+ if (pItem->m_ItemType == itDateTime)
+ {
+ // MEMO: handle date/time picker (with possibly open month calendar) separately
+ DateTime* pDateTime = reinterpret_cast<DateTime*>(pItem);
+
+ if (!pDateTime->isMonthCalVisible())
+ {
+ pDateTime->onDeselect();
+ }
+ }
+ else if (pItem->m_ItemType == itColor)
+ {
+ // MEMO: handle color picker separately
+ }
+ else
+ {
+ pItem->onDeselect();
+ }
+ }
+ }
+}
+
+LRESULT OptionsCtrlImpl::onTVNItemExpanding(NMTREEVIEW* pNMTreeView)
+{
+ return BOOL_(
+ pNMTreeView->action == TVE_COLLAPSE || pNMTreeView->action == TVE_COLLAPSERESET ||
+ (pNMTreeView->action == TVE_TOGGLE && pNMTreeView->itemNew.state & TVIS_EXPANDED));
+}
+
+void OptionsCtrlImpl::onTVNDeleteItem(NMTREEVIEW* pNMTreeView)
+{
+ if (pNMTreeView->itemOld.hItem)
+ {
+ // fake OCN_SELCHANGING message
+ NMOPTIONSCTRL nmoc;
+
+ nmoc.hdr.code = OCN_SELCHANGING;
+ nmoc.hdr.hwndFrom = m_hWnd;
+ nmoc.hdr.idFrom = m_nOwnId;
+ nmoc.hItem = 0;
+ nmoc.dwData = 0;
+
+ SendMessage(GetParent(m_hWnd), WM_NOTIFY, nmoc.hdr.idFrom, reinterpret_cast<LPARAM>(&nmoc));
+
+ // fake OCN_SELCHANGED message
+ nmoc.hdr.code = OCN_SELCHANGED;
+
+ SendMessage(GetParent(m_hWnd), WM_NOTIFY, nmoc.hdr.idFrom, reinterpret_cast<LPARAM>(&nmoc));
+
+ // do actual delete
+ Item* pItem = getItem(pNMTreeView->itemOld.hItem);
+ setItem(pNMTreeView->itemOld.hItem, NULL);
+
+ pItem->onDeselect();
+
+ if (--pItem->m_nRef == 0)
+ {
+ delete pItem;
+ }
+ }
+}
+
+void OptionsCtrlImpl::onTVNSelChanging(NMTREEVIEW* pNMTreeView)
+{
+ NMOPTIONSCTRL nmoc;
+
+ nmoc.hdr.code = OCN_SELCHANGING;
+ nmoc.hdr.hwndFrom = m_hWnd;
+ nmoc.hdr.idFrom = m_nOwnId;
+ nmoc.hItem = reinterpret_cast<HANDLE>(pNMTreeView->itemOld.hItem);
+ nmoc.dwData = pNMTreeView->itemOld.hItem ? reinterpret_cast<Item*>(pNMTreeView->itemOld.lParam)->m_dwData : 0;
+
+ SendMessage(GetParent(m_hWnd), WM_NOTIFY, nmoc.hdr.idFrom, reinterpret_cast<LPARAM>(&nmoc));
+
+ if (pNMTreeView->itemOld.hItem)
+ {
+ reinterpret_cast<Item*>(pNMTreeView->itemOld.lParam)->onDeselect();
+ }
+}
+
+void OptionsCtrlImpl::onTVNSelChanged(NMTREEVIEW* pNMTreeView)
+{
+ if (pNMTreeView->itemNew.hItem)
+ {
+ reinterpret_cast<Item*>(pNMTreeView->itemNew.lParam)->onSelect();
+ }
+
+ NMOPTIONSCTRL nmoc;
+
+ nmoc.hdr.code = OCN_SELCHANGED;
+ nmoc.hdr.hwndFrom = m_hWnd;
+ nmoc.hdr.idFrom = m_nOwnId;
+ nmoc.hItem = reinterpret_cast<HANDLE>(pNMTreeView->itemNew.hItem);
+ nmoc.dwData = pNMTreeView->itemNew.hItem ? reinterpret_cast<Item*>(pNMTreeView->itemNew.lParam)->m_dwData : 0;
+
+ SendMessage(GetParent(m_hWnd), WM_NOTIFY, nmoc.hdr.idFrom, reinterpret_cast<LPARAM>(&nmoc));
+}
+
+void OptionsCtrlImpl::onTVNBeginDrag(NMTREEVIEW* pNMTreeView)
+{
+ SetCapture(m_hWnd);
+ m_hDragItem = pNMTreeView->itemNew.hItem;
+ TreeView_SelectItem(m_hTree, m_hDragItem);
+}
+
+void OptionsCtrlImpl::onWMMouseMove(const POINT& pt)
+{
+ if (!m_hDragItem)
+ {
+ return;
+ }
+
+ TVHITTESTINFO hti;
+
+ hti.pt = pt;
+ ClientToScreen(m_hWnd, &hti.pt);
+ ScreenToClient(m_hTree, &hti.pt);
+ TreeView_HitTest(m_hTree, &hti);
+
+ if (hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT))
+ {
+ RECT rItem;
+
+ TreeView_GetItemRect(m_hTree, hti.hItem, &rItem, FALSE);
+ TreeView_SetInsertMark(m_hTree, hti.hItem, (hti.pt.y >= (rItem.top + rItem.bottom) / 2) ? TRUE : FALSE);
+ }
+ else
+ {
+ if (hti.flags & TVHT_ABOVE)
+ {
+ SendMessage(m_hTree, WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0);
+ }
+ else if (hti.flags & TVHT_BELOW)
+ {
+ SendMessage(m_hTree, WM_VSCROLL, MAKELPARAM(SB_LINEDOWN, 0), 0);
+ }
+
+ TreeView_SetInsertMark(m_hTree, NULL, FALSE);
+ }
+}
+
+void OptionsCtrlImpl::onWMLButtonUp(const POINT& pt)
+{
+ if (!m_hDragItem)
+ {
+ return;
+ }
+
+ // revert to noraml state
+ HTREEITEM hDragItem = m_hDragItem;
+
+ TreeView_SetInsertMark(m_hTree, NULL, FALSE);
+ m_hDragItem = NULL;
+ ReleaseCapture();
+
+ // check for drop target and handle
+ TVHITTESTINFO hti;
+
+ hti.pt = pt;
+ ClientToScreen(m_hWnd, &hti.pt);
+ ScreenToClient(m_hTree, &hti.pt);
+ TreeView_HitTest(m_hTree, &hti);
+
+ if (hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT))
+ {
+ RECT rItem;
+
+ TreeView_GetItemRect(m_hTree, hti.hItem, &rItem, FALSE);
+
+ bool bAbove = (hti.pt.y >= (rItem.top + rItem.bottom) / 2);
+
+ NMOPTIONSCTRLDROP nmocd;
+
+ nmocd.hdr.code = OCN_ITEMDROPPED;
+ nmocd.hdr.hwndFrom = m_hWnd;
+ nmocd.hdr.idFrom = m_nOwnId;
+ nmocd.hItem = reinterpret_cast<HANDLE>(hDragItem);
+ nmocd.dwData = hDragItem ? getItem(hDragItem)->m_dwData : 0;
+ nmocd.hDropTarget = reinterpret_cast<HANDLE>(hti.hItem);
+ nmocd.dwDropTargetData = hti.hItem ? getItem(hti.hItem)->m_dwData : 0;
+ nmocd.bAbove = BOOL_(bAbove);
+
+ SendMessage(GetParent(m_hWnd), WM_NOTIFY, nmocd.hdr.idFrom, reinterpret_cast<LPARAM>(&nmocd));
+ }
+}
+
+void OptionsCtrlImpl::onENChange()
+{
+ HTREEITEM hSelected = TreeView_GetSelection(m_hTree);
+
+ if (hSelected)
+ {
+ setModified(getItem(hSelected));
+ }
+}
+
+void OptionsCtrlImpl::onCBNSelChange()
+{
+ HTREEITEM hSelected = TreeView_GetSelection(m_hTree);
+
+ if (hSelected)
+ {
+ Item* pItem = getItem(hSelected);
+
+ assert(pItem->m_ItemType == itCombo);
+
+ reinterpret_cast<Combo*>(pItem)->onSelChanged();
+ setModified(pItem);
+ }
+}
+
+void OptionsCtrlImpl::onBNClicked()
+{
+ HTREEITEM hSelected = TreeView_GetSelection(m_hTree);
+
+ if (hSelected)
+ {
+ Item* pItem = getItem(hSelected);
+
+ assert(pItem->m_ItemType == itButton);
+
+ NMOPTIONSCTRL nmoc;
+
+ nmoc.hdr.code = OCN_CLICKED;
+ nmoc.hdr.hwndFrom = m_hWnd;
+ nmoc.hdr.idFrom = m_nOwnId;
+ nmoc.hItem = reinterpret_cast<HANDLE>(pItem->m_hItem);
+ nmoc.dwData = pItem->m_dwData;
+
+ SendMessage(GetParent(m_hWnd), WM_NOTIFY, nmoc.hdr.idFrom, reinterpret_cast<LPARAM>(&nmoc));
+ }
+}
+
+void OptionsCtrlImpl::onDTNDateTimeChange()
+{
+ HTREEITEM hSelected = TreeView_GetSelection(m_hTree);
+
+ if (hSelected)
+ {
+ Item* pItem = getItem(hSelected);
+
+ assert(pItem->m_ItemType == itDateTime);
+
+ reinterpret_cast<DateTime*>(pItem)->onDateTimeChange();
+ setModified(pItem);
+ }
+}
+
+void OptionsCtrlImpl::onCPNColorChanged()
+{
+ HTREEITEM hSelected = TreeView_GetSelection(m_hTree);
+
+ if (hSelected)
+ {
+ Item* pItem = getItem(hSelected);
+
+ assert(pItem->m_ItemType == itColor);
+
+ reinterpret_cast<Color*>(pItem)->onColorChange();
+ setModified(pItem);
+ }
+}
+
+void OptionsCtrlImpl::onTreeWMLButtonDown(UINT nFlags, POINTS point)
+{
+ TVHITTESTINFO hti = { { point.x, point.y } };
+
+ if (TreeView_HitTest(m_hTree, &hti) && hti.flags & TVHT_ONITEMICON)
+ {
+ getItem(hti.hItem)->onToggle();
+ }
+}
+
+void OptionsCtrlImpl::onTreeWMChar(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ if (nChar == VK_SPACE)
+ {
+ HTREEITEM hItem = TreeView_GetSelection(m_hTree);
+
+ if (hItem)
+ {
+ getItem(hItem)->onToggle();
+ }
+ }
+}
+
+void OptionsCtrlImpl::onTreeWMKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ if (nChar == VK_RIGHT)
+ {
+ HTREEITEM hItem = TreeView_GetSelection(m_hTree);
+
+ if (hItem)
+ {
+ getItem(hItem)->onActivate();
+ }
+ }
+}
+
+void OptionsCtrlImpl::onTreeXScroll()
+{
+ HTREEITEM hSelected = TreeView_GetSelection(m_hTree);
+
+ if (hSelected && isItemValid(hSelected))
+ {
+ getItem(hSelected)->onDeselect();
+ }
+}
+
+HTREEITEM OptionsCtrlImpl::onOCMInsertGroup(HTREEITEM hParent, OCGROUP* pGroup)
+{
+ assert(pGroup);
+ assert(pGroup->szLabel);
+
+ return (new Group(this, hParent ? getItem(hParent) : NULL, pGroup->szLabel, pGroup->dwFlags, pGroup->dwData))->m_hItem;
+}
+
+HTREEITEM OptionsCtrlImpl::onOCMInsertCheck(HTREEITEM hParent, OCCHECK* pCheck)
+{
+ assert(pCheck);
+ assert(pCheck->szLabel);
+
+ return (new Check(this, hParent ? getItem(hParent) : NULL, pCheck->szLabel, pCheck->dwFlags, pCheck->dwData))->m_hItem;
+}
+
+HTREEITEM OptionsCtrlImpl::onOCMInsertRadio(HTREEITEM hParent, OCRADIO* pRadio)
+{
+ assert(pRadio);
+ assert(pRadio->szLabel);
+
+ Item* pSibling = pRadio->hSibling ? getItem(reinterpret_cast<HTREEITEM>(pRadio->hSibling)) : NULL;
+
+ assert(!pSibling || pSibling->m_ItemType == itRadio);
+
+ return (new Radio(this, hParent ? getItem(hParent) : NULL, reinterpret_cast<Radio*>(pSibling), pRadio->szLabel, pRadio->dwFlags, pRadio->dwData))->m_hItem;
+}
+
+HTREEITEM OptionsCtrlImpl::onOCMInsertEdit(HTREEITEM hParent, OCEDIT* pEdit)
+{
+ assert(pEdit);
+ assert(pEdit->szLabel);
+ assert(pEdit->szEdit);
+
+ return (new Edit(this, hParent ? getItem(hParent) : NULL, pEdit->szLabel, pEdit->szEdit, pEdit->dwFlags, pEdit->dwData))->m_hItem;
+}
+
+HTREEITEM OptionsCtrlImpl::onOCMInsertCombo(HTREEITEM hParent, OCCOMBO* pCombo)
+{
+ assert(pCombo);
+ assert(pCombo->szLabel);
+
+ return (new Combo(this, hParent ? getItem(hParent) : NULL, pCombo->szLabel, pCombo->dwFlags, pCombo->dwData))->m_hItem;
+}
+
+HTREEITEM OptionsCtrlImpl::onOCMInsertButton(HTREEITEM hParent, OCBUTTON* pButton)
+{
+ assert(pButton);
+ assert(pButton->szLabel);
+ assert(pButton->szButton);
+
+ return (new Button(this, hParent ? getItem(hParent) : NULL, pButton->szLabel, pButton->szButton, pButton->dwFlags, pButton->dwData))->m_hItem;
+}
+
+HTREEITEM OptionsCtrlImpl::onOCMInsertDateTime(HTREEITEM hParent, OCDATETIME* pDateTime)
+{
+ assert(pDateTime);
+ assert(pDateTime->szLabel);
+ assert(pDateTime->szFormat);
+
+ return (new DateTime(this, hParent ? getItem(hParent) : NULL, pDateTime->szLabel, pDateTime->szFormat, pDateTime->dwDateTime, pDateTime->dwFlags, pDateTime->dwData))->m_hItem;
+}
+
+HTREEITEM OptionsCtrlImpl::onOCMInsertColor(HTREEITEM hParent, OCCOLOR* pColor)
+{
+ assert(pColor);
+ assert(pColor->szLabel);
+
+ return (new Color(this, hParent ? getItem(hParent) : NULL, pColor->szLabel, pColor->crColor, pColor->dwFlags, pColor->dwData))->m_hItem;
+}
+
+const mu_text* OptionsCtrlImpl::onOCMGetItemLabel(HTREEITEM hItem)
+{
+ return getItem(hItem)->getLabel();
+}
+
+void OptionsCtrlImpl::onOCMSetItemLabel(HTREEITEM hItem, const mu_text* szLabel)
+{
+ assert(szLabel);
+
+ getItem(hItem)->setLabel(szLabel);
+}
+
+bool OptionsCtrlImpl::onOCMIsItemEnabled(HTREEITEM hItem)
+{
+ return getItem(hItem)->m_bEnabled;
+}
+
+void OptionsCtrlImpl::onOCMEnableItem(HTREEITEM hItem, bool bEnable)
+{
+ getItem(hItem)->setEnabled(bEnable);
+}
+
+DWORD OptionsCtrlImpl::onOCMGetItemData(HTREEITEM hItem)
+{
+ return getItem(hItem)->m_dwData;
+}
+
+void OptionsCtrlImpl::onOCMSetItemData(HTREEITEM hItem, DWORD dwData)
+{
+ getItem(hItem)->m_dwData = dwData;
+}
+
+bool OptionsCtrlImpl::onOCMIsItemChecked(HTREEITEM hItem)
+{
+ Item* pItem = getItem(hItem);
+
+ assert(pItem->m_ItemType == itCheck || pItem->m_ItemType == itRadio);
+
+ return (pItem->m_ItemType == itCheck) ? reinterpret_cast<Check*>(pItem)->isChecked() : reinterpret_cast<Radio*>(pItem)->isChecked();
+}
+
+void OptionsCtrlImpl::onOCMCheckItem(HTREEITEM hItem, bool bCheck)
+{
+ Item* pItem = getItem(hItem);
+
+ assert(pItem->m_ItemType == itCheck || pItem->m_ItemType == itRadio);
+
+ if (pItem->m_ItemType == itCheck)
+ {
+ reinterpret_cast<Check*>(pItem)->setChecked(bCheck);
+ }
+ else
+ {
+ reinterpret_cast<Radio*>(pItem)->setChecked();
+ }
+}
+
+int OptionsCtrlImpl::onOCMGetRadioChecked(HTREEITEM hRadio)
+{
+ Item* pRadio = getItem(hRadio);
+
+ assert(pRadio->m_ItemType == itRadio);
+
+ return reinterpret_cast<Radio*>(pRadio)->m_pSiblings->getChecked();
+}
+
+void OptionsCtrlImpl::onOCMSetRadioChecked(HTREEITEM hRadio, int nCheck)
+{
+ Item* pRadio = getItem(hRadio);
+
+ assert(pRadio->m_ItemType == itRadio);
+
+ reinterpret_cast<Radio*>(pRadio)->m_pSiblings->setChecked(nCheck);
+}
+
+int OptionsCtrlImpl::onOCMGetEditNumber(HTREEITEM hEdit)
+{
+ Item* pEdit = getItem(hEdit);
+
+ assert(pEdit->m_ItemType == itEdit);
+
+ return reinterpret_cast<Edit*>(pEdit)->getNumber();
+}
+
+void OptionsCtrlImpl::onOCMSetEditNumber(HTREEITEM hEdit, int nNumber)
+{
+ Item* pEdit = getItem(hEdit);
+
+ assert(pEdit->m_ItemType == itEdit);
+
+ reinterpret_cast<Edit*>(pEdit)->setNumber(nNumber);
+}
+
+const mu_text* OptionsCtrlImpl::onOCMGetEditString(HTREEITEM hEdit)
+{
+ Item* pEdit = getItem(hEdit);
+
+ assert(pEdit->m_ItemType == itEdit);
+
+ return reinterpret_cast<Edit*>(pEdit)->getString();
+}
+
+void OptionsCtrlImpl::onOCMSetEditString(HTREEITEM hEdit, const mu_text *szString)
+{
+ assert(szString);
+
+ Item* pEdit = getItem(hEdit);
+
+ assert(pEdit->m_ItemType == itEdit);
+
+ reinterpret_cast<Edit*>(pEdit)->setString(szString);
+}
+
+void OptionsCtrlImpl::onOCMAddComboItem(HTREEITEM hCombo, const mu_text* szItem)
+{
+ assert(szItem);
+
+ Item* pCombo = getItem(hCombo);
+
+ assert(pCombo->m_ItemType == itCombo);
+
+ reinterpret_cast<Combo*>(pCombo)->addItem(szItem);
+}
+
+int OptionsCtrlImpl::onOCMGetComboSelected(HTREEITEM hCombo)
+{
+ Item* pCombo = getItem(hCombo);
+
+ assert(pCombo->m_ItemType == itCombo);
+
+ return reinterpret_cast<Combo*>(pCombo)->getSelected();
+}
+
+void OptionsCtrlImpl::onOCMSetComboSelected(HTREEITEM hCombo, int nSelect)
+{
+ Item* pCombo = getItem(hCombo);
+
+ assert(pCombo->m_ItemType == itCombo);
+
+ reinterpret_cast<Combo*>(pCombo)->setSelected(nSelect);
+}
+
+void OptionsCtrlImpl::onOCMEnsureVisible(HTREEITEM hItem)
+{
+ if (!hItem)
+ {
+ hItem = TreeView_GetChild(m_hTree, TVI_ROOT);
+ }
+
+ if (hItem)
+ {
+ TreeView_EnsureVisible(m_hTree, hItem);
+ }
+}
+
+void OptionsCtrlImpl::onOCMDeleteAllItems()
+{
+ TreeView_SelectItem(m_hTree, NULL);
+ TreeView_DeleteAllItems(m_hTree);
+}
+
+HTREEITEM OptionsCtrlImpl::onOCMGetSelection()
+{
+ return TreeView_GetSelection(m_hTree);
+}
+
+void OptionsCtrlImpl::onOCMSelectItem(HTREEITEM hItem)
+{
+ TreeView_SelectItem(m_hTree, hItem);
+}
+
+HTREEITEM OptionsCtrlImpl::onOCMGetItem(HTREEITEM hItem, DWORD dwFlag)
+{
+ switch (dwFlag)
+ {
+ case OCGI_FIRST:
+ return TreeView_GetRoot(m_hTree);
+
+ case OCGI_NEXT:
+ return TreeView_GetNextSibling(m_hTree, hItem);
+
+ case OCGI_PREV:
+ return TreeView_GetPrevSibling(m_hTree, hItem);
+
+ default:
+ return NULL;
+ }
+}
+
+void OptionsCtrlImpl::onOCMDeleteItem(HTREEITEM hItem)
+{
+ TreeView_DeleteItem(m_hTree, hItem);
+}
+
+void OptionsCtrlImpl::onOCMMoveItem(HTREEITEM& hItem, HTREEITEM hInsertAfter)
+{
+ assert(hItem);
+
+ TVINSERTSTRUCT tvis;
+
+ tvis.hParent = TreeView_GetParent(m_hTree, hItem);
+ tvis.hInsertAfter = hInsertAfter ? hInsertAfter : TVI_FIRST;
+ tvis.item.hItem = hItem;
+ tvis.item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE | TVIF_PARAM;
+ tvis.item.stateMask = TVIS_BOLD | TVIS_EXPANDED;
+
+ if (TreeView_GetItem(m_hTree, &tvis.item))
+ {
+ Item* pItem = reinterpret_cast<Item*>(tvis.item.lParam);
+
+ ++pItem->m_nRef;
+
+ TreeView_DeleteItem(m_hTree, hItem);
+
+ tvis.item.mask |= TVIF_TEXT;
+ tvis.item.pszText = muT("");
+
+ hItem = TreeView_InsertItem(m_hTree, &tvis);
+
+ ext::string strLabel = pItem->getLabel();
+
+ pItem->m_hItem = hItem;
+ pItem->setLabel(strLabel.c_str());
+ }
+}
+
+bool OptionsCtrlImpl::onOCMIsDateTimeNone(HTREEITEM hDateTime)
+{
+ Item* pDateTime = getItem(hDateTime);
+
+ assert(pDateTime->m_ItemType == itDateTime);
+
+ return reinterpret_cast<DateTime*>(pDateTime)->isNone();
+}
+
+void OptionsCtrlImpl::onOCMSetDateTimeNone(HTREEITEM hDateTime)
+{
+ Item* pDateTime = getItem(hDateTime);
+
+ assert(pDateTime->m_ItemType == itDateTime);
+
+ reinterpret_cast<DateTime*>(pDateTime)->setNone();
+}
+
+DWORD OptionsCtrlImpl::onOCMGetDateTime(HTREEITEM hDateTime, BOOL* pbNone)
+{
+ Item* pDateTime = getItem(hDateTime);
+
+ assert(pDateTime->m_ItemType == itDateTime);
+ assert(pbNone);
+
+ *pbNone = reinterpret_cast<DateTime*>(pDateTime)->isNone();
+
+ return reinterpret_cast<DateTime*>(pDateTime)->getTimestamp();
+}
+
+void OptionsCtrlImpl::onOCMSetDateTime(HTREEITEM hDateTime, DWORD dwTimestamp)
+{
+ Item* pDateTime = getItem(hDateTime);
+
+ assert(pDateTime->m_ItemType == itDateTime);
+
+ reinterpret_cast<DateTime*>(pDateTime)->setTimestamp(dwTimestamp);
+}
+
+COLORREF OptionsCtrlImpl::onOCMGetItemColor(HTREEITEM hColor)
+{
+ Item* pColor = getItem(hColor);
+
+ assert(pColor->m_ItemType == itColor);
+
+ return reinterpret_cast<Color*>(pColor)->getColor();
+}
+
+void OptionsCtrlImpl::onOCMSetItemColor(HTREEITEM hColor, COLORREF crColor)
+{
+ Item* pColor = getItem(hColor);
+
+ assert(pColor->m_ItemType == itColor);
+
+ reinterpret_cast<Color*>(pColor)->setColor(crColor);
+}
+
+void OptionsCtrlImpl::insertItem(Item* pParent, Item* pItem, const mu_text* szNodeText, DWORD dwFlags, int iImage)
+{
+ assert(!pParent || pParent->m_hItem);
+ assert(pItem);
+ assert(szNodeText);
+
+ TVINSERTSTRUCT tvis;
+
+ tvis.hParent = pParent ? pParent->m_hItem : TVI_ROOT;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE | TVIF_PARAM;
+ tvis.item.pszText = const_cast<mu_text*>(szNodeText);
+ tvis.item.iImage = iImage;
+ tvis.item.iSelectedImage = iImage;
+ tvis.item.stateMask = TVIS_EXPANDED | ((dwFlags & OCF_BOLD) ? TVIS_BOLD : 0);
+ tvis.item.state = tvis.item.stateMask;
+ tvis.item.lParam = reinterpret_cast<LPARAM>(pItem);
+
+ pItem->m_hItem = TreeView_InsertItem(m_hTree, &tvis);
+}
+
+void OptionsCtrlImpl::setModified(Item* pItem, bool bModified /* = true */)
+{
+ m_bModified = bModified;
+
+ if (bModified)
+ {
+ NMOPTIONSCTRL nmoc;
+
+ nmoc.hdr.code = OCN_MODIFIED;
+ nmoc.hdr.hwndFrom = m_hWnd;
+ nmoc.hdr.idFrom = m_nOwnId;
+ nmoc.hItem = reinterpret_cast<HANDLE>(pItem->m_hItem);
+ nmoc.dwData = pItem->m_dwData;
+
+ SendMessage(GetParent(m_hWnd), WM_NOTIFY, nmoc.hdr.idFrom, reinterpret_cast<LPARAM>(&nmoc));
+ }
+}
+
+bool OptionsCtrlImpl::isItemValid(HTREEITEM hItem)
+{
+ assert(hItem);
+
+ TVITEM tvi;
+
+ tvi.mask = TVIF_HANDLE | TVIF_PARAM;
+ tvi.hItem = hItem;
+
+ Item* pItem = TreeView_GetItem(m_hTree, &tvi) ? reinterpret_cast<Item*>(tvi.lParam) : NULL;
+
+ return bool_(pItem);
+}
+
+OptionsCtrlImpl::Item* OptionsCtrlImpl::getItem(HTREEITEM hItem)
+{
+ assert(hItem);
+
+ TVITEM tvi;
+
+ tvi.mask = TVIF_HANDLE | TVIF_PARAM;
+ tvi.hItem = hItem;
+
+ Item* pItem = TreeView_GetItem(m_hTree, &tvi) ? reinterpret_cast<Item*>(tvi.lParam) : NULL;
+
+ assert(pItem);
+
+ return pItem;
+}
+
+void OptionsCtrlImpl::setItem(HTREEITEM hItem, Item* pItem)
+{
+ TVITEM tvi;
+
+ tvi.mask = TVIF_HANDLE | TVIF_PARAM;
+ tvi.hItem = hItem;
+ tvi.lParam = reinterpret_cast<LPARAM>(pItem);
+
+ TreeView_SetItem(m_hTree, &tvi);
+}
+
+void OptionsCtrlImpl::setStateImage(HTREEITEM hItem, int iImage)
+{
+ assert(hItem);
+
+ TVITEM tvi;
+
+ tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvi.hItem = hItem;
+ tvi.iImage = iImage;
+ tvi.iSelectedImage = iImage;
+
+ TreeView_SetItem(m_hTree, &tvi);
+}
+
+void OptionsCtrlImpl::setNodeText(HTREEITEM hItem, const mu_text* szNodeText)
+{
+ assert(hItem);
+ assert(szNodeText);
+
+ TVITEM tvi;
+
+ tvi.mask = TVIF_HANDLE | TVIF_TEXT;
+ tvi.hItem = hItem;
+ tvi.pszText = const_cast<mu_text*>(szNodeText);
+
+ TreeView_SetItem(m_hTree, &tvi);
+}
+
+bool OptionsCtrlImpl::getItemFreeRect(HTREEITEM hItem, RECT& outRect)
+{
+ RECT rLine, rText;
+
+ if (TreeView_GetItemRect(m_hTree, hItem, &rLine, FALSE) && TreeView_GetItemRect(m_hTree, hItem, &rText, TRUE))
+ {
+ outRect.left = rText.right + 2;
+ outRect.top = rText.top;
+ outRect.right = rLine.right - 2;
+ outRect.bottom = rText.bottom;
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
|