Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

968 lines
25 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: favui.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // favui.cpp - favorites tree configuration UI
  11. #include "stdafx.h"
  12. #include "amcdoc.h"
  13. #include "favorite.h"
  14. #include "favui.h"
  15. #include "amcmsgid.h"
  16. #include "amcview.h"
  17. #include "mmcres.h"
  18. void EnableButton(HWND hwndDialog, int iCtrlID, BOOL bEnable);
  19. BEGIN_MESSAGE_MAP(CAddFavDialog, CDialog)
  20. //{{AFX_MSG_MAP(CAddFavDialog)
  21. ON_COMMAND(IDC_ADDFAVFOLDER, OnAddFolder)
  22. ON_EN_CHANGE(IDC_FAVNAME, OnChangeName)
  23. // NOTE: the ClassWizard will add message map macros here
  24. //}}AFX_MSG_MAP
  25. ON_MMC_CONTEXT_HELP()
  26. END_MESSAGE_MAP()
  27. CAddFavDialog::CAddFavDialog(LPCTSTR szName, CFavorites* pFavorites, CWnd* pParent)
  28. : CDialog(CAddFavDialog::IDD, pParent),
  29. m_pFavorites(pFavorites), m_lAdviseCookie(NULL)
  30. {
  31. m_strName = szName;
  32. ASSERT(pFavorites != NULL);
  33. }
  34. CAddFavDialog::~CAddFavDialog()
  35. {
  36. // disconnect fav view from source
  37. if (m_lAdviseCookie )
  38. {
  39. ASSERT(m_pFavorites != NULL);
  40. HRESULT hr = m_pFavorites->Unadvise(m_lAdviseCookie);
  41. ASSERT(SUCCEEDED(hr));
  42. m_FavTree.SetTreeSource(NULL);
  43. }
  44. // detach classes from windows
  45. m_FavTree.Detach();
  46. m_FavName.Detach();
  47. }
  48. HRESULT CAddFavDialog::CreateFavorite(CFavObject** pfavRet)
  49. {
  50. m_pfavItem = NULL;
  51. if (DoModal() != IDOK)
  52. return S_FALSE;
  53. if (pfavRet != NULL)
  54. *pfavRet = m_pfavItem;
  55. return m_hr;
  56. }
  57. BOOL CAddFavDialog::OnInitDialog()
  58. {
  59. DECLARE_SC (sc, _T("CAddFavDialog::OnInitDialog"));
  60. CDialog::OnInitDialog();
  61. ModifyStyleEx(0, WS_EX_CONTEXTHELP, SWP_NOSIZE);
  62. // Attach tree ctrl to favorites tree object
  63. BOOL bStat = m_FavTree.SubclassDlgItem(IDC_FAVTREE, this);
  64. ASSERT(bStat);
  65. bStat = m_FavName.Attach(GetDlgItem(IDC_FAVNAME)->GetSafeHwnd());
  66. ASSERT(bStat);
  67. m_FavName.SetWindowText(m_strName);
  68. m_FavName.SetSel(0,lstrlen(m_strName));
  69. m_FavName.SetFocus();
  70. // Add extra space between items
  71. TreeView_SetItemHeight(m_FavTree, TreeView_GetItemHeight(m_FavTree) + FAVVIEW_ITEM_SPACING);
  72. // Show only folders
  73. m_FavTree.SetStyle(TOBSRV_FOLDERSONLY);
  74. /*
  75. * validate m_pFavorites
  76. */
  77. sc = ScCheckPointers (m_pFavorites, E_UNEXPECTED);
  78. if (sc)
  79. {
  80. EndDialog (IDCANCEL);
  81. return (0);
  82. }
  83. // Attach favorites image list to tree control
  84. m_FavTree.SetImageList(m_pFavorites->GetImageList(), TVSIL_NORMAL);
  85. // attach view to source as observer
  86. HRESULT hr = m_pFavorites->Advise(static_cast<CTreeObserver*>(&m_FavTree), &m_lAdviseCookie);
  87. ASSERT(SUCCEEDED(hr) && m_lAdviseCookie != 0);
  88. // hand tree data source to tree view
  89. m_FavTree.SetTreeSource(static_cast<CTreeSource*>(m_pFavorites));
  90. // Select the root
  91. m_FavTree.SetSelection(m_pFavorites->GetRootItem());
  92. // return 0 so focus isn't changed
  93. return 0;
  94. }
  95. void CAddFavDialog::OnChangeName()
  96. {
  97. EnableButton(m_hWnd, IDOK, (m_FavName.LineLength() != 0));
  98. }
  99. void CAddFavDialog::OnOK( )
  100. {
  101. // Get favorite name
  102. TCHAR strName[MAX_PATH];
  103. m_hr = E_FAIL;
  104. m_pfavItem = NULL;
  105. int cChar = m_FavName.GetWindowText(strName, countof(strName));
  106. ASSERT(cChar != 0);
  107. if (cChar == 0)
  108. return;
  109. // Get selected folder
  110. TREEITEMID tid = m_FavTree.GetSelection();
  111. ASSERT(tid != NULL);
  112. if (tid == NULL)
  113. return;
  114. // Detach fav tree from source because it doesn't need updating
  115. ASSERT(m_pFavorites != NULL);
  116. HRESULT hr = m_pFavorites->Unadvise(m_lAdviseCookie);
  117. ASSERT(SUCCEEDED(hr));
  118. m_lAdviseCookie = 0;
  119. // Inform source of disconnection
  120. m_FavTree.SetTreeSource(NULL);
  121. // Create a favorite
  122. ASSERT(m_pFavorites != NULL);
  123. m_hr = m_pFavorites->AddFavorite(tid, strName, &m_pfavItem);
  124. ASSERT(SUCCEEDED(hr));
  125. CDialog::OnOK();
  126. }
  127. void CAddFavDialog::OnAddFolder()
  128. {
  129. ASSERT(m_pFavorites != NULL);
  130. // Get selected group
  131. TREEITEMID tidParent = m_FavTree.GetSelection();
  132. ASSERT(tidParent != NULL);
  133. // Put up dialog to get folder name
  134. CAddFavGroupDialog dlgAdd(this);
  135. if (dlgAdd.DoModal() != IDOK)
  136. return;
  137. LPCTSTR strName = dlgAdd.GetGroupName();
  138. ASSERT(strName[0] != 0);
  139. CFavObject* pfavGroup = NULL;
  140. HRESULT hr = m_pFavorites->AddGroup(tidParent, strName, &pfavGroup);
  141. if (SUCCEEDED(hr))
  142. {
  143. ASSERT(pfavGroup != NULL);
  144. m_FavTree.SetSelection(reinterpret_cast<TREEITEMID>(pfavGroup));
  145. }
  146. }
  147. /////////////////////////////////////////////////////////////////////
  148. // CAddFavGroup dialog
  149. BEGIN_MESSAGE_MAP(CAddFavGroupDialog, CDialog)
  150. //{{AFX_MSG_MAP(CAddFavGroupDialog)
  151. ON_EN_CHANGE(IDC_FAVFOLDER, OnChangeName)
  152. // NOTE: the ClassWizard will add message map macros here
  153. //}}AFX_MSG_MAP
  154. ON_MMC_CONTEXT_HELP()
  155. END_MESSAGE_MAP()
  156. CAddFavGroupDialog::CAddFavGroupDialog(CWnd* pParent)
  157. : CDialog(CAddFavGroupDialog::IDD, pParent)
  158. {
  159. }
  160. CAddFavGroupDialog::~CAddFavGroupDialog()
  161. {
  162. // detach classes from windows
  163. m_GrpName.Detach();
  164. }
  165. CAddFavGroupDialog::OnInitDialog()
  166. {
  167. CDialog::OnInitDialog();
  168. ModifyStyleEx(0, WS_EX_CONTEXTHELP, SWP_NOSIZE);
  169. BOOL bStat = m_GrpName.Attach(GetDlgItem(IDC_FAVFOLDER)->GetSafeHwnd());
  170. ASSERT(bStat);
  171. // Set default favorite name and select it
  172. CString strDefault;
  173. LoadString(strDefault, IDS_NEWFOLDER);
  174. m_GrpName.SetWindowText(strDefault);
  175. m_GrpName.SetSel(0,lstrlen(strDefault));
  176. m_GrpName.SetFocus();
  177. // return 0 so focus isn't changed
  178. return 0;
  179. }
  180. void CAddFavGroupDialog::OnChangeName()
  181. {
  182. EnableButton(m_hWnd, IDOK, (m_GrpName.LineLength() != 0));
  183. }
  184. void CAddFavGroupDialog::OnOK( )
  185. {
  186. // Get group name
  187. int cChar = GetDlgItemText(IDC_FAVFOLDER, m_strName, sizeof(m_strName)/sizeof(TCHAR));
  188. ASSERT(cChar != 0);
  189. CDialog::OnOK();
  190. }
  191. //////////////////////////////////////////////////////////////////////////////
  192. //
  193. BEGIN_MESSAGE_MAP(COrganizeFavDialog, CDialog)
  194. //{{AFX_MSG_MAP(COrganizeFavDialog)
  195. ON_COMMAND(IDC_ADDFAVFOLDER, OnAddFolder)
  196. ON_COMMAND(IDC_FAVRENAME, OnRename)
  197. ON_COMMAND(IDC_FAVDELETE, OnDelete)
  198. ON_COMMAND(IDC_FAVMOVETO, OnMoveTo)
  199. ON_NOTIFY(TVN_SELCHANGED, IDC_FAVTREE, OnSelChanged)
  200. ON_NOTIFY(TVN_BEGINLABELEDIT, IDC_FAVTREE, OnBeginLabelEdit)
  201. ON_NOTIFY(TVN_ENDLABELEDIT, IDC_FAVTREE, OnEndLabelEdit)
  202. // NOTE: the ClassWizard will add message map macros here
  203. //}}AFX_MSG_MAP
  204. ON_MMC_CONTEXT_HELP()
  205. END_MESSAGE_MAP()
  206. COrganizeFavDialog::COrganizeFavDialog(CFavorites* pFavorites, CWnd* pParent)
  207. : CDialog(COrganizeFavDialog::IDD, pParent),
  208. m_pFavorites(pFavorites), m_lAdviseCookie(NULL), m_tidRenameItem(0), m_bRenameMode(FALSE)
  209. {
  210. ASSERT(pFavorites != NULL);
  211. }
  212. COrganizeFavDialog::~COrganizeFavDialog()
  213. {
  214. // disconnect fav view from source
  215. if (m_lAdviseCookie)
  216. {
  217. ASSERT(m_pFavorites != NULL);
  218. m_pFavorites->Unadvise(m_lAdviseCookie);
  219. m_FavTree.SetTreeSource(NULL);
  220. }
  221. // detach classes from windows
  222. m_FavTree.Detach();
  223. m_FavName.Detach();
  224. m_FavInfo.Detach();
  225. }
  226. BOOL COrganizeFavDialog::OnInitDialog()
  227. {
  228. DECLARE_SC (sc, _T("COrganizeFavDialog::OnInitDialog"));
  229. ASSERT(m_pFavorites != NULL);
  230. CDialog::OnInitDialog();
  231. ModifyStyleEx(0, WS_EX_CONTEXTHELP, SWP_NOSIZE);
  232. // Attach tree ctrl to favorites tree object
  233. BOOL bStat = m_FavTree.SubclassDlgItem(IDC_FAVTREE, this);
  234. ASSERT(bStat);
  235. bStat = m_FavName.Attach(GetDlgItem(IDC_FAVNAME)->GetSafeHwnd());
  236. ASSERT(bStat);
  237. bStat = m_FavInfo.Attach(GetDlgItem(IDC_FAVINFO)->GetSafeHwnd());
  238. ASSERT(bStat);
  239. // Add extra space between items
  240. TreeView_SetItemHeight(m_FavTree, TreeView_GetItemHeight(m_FavTree) + FAVVIEW_ITEM_SPACING);
  241. /*
  242. * validate m_pFavorites
  243. */
  244. sc = ScCheckPointers (m_pFavorites, E_UNEXPECTED);
  245. if (sc)
  246. {
  247. EndDialog (IDCANCEL);
  248. return (0);
  249. }
  250. // Attach favorites image list to tree control
  251. m_FavTree.SetImageList(m_pFavorites->GetImageList(), TVSIL_NORMAL);
  252. // Attach view to source as observer
  253. HRESULT hr = m_pFavorites->Advise(static_cast<CTreeObserver*>(&m_FavTree), &m_lAdviseCookie);
  254. ASSERT(SUCCEEDED(hr) && m_lAdviseCookie != 0);
  255. // Hand tree data source to tree view
  256. m_FavTree.SetTreeSource(static_cast<CTreeSource*>(m_pFavorites));
  257. // Select the root item and give it focus
  258. m_FavTree.SetSelection(m_pFavorites->GetRootItem());
  259. m_FavTree.SetFocus();
  260. // Create bold font for favorite name control
  261. LOGFONT logfont;
  262. m_FavName.GetFont()->GetLogFont(&logfont);
  263. logfont.lfWeight = FW_BOLD;
  264. if (m_FontBold.CreateFontIndirect(&logfont))
  265. m_FavName.SetFont(&m_FontBold);
  266. // return 0 so focus isn't changed
  267. return 0;
  268. }
  269. void COrganizeFavDialog::OnOK( )
  270. {
  271. // if in rename mode, end it with success
  272. if (m_bRenameMode)
  273. {
  274. m_FavTree.SendMessage(TVM_ENDEDITLABELNOW, FALSE);
  275. return;
  276. }
  277. CDialog::OnOK();
  278. }
  279. void COrganizeFavDialog::OnCancel( )
  280. {
  281. // if in rename mode, cancel it
  282. if (m_bRenameMode)
  283. {
  284. m_FavTree.SendMessage(TVM_ENDEDITLABELNOW, FALSE);
  285. return;
  286. }
  287. CDialog::OnOK();
  288. }
  289. void COrganizeFavDialog::OnSelChanged(NMHDR* pMNHDR, LRESULT* plResult)
  290. {
  291. ASSERT(pMNHDR != NULL);
  292. NM_TREEVIEW* pnmtv = (NM_TREEVIEW*)pMNHDR;
  293. TREEITEMID tid = pnmtv->itemNew.lParam;
  294. TCHAR name[100];
  295. m_pFavorites->GetItemName(tid, name, 100);
  296. m_FavName.SetWindowText(name);
  297. if (m_pFavorites->IsFolderItem(tid))
  298. {
  299. CString strPath;
  300. LoadString(strPath, IDS_FAVFOLDER);
  301. m_FavInfo.SetWindowText(strPath);
  302. }
  303. else
  304. {
  305. TCHAR szPath[MAX_PATH];
  306. m_pFavorites->GetItemPath(tid, szPath, MAX_PATH);
  307. m_FavInfo.SetWindowText(szPath);
  308. }
  309. // Disable some operation for the root item
  310. BOOL bRoot = (tid == m_pFavorites->GetRootItem());
  311. EnableButton(m_hWnd, IDC_FAVRENAME, !bRoot);
  312. EnableButton(m_hWnd, IDC_FAVDELETE, !bRoot);
  313. EnableButton(m_hWnd, IDC_FAVMOVETO, !bRoot);
  314. }
  315. void COrganizeFavDialog::OnBeginLabelEdit(NMHDR* pMNHDR, LRESULT* plResult)
  316. {
  317. // Only allow renaming if an item has been selected
  318. // This is to prevent an edit starting from an item click because
  319. // that is confusing when used with the single-click expand style.
  320. // (returning TRUE disables it)
  321. if (m_tidRenameItem != 0)
  322. {
  323. m_bRenameMode = TRUE;
  324. *plResult = FALSE;
  325. }
  326. else
  327. {
  328. *plResult = TRUE;
  329. }
  330. }
  331. void COrganizeFavDialog::OnEndLabelEdit(NMHDR* pMNHDR, LRESULT* plResult)
  332. {
  333. ASSERT(m_bRenameMode && m_tidRenameItem != 0);
  334. *plResult = FALSE;
  335. if (m_tidRenameItem != 0)
  336. {
  337. NMTVDISPINFO* pnmtvd = (NMTVDISPINFO*)pMNHDR;
  338. // Is this for the expected item?
  339. ASSERT(pnmtvd->item.lParam == m_tidRenameItem);
  340. if (pnmtvd->item.pszText != NULL && pnmtvd->item.pszText[0] != 0)
  341. {
  342. m_pFavorites->SetItemName(m_tidRenameItem, pnmtvd->item.pszText);
  343. *plResult = TRUE;
  344. // update displayed name in info window
  345. m_FavName.SetWindowText(pnmtvd->item.pszText);
  346. }
  347. m_tidRenameItem = 0;
  348. }
  349. m_bRenameMode = FALSE;
  350. }
  351. void COrganizeFavDialog::OnAddFolder()
  352. {
  353. ASSERT(m_pFavorites != NULL);
  354. // Get selected group
  355. TREEITEMID tidParent = m_FavTree.GetSelection();
  356. ASSERT(tidParent != NULL);
  357. // if selected item is not a group then
  358. // add the new group as a sibling
  359. if (!m_pFavorites->IsFolderItem(tidParent))
  360. tidParent = m_pFavorites->GetParentItem(tidParent);
  361. // Put up dialog to get folder name
  362. CAddFavGroupDialog dlgAdd(this);
  363. if (dlgAdd.DoModal() != IDOK)
  364. return;
  365. LPCTSTR strName = dlgAdd.GetGroupName();
  366. ASSERT(strName[0] != 0);
  367. CFavObject* pfavGroup = NULL;
  368. HRESULT hr = m_pFavorites->AddGroup(tidParent, strName, &pfavGroup);
  369. if (SUCCEEDED(hr))
  370. {
  371. m_FavTree.ExpandItem(tidParent);
  372. }
  373. }
  374. void COrganizeFavDialog::OnDelete()
  375. {
  376. TREEITEMID tid = m_FavTree.GetSelection();
  377. if (tid != 0 && tid != m_pFavorites->GetRootItem())
  378. m_pFavorites->DeleteItem(tid);
  379. }
  380. void COrganizeFavDialog::OnRename()
  381. {
  382. ASSERT(m_pFavorites != NULL);
  383. // Get selected item
  384. TREEITEMID tid = m_FavTree.GetSelection();
  385. if (tid != 0 && tid != m_pFavorites->GetRootItem())
  386. {
  387. HTREEITEM hti = m_FavTree.FindHTI(tid, TRUE);
  388. ASSERT(hti != NULL);
  389. m_tidRenameItem = tid;
  390. m_FavTree.SetFocus();
  391. m_FavTree.EditLabel(hti);
  392. }
  393. }
  394. void COrganizeFavDialog::OnMoveTo()
  395. {
  396. ASSERT(m_pFavorites != NULL);
  397. // Put up dialog to get destination folder ID
  398. CFavFolderDialog dlgAdd(m_pFavorites, this);
  399. if (dlgAdd.DoModal() != IDOK)
  400. return;
  401. TREEITEMID tidNewParent = dlgAdd.GetFolderID();
  402. // Get selected object
  403. TREEITEMID tid = m_FavTree.GetSelection();
  404. ASSERT(tid != NULL);
  405. HRESULT hr = m_pFavorites->MoveItem(tid, tidNewParent, TREEID_LAST);
  406. // on failure tell user selected destination is invalid
  407. }
  408. /////////////////////////////////////////////////////////////////////
  409. // CFavFolderDialog dialog
  410. BEGIN_MESSAGE_MAP(CFavFolderDialog, CDialog)
  411. //{{AFX_MSG_MAP(CFavFolderDialog)
  412. // NOTE: the ClassWizard will add message map macros here
  413. //}}AFX_MSG_MAP
  414. ON_MMC_CONTEXT_HELP()
  415. END_MESSAGE_MAP()
  416. CFavFolderDialog::CFavFolderDialog(CFavorites* pFavorites, CWnd* pParent)
  417. : CDialog(CFavFolderDialog::IDD, pParent),
  418. m_pFavorites(pFavorites), m_lAdviseCookie(NULL)
  419. {
  420. ASSERT(pFavorites != NULL);
  421. }
  422. CFavFolderDialog::~CFavFolderDialog()
  423. {
  424. // disconnect fav view from source
  425. if (m_lAdviseCookie )
  426. {
  427. ASSERT(m_pFavorites != NULL);
  428. m_pFavorites->Unadvise(m_lAdviseCookie);
  429. m_FavTree.SetTreeSource(NULL);
  430. }
  431. // detach classes from windows
  432. m_FavTree.Detach();
  433. }
  434. CFavFolderDialog::OnInitDialog()
  435. {
  436. DECLARE_SC (sc, _T("CFavFolderDialog::OnInitDialog"));
  437. ASSERT(m_pFavorites != NULL);
  438. CDialog::OnInitDialog();
  439. ModifyStyleEx(0, WS_EX_CONTEXTHELP, SWP_NOSIZE);
  440. // Attach tree ctrl to favorites tree object
  441. BOOL bStat = m_FavTree.SubclassDlgItem(IDC_FAVTREE, this);
  442. ASSERT(bStat);
  443. // Add extra space between items
  444. TreeView_SetItemHeight(m_FavTree, TreeView_GetItemHeight(m_FavTree) + FAVVIEW_ITEM_SPACING);
  445. // Show only folders
  446. m_FavTree.SetStyle(TOBSRV_FOLDERSONLY);
  447. /*
  448. * validate m_pFavorites
  449. */
  450. sc = ScCheckPointers (m_pFavorites, E_UNEXPECTED);
  451. if (sc)
  452. {
  453. EndDialog (IDCANCEL);
  454. return (0);
  455. }
  456. // Attach favorites image list to tree control
  457. m_FavTree.SetImageList(m_pFavorites->GetImageList(), TVSIL_NORMAL);
  458. // attach view to source as observer
  459. HRESULT hr = m_pFavorites->Advise(static_cast<CTreeObserver*>(&m_FavTree), &m_lAdviseCookie);
  460. ASSERT(SUCCEEDED(hr) && m_lAdviseCookie != 0);
  461. // hand tree data source to tree view
  462. m_FavTree.SetTreeSource(static_cast<CTreeSource*>(m_pFavorites));
  463. // Select the root and give it focus
  464. m_FavTree.SetSelection(m_pFavorites->GetRootItem());
  465. m_FavTree.SetFocus();
  466. // return 0 so focus isn't changed
  467. return 0;
  468. }
  469. void CFavFolderDialog::OnOK()
  470. {
  471. // Get group name
  472. m_tidFolder = m_FavTree.GetSelection();
  473. // disconnect fav view from source before window goes away
  474. if (m_lAdviseCookie)
  475. {
  476. ASSERT(m_pFavorites != NULL);
  477. m_pFavorites->Unadvise(m_lAdviseCookie);
  478. m_FavTree.SetTreeSource(NULL);
  479. m_lAdviseCookie = 0;
  480. }
  481. CDialog::OnOK();
  482. }
  483. //////////////////////////////////////////////////////////////////////////////
  484. // CFavTreeCtrl
  485. SC CFavTreeCtrl::ScInitialize(CFavorites* pFavorites, DWORD dwStyles)
  486. {
  487. DECLARE_SC (sc, _T("CFavTreeCtrl::Initialize"));
  488. /*
  489. * validate pFavorites
  490. */
  491. sc = ScCheckPointers (pFavorites);
  492. if (sc)
  493. return (sc);
  494. // Attach favorites image list to tree control
  495. m_FavTree.SetImageList(pFavorites->GetImageList(), TVSIL_NORMAL);
  496. m_FavTree.SetStyle(dwStyles);
  497. // Attach favorites data source
  498. m_FavTree.SetTreeSource(static_cast<CTreeSource*>(pFavorites));
  499. return (sc);
  500. }
  501. int CFavTreeCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
  502. {
  503. if (CWnd::OnCreate(lpCreateStruct) == -1)
  504. return -1;
  505. RECT rect;
  506. GetClientRect(&rect);
  507. m_FavTree.Create(WS_VISIBLE | TVS_SINGLEEXPAND | TVS_TRACKSELECT |
  508. TVS_FULLROWSELECT, rect, this, IDC_FAVTREECTRL);
  509. // Add extra space between items
  510. TreeView_SetItemHeight(m_FavTree, TreeView_GetItemHeight(m_FavTree) + FAVVIEW_ITEM_SPACING);
  511. // Dont' show the "Favorites" root item
  512. m_FavTree.SetStyle(TOBSRV_HIDEROOT);
  513. return 0;
  514. }
  515. void CFavTreeCtrl::PostNcDestroy()
  516. {
  517. /*
  518. * Commit suicide. See the comment for this class's ctor for reasoning
  519. * why this is safe.
  520. */
  521. delete this;
  522. }
  523. void CFavTreeCtrl::OnSize(UINT nType, int cx, int cy)
  524. {
  525. // size tree control to parent
  526. m_FavTree.MoveWindow(0, 0, cx, cy);
  527. }
  528. void CFavTreeCtrl::OnSetFocus(CWnd* pOldWnd)
  529. {
  530. // pass focus to tree control
  531. m_FavTree.SetFocus();
  532. }
  533. void CFavTreeCtrl::OnSelChanged(NMHDR* pMNHDR, LRESULT* plResult)
  534. {
  535. ASSERT(pMNHDR != NULL);
  536. NM_TREEVIEW* pnmtv = (NM_TREEVIEW*)pMNHDR;
  537. TREEITEMID tid = pnmtv->itemNew.lParam;
  538. CFavObject* pFav = (CFavObject*)tid;
  539. WPARAM wParam = pFav->IsGroup() ?
  540. NULL : reinterpret_cast<WPARAM>(pFav->GetMemento());
  541. GetParent()->SendMessage(MMC_MSG_FAVORITE_SELECTION, wParam, 0);
  542. }
  543. BEGIN_MESSAGE_MAP(CFavTreeCtrl, CWnd)
  544. ON_WM_CREATE()
  545. ON_WM_SIZE()
  546. ON_WM_SETFOCUS()
  547. ON_NOTIFY(TVN_SELCHANGED, IDC_FAVTREECTRL, OnSelChanged)
  548. END_MESSAGE_MAP()
  549. //--------------------------------------------------------------------------
  550. // EnableButton
  551. //
  552. // Enables or disables a dialog control. If the control has the focus when
  553. // it is disabled, the focus is moved to the next control
  554. //--------------------------------------------------------------------------
  555. void EnableButton(HWND hwndDialog, int iCtrlID, BOOL bEnable)
  556. {
  557. HWND hWndCtrl = ::GetDlgItem(hwndDialog, iCtrlID);
  558. ASSERT(::IsWindow(hWndCtrl));
  559. if (!bEnable && ::GetFocus() == hWndCtrl)
  560. {
  561. HWND hWndNextCtrl = ::GetNextDlgTabItem(hwndDialog, hWndCtrl, FALSE);
  562. if (hWndNextCtrl != NULL && hWndNextCtrl != hWndCtrl)
  563. {
  564. ::SetFocus(hWndNextCtrl);
  565. }
  566. }
  567. ::EnableWindow(hWndCtrl, bEnable);
  568. }
  569. //+-------------------------------------------------------------------
  570. //
  571. // Member : OnFavoritesMenu
  572. //
  573. // Synopsis : Display the favorites menu.
  574. //
  575. // Arguments : [point] - x,y co-ordinates for menu.
  576. //
  577. // Returns : None.
  578. //
  579. //--------------------------------------------------------------------
  580. void CAMCView::OnFavoritesMenu(CPoint point, LPCRECT prcExclude)
  581. {
  582. DECLARE_SC (sc, _T("CAMCView::OnFavoritesMenu"));
  583. TRACE_METHOD(CAMCView, OnFavoritesMenu);
  584. CMenu menu;
  585. VERIFY( menu.CreatePopupMenu() );
  586. // Default items available only in Author mode.
  587. if (AMCGetApp()->GetMode() == eMode_Author)
  588. {
  589. CString strItem;
  590. // Menu Command Ids for below items are string resource
  591. // IDs. The real favorites use the TREEITEMID as ID,
  592. // which are pointers and wont clash with below resource
  593. // IDs which are less than 0xFFFF
  594. LoadString(strItem, IDS_ADD_TO_FAVORITES);
  595. int iSeparator = strItem.Find(_T('\n'));
  596. if (iSeparator > 0)
  597. strItem = strItem.Left(iSeparator);
  598. VERIFY(menu.AppendMenu(MF_DEFAULT, IDS_ADD_TO_FAVORITES, (LPCTSTR)strItem));
  599. LoadString(strItem, IDS_ORGANIZEFAVORITES);
  600. iSeparator = strItem.Find(_T('\n'));
  601. if (iSeparator > 0)
  602. strItem = strItem.Left(iSeparator);
  603. VERIFY(menu.AppendMenu(MF_DEFAULT, IDS_ORGANIZEFAVORITES, (LPCTSTR)strItem));
  604. }
  605. CAMCDoc* pDoc = GetDocument();
  606. ASSERT(pDoc);
  607. CFavorites* pFavorites = pDoc->GetFavorites();
  608. /*
  609. * Index 0 of the vector is unused (a 0 return from TrackPopupMenu
  610. * means nothing was selected). Put a placeholder there.
  611. */
  612. TIDVector vItemIDs;
  613. vItemIDs.push_back (NULL);
  614. /*
  615. * make sure IDS_ADD_TO_FAVORITES and IDS_ORGANIZEFAVORITES
  616. * won't conflict with any indices in the TID vector, given a
  617. * reasonable upper bound on the number of favorites
  618. */
  619. const int cMaxReasonableFavorites = 1024;
  620. ASSERT (vItemIDs.size () <= cMaxReasonableFavorites);
  621. COMPILETIME_ASSERT (IDS_ADD_TO_FAVORITES > cMaxReasonableFavorites);
  622. COMPILETIME_ASSERT (IDS_ORGANIZEFAVORITES > cMaxReasonableFavorites);
  623. // Add existing favorites.
  624. if ( (NULL != pFavorites) && (pFavorites->IsEmpty() == false))
  625. {
  626. TREEITEMID tid = pFavorites->GetRootItem();
  627. if (NULL != tid)
  628. {
  629. tid = pFavorites->GetChildItem(tid);
  630. if (NULL != tid)
  631. {
  632. // Add separator.
  633. if (AMCGetApp()->GetMode() == eMode_Author)
  634. VERIFY(menu.AppendMenu(MF_SEPARATOR, 0, _T("")));
  635. // Add child items.
  636. AddFavItemsToCMenu(menu, pFavorites, tid, vItemIDs);
  637. }
  638. }
  639. }
  640. // Display the context menu.
  641. TPMPARAMS* ptpm = NULL;
  642. TPMPARAMS tpm;
  643. /*
  644. * if given, initialize the rectangle not to obscure
  645. */
  646. if (prcExclude != NULL)
  647. {
  648. tpm.cbSize = sizeof(tpm);
  649. tpm.rcExclude = *prcExclude;
  650. ptpm = &tpm;
  651. }
  652. LONG lSelected = TrackPopupMenuEx (
  653. menu.GetSafeHmenu(),
  654. TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTBUTTON | TPM_LEFTBUTTON | TPM_VERTICAL,
  655. point.x,
  656. point.y,
  657. GetSafeHwnd(),
  658. ptpm );
  659. // Handle the selection.
  660. switch (lSelected)
  661. {
  662. case 0: // Nothing is selected
  663. break;
  664. case IDS_ADD_TO_FAVORITES: // Bring the Add To Favorites dialog.
  665. OnAddToFavorites();
  666. break;
  667. case IDS_ORGANIZEFAVORITES: // Bring the organize favorites dialog.
  668. {
  669. CAMCDoc* pDoc = GetDocument();
  670. ASSERT(pDoc != NULL && pDoc->GetFavorites() != NULL);
  671. pDoc->GetFavorites()->OrganizeFavorites(this);
  672. }
  673. break;
  674. default: // This is a favorite item. Select it.
  675. {
  676. CFavorites* pFavs = GetDocument()->GetFavorites();
  677. sc = ScCheckPointers (pFavs, E_UNEXPECTED);
  678. if (sc)
  679. break;
  680. sc = (lSelected < vItemIDs.size()) ? S_OK : E_UNEXPECTED;
  681. if (sc)
  682. break;
  683. TREEITEMID tid = vItemIDs[lSelected];
  684. CFavObject* pFavObj = pFavs->FavObjFromTID(tid);
  685. sc = ScCheckPointers (pFavObj, E_UNEXPECTED);
  686. if (sc)
  687. break;
  688. sc = ScViewMemento(pFavObj->GetMemento());
  689. if (sc == ScFromMMC(IDS_NODE_NOT_FOUND) )
  690. {
  691. MMCMessageBox(sc, MB_ICONEXCLAMATION | MB_OK);
  692. sc.Clear();
  693. return;
  694. }
  695. if (sc)
  696. return;
  697. }
  698. break;
  699. }
  700. return;
  701. }
  702. //+-------------------------------------------------------------------
  703. //
  704. // Member : AddFavItemsToCMenu.
  705. //
  706. // Synopsis : Enumerate the favorites tree and add them as menu items.
  707. //
  708. // Arguments : [menu] - Parent menu item.
  709. // [pFavs] - Favorites object.
  710. // [tid] - Tree Item ID.
  711. //
  712. // Returns : None.
  713. //
  714. //--------------------------------------------------------------------
  715. void CAMCView::AddFavItemsToCMenu(CMenu& menu, CFavorites* pFavs, TREEITEMID tid, TIDVector& vItemIDs)
  716. {
  717. TCHAR szName[MAX_PATH];
  718. while (NULL != tid)
  719. {
  720. UINT nFlags = MF_DEFAULT;
  721. UINT_PTR nCommandID;
  722. // If this is folder item then
  723. // create a popup menu.
  724. if (pFavs->IsFolderItem(tid))
  725. {
  726. TREEITEMID tidChild = pFavs->GetChildItem(tid);
  727. CMenu submenu;
  728. VERIFY(submenu.CreatePopupMenu());
  729. // Add the children.
  730. if (NULL != tidChild)
  731. {
  732. AddFavItemsToCMenu(submenu, pFavs, tidChild, vItemIDs);
  733. }
  734. else
  735. {
  736. // Add an empty item.
  737. CString strItem;
  738. LoadString(strItem, IDS_Empty);
  739. VERIFY(submenu.AppendMenu(MF_GRAYED, 0, (LPCTSTR)strItem));
  740. }
  741. HMENU hSubmenu = submenu.Detach();
  742. ASSERT( NULL != hSubmenu );
  743. nFlags = MF_POPUP;
  744. nCommandID = (UINT_PTR)hSubmenu;
  745. }
  746. else
  747. {
  748. /*
  749. * The command ID will be used as an index into vItemIDs,
  750. * so the ID for this item is the size of the vector *before*
  751. * the item is added to the vector.
  752. */
  753. nCommandID = vItemIDs.size();
  754. vItemIDs.push_back (tid);
  755. }
  756. pFavs->GetItemName(tid, szName, countof(szName));
  757. VERIFY(menu.AppendMenu(nFlags, nCommandID, szName));
  758. // Get the next sibling.
  759. tid = pFavs->GetNextSiblingItem(tid);
  760. }
  761. return;
  762. }