SVRVIEW.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:29k
源码类别:

Windows编程

开发平台:

Visual C++

  1. // svrview.cpp : implementation of the CServerView class
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1995 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and Microsoft
  9. // QuickHelp and/or WinHelp documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12. #include "stdafx.h"
  13. #include "afxdlgs.h"        // for FileOpen
  14. #include "$$root$$.h"
  15. #include "svrdoc.h"
  16. #include "svrview.h"
  17. #include "svritem.h"
  18. #include "zoomdlg.h"
  19. $$IF(WANTS_TEXTVIEW)
  20. #include "textview.h"
  21. $$ENDIF
  22. #ifdef _DEBUG
  23. #undef THIS_FILE
  24. static char BASED_CODE THIS_FILE[] = __FILE__;
  25. #endif
  26. CServerNode* NEAR CServerView::m_pDragNode = NULL;
  27. static int ReadString(CArchive& ar, char* pString, int nMaxLen);
  28. static BOOL FindItemRect(CDC* pDC, CServerNode* pItemFind, LPRECT lpRect,
  29. CPoint& ptStart, CServerNode* pRoot);
  30. static CServerNode* HitDetect(CDC* pDC, CPoint point,
  31. CPoint& ptStart, CServerNode* pRoot);
  32. /////////////////////////////////////////////////////////////////////////////
  33. // support for zooming
  34. static int NEAR rgiZoomFactor[] =
  35. {
  36. 25, 50, 75, 100, 125, 150, 175, 200, 250, 300
  37. };
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CServerView
  40. IMPLEMENT_DYNCREATE(CServerView, CScrollView)
  41. BEGIN_MESSAGE_MAP(CServerView, CScrollView)
  42. //{{AFX_MSG_MAP(CServerView)
  43. ON_COMMAND(ID_CHANGE_NAME, OnChangeName)
  44. ON_COMMAND(ID_ADD_NODE, OnAddNode)
  45. ON_UPDATE_COMMAND_UI(ID_CHANGE_NAME, OnUpdateHasSel)
  46. ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
  47. ON_WM_LBUTTONDOWN()
  48. ON_WM_RBUTTONDOWN()
  49. ON_COMMAND(ID_IMPORT_TEXT, OnImportText)
  50. ON_COMMAND(ID_VIEW_ZOOMCUSTOM, OnViewZoomCustom)
  51. ON_COMMAND(ID_EDIT_CUT, OnEditCut)
  52. ON_WM_LBUTTONDBLCLK()
  53. ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
  54. ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
  55. ON_WM_CREATE()
  56. ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
  57. ON_COMMAND(ID_TREE_COLLAPSEBRANCH, OnTreeCollapsebranch)
  58. ON_COMMAND(ID_TREE_EXPANDALL, OnTreeExpandall)
  59. ON_COMMAND(ID_TREE_EXPANDBRANCH, OnTreeExpandbranch)
  60. ON_COMMAND(ID_TREE_EXPANDONELEVEL, OnTreeExpandonelevel)
  61. ON_UPDATE_COMMAND_UI(ID_TREE_COLLAPSEBRANCH, OnUpdateTreeCollapsebranch)
  62. ON_UPDATE_COMMAND_UI(ID_TREE_EXPANDONELEVEL, OnUpdateTreeExpandonelevel)
  63. ON_UPDATE_COMMAND_UI(ID_TREE_EXPANDALL, OnUpdateTreeExpandall)
  64. ON_UPDATE_COMMAND_UI(ID_TREE_EXPANDBRANCH, OnUpdateTreeExpandbranch)
  65. ON_WM_KEYDOWN()
  66. ON_UPDATE_COMMAND_UI(ID_ADD_NODE, OnUpdateHasSel)
  67. ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateHasSel)
  68. ON_UPDATE_COMMAND_UI(ID_IMPORT_TEXT, OnUpdateHasSel)
  69. ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateHasSel)
  70. ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR, OnUpdateHasSel)
  71. $$IF(WANTS_TEXTVIEW)
  72. ON_COMMAND(ID_VIEW_TEXT_VIEW, OnViewTextView)
  73. $$ENDIF
  74. ON_WM_SIZE()
  75. //}}AFX_MSG_MAP
  76. ON_COMMAND_RANGE(ID_VIEW_ZOOM25, ID_VIEW_ZOOM300, OnZoom)
  77. ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_ZOOM25, ID_VIEW_ZOOM300, OnUpdateZoom)
  78. END_MESSAGE_MAP()
  79. /////////////////////////////////////////////////////////////////////////////
  80. // CServerView construction/destruction
  81. CServerView::CServerView()
  82. {
  83. m_pSelectedNode = NULL;
  84. m_ptStart = CPoint(CX_MARGIN, CY_MARGIN);   // upper left position
  85. // initialize zoom state (100% from size cache)
  86. m_zoomNum = CSize(100, 100);
  87. m_zoomDenom = CSize(100, 100);
  88. m_prevDropEffect = DROPEFFECT_NONE;
  89. }
  90. CServerView::~CServerView()
  91. {
  92. }
  93. /////////////////////////////////////////////////////////////////////////////
  94. // Attributes -- public
  95. void CServerView::SetSelection(CServerNode* pNewSel, CDC* pDC)
  96. {
  97. if (pNewSel == m_pSelectedNode)
  98. return;     // already set
  99. InvalidateItem(m_pSelectedNode, pDC);
  100. m_pSelectedNode = pNewSel;
  101. InvalidateItem(m_pSelectedNode, pDC);
  102. }
  103. void CServerView::SetSelection(CServerNode* pNewSel)
  104. {
  105. CServerDC dc(this);
  106. SetSelection(pNewSel, &dc);
  107. }
  108. /////////////////////////////////////////////////////////////////////////////
  109. // Operations -- public
  110. void CServerView::SetScrollInfo()
  111. {
  112. CServerNode* pRoot = GetDocument()->m_pRoot;
  113. ASSERT(pRoot != NULL);
  114. //BLOCK: determine new scrolling sizes
  115. CSize sizeLine;
  116. CSize sizePage;
  117. CSize sizeTotal;
  118. {
  119. CServerDC dc(this);
  120. pRoot->CalcNodeSize(&dc, sizeLine);
  121. sizeLine.cx = sizeDefault.cx;
  122. sizeLine.cy += CY_SEPARATOR;
  123. sizePage.cx = sizeDefault.cx;
  124. sizePage.cy = sizeLine.cy * 10;
  125. // set the scroll sizes dependent on the zoom factor
  126. dc.LPtoDP(&sizePage);
  127. dc.LPtoDP(&sizeLine);
  128. sizeTotal = CalcActualViewSize(&dc);
  129. // subtract out the right and bottom margins
  130. // these are not interesting and this way we avoid
  131. // some problems with nonlinear scaling of fonts
  132. CSize sizeMargin(CX_MARGIN, CY_MARGIN);
  133. CRect rect(CPoint(0, 0), sizeMargin);
  134. dc.LPtoDP(rect);
  135. sizeTotal -= rect.Size();
  136. }
  137. SetScrollSizes(MM_TEXT, sizeTotal, sizePage, sizeLine);
  138. }
  139. BOOL CServerView::SetZoomFactor(CSize zoomNum, CSize zoomDenom)
  140. {
  141. if (zoomDenom != m_zoomDenom || zoomNum != m_zoomNum)
  142. {
  143. // sync to new zoom factor
  144. m_zoomNum = zoomNum;
  145. m_zoomDenom = zoomDenom;
  146. // resync to new sizes
  147. Invalidate();
  148. return TRUE;
  149. }
  150. return FALSE;
  151. }
  152. void CServerView::UpdateServerView()
  153. {
  154. CServerDoc* pDoc = GetDocument();
  155. pDoc->SetModifiedFlag();
  156. pDoc->UpdateAllItems(NULL);
  157. pDoc->UpdateAllViews(NULL);
  158. }
  159. CSize CServerView::CalcActualViewSize(CDC *pDC)
  160. {
  161. return CalcActualItemSize(GetDocument()->m_pRoot, pDC);
  162. }
  163. CSize CServerView::CalcActualItemSize(CServerNode* pItem, CDC *pDC)
  164. {
  165. CSize sizeTotal(0, 0);
  166. CPoint ptStart = m_ptStart;
  167. pItem->CalcBounding(pDC, ptStart, sizeTotal);
  168. sizeTotal.cx += CX_MARGIN;
  169. // sizeTotal is the extent in logical coords
  170. // convert from logical to device
  171. CRect rc(CPoint(0,0),sizeTotal);
  172. pDC->LPtoDP(rc);
  173. return rc.Size();
  174. }
  175. CSize CServerView::CalcScaledViewSize()
  176. {
  177. return CalcScaledItemSize(GetDocument()->m_pRoot);
  178. }
  179. CSize CServerView::CalcScaledItemSize(CServerNode* pItem)
  180. {
  181. CServerDC dc(this);
  182. // set extent to 100%
  183. dc.SetViewportExt(CSize(1,1));
  184. dc.SetWindowExt(CSize(1,1));
  185. CSize sizeTotal(0, 0);
  186. CPoint ptStart = m_ptStart;
  187. pItem->CalcBounding(&dc, ptStart, sizeTotal);
  188. sizeTotal.cx += CX_MARGIN;
  189. // sizeTotal is the native extent in device coords
  190. sizeTotal.cx = MulDiv(sizeTotal.cx,m_zoomNum.cx,m_zoomDenom.cx);
  191. sizeTotal.cy = MulDiv(sizeTotal.cy,m_zoomNum.cy,m_zoomDenom.cy);
  192. return sizeTotal;
  193. }
  194. CServerNode* CServerView::DoPasteItem(COleDataObject* pDataObject)
  195. {
  196. ASSERT(pDataObject != NULL);
  197. ASSERT_VALID(this);
  198. ASSERT(m_pSelectedNode != NULL);
  199. BeginWaitCursor();
  200. CServerNode* pItem = new CServerNode(GetDocument());
  201. ASSERT_VALID(pItem);
  202. TRY
  203. {
  204. if (pDataObject->IsDataAvailable(CServerDoc::m_cfPrivate))
  205. DoPasteNative(pDataObject,pItem);
  206. else if (pDataObject->IsDataAvailable(CF_TEXT))
  207. DoPasteText(pDataObject,pItem);
  208. else
  209. AfxThrowNotSupportedException();
  210. }
  211. CATCH_ALL(e)
  212. {
  213. // general cleanup
  214. TRACE0("failed to embed/link an OLE objectn");
  215. delete pItem;
  216. pItem = NULL;
  217. }
  218. END_CATCH_ALL
  219. EndWaitCursor();
  220. // update the document and views
  221. SetSelection(pItem);
  222. return pItem;
  223. }
  224. void CServerView::DoPasteNative(COleDataObject *pDataObject,CServerNode *pItem)
  225. {
  226. ASSERT(m_pSelectedNode != NULL);
  227. // get file refering to clipboard data
  228. CFile *pFile = pDataObject->GetFileData(CServerDoc::m_cfPrivate);
  229. if (pFile == NULL)
  230. return;
  231. // connect the file to the archive and read the contents
  232. CArchive ar(pFile, CArchive::load);
  233. ar.m_pDocument = GetDocument(); // for COleClientItem serialize
  234. pItem->Serialize(ar);
  235. ar.Close();
  236. delete pFile;
  237. // add the item to selected node
  238. m_pSelectedNode->m_listChild.AddHead(pItem);
  239. }
  240. void CServerView::DoPasteText(COleDataObject *pDataObject, CServerNode*)
  241. {
  242. ASSERT(m_pSelectedNode != NULL);
  243. // get file refering to clipboard data
  244. CFile *pFile = pDataObject->GetFileData(CF_TEXT);
  245. if (pFile == NULL)
  246. return;
  247. // connect the file to the archive and read the contents
  248. CArchive ar(pFile, CArchive::load);
  249. DoImportText(ar);
  250. ar.Close();
  251. delete pFile;
  252. }
  253. void CServerView::DoImportText(CArchive &ar)
  254. {
  255. // read in lines appending items from this node
  256. char szNode[256];
  257. #ifdef _UNICODE
  258. TCHAR szT[256];
  259. #endif
  260. int nCurLevel = 0;
  261. CServerNode* parents[MAX_LEVEL];
  262. parents[0] = m_pSelectedNode;   // must have a parent at the current level
  263. while (ReadString(ar, szNode, sizeof(szNode)) != NULL)
  264. {
  265. int cch = strlen(szNode);
  266. if (cch == 0)
  267. continue;
  268. if (szNode[cch-1] != 'n')
  269. {
  270. AfxMessageBox(
  271. _T("Text file contains too long a line - aborting readn"));
  272. break;      // leaves items loaded so far
  273. }
  274. szNode[cch-1] = '';
  275. // check the indentation level
  276. char* pch = szNode;
  277. while (*pch == 't')
  278. pch++;
  279. int nLevel = (pch - szNode)+1;
  280. ASSERT(nLevel >= 1);        // levels are 1 based, 0 is the root
  281. if (*pch == '')
  282. continue;       // skip blank lines
  283. if (nLevel > nCurLevel + 1 || nLevel >= MAX_LEVEL)
  284. {
  285. AfxMessageBox(
  286. _T("Text file contains too many tabs = aborting readn"));
  287. break;      // leaves items loaded so far
  288. }
  289. #ifdef _UNICODE
  290. _mbstowcsz(szT, pch, sizeof(szT)/sizeof(szT[0]));
  291. parents[nLevel] = parents[nLevel-1]->CreateChildNode(szT);
  292. #else
  293. parents[nLevel] = parents[nLevel-1]->CreateChildNode(pch);
  294. #endif
  295. nCurLevel = nLevel;
  296. }
  297. if (nCurLevel == 0)
  298. return;     // nothing added
  299. UpdateServerView();
  300. }
  301. void CServerView::ScrollToItem(CServerNode *pItem, BOOL bScrollUp)
  302. {
  303. CServerDC dc(this);
  304. CRect rect;
  305. CPoint ptStart = m_ptStart;
  306. if (FindItemRect(&dc, pItem, &rect, ptStart, GetDocument()->m_pRoot))
  307. {
  308. CRect rc;
  309. dc.LPtoDP(rect);
  310. if (GetDocument()->IsInPlaceActive())
  311. {
  312. CRect rcPos,rcClip;
  313. GetDocument()->GetItemPosition(&rcPos);
  314. GetDocument()->GetItemClipRect(&rcClip);
  315. rc.IntersectRect(&rcPos,&rcClip);
  316. rc.OffsetRect(-rcPos.left,-rcPos.top);
  317. if (!rc.PtInRect(rect.TopLeft()) || !rc.PtInRect(rect.BottomRight()))
  318. {
  319. CSize size(0, 0);
  320. // scroll inplace site
  321. if (bScrollUp)
  322. size.cy = rect.top - rc.top;
  323. else
  324. size.cy = rect.bottom + rcPos.top - rcClip.bottom;
  325. GetDocument()->ScrollContainerBy(size);
  326. }
  327. }
  328. else
  329. {
  330. GetClientRect(rc);
  331. if (!rc.PtInRect(rect.TopLeft()) || !rc.PtInRect(rect.BottomRight()))
  332. {
  333. CPoint ptDevScroll = GetDeviceScrollPosition();
  334. if (bScrollUp)
  335. ScrollToPosition(CPoint(0,rect.top + ptDevScroll.y));
  336. else
  337. ScrollToPosition(
  338. CPoint(0,ptDevScroll.y + rect.bottom - rc.Height()));
  339. }
  340. }
  341. }
  342. }
  343. void CServerView::Locate(int nCount, BOOL bScrollUp)
  344. {
  345. CServerNode* pRoot = GetDocument()->m_pRoot;
  346. CServerNode* pItem = pRoot;
  347. if (m_pSelectedNode == NULL)
  348. SetSelection(pRoot);
  349. if (nCount == 0) // goto top or bottom depending on direction
  350. {
  351. if (bScrollUp)
  352. pItem = pRoot;
  353. else
  354. {
  355. while (pItem->HasChildren())
  356. pItem = (CServerNode *)(pItem->m_listChild.GetTail());
  357. }
  358. }
  359. else if (bScrollUp)
  360. {
  361. pItem = m_pSelectedNode;
  362. while (nCount--)
  363. pItem = pRoot->GetPrev(pItem);
  364. }
  365. else // going down
  366. {
  367. pItem = m_pSelectedNode;
  368. while (nCount--)
  369. pItem = pRoot->GetNext(pItem);
  370. }
  371. ScrollToItem(pItem, bScrollUp);
  372. SetSelection(pItem);
  373. UpdateWindow();
  374. }
  375. void CServerView::InvalidateItem(CServerNode *pItem, CDC* pDC)
  376. {
  377. if (pItem != NULL)
  378. {
  379. CRect rect;
  380. CPoint ptStart = m_ptStart;
  381. if (FindItemRect(pDC, pItem, &rect, ptStart, GetDocument()->m_pRoot))
  382. {
  383. pDC->LPtoDP(rect);
  384. InvalidateRect(rect, FALSE);
  385. }
  386. }
  387. }
  388. void CServerView::InvalidateItem(CServerNode* pItem)
  389. {
  390. CServerDC dc(this);
  391. InvalidateItem(pItem, &dc);
  392. }
  393. void CServerView::ToggleSelectedItem()
  394. {
  395. if (m_pSelectedNode != NULL && m_pSelectedNode->HasChildren())
  396. {
  397. if (m_pSelectedNode->m_bHideChildren)
  398. OnTreeExpandonelevel();
  399. else
  400. OnTreeCollapsebranch();
  401. }
  402. }
  403. /////////////////////////////////////////////////////////////////////////////
  404. // Implementation
  405. void CServerView::OnDraw(CDC* pDC)
  406. {
  407. if (GetDocument()->DrawTree(pDC, m_ptStart, m_pSelectedNode) == -1)
  408. TRACE0("Error: CServerDoc::DrawTree failed!!n");
  409. }
  410. void CServerView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
  411. {
  412. CScrollView::OnUpdate(pSender, lHint, pHint);
  413. CServerDoc* pDoc = GetDocument();
  414. CServerNode* pRoot = pDoc->m_pRoot;
  415. ASSERT(pRoot != NULL);
  416. if (m_pSelectedNode == NULL)
  417. m_pSelectedNode = pRoot;
  418. if (pDoc->IsInPlaceActive())
  419. {
  420. ASSERT_VALID(pDoc->m_pRoot);
  421. CRect rect;
  422. pDoc->GetItemPosition(rect);
  423. // adjust rect for new size of view
  424. rect.BottomRight() = rect.TopLeft() + CalcScaledViewSize();
  425. pDoc->RequestPositionChange(rect);
  426. // may resize the window before returning
  427. }
  428. SetScrollInfo();
  429. }
  430. void CServerView::OnInitialUpdate()
  431. {
  432. // initialize zoom state (100% from size cache)
  433. m_zoomNum = CSize(100, 100);
  434. m_zoomDenom = CSize(100, 100);
  435. // call base class last (will call OnUpdate)
  436. CScrollView::OnInitialUpdate();
  437. }
  438. void CServerView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
  439. {
  440. CScrollView::OnPrepareDC(pDC, pInfo);
  441. pDC->SetMapMode(MM_ANISOTROPIC);
  442. pDC->SetViewportExt(m_zoomNum);
  443. pDC->SetWindowExt(m_zoomDenom);
  444. }
  445. void CServerView::SelectAtPoint(CPoint point, CPoint& pointHit)
  446. {
  447. CServerDC dc(this);
  448. // change the selection as appropriate
  449. pointHit = m_ptStart;
  450. CServerNode* pSelection = HitDetect(&dc, point, pointHit,
  451. GetDocument()->m_pRoot);
  452. // now set the selection to new hit-tested node
  453. SetSelection(pSelection, &dc);
  454. }
  455. void CServerView::DoBranch(CServerNode *pItem, BOOL bHide)
  456. {
  457. if (pItem->HasChildren())
  458. {
  459. pItem->m_bHideChildren = bHide;
  460. POSITION pos = pItem->m_listChild.GetHeadPosition();
  461. while (pos != NULL)
  462. DoBranch((CServerNode *)pItem->m_listChild.GetNext(pos),bHide);
  463. }
  464. }
  465. BOOL CServerView::OnDrop(COleDataObject* pDataObject, DROPEFFECT, CPoint)
  466. {
  467. ASSERT_VALID(this);
  468. OnDragLeave();
  469. if (DoPasteItem(pDataObject) != NULL)
  470. {
  471. UpdateServerView();
  472. return TRUE;
  473. }
  474. else
  475. return FALSE;
  476. }
  477. DROPEFFECT CServerView::OnDragEnter(COleDataObject* pDataObject,
  478. DWORD grfKeyState, CPoint point)
  479. {
  480. ASSERT(m_prevDropEffect == DROPEFFECT_NONE);
  481. return OnDragOver(pDataObject, grfKeyState, point);
  482. }
  483. DROPEFFECT CServerView::OnDragOver(COleDataObject* pDataObject,
  484. DWORD grfKeyState, CPoint point)
  485. {
  486. DROPEFFECT dropEffect = DROPEFFECT_NONE;
  487. if (pDataObject->IsDataAvailable(CServerDoc::m_cfPrivate) ||
  488. pDataObject->IsDataAvailable(CF_TEXT))
  489. {
  490. CPoint pointHit;
  491. SelectAtPoint(point, pointHit);
  492. UpdateWindow();
  493. if (m_pSelectedNode != NULL)
  494. {
  495. // don't allow a node to drop on itself
  496. if (m_pDragNode == m_pSelectedNode)
  497. dropEffect = DROPEFFECT_NONE;
  498. // if drop target is a child of drag source
  499. // then don't drop
  500. else if (m_pDragNode != NULL && m_pDragNode->IsChild(m_pSelectedNode))
  501. dropEffect = DROPEFFECT_NONE;
  502. // check for force link
  503. else if ((grfKeyState & (MK_CONTROL|MK_SHIFT)) == (MK_CONTROL|MK_SHIFT))
  504. dropEffect = DROPEFFECT_COPY;
  505. // check for force copy
  506. else if ((grfKeyState & MK_CONTROL) == MK_CONTROL)
  507. dropEffect = DROPEFFECT_COPY;
  508. // check for force move
  509. else if ((grfKeyState & MK_ALT) == MK_ALT)
  510. dropEffect = DROPEFFECT_MOVE;
  511. // if m_pDragNode == NULL then not dropping on self
  512. // so make default effect be copy
  513. // if dropping on self make default be move
  514. else
  515. dropEffect = (m_pDragNode == NULL) ? DROPEFFECT_COPY :
  516. DROPEFFECT_MOVE;
  517. }
  518. }
  519. m_prevDropEffect = dropEffect;
  520. return dropEffect;
  521. }
  522. void CServerView::OnDragLeave()
  523. {
  524. m_prevDropEffect = DROPEFFECT_NONE;
  525. }
  526. /////////////////////////////////////////////////////////////////////////////
  527. // CServerView commands
  528. void CServerView::OnUpdateHasSel(CCmdUI* pCmdUI)
  529. {
  530. pCmdUI->Enable(m_pSelectedNode != NULL);
  531. }
  532. void CServerView::OnChangeName()
  533. {
  534. if (m_pSelectedNode != NULL && m_pSelectedNode->PromptChangeNode())
  535. {
  536. GetDocument()->SetModifiedFlag();
  537. GetDocument()->UpdateAllItems(NULL);
  538. GetDocument()->UpdateAllViews(NULL);
  539. }
  540. }
  541. void CServerView::OnAddNode()
  542. {
  543. if (m_pSelectedNode == NULL)
  544. AfxThrowNotSupportedException();
  545. CServerNode* pNew;
  546. if ((pNew = m_pSelectedNode->PromptNewChildNode()) == NULL)
  547. return;
  548. SetSelection(pNew);
  549. UpdateServerView();
  550. }
  551. void CServerView::OnEditCopy()
  552. {
  553. ASSERT_VALID(this);
  554. if (m_pSelectedNode == NULL)
  555. return;
  556. // get a server item suitable to generate the clipboard data
  557. CServerItem* pItem = m_pSelectedNode->m_pServerItem;
  558. if (pItem == NULL)
  559. pItem = new CServerItem(GetDocument(), m_pSelectedNode);
  560. ASSERT_VALID(pItem);
  561. pItem->CopyToClipboard(TRUE);
  562. }
  563. void CServerView::OnLButtonDown(UINT, CPoint point)
  564. {
  565. // m_pDragNode != NULL only when drag in progress
  566. ASSERT(m_pDragNode == NULL);
  567. CPoint pointHit;
  568. SelectAtPoint(point, pointHit);
  569. UpdateWindow();
  570. // maybe start drag drop operation on selection
  571. if (m_pSelectedNode != NULL)
  572. {
  573. // record current selection because a drop back in same view
  574. // will change the current selection
  575. m_pDragNode = m_pSelectedNode;
  576. // determine rectangle of object we'll be dragging
  577. CServerDC dc(this);
  578. CSize size = CalcActualItemSize(m_pSelectedNode, &dc);
  579. CRect rect(pointHit, size);
  580. // get a server item suitable to generate the clipboard data
  581. CServerItem* pItem = m_pSelectedNode->m_pServerItem;
  582. if (pItem == NULL)
  583. pItem = new CServerItem(GetDocument(), m_pSelectedNode);
  584. ASSERT_VALID(pItem);
  585. // rect must be in screen co-ordinates
  586. dc.LPtoDP(&rect);
  587. CPoint ptOffset = point - rect.TopLeft();
  588. ClientToScreen(&rect);
  589. // drag the object
  590. if (pItem->DoDragDrop(rect, ptOffset, TRUE,
  591. DROPEFFECT_COPY | DROPEFFECT_MOVE) == DROPEFFECT_MOVE)
  592. {
  593. // the object was moved, need to delete/move depending on dest
  594. CServerDoc* pDoc = GetDocument();
  595. if (m_pSelectedNode == m_pDragNode)
  596. SetSelection(pDoc->m_pRoot->GetPrev(m_pSelectedNode));
  597. if (m_pDragNode == pDoc->m_pRoot)
  598. pDoc->m_pRoot->InitRootNode();
  599. else
  600. pDoc->m_pRoot->FindAndDelete(m_pDragNode);
  601. // if drop was not back in same view clear selected node
  602. UpdateServerView();
  603. }
  604. m_pDragNode = NULL;
  605. }
  606. }
  607. void CServerView::OnRButtonDown(UINT /*nFlags*/, CPoint point)
  608. {
  609. // make sure window is active
  610. GetParentFrame()->ActivateFrame();
  611. CPoint pointHit;
  612. SelectAtPoint(point, pointHit); // select node first
  613. UpdateWindow();
  614. int iSub;
  615. if (m_pSelectedNode == NULL ||
  616.   (iSub = m_pSelectedNode->GetPopupMenuIndex()) == -1)
  617.    return;  // nothing if no selection or no popup
  618. CMenu popups;
  619. if (!popups.LoadMenu(IDR_POPUPS))
  620. AfxThrowResourceException();
  621. CMenu* pMenu = popups.GetSubMenu(iSub);
  622. ASSERT(pMenu != NULL);
  623. ClientToScreen(&point);
  624. pMenu->TrackPopupMenu(TPM_CENTERALIGN | TPM_RIGHTBUTTON,
  625. point.x, point.y, AfxGetMainWnd());
  626. }
  627. void CServerView::OnImportText()
  628. {
  629. if (m_pSelectedNode == NULL)
  630. AfxThrowNotSupportedException();
  631. CFileDialog dlg(TRUE, _T("txt"), NULL,
  632. OFN_FILEMUSTEXIST | OFN_HIDEREADONLY,
  633. _T("Text Files (*.txt)|*.txt|All Files (*.*)|*.*||"));
  634. if (dlg.DoModal() != IDOK)
  635. return;                 // stay with old data file
  636. OpenTextFile(dlg.GetPathName());
  637. }
  638. void CServerView::OpenTextFile(CString Name)
  639. {
  640. CFile file;
  641. if (!file.Open(Name, CFile::modeRead))
  642. {
  643. AfxMessageBox(_T("Failed to open text file"));
  644. return;
  645. }
  646. CArchive ar(&file,CArchive::load);
  647. DoImportText(ar);
  648. ar.Close();
  649. file.Close();
  650. }
  651. static int ReadString(CArchive& ar, char* pString, int nMaxLen)
  652. {
  653. int nCount = 0;
  654. char ch;
  655. pString[nCount] = (char)0;
  656. TRY
  657. {
  658. do
  659. {
  660. ar >> (BYTE&)ch;
  661. // watch out for ^Z (EOF under DOS)
  662. if (ch == 0x1A)
  663. break;
  664. // combine "rn" pair into single "n"
  665. if (ch == 'n' && nCount != 0 && pString[nCount-1] == 'r')
  666. nCount--;
  667. //Remove any extra r
  668. if (ch == 'r' && nCount != 0 && pString[nCount-1] == 'r')
  669. nCount--;
  670. pString[nCount++] = ch;
  671. } while (nCount < nMaxLen-1 && ch != 'n');
  672. }
  673. END_TRY
  674. // insert newline if missing
  675. if (nCount != 0 && pString[nCount-1] != 'n' && nCount < nMaxLen-1)
  676. pString[nCount++] = 'n';
  677. pString[nCount] = (char)0;
  678. return nCount;
  679. }
  680. /////////////////////////////////////////////////////////////////////////////
  681. // Zooming user interface
  682. void CServerView::OnZoom(UINT nID)
  683. {
  684. ASSERT(nID >= ID_VIEW_ZOOM25 && nID <= ID_VIEW_ZOOM300);
  685. CSize zoomDenom;
  686. CSize zoomNum;
  687. // all of our zoom factors use denominator of 100
  688. zoomDenom.cx = 100;
  689. zoomDenom.cy = 100;
  690. // get zoom factor numerator and set it
  691. ASSERT(nID-ID_VIEW_ZOOM25 < sizeof(rgiZoomFactor)/sizeof(rgiZoomFactor[0]));
  692. int iZoomFactor = rgiZoomFactor[nID-ID_VIEW_ZOOM25];
  693. zoomNum.cx = iZoomFactor;
  694. zoomNum.cy = iZoomFactor;
  695. // change the zoom factor to new zoom factor
  696. SetZoomFactor(zoomNum, zoomDenom);
  697. SetScrollInfo();
  698. }
  699. void CServerView::OnUpdateZoom(CCmdUI* pCmdUI)
  700. {
  701. UINT nID = pCmdUI->m_nID;
  702. if (m_zoomDenom.cx == 100 && m_zoomDenom.cy == 100 &&
  703. nID != ID_VIEW_ZOOMCUSTOM)
  704. {
  705. ASSERT(nID-ID_VIEW_ZOOM25 <
  706. sizeof(rgiZoomFactor)/sizeof(rgiZoomFactor[0]));
  707. int iZoomFactor = rgiZoomFactor[nID-ID_VIEW_ZOOM25];
  708. if (iZoomFactor == m_zoomNum.cx && iZoomFactor == m_zoomNum.cy)
  709. {
  710. pCmdUI->SetCheck(TRUE);
  711. return;
  712. }
  713. }
  714. // default to not checked
  715. pCmdUI->SetCheck(FALSE);
  716. }
  717. void CServerView::OnViewZoomCustom()
  718. {
  719. // prepare dialog data
  720. CZoomDlg dlg;
  721. dlg.m_zoomX = m_zoomNum.cx;
  722. dlg.m_zoomY = m_zoomNum.cy;
  723. // launch dialog
  724. if (dlg.DoModal() == IDOK)
  725. {
  726. // set new zoom factors
  727. CSize zoomNum(dlg.m_zoomX, dlg.m_zoomY);
  728. SetZoomFactor(zoomNum, m_zoomDenom);
  729. SetScrollInfo();
  730. }
  731. }
  732. /////////////////////////////////////////////////////////////////////////////
  733. void CServerView::OnEditCut()
  734. {
  735. ASSERT(m_pSelectedNode != NULL);
  736. CServerDoc* pDoc = GetDocument();
  737. OnEditCopy();
  738. if (m_pSelectedNode == pDoc->m_pRoot)
  739. pDoc->m_pRoot->InitRootNode();
  740. else if (pDoc->m_pRoot->FindAndDelete(m_pSelectedNode))
  741. m_pSelectedNode = NULL;
  742. UpdateServerView();
  743. }
  744. void CServerView::OnLButtonDblClk(UINT /*nFlags*/, CPoint point)
  745. {
  746. CPoint pointHit;
  747. SelectAtPoint(point, pointHit);
  748. ToggleSelectedItem();
  749. }
  750. void CServerView::OnEditPaste()
  751. {
  752. COleDataObject clipboardData;
  753. clipboardData.AttachClipboard();
  754. DoPasteItem(&clipboardData);
  755. UpdateServerView();
  756. }
  757. void CServerView::OnUpdateEditPaste(CCmdUI* pCmdUI)
  758. {
  759. // determine if private or standard OLE formats are on the clipboard
  760. COleDataObject dataObj;
  761. BOOL bEnable = m_pSelectedNode != NULL &&
  762. dataObj.AttachClipboard() &&
  763. (dataObj.IsDataAvailable(CServerDoc::m_cfPrivate) ||
  764.  dataObj.IsDataAvailable(CF_TEXT));
  765. // enable command based on availability
  766. pCmdUI->Enable(bEnable);
  767. }
  768. int CServerView::OnCreate(LPCREATESTRUCT lpCreateStruct)
  769. {
  770. if (CScrollView::OnCreate(lpCreateStruct) == -1)
  771. return -1;
  772. // register drop target
  773. m_dropTarget.Register(this);
  774. // setup scroll state so it is possible to calculate the extent
  775. SetScrollSizes(MM_TEXT, CSize(0, 0));
  776. return 0;
  777. }
  778. void CServerView::OnEditClear()
  779. {
  780. CServerNode* pRoot = GetDocument()->m_pRoot;
  781. if (m_pSelectedNode == NULL)
  782. return;
  783. if (m_pSelectedNode == pRoot)
  784. pRoot->InitRootNode();
  785. else
  786. {
  787. CServerNode *pItem = pRoot->GetPrev(m_pSelectedNode);
  788. if (pRoot->FindAndDelete(m_pSelectedNode))
  789. m_pSelectedNode = pRoot->GetNext(pItem);
  790. }
  791. UpdateServerView();
  792. }
  793. void CServerView::OnTreeCollapsebranch()
  794. {
  795. DoBranch(m_pSelectedNode,TRUE);
  796. UpdateServerView();
  797. }
  798. void CServerView::OnTreeExpandall()
  799. {
  800. DoBranch(GetDocument()->m_pRoot,FALSE);
  801. UpdateServerView();
  802. }
  803. void CServerView::OnTreeExpandbranch()
  804. {
  805. DoBranch(m_pSelectedNode,FALSE);
  806. UpdateServerView();
  807. }
  808. void CServerView::OnTreeExpandonelevel()
  809. {
  810. if (m_pSelectedNode->HasChildren())
  811. {
  812. m_pSelectedNode->m_bHideChildren = FALSE;
  813. UpdateServerView();
  814. }
  815. }
  816. void CServerView::OnUpdateTreeCollapsebranch(CCmdUI* pCmdUI)
  817. {
  818. pCmdUI->Enable(m_pSelectedNode != NULL && m_pSelectedNode->HasChildren() &&
  819. !m_pSelectedNode->m_bHideChildren);
  820. }
  821. void CServerView::OnUpdateTreeExpandonelevel(CCmdUI* pCmdUI)
  822. {
  823. pCmdUI->Enable(m_pSelectedNode != NULL && m_pSelectedNode->HasChildren() &&
  824. m_pSelectedNode->m_bHideChildren);
  825. }
  826. void CServerView::OnUpdateTreeExpandall(CCmdUI* pCmdUI)
  827. {
  828. pCmdUI->Enable(GetDocument()->m_pRoot != NULL &&
  829. GetDocument()->m_pRoot->HasChildren());
  830. }
  831. void CServerView::OnUpdateTreeExpandbranch(CCmdUI* pCmdUI)
  832. {
  833. pCmdUI->Enable(m_pSelectedNode != NULL && m_pSelectedNode->HasChildren());
  834. }
  835. void CServerView::OnKeyDown(UINT nChar, UINT /*nRepCnt*/, UINT /*nFlags*/)
  836. {
  837. switch (nChar)
  838. {
  839. case VK_RETURN:
  840. ToggleSelectedItem();
  841. break;
  842. case VK_UP:
  843. Locate(1, TRUE);
  844. break;
  845. case VK_DOWN:
  846. Locate(1, FALSE);
  847. break;
  848. case VK_HOME:
  849. Locate(0, TRUE);
  850. break;
  851. case VK_END:
  852. Locate(0, FALSE);
  853. break;
  854. case VK_PRIOR:
  855. Locate(10, TRUE);
  856. break;
  857. case VK_NEXT:
  858. Locate(10, FALSE);
  859. break;
  860. }
  861. }
  862. void CServerView::OnSize(UINT nType, int cx, int cy)
  863. {
  864. // update scroll bar size before handling the size message
  865. //  (this avoids multiple updates during in-place activation)
  866. SetScrollInfo();
  867. CScrollView::OnSize(nType, cx, cy);
  868. }
  869. /////////////////////////////////////////////////////////////////////////////
  870. // CServerDC class -- helper for setting up and cleaning up DC
  871. CServerDC::CServerDC(CServerView *pView) : CClientDC(pView)
  872. {
  873. pView->OnPrepareDC(this);
  874. pOldFont = pView->GetDocument()->SelectDocFont(this, font);
  875. }
  876. CServerDC::~CServerDC()
  877. {
  878. if (pOldFont != NULL)
  879. SelectObject(pOldFont);
  880. }
  881. /////////////////////////////////////////////////////////////////////////////
  882. // non-member static functions
  883. // calculate the bounding rect for a given item in the context of this view
  884. static BOOL FindItemRect(CDC* pDC, CServerNode* pItemFind, LPRECT lpRect,
  885. CPoint& ptStart, CServerNode* pRoot)
  886. {
  887. ASSERT(pItemFind != NULL);
  888. ASSERT(lpRect != NULL);
  889. ASSERT(pRoot != NULL);
  890. CSize sizeNode;
  891. pRoot->CalcNodeSize(pDC, sizeNode);
  892. if (pItemFind == pRoot)
  893. {
  894. // item rect does not include separator
  895. lpRect->right = (lpRect->left = ptStart.x) + sizeNode.cx;
  896. lpRect->bottom = (lpRect->top = ptStart.y) + sizeNode.cy;
  897. return TRUE;
  898. }
  899. CPoint pt(CX_INDENT, CY_SEPARATOR);
  900. ptStart.x += CX_INDENT; // not essential for calculation
  901. ptStart.y += sizeNode.cy + CY_SEPARATOR;
  902. // check the kids
  903. if (!pRoot->m_bHideChildren)
  904. {
  905. POSITION pos = pRoot->m_listChild.GetHeadPosition();
  906. while (pos != NULL)
  907. {
  908. CServerNode* pChild = (CServerNode*) (pRoot->m_listChild.GetNext(pos));
  909. if (FindItemRect(pDC, pItemFind, lpRect, ptStart, pChild))
  910. return TRUE;    // found
  911. }
  912. }
  913. ptStart.x -= CX_INDENT;
  914. return FALSE;
  915. }
  916. // calculate the bounding rect for a given item in the context of this view
  917. static CServerNode* HitDetect(CDC* pDC, CPoint point,
  918. CPoint& ptStart, CServerNode* pRoot)
  919. {
  920. ASSERT(pRoot != NULL);
  921. CSize sizeNode;
  922. pRoot->CalcNodeSize(pDC, sizeNode);
  923. CRect rect(ptStart, sizeNode);
  924. pDC->LPtoDP(rect);
  925. if (rect.PtInRect(point))
  926. return pRoot;
  927. ptStart.x += CX_INDENT;
  928. ptStart.y += sizeNode.cy + CY_SEPARATOR;
  929. CPoint pt = ptStart;
  930. pDC->LPtoDP(&pt);
  931. if (pt.y >= point.y)
  932. return FALSE;       // no point in looking any lower
  933. // check the kids
  934. if (!pRoot->m_bHideChildren)
  935. {
  936. POSITION pos = pRoot->m_listChild.GetHeadPosition();
  937. while (pos != NULL)
  938. {
  939. CServerNode* pChild = (CServerNode*) (pRoot->m_listChild.GetNext(pos));
  940. CServerNode* pItem = HitDetect(pDC, point, ptStart, pChild);
  941. if (pItem != NULL)
  942. return pItem;   // found
  943. }
  944. }
  945. ptStart.x -= CX_INDENT;
  946. return NULL;
  947. }
  948. /////////////////////////////////////////////////////////////////////////////
  949. // CServerView diagnostics
  950. #ifdef _DEBUG
  951. void CServerView::AssertValid() const
  952. {
  953. CScrollView::AssertValid();
  954. }
  955. void CServerView::Dump(CDumpContext& dc) const
  956. {
  957. CScrollView::Dump(dc);
  958. }
  959. #endif //_DEBUG
  960. $$IF(WANTS_TEXTVIEW)
  961. void CServerView::OnViewTextView()
  962. {
  963. // Show the active document in text view.
  964. CServerDoc* pServerDoc = GetDocument();
  965. CDocument * pNewDoc ;
  966. pNewDoc = ((CServerApp *)AfxGetApp())->pDocTxtTemplate->OpenDocumentFile(NULL);
  967.    //Detach the view from the newly created doc and attach it to the CServerDoc document
  968. POSITION pos = pNewDoc->GetFirstViewPosition() ;
  969. CTextView * pTxtvw = ( CTextView *)pNewDoc->GetNextView(pos) ;
  970. pNewDoc->RemoveView(pTxtvw) ;
  971. pServerDoc->AddView(pTxtvw) ;
  972. pTxtvw->RedrawText() ; // Do an initial draw of textview
  973. }
  974. void CServerView::CreateTextView()
  975. {
  976. OnViewTextView() ;
  977. }
  978. $$ENDIF //WANTS_TEXTVIEW