PageRenderTime 42ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/cdex1/branches/CDEX_160_BRANCH/cdexos/LineList.cpp

#
C++ | 472 lines | 286 code | 69 blank | 117 comment | 54 complexity | 3d5c0757bbba971f790d7f24d7abf24b MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, LGPL-2.0, BSD-3-Clause, AGPL-1.0, CC-BY-SA-3.0, GPL-3.0
  1. /*
  2. ** Copyright (C) 1999 Albert L. Faber
  3. **
  4. ** This program is free software; you can redistribute it and/or modify
  5. ** it under the terms of the GNU General Public License as published by
  6. ** the Free Software Foundation; either version 2 of the License, or
  7. ** (at your option) any later version.
  8. **
  9. ** This program is distributed in the hope that it will be useful,
  10. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ** GNU General Public License for more details.
  13. **
  14. ** You should have received a copy of the GNU General Public License
  15. ** along with this program; if not, write to the Free Software
  16. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include "Stdafx.h"
  19. #include "LineList.h"
  20. #ifdef _DEBUG
  21. #define new DEBUG_NEW
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25. /////////////////////////////////////////////////////////////////////////////
  26. // LListCtrl
  27. /////////////////////////////////////////////////////////////////////////////
  28. // GetCurSel -
  29. // an obvious CListCtrl deficiency, tell us index of current selection.
  30. /////////////////////////////////////////////////////////////////////////////
  31. int LListCtrl::GetCurSel() const
  32. {
  33. return GetNextItem(-1,LVNI_ALL|LVNI_SELECTED);
  34. }
  35. /////////////////////////////////////////////////////////////////////////////
  36. // SetCurSel -
  37. // an obvious CListCtrl deficiency, specify and make visible a new selection.
  38. /////////////////////////////////////////////////////////////////////////////
  39. int LListCtrl::SetCurSel(int nSelect)
  40. {
  41. if(!SetItemState(nSelect,LVIS_SELECTED,LVIS_SELECTED))
  42. {
  43. return LB_ERR;
  44. }
  45. if(!EnsureVisible(nSelect,FALSE))
  46. {
  47. return LB_ERR;
  48. }
  49. return TRUE;
  50. }
  51. BEGIN_MESSAGE_MAP(LListCtrl, CListCtrl)
  52. //{{AFX_MSG_MAP(LListCtrl)
  53. ON_NOTIFY_REFLECT(LVN_INSERTITEM, OnInsertitem)
  54. ON_WM_GETDLGCODE()
  55. ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
  56. //}}AFX_MSG_MAP
  57. // ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
  58. // ON_NOTIFY_REFLECT(LVN_BEGINLABELEDIT, OnBeginlabeledit)
  59. END_MESSAGE_MAP()
  60. /////////////////////////////////////////////////////////////////////////////
  61. // OnGetDialogCode -
  62. // allow our control to recieve crack at parent dialog's key codes
  63. // this allows the control to catch RETURN rather than the dialog's
  64. // default push button and hence to support up arrow/down arrow/return
  65. // item selection (must also place a NM_RETURN message handler in the
  66. // dialog's message map).
  67. /////////////////////////////////////////////////////////////////////////////
  68. //UINT LListCtrl::OnGetDlgCode()
  69. //{
  70. //return CListCtrl::OnGetDlgCode() | DLGC_WANTALLKEYS;
  71. //}
  72. /////////////////////////////////////////////////////////////////////////////
  73. // OnInsertItem -
  74. // make item selectable and hi-lighted by entire row, not just first
  75. // column sub-item (an undocumented tid-bit of the Net). Yes there must
  76. // be a better place for this but I'll be damned if I can find it.
  77. // OnCreate(), Create(), etc, as added by ClassWizard do not hook,
  78. // place it here for now.
  79. /////////////////////////////////////////////////////////////////////////////
  80. void LListCtrl::OnInsertitem(NMHDR* pNMHDR, LRESULT* pResult)
  81. {
  82. ListView_SetExtendedListViewStyle(m_hWnd,LVS_EX_FULLROWSELECT);
  83. }
  84. // hard coded margins in inches and pixels:
  85. #define PRINTMARGIN_Y 0.50
  86. #define PRINTMARGIN_X 0.50
  87. #define PRINTMARGINY ((int)((double)pDC->GetDeviceCaps(LOGPIXELSY)*PRINTMARGIN_Y))
  88. #define PRINTMARGINX ((int)((double)pDC->GetDeviceCaps(LOGPIXELSX)*PRINTMARGIN_X))
  89. #define LINESPACING ((csCharSize.cy * 6)/5)
  90. void LListCtrl::OnPrint(CString strHeader, CString strFooter, DWORD dwFlags)
  91. {
  92. CRect crPrintedPage;
  93. CSize csCharSize;
  94. CPoint cpCurPos;
  95. DWORD dwLinesPerPage;
  96. DWORD dwPagesTotal;
  97. DWORD dwLinesTotal;
  98. CFont Font;
  99. CDC *pDC;
  100. // confirm null-list print:
  101. if( GetItemCount() == 0 && AfxMessageBox( _T( "" ), MB_OKCANCEL | MB_ICONQUESTION) == IDCANCEL )
  102. {
  103. return;
  104. }
  105. // Create and do a print setup dialog (bPrintSetupOnly=TRUE to get a more useful dialog, loses the "print all/select" and "copies" controls):
  106. CPrintDialog dlg(TRUE,PD_ALLPAGES|PD_RETURNDC,NULL);
  107. dlg.m_pd.Flags |= PD_NOSELECTION;
  108. if(dwFlags&LLC_LANDSCAPE)
  109. {
  110. // ((theApp*)AfxGetApp())->SetPortraitLandscape(dlg.m_pd,DMORIENT_LANDSCAPE);
  111. }
  112. if(dlg.DoModal() != IDOK || dlg.m_pd.hDC == NULL)
  113. {
  114. return;
  115. }
  116. // create a new CDC object to access printer device context:
  117. pDC = new CDC;
  118. pDC->Attach(dlg.m_pd.hDC);
  119. // setup a printer font if none provided:
  120. csCharSize.cy = ((pDC->GetDeviceCaps(LOGPIXELSY)*10)/72);
  121. Font.CreateFont(-((int)csCharSize.cy),0,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET
  122. ,OUT_CHARACTER_PRECIS,CLIP_CHARACTER_PRECIS,
  123. DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, _T( "Courier New" ) );
  124. // activate the printer font:
  125. CFont *pOldFont = pDC->SelectObject(&Font);
  126. // get size, lines/page, and page count:
  127. TEXTMETRIC tm;
  128. pDC->GetTextMetrics(&tm);
  129. csCharSize.cx = tm.tmAveCharWidth;
  130. csCharSize.cy = tm.tmHeight + tm.tmExternalLeading;
  131. dwLinesTotal = GetItemCount();
  132. dwLinesPerPage = (pDC->GetDeviceCaps(VERTRES) - 2*PRINTMARGINY - 3*LINESPACING) / LINESPACING;
  133. dwPagesTotal = max(1,(dwLinesTotal + (dwLinesPerPage-1))/dwLinesPerPage);
  134. crPrintedPage.left = PRINTMARGINX;
  135. crPrintedPage.right = pDC->GetDeviceCaps(HORZRES) - PRINTMARGINX;
  136. crPrintedPage.top = PRINTMARGINY;
  137. crPrintedPage.bottom = pDC->GetDeviceCaps(VERTRES) - PRINTMARGINY;
  138. // prep for printing:
  139. pDC->StartDoc( _T( "Error Stack Document" ) );
  140. // print page loop:
  141. for(DWORD dwPage=0; dwPage<dwPagesTotal; dwPage++ )
  142. {
  143. pDC->StartPage();
  144. print_header(pDC, crPrintedPage, csCharSize, cpCurPos, strHeader, dwFlags);
  145. // print line loop:
  146. for(DWORD dwLine=0; dwLine<dwLinesPerPage && dwPage*dwLinesPerPage+dwLine<(DWORD)GetItemCount(); dwLine++ )
  147. {
  148. print_line(pDC, crPrintedPage, csCharSize, cpCurPos, dwPage*dwLinesPerPage+dwLine);
  149. }
  150. print_footer(pDC, crPrintedPage, csCharSize, strFooter, dwPage+1, dwPagesTotal);
  151. pDC->EndPage();
  152. }
  153. // end printing:
  154. pDC->EndDoc();
  155. // clean up fonts:
  156. pDC->SelectObject(pOldFont);
  157. Font.DeleteObject();
  158. // clean up CDC:
  159. pDC->DeleteDC();
  160. pDC->Detach();
  161. delete pDC;
  162. }
  163. void LListCtrl::print_header(CDC *pDC,CRect crPrintedPage,CSize csCharSize, CPoint& cpCurPos, CString& strHeader, DWORD dwFlags )
  164. {
  165. CString strTime;
  166. LV_COLUMN lvcColumn;
  167. DWORD dwColumnWidths=0;
  168. TCHAR pszBuffer[ MAX_PATH ];
  169. int iCol=0;
  170. CRect r;
  171. // format time string for above margin header:
  172. CTime m_ctTime = CTime::GetCurrentTime();
  173. if(!(dwFlags&LLC_HDRNODATE))
  174. {
  175. strTime = m_ctTime.Format("%m/%d/%y");
  176. }
  177. if(!(dwFlags&LLC_HDRNOTIME))
  178. {
  179. if(!(dwFlags&LLC_HDRNODATE))
  180. {
  181. strTime += " - ";
  182. }
  183. strTime += m_ctTime.Format("%I:%M:%S %p");
  184. }
  185. // print it and user supplied header above the margin:
  186. cpCurPos.y = crPrintedPage.top - LINESPACING;
  187. pDC->TextOut(crPrintedPage.left,cpCurPos.y,strHeader);
  188. pDC->TextOut(crPrintedPage.right-pDC->GetTextExtent(strTime).cx,cpCurPos.y,strTime);
  189. cpCurPos.y += LINESPACING;
  190. // underline it:
  191. pDC->MoveTo(crPrintedPage.left,crPrintedPage.top);
  192. pDC->LineTo(crPrintedPage.right,crPrintedPage.top);
  193. // display sub-header as on-screen column headers:
  194. cpCurPos.x = crPrintedPage.left;
  195. cpCurPos.y = crPrintedPage.top + LINESPACING/2;
  196. GetClientRect(&r);
  197. lvcColumn.mask = LVCF_WIDTH | LVCF_FMT | LVCF_TEXT;
  198. lvcColumn.pszText = pszBuffer;
  199. lvcColumn.cchTextMax = MAX_PATH;
  200. while( GetColumn( iCol, &lvcColumn ) )
  201. {
  202. // postition column wise:
  203. cpCurPos.x = crPrintedPage.left + (dwColumnWidths*crPrintedPage.Width())/r.Width();
  204. if(lvcColumn.fmt&LVCFMT_CENTER)
  205. {
  206. cpCurPos.x += (lvcColumn.cx*crPrintedPage.Width())/(2*r.Width());
  207. cpCurPos.x -= pDC->GetTextExtent(lvcColumn.pszText).cx/2;
  208. }
  209. else if(lvcColumn.fmt&LVCFMT_RIGHT)
  210. {
  211. cpCurPos.x += (lvcColumn.cx*crPrintedPage.Width())/r.Width();
  212. cpCurPos.x -= pDC->GetTextExtent(lvcColumn.pszText).cx;
  213. }
  214. // print:
  215. pDC->TextOut(cpCurPos.x,cpCurPos.y,lvcColumn.pszText);
  216. dwColumnWidths += lvcColumn.cx;
  217. iCol++;
  218. }
  219. // underline it:
  220. cpCurPos.y += (3*LINESPACING)/2;
  221. cpCurPos.x = crPrintedPage.left + (dwColumnWidths*crPrintedPage.Width())/r.Width();
  222. pDC->MoveTo(crPrintedPage.left,cpCurPos.y);
  223. pDC->LineTo(crPrintedPage.right,cpCurPos.y);
  224. // prep for first data line:
  225. cpCurPos.y += LINESPACING/2;
  226. }
  227. void LListCtrl::print_line(CDC *pDC, CRect crPrintedPage, CSize csCharSize, CPoint& cpCurPos, DWORD dwLine)
  228. {
  229. LV_COLUMN lvcColumn;
  230. DWORD dwColumnWidths=0;
  231. int iCol=0;
  232. CRect r;
  233. // display item text as on-screen:
  234. GetClientRect(&r);
  235. cpCurPos.x = crPrintedPage.left;
  236. lvcColumn.mask = LVCF_WIDTH | LVCF_FMT;
  237. while( GetColumn( iCol, &lvcColumn ) )
  238. {
  239. // postition column wise:
  240. cpCurPos.x = crPrintedPage.left + (dwColumnWidths*crPrintedPage.Width())/r.Width();
  241. if(lvcColumn.fmt&LVCFMT_CENTER)
  242. {
  243. cpCurPos.x += (lvcColumn.cx*crPrintedPage.Width())/(2*r.Width());
  244. cpCurPos.x -= pDC->GetTextExtent(GetItemText(dwLine,iCol)).cx/2;
  245. }
  246. else if(lvcColumn.fmt&LVCFMT_RIGHT)
  247. {
  248. cpCurPos.x += (lvcColumn.cx*crPrintedPage.Width())/r.Width();
  249. cpCurPos.x -= pDC->GetTextExtent(GetItemText(dwLine,iCol)).cx;
  250. }
  251. // print
  252. pDC->TextOut(cpCurPos.x,cpCurPos.y,GetItemText(dwLine,iCol));
  253. dwColumnWidths += lvcColumn.cx;
  254. iCol++;
  255. }
  256. // advance for next line call:
  257. cpCurPos.y += LINESPACING;
  258. }
  259. void LListCtrl::print_footer(CDC *pDC,CRect crPrintedPage,CSize csCharSize, CString& strFooter, DWORD dwPage, DWORD dwPagesTotal)
  260. {
  261. // overline it:
  262. pDC->MoveTo(crPrintedPage.left,crPrintedPage.bottom);
  263. pDC->LineTo(crPrintedPage.right,crPrintedPage.bottom);
  264. // print user footer:
  265. pDC->TextOut(crPrintedPage.left,crPrintedPage.bottom+LINESPACING,strFooter);
  266. // format footer as page n of N:
  267. CString strPage;
  268. strPage.Format( _T( "%d of %d" ), dwPage, dwPagesTotal );
  269. // print it:
  270. pDC->TextOut(crPrintedPage.right-pDC->GetTextExtent(strPage).cx,crPrintedPage.bottom+LINESPACING,strPage);
  271. }
  272. int LListCtrl::SelectAll()
  273. {
  274. for (int i=0;i<GetItemCount();i++)
  275. {
  276. SetCurSel(i);
  277. }
  278. // Scroll up to the first selected
  279. SetCurSel(0);
  280. SetItemState(-1,LVIS_FOCUSED,LVIS_FOCUSED);
  281. return TRUE;
  282. }
  283. #define VK_C 67
  284. #define VK_V 86
  285. #define VK_X 88
  286. #define VK_Z 90
  287. BOOL LListCtrl::PreTranslateMessage(MSG* pMsg)
  288. {
  289. // If edit control is visible in tree view control, sending a
  290. // WM_KEYDOWN message to the edit control will dismiss the edit
  291. // control. When ENTER key was sent to the edit control, the parent
  292. // window of the tree view control is responsible for updating the
  293. // item's label in TVN_ENDLABELEDIT notification code.
  294. if ( pMsg->message == WM_KEYDOWN )
  295. {
  296. CHAR ckey=toupper( pMsg->wParam &0xFF );
  297. if ( VK_RETURN == pMsg->wParam )
  298. m_bEditNext = TRUE;
  299. if ( VK_ESCAPE == pMsg->wParam )
  300. m_bEditNext = FALSE;
  301. if( GetKeyState( VK_CONTROL )<-1 && (ckey== 'A') )
  302. {
  303. SelectAll();
  304. return TRUE;
  305. }
  306. if( GetKeyState( VK_CONTROL )<-1 && (ckey== 'N') )
  307. {
  308. SelectNone();
  309. return TRUE;
  310. }
  311. CEdit* edit = GetEditControl();
  312. if (edit)
  313. {
  314. // LTRACE("Control key status = %d %d\n",LOBYTE(GetKeyState( VK_CONTROL )),HIWORD(GetKeyState( VK_CONTROL )));
  315. if( GetKeyState( VK_CONTROL )<-1 && (ckey== _T( 'C' ) ) )
  316. {
  317. edit->Copy();
  318. return TRUE;
  319. }
  320. if( GetKeyState( VK_CONTROL )<-1 && (ckey== _T( 'V' ) ) )
  321. {
  322. edit->Paste();
  323. return TRUE;
  324. }
  325. if( GetKeyState( VK_CONTROL )<-1 && (ckey== _T( 'X' ) ) )
  326. {
  327. edit->Cut();
  328. return TRUE;
  329. }
  330. if( GetKeyState( VK_CONTROL )<-1 && (ckey== _T( 'Z' ) ) )
  331. {
  332. edit->Undo();
  333. return TRUE;
  334. }
  335. if( pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_CONTROL || pMsg->wParam == VK_INSERT || pMsg->wParam == VK_SHIFT )
  336. {
  337. edit->SendMessage(WM_KEYDOWN, pMsg->wParam, pMsg->lParam);
  338. return TRUE;
  339. }
  340. }
  341. }
  342. return CListCtrl::PreTranslateMessage(pMsg);
  343. }
  344. int LListCtrl::SelectNone()
  345. {
  346. // -1 changes the state of all items in the list.
  347. return SetItemState(-1, ~LVIS_SELECTED, LVIS_SELECTED);
  348. // return SetCurSel(-1);
  349. }
  350. void LListCtrl::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
  351. {
  352. /*
  353. LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
  354. LV_ITEM *pItem = &pDispInfo->item;
  355. if ( pItem->pszText != NULL )
  356. SetItemText( pItem->iItem, pItem->iSubItem, pItem->pszText );
  357. */
  358. int nFocused = GetNextItem(-1,LVNI_FOCUSED);
  359. // select next item
  360. nFocused++;
  361. // PostMessage( WM_KEYDOWN, 28, 0x1500001 );
  362. // PostMessage( WM_KEYUP, 28, 0x1500001 );
  363. // PostMessage( WM_KEYDOWN, 71, 0x3c0001 );
  364. // PostMessage( WM_KEYUP, 71, 0x3c0001 );
  365. /*
  366. int nCount = GetItemCount();
  367. if ( nFocused < GetItemCount() )
  368. {
  369. // SetFocus( nFocused );
  370. EditLabel( nFocused );
  371. }
  372. */
  373. *pResult = TRUE;
  374. }
  375. CMutex myLockListCtrl;
  376. void LListCtrl::SetHeaderControlText( DWORD dwPos, const CString& strValue )
  377. {
  378. myLockListCtrl.Lock();
  379. if ( m_hWnd )
  380. {
  381. CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl();
  382. ASSERT( dwPos < pHeaderCtrl->GetItemCount() );
  383. HDITEM hdi;
  384. memset( &hdi, 0, sizeof( HDITEM ) );
  385. // Get header item data
  386. pHeaderCtrl->GetItem( dwPos, &hdi );
  387. // modify item data
  388. hdi.pszText = (LPTSTR)(LPCTSTR)strValue;
  389. hdi.mask = HDI_TEXT;
  390. // Set item data
  391. pHeaderCtrl->SetItem( dwPos, &hdi );
  392. }
  393. myLockListCtrl.Unlock();
  394. }
  395. void LListCtrl::OnClick(NMHDR* pNMHDR, LRESULT* pResult)
  396. {
  397. // TODO: Add your control notification handler code here
  398. *pResult = 0;
  399. }