diff options
author | George Hazan <george.hazan@gmail.com> | 2014-02-20 18:43:33 +0000 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2014-02-20 18:43:33 +0000 |
commit | b26198b243f682cfd66aa5d06acbb62d6d35206c (patch) | |
tree | 0bb4c9efbcb9b3418a82f804ca5825e055f6169e /plugins/NewAwaySysMod/src/MsgTree.cpp | |
parent | b9567416b251f589ba5ac4ed1dadc644e79d6912 (diff) |
attempt to revive NAS
git-svn-id: http://svn.miranda-ng.org/main/trunk@8194 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/NewAwaySysMod/src/MsgTree.cpp')
-rw-r--r-- | plugins/NewAwaySysMod/src/MsgTree.cpp | 790 |
1 files changed, 790 insertions, 0 deletions
diff --git a/plugins/NewAwaySysMod/src/MsgTree.cpp b/plugins/NewAwaySysMod/src/MsgTree.cpp new file mode 100644 index 0000000000..e53ea75cfc --- /dev/null +++ b/plugins/NewAwaySysMod/src/MsgTree.cpp @@ -0,0 +1,790 @@ +/*
+ New Away System - plugin for Miranda IM
+ Copyright (c) 2005-2007 Chervov Dmitry
+
+ 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 "Common.h"
+#include "MsgTree.h"
+#include "Properties.h"
+
+#define UM_MSGTREE_INIT (WM_USER + 0x2103)
+#define UM_MSGTREE_UPDATE (WM_USER + 0x2104)
+
+#define MSGTREE_TIMER_ID 0x2103
+#define MSGTREE_DRAGANDDROP_GROUPEXPANDTIME 600
+
+#define IMGLIST_NEWMESSAGE 0
+#define IMGLIST_NEWCATEGORY 1
+#define IMGLIST_DELETE 2
+
+struct {
+ int DBSetting, Status, MenuItemID;
+} StatusModeList[] = {
+ IDS_MESSAGEDLG_DEF_ONL, ID_STATUS_ONLINE, IDR_MSGTREEMENU_DEF_ONL,
+ IDS_MESSAGEDLG_DEF_AWAY, ID_STATUS_AWAY, IDR_MSGTREEMENU_DEF_AWAY,
+ IDS_MESSAGEDLG_DEF_NA, ID_STATUS_NA, IDR_MSGTREEMENU_DEF_NA,
+ IDS_MESSAGEDLG_DEF_OCC, ID_STATUS_OCCUPIED, IDR_MSGTREEMENU_DEF_OCC,
+ IDS_MESSAGEDLG_DEF_DND, ID_STATUS_DND, IDR_MSGTREEMENU_DEF_DND,
+ IDS_MESSAGEDLG_DEF_FFC, ID_STATUS_FREECHAT, IDR_MSGTREEMENU_DEF_FFC,
+ IDS_MESSAGEDLG_DEF_INV, ID_STATUS_INVISIBLE, IDR_MSGTREEMENU_DEF_INV,
+ IDS_MESSAGEDLG_DEF_OTP, ID_STATUS_ONTHEPHONE, IDR_MSGTREEMENU_DEF_OTP,
+ IDS_MESSAGEDLG_DEF_OTL, ID_STATUS_OUTTOLUNCH, IDR_MSGTREEMENU_DEF_OTL
+};
+
+static HANDLE hMTWindowList;
+static WNDPROC g_OrigEditProc;
+
+
+void LoadMsgTreeModule()
+{
+ hMTWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0);
+}
+
+
+static LRESULT CALLBACK EditSubclassProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (Msg)
+ {
+ case WM_GETDLGCODE:
+ {
+ return CallWindowProc(g_OrigEditProc, hWnd, Msg, wParam, lParam) | DLGC_WANTALLKEYS;
+ } break;
+ }
+ return CallWindowProc(g_OrigEditProc, hWnd, Msg, wParam, lParam);
+}
+
+static LRESULT CALLBACK ParentSubclassProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ CMsgTree *dat = CWndUserData(hWnd).GetMsgTree();
+ switch (Msg)
+ {
+ case WM_NOTIFY:
+ {
+ if (((LPNMHDR)lParam)->hwndFrom == dat->hTreeView)
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case TVN_BEGINDRAGA:
+ case TVN_BEGINDRAGW:
+ {
+ LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam;
+ NMMSGTREE nm = {0};
+ COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl();
+ int Order = TreeCtrl->hItemToOrder(pnmtv->itemNew.hItem);
+ _ASSERT(Order != -1);
+ if (Order != -1)
+ {
+ nm.ItemOld = (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order];
+ nm.hdr.code = MTN_BEGINDRAG;
+ nm.hdr.hwndFrom = dat->hTreeView;
+ nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView);
+ if (!SendMessage(hWnd, WM_NOTIFY, 0, (LPARAM)&nm))
+ {
+ SetCapture(hWnd);
+ dat->hPrevDropTarget = dat->hDragItem = pnmtv->itemNew.hItem;
+ SetFocus(dat->hTreeView);
+ TreeView_SelectItem(dat->hTreeView, dat->hDragItem);
+ }
+ }
+ } break;
+ case TVN_SELCHANGEDA:
+ case TVN_SELCHANGEDW:
+ {
+ if (dat->UpdateLock)
+ {
+ return 0;
+ }
+ LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam;
+ NMMSGTREE nm = {0};
+ COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl();
+ if (pnmtv->itemOld.hItem)
+ {
+ int Order = TreeCtrl->IDToOrder(pnmtv->itemOld.lParam);
+ if (Order != -1)
+ {
+ nm.ItemOld = (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order];
+ }
+ }
+ if (pnmtv->itemNew.hItem)
+ {
+ int Order = TreeCtrl->IDToOrder(pnmtv->itemNew.lParam);
+ if (Order != -1)
+ {
+ nm.ItemNew = (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order];
+ }
+ }
+ nm.hdr.code = MTN_SELCHANGED;
+ nm.hdr.hwndFrom = dat->hTreeView;
+ nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView);
+ SendMessage(hWnd, WM_NOTIFY, 0, (LPARAM)&nm);
+ } break;
+ case TVN_BEGINLABELEDITA:
+ case TVN_BEGINLABELEDITW:
+ {
+ if (dat->GetTreeCtrl()->IDToOrder(((LPNMTVDISPINFO)lParam)->item.lParam) < 0)
+ {
+ return true; // cancel editing
+ }
+ g_OrigEditProc = (WNDPROC)SetWindowLongPtr(TreeView_GetEditControl(dat->hTreeView), GWLP_WNDPROC, (LONG_PTR)EditSubclassProc);
+ } break;
+// case TVN_ENDLABELEDITA: // stupid miranda options.. how am I supposed to get ptvdi->item.pszText if it's in ANSI??
+ case TVN_ENDLABELEDIT:
+ {
+ LPNMTVDISPINFO ptvdi = (LPNMTVDISPINFO)lParam;
+ if (ptvdi->item.pszText)
+ {
+ COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl();
+ int Order = TreeCtrl->IDToOrder(ptvdi->item.lParam);
+ if (Order >= 0)
+ {
+ TreeCtrl->Value[Order].Title = ptvdi->item.pszText;
+ TreeCtrl->SetModified(true);
+ NMMSGTREE nm = {0};
+ nm.ItemNew = &TreeCtrl->Value[Order];
+ nm.hdr.code = MTN_ITEMRENAMED;
+ nm.hdr.hwndFrom = dat->hTreeView;
+ nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView);
+ SendMessage(GetParent(dat->hTreeView), WM_NOTIFY, 0, (LPARAM)&nm);
+ return true; // commit new text
+ }
+ }
+ } break;
+ case NM_CLICK:
+ case NM_RCLICK:
+ {
+ TVHITTESTINFO hitTest;
+ hitTest.pt.x = (short)LOWORD(GetMessagePos());
+ hitTest.pt.y = (short)HIWORD(GetMessagePos());
+ ScreenToClient(dat->hTreeView, &hitTest.pt);
+ TreeView_HitTest(dat->hTreeView, &hitTest);
+ if (hitTest.hItem)
+ {
+ if (TreeView_GetSelection(dat->hTreeView) == hitTest.hItem)
+ { // make sure TVN_SELCHANGED notification is sent always, even if previous selected item was the same as new
+ TreeView_SelectItem(dat->hTreeView, NULL);
+ }
+ TreeView_SelectItem(dat->hTreeView, hitTest.hItem);
+ }
+ } break;
+ case NM_CUSTOMDRAW:
+ {
+ NMTVCUSTOMDRAW *lpNMCD = (NMTVCUSTOMDRAW*)lParam;
+ switch (lpNMCD->nmcd.dwDrawStage)
+ {
+ case CDDS_PREPAINT: // the control is about to start painting
+ {
+ return CDRF_NOTIFYITEMDRAW; // instruct the control to return information when it draws items
+ } break;
+ case CDDS_ITEMPREPAINT:
+ {
+ return CDRF_NOTIFYPOSTPAINT;
+ } break;
+ case CDDS_ITEMPOSTPAINT:
+ {
+ RECT rc;
+ TreeView_GetItemRect(lpNMCD->nmcd.hdr.hwndFrom, (HTREEITEM)lpNMCD->nmcd.dwItemSpec, &rc, true);
+ int iSize = GetSystemMetrics(SM_CXSMICON);
+ int I;
+ int x = rc.left - iSize - 5;
+ for (I = 0; I < lengthof(StatusModeList); I++)
+ {
+ if (lpNMCD->nmcd.lItemlParam == dat->MsgTreePage.GetValue(StatusModeList[I].DBSetting))
+ {
+ DrawIconEx(lpNMCD->nmcd.hdc, x, rc.top, LoadSkinnedProtoIcon(NULL, StatusModeList[I].Status), iSize, iSize, 0, GetSysColorBrush(COLOR_WINDOW), DI_NORMAL);
+ x -= iSize + 1;
+ }
+/* if (lpNMCD->nmcd.lItemlParam == GetRecentGroupID(StatusModeList[I].Status))
+ {
+ DrawIconEx(lpNMCD->nmcd.hdc, 3, rc.top, LoadSkinnedProtoIcon(NULL, StatusModeList[I].Status), iSize, iSize, 0, GetSysColorBrush(COLOR_WINDOW), DI_NORMAL);
+ }*/
+ }
+ } break;
+ }
+ } break;
+ }
+ }
+ } break;
+ case WM_MOUSEMOVE:
+ {
+ if (dat->hDragItem)
+ {
+ TVHITTESTINFO hti;
+ hti.pt.x = (short)LOWORD(lParam);
+ hti.pt.y = (short)HIWORD(lParam);
+ ClientToScreen(hWnd, &hti.pt);
+ ScreenToClient(dat->hTreeView, &hti.pt);
+ TreeView_HitTest(dat->hTreeView, &hti);
+ if (hti.hItem)
+ {
+ TreeView_SelectDropTarget(dat->hTreeView, hti.hItem);
+ SetTimer(hWnd, MSGTREE_TIMER_ID, MSGTREE_DRAGANDDROP_GROUPEXPANDTIME, NULL);
+ } else
+ {
+ if (hti.flags & TVHT_ABOVE)
+ {
+ SendMessage(dat->hTreeView, WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0);
+ }
+ if (hti.flags & TVHT_BELOW)
+ {
+ SendMessage(dat->hTreeView, WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0);
+ }
+ TreeView_SelectDropTarget(dat->hTreeView, NULL);
+ KillTimer(hWnd, MSGTREE_TIMER_ID);
+ }
+ }
+ } break;
+ case WM_LBUTTONUP:
+ {
+ if (dat->hDragItem)
+ {
+ TreeView_SelectDropTarget(dat->hTreeView, NULL);
+ KillTimer(hWnd, MSGTREE_TIMER_ID);
+ ReleaseCapture();
+ TVHITTESTINFO hti;
+ hti.pt.x = (short)LOWORD(lParam);
+ hti.pt.y = (short)HIWORD(lParam);
+ ClientToScreen(hWnd, &hti.pt);
+ ScreenToClient(dat->hTreeView, &hti.pt);
+ TreeView_HitTest(dat->hTreeView, &hti);
+ if (hti.hItem && dat->hDragItem != hti.hItem)
+ {
+ NMMSGTREE nm = {0};
+ COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl();
+ int OrderOld = TreeCtrl->hItemToOrder(dat->hDragItem);
+ int OrderNew = TreeCtrl->hItemToOrder(hti.hItem);
+ _ASSERT(OrderOld != -1 && OrderNew != -1);
+ nm.ItemOld = (OrderOld <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(OrderOld)] : (CBaseTreeItem*)&TreeCtrl->Value[OrderOld];
+ nm.ItemNew = (OrderNew <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(OrderNew)] : (CBaseTreeItem*)&TreeCtrl->Value[OrderNew];
+ nm.hdr.code = MTN_ENDDRAG;
+ nm.hdr.hwndFrom = dat->hTreeView;
+ nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView);
+ if (!SendMessage(hWnd, WM_NOTIFY, 0, (LPARAM)&nm))
+ {
+ dat->UpdateLock++;
+ dat->GetTreeCtrl()->MoveItem(hWnd, dat->hDragItem, hti.hItem);
+ dat->UpdateLock--;
+ }
+ }
+ dat->hDragItem = NULL;
+ }
+ } break;
+ case WM_TIMER:
+ {
+ if (wParam == MSGTREE_TIMER_ID)
+ {
+ KillTimer(hWnd, MSGTREE_TIMER_ID);
+ TVHITTESTINFO hti;
+ hti.pt.x = (short)LOWORD(GetMessagePos());
+ hti.pt.y = (short)HIWORD(GetMessagePos());
+ ScreenToClient(dat->hTreeView, &hti.pt);
+ TreeView_HitTest(dat->hTreeView, &hti);
+ if (hti.hItem && dat->hDragItem != hti.hItem && TreeView_GetChild(dat->hTreeView, hti.hItem)) // target is a group and is not the same item that we're dragging
+ {
+ TreeView_Expand(dat->hTreeView, hti.hItem, TVE_EXPAND);
+ }
+ }
+ } break;
+ }
+ return CallWindowProc(dat->OrigParentProc, hWnd, Msg, wParam, lParam);
+}
+
+
+static LRESULT CALLBACK MsgTreeSubclassProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ CMsgTree *dat = CWndUserData(GetParent(hWnd)).GetMsgTree();
+ switch (Msg)
+ {
+ case UM_MSGTREE_UPDATE: // returns TRUE if updated
+ {
+ bool Modified = dat->MsgTreePage.GetModified();
+ TCString WndTitle;
+ if (Modified)
+ {
+ WndTitle.GetBuffer(256);
+ HWND hCurWnd = hWnd;
+ do
+ {
+ hCurWnd = GetParent(hCurWnd);
+ } while (hCurWnd && !GetWindowText(hCurWnd, WndTitle, 256));
+ WndTitle.ReleaseBuffer();
+ }
+ if (!Modified || MessageBox(GetParent(hWnd), TCString(TranslateT("You've made changes to multiple Message trees at a time.\r\nDo you want to leave changes in \"")) + WndTitle + TranslateT("\" dialog?\r\nPress Yes to leave changes in this dialog, or No to discard its changes and save changes of the other Message tree instead."), WndTitle + _T(" - ") + TranslateT("New Away System"), MB_ICONQUESTION | MB_YESNO) == IDNO)
+ {
+ COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl();
+ TCString OldTitle, OldMsg, NewTitle, NewMsg;
+ int OldOrder = TreeCtrl->IDToOrder(TreeCtrl->GetSelectedItemID(GetParent(hWnd)));
+ if (OldOrder != -1)
+ {
+ CBaseTreeItem* ItemOld = (OldOrder <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(OldOrder)] : (CBaseTreeItem*)&TreeCtrl->Value[OldOrder];
+ OldTitle = ItemOld->Title;
+ if (!(ItemOld->Flags & TIF_ROOTITEM))
+ {
+ OldMsg = ((CTreeItem*)ItemOld)->User_Str1;
+ }
+ }
+ dat->UpdateLock++;
+ dat->MsgTreePage.DBToMemToPage();
+ dat->UpdateLock--;
+ NMMSGTREE nm = {0};
+ int Order = TreeCtrl->IDToOrder(TreeCtrl->GetSelectedItemID(GetParent(hWnd)));
+ if (Order != -1)
+ {
+ nm.ItemNew = (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order];
+ NewTitle = nm.ItemNew->Title;
+ if (!(nm.ItemNew->Flags & TIF_ROOTITEM))
+ {
+ NewMsg = ((CTreeItem*)nm.ItemNew)->User_Str1;
+ }
+ }
+ if (OldTitle.IsEmpty())
+ {
+ OldTitle = _T(""); // to be sure that NULL will be equal to "" in the latter comparisons
+ }
+ if (OldMsg.IsEmpty())
+ {
+ OldMsg = _T("");
+ }
+ if (NewTitle.IsEmpty())
+ {
+ NewTitle = _T("");
+ }
+ if (NewMsg.IsEmpty())
+ {
+ NewMsg = _T("");
+ }
+ if (OldTitle != (const TCHAR*)NewTitle || OldMsg != (const TCHAR*)NewMsg)
+ {
+ // probably it's better to leave nm.ItemOld = NULL, to prevent accidental rewriting of it with old data from an edit control etc.
+ nm.hdr.code = MTN_SELCHANGED;
+ nm.hdr.hwndFrom = hWnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hWnd);
+ SendMessage(GetParent(hWnd), WM_NOTIFY, 0, (LPARAM)&nm);
+ }
+ return true;
+ }
+ return false;
+ } break;
+ case WM_KEYDOWN:
+ {
+ switch (wParam)
+ {
+ case VK_DELETE:
+ {
+ dat->DeleteSelectedItem();
+ } break;
+ case VK_INSERT:
+ {
+ dat->AddMessage();
+ } break;
+ }
+ } break;
+ case WM_RBUTTONDOWN:
+ {
+ SetFocus(hWnd);
+ TVHITTESTINFO hitTest;
+ hitTest.pt.x = (short)LOWORD(lParam);
+ hitTest.pt.y = (short)HIWORD(lParam);
+ TreeView_HitTest(hWnd, &hitTest);
+ if (hitTest.hItem && hitTest.flags & TVHT_ONITEM)
+ {
+ TreeView_SelectItem(hWnd, hitTest.hItem);
+ }
+ return DefWindowProc(hWnd, Msg, wParam, lParam);
+ } break;
+ case WM_CONTEXTMENU:
+ {
+ TVHITTESTINFO ht;
+ ht.pt.x = (short)LOWORD(lParam);
+ ht.pt.y = (short)HIWORD(lParam);
+ TVITEM tvi = {0};
+ if (ht.pt.x == -1 && ht.pt.y == -1) // use selected item
+ {
+ if (tvi.hItem = TreeView_GetSelection(hWnd))
+ {
+ TreeView_EnsureVisible(hWnd, tvi.hItem);
+ RECT rc;
+ TreeView_GetItemRect(hWnd, tvi.hItem, &rc, true);
+ ht.pt.x = rc.left;
+ ht.pt.y = rc.bottom;
+ }
+ } else
+ {
+ ScreenToClient(hWnd, &ht.pt);
+ TreeView_HitTest(hWnd, &ht);
+ if (ht.hItem && ht.flags & TVHT_ONITEM)
+ {
+ tvi.hItem = ht.hItem;
+ }
+ }
+ if (tvi.hItem)
+ {
+ COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl();
+ tvi.mask = TVIF_HANDLE | TVIF_PARAM;
+ TreeView_GetItem(hWnd, &tvi);
+ int Order = TreeCtrl->IDToOrder(tvi.lParam);
+ if (Order >= 0)
+ {
+ HMENU hMenu;
+ if (TreeCtrl->Value[Order].Flags & TIF_GROUP)
+ {
+ hMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_MSGTREE_CATEGORYMENU));
+ } else
+ {
+ hMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_MSGTREE_MESSAGEMENU));
+ }
+ _ASSERT(hMenu);
+ HMENU hPopupMenu = GetSubMenu(hMenu, 0);
+ TranslateMenu(hPopupMenu);
+ ClientToScreen(hWnd, &ht.pt);
+ struct
+ {
+ int ItemID, IconID;
+ } MenuItems[] = {
+ IDM_MSGTREEMENU_NEWMESSAGE, IMGLIST_NEWMESSAGE,
+ IDM_MSGTREEMENU_NEWCATEGORY, IMGLIST_NEWCATEGORY,
+ IDM_MSGTREEMENU_DELETE, IMGLIST_DELETE
+ };
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_BITMAP | MIIM_DATA | MIIM_STATE | MIIM_CHECKMARKS;
+ mii.hbmpItem = HBMMENU_CALLBACK;
+ int I;
+ for (I = 0; I < lengthof(MenuItems); I++) // set icons
+ {
+ mii.dwItemData = MenuItems[I].IconID;
+ SetMenuItemInfo(hPopupMenu, MenuItems[I].ItemID, false, &mii);
+ }
+ mii.fMask = MIIM_STATE;
+ mii.fState = MFS_CHECKED;
+ for (I = 0; I < lengthof(StatusModeList); I++) // set checkmarks
+ {
+ if (TreeCtrl->Value[Order].ID == dat->MsgTreePage.GetValue(StatusModeList[I].DBSetting))
+ {
+ SetMenuItemInfo(hPopupMenu, StatusModeList[I].MenuItemID, false, &mii);
+ }
+ }
+ int MenuResult = TrackPopupMenu(hPopupMenu, TPM_RIGHTBUTTON | TPM_RETURNCMD, ht.pt.x, ht.pt.y, 0, hWnd, NULL);
+ switch (MenuResult)
+ {
+ case IDM_MSGTREEMENU_NEWMESSAGE:
+ {
+ dat->AddMessage();
+ } break;
+ case IDM_MSGTREEMENU_NEWCATEGORY:
+ {
+ dat->AddCategory();
+ } break;
+ case IDM_MSGTREEMENU_RENAME:
+ {
+ TreeView_EditLabel(hWnd, tvi.hItem);
+ } break;
+ case IDM_MSGTREEMENU_DELETE:
+ {
+ dat->DeleteSelectedItem();
+ } break;
+ case IDR_MSGTREEMENU_DEF_ONL:
+ case IDR_MSGTREEMENU_DEF_AWAY:
+ case IDR_MSGTREEMENU_DEF_NA:
+ case IDR_MSGTREEMENU_DEF_OCC:
+ case IDR_MSGTREEMENU_DEF_DND:
+ case IDR_MSGTREEMENU_DEF_FFC:
+ case IDR_MSGTREEMENU_DEF_INV:
+ case IDR_MSGTREEMENU_DEF_OTP:
+ case IDR_MSGTREEMENU_DEF_OTL:
+ {
+ int I;
+ for (I = 0; I < lengthof(StatusModeList); I++)
+ {
+ if (StatusModeList[I].MenuItemID == MenuResult)
+ {
+ dat->SetDefMsg(StatusModeList[I].Status, tvi.lParam);
+ break;
+ }
+ }
+ } break;
+ }
+ DestroyMenu(hMenu);
+ return 0;
+ }
+ }
+ } break;
+ case WM_MEASUREITEM:
+ {
+ LPMEASUREITEMSTRUCT lpmi = (LPMEASUREITEMSTRUCT)lParam;
+ if (lpmi->CtlType == ODT_MENU)
+ {
+ lpmi->itemWidth = max(0, GetSystemMetrics(SM_CXSMICON) - GetSystemMetrics(SM_CXMENUCHECK) + 4);
+ lpmi->itemHeight = GetSystemMetrics(SM_CYSMICON) + 2;
+ return true;
+ }
+ } break;
+ case WM_DRAWITEM:
+ {
+ LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
+ if (dis->CtlType == ODT_MENU)
+ {
+ ImageList_DrawEx(dat->hImageList, dis->itemData, dis->hDC, 2, (dis->rcItem.bottom + dis->rcItem.top - GetSystemMetrics(SM_CYSMICON)) / 2 + 1, 0, 0, GetSysColor(COLOR_WINDOW), CLR_NONE, ILD_NORMAL);
+ return true;
+ }
+ } break;
+ }
+ return CallWindowProc(dat->OrigTreeViewProc, hWnd, Msg, wParam, lParam);
+}
+
+
+CMsgTree::CMsgTree(HWND hTreeView): MsgTreePage(g_MsgTreePage), hTreeView(hTreeView), hDragItem(NULL), hPrevDropTarget(NULL), UpdateLock(0)
+{
+ CWndUserData(GetParent(hTreeView)).SetMsgTree(this);
+ OrigParentProc = (WNDPROC)SetWindowLongPtr(GetParent(hTreeView), GWLP_WNDPROC, (LONG_PTR)ParentSubclassProc);
+ OrigTreeViewProc = (WNDPROC)SetWindowLongPtr(hTreeView, GWLP_WNDPROC, (LONG_PTR)MsgTreeSubclassProc);
+ MsgTreePage.SetWnd(GetParent(hTreeView));
+ COptItem_TreeCtrl* TreeCtrl = (COptItem_TreeCtrl*)MsgTreePage.Find(IDV_MSGTREE);
+ TreeCtrl->SetDlgItemID(GetDlgCtrlID(hTreeView));
+ hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, 5, 2);
+ ImageList_AddIcon(hImageList, LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_NEWMESSAGE)));
+ ImageList_AddIcon(hImageList, LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_NEWCATEGORY)));
+ ImageList_AddIcon(hImageList, LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_DELETE)));
+ MsgTreePage.DBToMemToPage();
+ if (!g_MoreOptPage.GetDBValueCopy(IDC_MOREOPTDLG_RECENTMSGSCOUNT))
+ { // show "Recent messages" group only when RECENTMSGSCOUNT is not set to 0.
+ TreeView_DeleteItem(hTreeView, TreeCtrl->RootItems[g_Messages_RecentRootID].hItem);
+ }
+ WindowList_Add(hMTWindowList, hTreeView, NULL);
+}
+
+CMsgTree::~CMsgTree()
+{
+ _ASSERT(GetWindowLongPtr(GetParent(hTreeView), GWLP_WNDPROC) == (LONG_PTR)ParentSubclassProc); // we won't allow anyone to change our WNDPROC. otherwise we're not sure that we're setting the right WNDPROC back
+ SetWindowLongPtr(hTreeView, GWLP_WNDPROC, (GetWindowLongPtr(GetParent(hTreeView), GWLP_WNDPROC) == (LONG_PTR)ParentSubclassProc) ? (LONG_PTR)OrigTreeViewProc : (LONG_PTR)DefDlgProc); // yeah, if that crazy Help plugin substituted MY WndProc again, he won't get his WndProc back.. he-he >:)
+ SetWindowLongPtr(GetParent(hTreeView), GWLP_WNDPROC, (LONG_PTR)OrigParentProc);
+ CWndUserData(GetParent(hTreeView)).SetMsgTree(NULL);
+ WindowList_Remove(hMTWindowList, hTreeView);
+ ImageList_Destroy(hImageList);
+}
+
+CBaseTreeItem* CMsgTree::GetSelection() // returns NULL if there's nothing selected
+{
+ COptItem_TreeCtrl *TreeCtrl = GetTreeCtrl();
+ int Order = TreeCtrl->IDToOrder(TreeCtrl->GetSelectedItemID(GetParent(hTreeView)));
+ if (Order != -1)
+ {
+ return (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order];
+ }
+ return NULL;
+}
+
+bool CMsgTree::SetSelection(int ID, int Flags) // set ID = -1 to unselect; returns TRUE on unselect and on successful select
+{
+ COptItem_TreeCtrl *TreeCtrl = GetTreeCtrl();
+ int Order = (Flags & MTSS_BYORDER) ? ID : TreeCtrl->IDToOrder(ID);
+ if (Order == -1 && ID != -1)
+ {
+ return false;
+ }
+ TreeView_SelectItem(hTreeView, (Order == -1) ? NULL : ((Order <= TREECTRL_ROOTORDEROFFS) ? TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)].hItem : TreeCtrl->Value[Order].hItem));
+ return true;
+}
+
+int CMsgTree::GetDefMsg(int iMode)
+{
+ int I;
+ for (I = 0; I < lengthof(StatusModeList); I++)
+ {
+ if (StatusModeList[I].Status == iMode)
+ {
+ return MsgTreePage.GetValue(StatusModeList[I].DBSetting);
+ }
+ }
+ return 0;
+}
+
+void CMsgTree::SetDefMsg(int iMode, int ID)
+{
+ int I;
+ for (I = 0; I < lengthof(StatusModeList); I++)
+ {
+ if (StatusModeList[I].Status == iMode)
+ {
+ if (MsgTreePage.GetValue(StatusModeList[I].DBSetting) != ID)
+ {
+ RECT rc;
+ COptItem_TreeCtrl *TreeCtrl = GetTreeCtrl();
+ int OrderOld = TreeCtrl->IDToOrder(MsgTreePage.GetValue(StatusModeList[I].DBSetting));
+ if (OrderOld >= 0 && TreeView_GetItemRect(hTreeView, TreeCtrl->Value[OrderOld].hItem, &rc, false))
+ {
+ InvalidateRect(hTreeView, &rc, true); // refresh icons of previous default tree item
+ }
+ int OrderNew = TreeCtrl->IDToOrder(ID);
+ if (OrderNew >= 0 && TreeView_GetItemRect(hTreeView, TreeCtrl->Value[OrderNew].hItem, &rc, false))
+ {
+ InvalidateRect(hTreeView, &rc, true); // refresh new default item icons
+ }
+ MsgTreePage.SetValue(StatusModeList[I].DBSetting, ID);
+ NMMSGTREE nm = {0};
+ if (OrderOld >= 0)
+ {
+ nm.ItemOld = &TreeCtrl->Value[OrderOld];
+ }
+ if (OrderNew >= 0)
+ {
+ nm.ItemNew = &TreeCtrl->Value[OrderNew];
+ }
+ nm.hdr.code = MTN_DEFMSGCHANGED;
+ nm.hdr.hwndFrom = hTreeView;
+ nm.hdr.idFrom = GetDlgCtrlID(hTreeView);
+ SendMessage(GetParent(hTreeView), WM_NOTIFY, 0, (LPARAM)&nm);
+ }
+ break;
+ }
+ }
+}
+
+void CMsgTree::Save()
+{
+ if (MsgTreePage.GetModified())
+ {
+ MsgTreePage.PageToMemToDB();
+ WindowList_BroadcastAsync(hMTWindowList, UM_MSGTREE_UPDATE, 0, 0);
+ }
+}
+
+void CMsgTree::UpdateItem(int ID) // updates item title, and expanded/collapsed state for groups
+{
+ COptItem_TreeCtrl *TreeCtrl = GetTreeCtrl();
+ int Order = TreeCtrl->IDToOrder(ID);
+ if (Order != -1)
+ {
+ CBaseTreeItem* TreeItem = (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order];
+ TCString NewTitle;
+ TVITEM tvi;
+ tvi.mask = TVIF_HANDLE | TVIF_TEXT;
+ tvi.hItem = TreeItem->hItem;
+ tvi.pszText = NewTitle.GetBuffer(TREEITEMTITLE_MAXLEN);
+ tvi.cchTextMax = TREEITEMTITLE_MAXLEN;
+ TreeView_GetItem(hTreeView, &tvi);
+ if (TreeItem->Title != (const TCHAR*)tvi.pszText)
+ {
+ TreeCtrl->SetModified(true);
+ NMMSGTREE nm = {0};
+ nm.ItemNew = TreeItem;
+ nm.hdr.code = MTN_ITEMRENAMED;
+ nm.hdr.hwndFrom = hTreeView;
+ nm.hdr.idFrom = GetDlgCtrlID(hTreeView);
+ SendMessage(GetParent(hTreeView), WM_NOTIFY, 0, (LPARAM)&nm);
+ }
+ tvi.mask = TVIF_HANDLE | TVIF_TEXT;
+ tvi.pszText = TreeItem->Title;
+ TreeView_SetItem(hTreeView, &tvi);
+ TreeView_Expand(hTreeView, tvi.hItem, (TreeItem->Flags & TIF_EXPANDED) ? TVE_EXPAND : TVE_COLLAPSE);
+ }
+}
+
+bool CMsgTree::DeleteSelectedItem() // returns true if the item was deleted
+{
+ COptItem_TreeCtrl *TreeCtrl = GetTreeCtrl();
+ int Order = TreeCtrl->IDToOrder(TreeCtrl->GetSelectedItemID(GetParent(hTreeView)));
+ _ASSERT(Order >= 0);
+ CTreeItem *SelectedItem = &TreeCtrl->Value[Order];
+ //NightFox: fix for langpack and fix cut char space in text
+ //if (MessageBox(GetParent(hTreeView), TCString(TranslateT("Do you really want to delete this ")) + ((SelectedItem->Flags & TIF_GROUP) ? TranslateT("category with its messages?") : TranslateT("message?")), TranslateT("New Away System"), MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2) == IDYES)
+ if (MessageBox(GetParent(hTreeView),
+ ((SelectedItem->Flags & TIF_GROUP) ?
+ TranslateT("Do you really want to delete this category with its messages?")
+ :
+ TranslateT("Do you really want to delete this message?"))
+ ,
+ TranslateT("New Away System"), MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2) == IDYES)
+ {
+ NMMSGTREE nm = {0};
+ nm.ItemOld = SelectedItem;
+ nm.hdr.code = MTN_DELETEITEM;
+ nm.hdr.hwndFrom = hTreeView;
+ nm.hdr.idFrom = GetDlgCtrlID(hTreeView);
+ if (!SendMessage(GetParent(hTreeView), WM_NOTIFY, 0, (LPARAM)&nm))
+ {
+ TreeCtrl->Delete(GetParent(hTreeView), TreeCtrl->GetSelectedItemID(GetParent(hTreeView)));
+ return true;
+ }
+ }
+ return false;
+}
+
+CTreeItem* CMsgTree::AddCategory()
+{
+ COptItem_TreeCtrl *TreeCtrl = GetTreeCtrl();
+ CTreeItem* TreeItem = TreeCtrl->InsertItem(GetParent(hTreeView), CTreeItem(_T(""), 0, 0, TIF_GROUP));
+ TVITEM tvi;
+ tvi.mask = TVIF_HANDLE | TVIF_TEXT;
+ tvi.hItem = TreeItem->hItem;
+ TreeItem->Title = tvi.pszText = TranslateT("New category");
+ TreeView_SetItem(hTreeView, &tvi);
+ TreeView_EditLabel(hTreeView, TreeItem->hItem);
+ NMMSGTREE nm = {0};
+ nm.ItemNew = TreeItem;
+ nm.hdr.code = MTN_NEWCATEGORY;
+ nm.hdr.hwndFrom = hTreeView;
+ nm.hdr.idFrom = GetDlgCtrlID(hTreeView);
+ SendMessage(GetParent(hTreeView), WM_NOTIFY, 0, (LPARAM)&nm);
+ return TreeItem;
+}
+
+CTreeItem* CMsgTree::AddMessage()
+{
+ COptItem_TreeCtrl *TreeCtrl = GetTreeCtrl();
+ CTreeItem* TreeItem = TreeCtrl->InsertItem(GetParent(hTreeView), CTreeItem(_T(""), 0, 0));
+ TVITEM tvi;
+ tvi.mask = TVIF_HANDLE | TVIF_TEXT;
+ tvi.hItem = TreeItem->hItem;
+ TreeItem->Title = tvi.pszText = TranslateT("New message");
+ TreeView_SetItem(hTreeView, &tvi);
+ TreeView_EditLabel(hTreeView, TreeItem->hItem);
+ NMMSGTREE nm = {0};
+ nm.ItemNew = TreeItem;
+ nm.hdr.code = MTN_NEWMESSAGE;
+ nm.hdr.hwndFrom = hTreeView;
+ nm.hdr.idFrom = GetDlgCtrlID(hTreeView);
+ SendMessage(GetParent(hTreeView), WM_NOTIFY, 0, (LPARAM)&nm);
+ return TreeItem;
+}
+
+CBaseTreeItem* CMsgTree::GetNextItem(int Flags, CBaseTreeItem* Item) // Item is 'int ID' if MTGN_BYID flag is set; returns CBaseTreeItem* or NULL
+{
+ COptItem_TreeCtrl *TreeCtrl = GetTreeCtrl();
+ CBaseTreeItem* TreeItem = Item;
+ if (Flags & MTGN_BYID)
+ {
+ int Order = TreeCtrl->IDToOrder((int)Item);
+ _ASSERT(Order != -1);
+ TreeItem = (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order];
+ }
+ int TVFlag = 0;
+ switch (Flags & ~MTGN_BYID)
+ {
+ case MTGN_ROOT: TVFlag = TVGN_ROOT; break;
+ case MTGN_CHILD: TVFlag = TVGN_CHILD; break;
+ case MTGN_PARENT: TVFlag = TVGN_PARENT; break;
+ case MTGN_NEXT: TVFlag = TVGN_NEXT; break;
+ case MTGN_PREV: TVFlag = TVGN_PREVIOUS; break;
+ default: _ASSERT(0);
+ }
+ int Order = TreeCtrl->hItemToOrder(TreeView_GetNextItem(hTreeView, TreeItem ? TreeItem->hItem : NULL, TVFlag));
+ if (Order != -1)
+ {
+ return (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order];
+ }
+ return NULL;
+}
|