doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PropTreeList.cpp
Go to the documentation of this file.
1 // PropTreeList.cpp : implementation file
2 //
3 // Copyright (C) 1998-2001 Scott Ramsay
4 // sramsay@gonavi.com
5 // http://www.gonavi.com
6 //
7 // This material is provided "as is", with absolutely no warranty expressed
8 // or implied. Any use is at your own risk.
9 //
10 // Permission to use or copy this software for any purpose is hereby granted
11 // without fee, provided the above notices are retained on all copies.
12 // Permission to modify the code and to distribute modified code is granted,
13 // provided the above notices are retained, and a notice that the code was
14 // modified is included with the above copyright notice.
15 //
16 // If you use this code, drop me an email. I'd like to know if you find the code
17 // useful.
18 
19 //#include "stdafx.h"
20 #include "../../../idlib/precompiled.h"
21 #pragma hdrstop
22 
23 #include "PropTree.h"
24 #include "../../../sys/win32/rc/proptree_Resource.h"
25 #include "PropTreeList.h"
26 
27 #ifdef _DEBUG
28 #define new DEBUG_NEW
29 #undef THIS_FILE
30 static char THIS_FILE[] = __FILE__;
31 #endif
32 
33 #define PROPTREEITEM_EXPANDCOLUMN 16 // width of the expand column
34 #define PROPTREEITEM_COLRNG 5 // width of splitter
35 #define PROPTREEITEM_DEFHEIGHT 21 // default heigt of an item
36 
37 extern HINSTANCE ghInst;
38 
40 // CPropTreeList
41 
43  m_pProp(NULL),
44  m_BackBufferSize(0,0),
45  m_bColDrag(FALSE),
46  m_nPrevCol(0)
47 {
48 }
49 
51 {
52 }
53 
54 
55 BEGIN_MESSAGE_MAP(CPropTreeList, CWnd)
56  //{{AFX_MSG_MAP(CPropTreeList)
57  ON_WM_SIZE()
58  ON_WM_PAINT()
59  ON_WM_SETCURSOR()
60  ON_WM_LBUTTONDOWN()
61  ON_WM_LBUTTONUP()
62  ON_WM_LBUTTONDBLCLK()
63  ON_WM_MOUSEMOVE()
64  ON_WM_MOUSEWHEEL()
65  ON_WM_KEYDOWN()
66  ON_WM_GETDLGCODE()
67  ON_WM_VSCROLL()
68  //}}AFX_MSG_MAP
69 END_MESSAGE_MAP()
70 
71 
73 // CPropTreeList message handlers
74 
75 void CPropTreeList::SetPropOwner(CPropTree* pProp)
76 {
77  m_pProp = pProp;
78 }
79 
80 
81 BOOL CPropTreeList::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
82 {
83  CWnd* pWnd = this;
84 
85  LPCTSTR pszCreateClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, ::LoadCursor(NULL, IDC_ARROW));
86 
87  return pWnd->Create(pszCreateClass, _T(""), dwStyle, rect, pParentWnd, nID);
88 }
89 
90 
91 void CPropTreeList::OnSize(UINT nType, int cx, int cy)
92 {
93  CWnd::OnSize(nType, cx, cy);
94 
95  RecreateBackBuffer(cx, cy);
96 
97  if (m_pProp)
98  {
99  UpdateResize();
100  Invalidate();
101  UpdateWindow();
102 
103  // inform all items that a resize has been made
105  }
106 }
107 
108 
110 {
111  if (m_BackBufferSize.cx<cx || m_BackBufferSize.cy<cy)
112  {
113  m_BackBufferSize = CSize(cx, cy);
114 
115  CWindowDC dc(NULL);
116 
117  int nPlanes = dc.GetDeviceCaps(PLANES);
118  int nBitCount = dc.GetDeviceCaps(BITSPIXEL);
119 
120  m_BackBuffer.DeleteObject();
121  m_BackBuffer.CreateBitmap(cx, cy, nPlanes, nBitCount, NULL);
122  }
123 }
124 
125 
127 {
128  SCROLLINFO si;
129  LONG nHeight;
130  CRect rc;
131 
132  ASSERT(m_pProp!=NULL);
133 
134  GetClientRect(rc);
135  nHeight = rc.Height() + 1;
136 
137  ZeroMemory(&si, sizeof(SCROLLINFO));
138  si.cbSize = sizeof(SCROLLINFO);
139  si.fMask = SIF_RANGE|SIF_PAGE;
140  si.nMin = 0;
141  si.nMax = m_pProp->GetRootItem()->GetTotalHeight();
142  si.nPage = nHeight;
143 
144  if ((int)si.nPage>si.nMax)
146 
147  SetScrollInfo(SB_VERT, &si, TRUE);
148 
149  // force set column for clipping
151 }
152 
153 
155 {
156  CPaintDC dc(this);
157  CDC memdc;
158  CBitmap* pOldBitmap;
159 
160  ASSERT(m_pProp!=NULL);
161 
163 
164  memdc.CreateCompatibleDC(&dc);
165  pOldBitmap = memdc.SelectObject(&m_BackBuffer);
166 
167  CRect rc;
168  GetClientRect(rc);
169 
170  // draw control background
171  memdc.SelectObject(GetSysColorBrush(COLOR_BTNFACE));
172  memdc.PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATCOPY);
173 
174  // draw control inside fill color
175  rc.DeflateRect(2,2);
176  memdc.PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), m_pProp->IsWindowEnabled() ? WHITENESS : PATCOPY);
177  rc.InflateRect(2,2);
178 
179  // draw expand column
180  memdc.SelectObject(GetSysColorBrush(COLOR_BTNFACE));
181  memdc.PatBlt(0, 0, PROPTREEITEM_EXPANDCOLUMN, rc.Height(), PATCOPY);
182 
183  // draw edge
184  memdc.DrawEdge(&rc, BDR_SUNKENOUTER, BF_RECT);
185 
186  CPropTreeItem* pItem;
187  LONG nTotal = 0;
188 
189  ASSERT(m_pProp->GetRootItem()!=NULL);
190 
191  rc.DeflateRect(2,2);
192 
193  // create clip region
194  HRGN hRgn = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
195  SelectClipRgn(memdc.m_hDC, hRgn);
196 
197  // draw all items
198  for (pItem = m_pProp->GetRootItem()->GetChild(); pItem; pItem = pItem->GetSibling())
199  {
200  LONG nHeight = pItem->DrawItem(&memdc, rc, 0, nTotal);
201  nTotal += nHeight;
202  }
203 
204  // remove clip region
205  SelectClipRgn(memdc.m_hDC, NULL);
206  DeleteObject(hRgn);
207 
208  // copy back buffer to the display
209  dc.GetClipBox(&rc);
210  dc.BitBlt(rc.left, rc.top, rc.Width(), rc.Height(), &memdc, rc.left, rc.top, SRCCOPY);
211  memdc.DeleteDC();
212 }
213 
214 
215 BOOL CPropTreeList::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
216 {
217  if (nHitTest==HTCLIENT)
218  {
219  CPoint pt;
220 
221  ASSERT(m_pProp!=NULL);
222 
223  GetCursorPos(&pt);
224  ScreenToClient(&pt);
225 
226  switch (m_pProp->HitTest(pt))
227  {
228  case HTCOLUMN:
229  SetCursor(LoadCursor(ghInst, MAKEINTRESOURCE(IDC_SPLITTER)));
230  return TRUE;
231 
232  case HTCHECKBOX:
233  case HTBUTTON:
234  case HTEXPAND:
235  SetCursor(LoadCursor(ghInst, MAKEINTRESOURCE(IDC_FPOINT)));
236  return TRUE;
237  }
238  }
239 
240  return CWnd::OnSetCursor(pWnd, nHitTest, message);
241 }
242 
243 
244 void CPropTreeList::OnLButtonDown(UINT, CPoint point)
245 {
246  ASSERT(m_pProp!=NULL);
247 
248  if (m_pProp->IsDisableInput())
249  return;
250 
251  m_pProp->SendNotify(NM_CLICK);
252 
253  if (!m_pProp->IsWindowEnabled())
254  return;
255 
256  SetFocus();
257 
258  LONG nHit = m_pProp->HitTest(point);
259 
260  CPropTreeItem* pItem;
261  CRect rc;
262  CDC* pDC;
263 
264  switch (nHit)
265  {
266  case HTCOLUMN:
268  break;
269 
270  m_bColDrag = TRUE;
271  SetCapture();
272 
274 
275  // paint drag line
276  pDC = GetDC();
277  GetClientRect(rc);
278  pDC->PatBlt(m_nPrevCol - PROPTREEITEM_COLRNG/2, 0, PROPTREEITEM_COLRNG, rc.bottom, PATINVERT);
279  ReleaseDC(pDC);
280  break;
281 
282  case HTCHECKBOX:
283  if ((pItem = m_pProp->FindItem(point))!=NULL)
284  {
285  pItem->Check(!pItem->IsChecked());
287  Invalidate();
288  }
289  break;
290  case HTBUTTON:
291  if ((pItem = m_pProp->FindItem(point))!=NULL)
292  {
293  pItem->Check();
295  Invalidate();
296  }
297  break;
298  case HTEXPAND:
299  if ((pItem = m_pProp->FindItem(point))!=NULL)
300  {
301  if (pItem->GetChild() && !m_pProp->SendNotify(PTN_ITEMEXPANDING, pItem))
302  {
303  pItem->Expand(!pItem->IsExpanded());
304 
305  UpdateResize();
306  Invalidate();
307  UpdateWindow();
309  }
310  }
311  break;
312 
313  default:
314  if ((pItem = m_pProp->FindItem(point))!=NULL)
315  {
316  CPropTreeItem* pOldFocus = m_pProp->GetFocusedItem();
317 
319  m_pProp->SetFocusedItem(pItem);
320 
321  pItem->Select();
322 
323  Invalidate();
324 
325  if (pItem!=pOldFocus)
327 
328  if (nHit==HTATTRIBUTE && !pItem->IsRootLevel())
329  {
330  if (!m_pProp->SendNotify(PTN_PROPCLICK, pItem) && !pItem->IsReadOnly())
332  }
333  }
334  else
335  {
339  Invalidate();
340  }
341  break;
342  }
343 }
344 
345 
346 void CPropTreeList::OnLButtonUp(UINT, CPoint point)
347 {
348  if (m_bColDrag)
349  {
350  CDC* pDC = GetDC();
351  CRect rc;
352 
353  GetClientRect(rc);
354  pDC->PatBlt(m_nPrevCol - PROPTREEITEM_COLRNG/2, 0, PROPTREEITEM_COLRNG, rc.bottom, PATINVERT);
355  ReleaseDC(pDC);
356 
357  m_bColDrag = FALSE;
358  ReleaseCapture();
359 
360  m_pProp->SetColumn(point.x);
362  Invalidate();
363  } else {
364  LONG nHit = m_pProp->HitTest(point);
365  CPropTreeItem* pItem;
366 
367  switch (nHit)
368  {
369  case HTBUTTON:
370  if ((pItem = m_pProp->FindItem(point))!=NULL)
371  {
372  pItem->Check( FALSE );
373  Invalidate();
374  }
375  break;
376  default:
377  break;
378  }
379  }
380 }
381 
382 
384 {
385  ASSERT(m_pProp!=NULL);
386 
387  m_pProp->SendNotify(NM_DBLCLK);
388 
389  CPropTreeItem* pItem;
390  CPropTreeItem* pOldFocus;
391 
392  if ((pItem = m_pProp->FindItem(point))!=NULL && pItem->GetChild())
393  {
394  switch (m_pProp->HitTest(point))
395  {
396  case HTCOLUMN:
397  break;
398 
399  case HTCHECKBOX:
400  pItem->Check(!pItem->IsChecked());
402  Invalidate();
403  break;
404 
405  case HTATTRIBUTE:
406  if (!pItem->IsRootLevel())
407  break;
408 
409  // pass thru to default
410 
411  default:
412  pOldFocus = m_pProp->GetFocusedItem();
414  m_pProp->SetFocusedItem(pItem);
415  pItem->Select();
416 
417  if (pItem!=pOldFocus)
419 
420  // pass thru to HTEXPAND
421 
422  case HTEXPAND:
423  if (!m_pProp->SendNotify(PTN_ITEMEXPANDING, pItem))
424  {
425  pItem->Expand(!pItem->IsExpanded());
426 
427  UpdateResize();
428  Invalidate();
429  UpdateWindow();
431  }
432  break;
433  }
434  }
435 }
436 
437 
438 void CPropTreeList::OnMouseMove(UINT, CPoint point)
439 {
440  if (m_bColDrag)
441  {
442  CDC* pDC = GetDC();
443  CRect rc;
444 
445  GetClientRect(rc);
446  pDC->PatBlt(m_nPrevCol - PROPTREEITEM_COLRNG/2, 0, PROPTREEITEM_COLRNG, rc.bottom, PATINVERT);
447  pDC->PatBlt(point.x - PROPTREEITEM_COLRNG/2, 0, PROPTREEITEM_COLRNG, rc.bottom, PATINVERT);
448  m_nPrevCol = point.x;
449  ReleaseDC(pDC);
450  }
451 }
452 
453 
454 BOOL CPropTreeList::OnMouseWheel(UINT, short zDelta, CPoint)
455 {
456  SCROLLINFO si;
457 
458  ZeroMemory(&si, sizeof(SCROLLINFO));
459  si.cbSize = sizeof(SCROLLINFO);
460  si.fMask = SIF_RANGE;
461 
462  GetScrollInfo(SB_VERT, &si);
463 
464  CRect rc;
465  GetClientRect(rc);
466 
467  if (si.nMax - si.nMin < rc.Height())
468  return TRUE;
469 
470  SetFocus();
471  OnVScroll(zDelta < 0 ? SB_LINEDOWN : SB_LINEUP, 0, NULL);
472 
473  return TRUE;
474 }
475 
476 
478 {
479 
480  CPropTreeItem* pItem;
481 
482  ASSERT(m_pProp!=NULL);
483 
484  if (m_pProp->IsDisableInput() || !m_pProp->IsWindowEnabled())
485  return;
486 
487  switch (nChar)
488  {
489  case VK_RETURN:
490  if ((pItem = m_pProp->GetFocusedItem())!=NULL && !pItem->IsRootLevel() && !pItem->IsReadOnly())
491  {
492  pItem->Activate(CPropTreeItem::ACTIVATE_TYPE_KEYBOARD, CPoint(0,0));
493  }
494  break;
495 
496  case VK_HOME:
497  if (m_pProp->FocusFirst())
498  Invalidate();
499  break;
500 
501  case VK_END:
502  if (m_pProp->FocusLast())
503  Invalidate();
504  break;
505 
506  case VK_LEFT:
507  if ((pItem = m_pProp->GetFocusedItem())!=NULL)
508  {
509  if (!m_pProp->SendNotify(PTN_ITEMEXPANDING, pItem))
510  {
511  if (pItem->GetChild() && pItem->IsExpanded())
512  {
513  pItem->Expand(FALSE);
514  UpdateResize();
515  Invalidate();
516  UpdateWindow();
518  break;
519  }
520  }
521  }
522  else
523  break;
524  // pass thru to next case VK_UP
525  case VK_UP:
526  if (m_pProp->FocusPrev())
527  Invalidate();
528  break;
529 
530  case VK_RIGHT:
531  if ((pItem = m_pProp->GetFocusedItem())!=NULL)
532  {
533  if (!m_pProp->SendNotify(PTN_ITEMEXPANDING, pItem))
534  {
535  if (pItem->GetChild() && !pItem->IsExpanded())
536  {
537  pItem->Expand();
538  UpdateResize();
539  Invalidate();
540  UpdateWindow();
542  break;
543  }
544  }
545  }
546  else
547  break;
548  // pass thru to next case VK_DOWN
549  case VK_DOWN:
550  if (m_pProp->FocusNext())
551  Invalidate();
552  break;
553  }
554 }
555 
556 
558 {
559  return DLGC_WANTARROWS|DLGC_WANTCHARS|DLGC_WANTALLKEYS;
560 }
561 
562 
563 void CPropTreeList::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar*)
564 {
565  SCROLLINFO si;
566  CRect rc;
567  LONG nHeight;
568 
569  SetFocus();
570 
571  GetClientRect(rc);
572  nHeight = rc.Height() + 1;
573 
574  ZeroMemory(&si, sizeof(SCROLLINFO));
575  si.cbSize = sizeof(SCROLLINFO);
576  si.fMask = SIF_RANGE;
577 
578  GetScrollInfo(SB_VERT, &si);
579 
580  LONG ny = m_pProp->GetOrigin().y;
581 
582  switch (nSBCode)
583  {
584  case SB_LINEDOWN:
586  break;
587 
588  case SB_LINEUP:
590  break;
591 
592  case SB_PAGEDOWN:
593  ny += nHeight;
594  break;
595 
596  case SB_PAGEUP:
597  ny -= nHeight;
598  break;
599 
600  case SB_THUMBTRACK:
601  ny = nPos;
602  break;
603  }
604 
605  ny = __min(__max(ny, si.nMin), si.nMax - nHeight);
606 
608  si.fMask = SIF_POS;
609  si.nPos = ny;
610 
611  SetScrollInfo(SB_VERT, &si, TRUE);
612  Invalidate();
613 }
614 
615 
617 {
618  ASSERT(m_pProp!=NULL);
619 
620  CPropTreeItem* pItem;
621 
622  if ((pItem = m_pProp->GetFocusedItem())==NULL)
623  return;
624 
625  if (!m_pProp->IsItemVisible(pItem))
626  {
627  if (m_pProp->IsSingleSelection())
628  pItem->Select(FALSE);
629 
632 
633  Invalidate();
634  }
635 }
virtual ~CPropTreeList()
afx_msg void OnPaint()
LONG GetColumn()
Definition: PropTree.cpp:391
CPropTreeItem * FocusPrev()
Definition: PropTree.cpp:742
void Select(BOOL bSelect=TRUE)
void Check(BOOL bCheck=TRUE)
const POINT & GetOrigin()
Definition: PropTree.cpp:124
CONST PIXELFORMATDESCRIPTOR UINT
Definition: win_qgl.cpp:47
BOOL IsItemVisible(CPropTreeItem *pItem)
Definition: PropTree.cpp:487
void SelectItems(CPropTreeItem *pItem, BOOL bSelect=TRUE)
Definition: PropTree.cpp:682
virtual LONG DrawItem(CDC *pDC, const RECT &rc, LONG x, LONG y)
#define PROPTREEITEM_EXPANDCOLUMN
CSize m_BackBufferSize
Definition: PropTreeList.h:51
DWORD
Definition: win_qgl.cpp:61
GLfloat ny
Definition: glext.h:4668
afx_msg void OnLButtonUp(UINT nFlags, CPoint point)
CPropTreeItem * FocusNext()
Definition: PropTree.cpp:779
#define PTN_CHECKCLICK
Definition: PropTree.h:106
void RecreateBackBuffer(int cx, int cy)
#define PTN_SELCHANGE
Definition: PropTree.h:102
void SetFocusedItem(CPropTreeItem *pItem)
Definition: PropTree.cpp:464
CPropTreeItem * GetFocusedItem()
Definition: PropTree.cpp:284
#define BOOL
Definition: mprintf.c:71
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point)
afx_msg BOOL OnSetCursor(CWnd *pWnd, UINT nHitTest, UINT message)
afx_msg UINT OnGetDlgCode()
LRESULT SendNotify(UINT nNotifyCode, CPropTreeItem *pItem=NULL)
Definition: PropTree.cpp:860
#define HTBUTTON
Definition: PropTree.h:85
void ClearVisibleList()
Definition: PropTree.cpp:296
LONG GetTotalHeight()
BOOL IsSingleSelection()
Definition: PropTree.cpp:919
#define PTN_PROPCLICK
Definition: PropTree.h:105
CPropTree * m_pProp
Definition: PropTreeList.h:45
afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
#define IDC_FPOINT
CPropTreeItem * GetSibling()
#define NULL
Definition: Lib.h:88
void SetColumn(LONG nColumn)
Definition: PropTree.cpp:397
CPropTreeItem * GetChild()
void SetOriginOffset(LONG nOffset)
Definition: PropTree.cpp:358
CPropTreeItem * GetRootItem()
Definition: PropTree.cpp:290
#define PTN_COLUMNCLICK
Definition: PropTree.h:104
#define PTN_ITEMBUTTONCLICK
Definition: PropTree.h:101
#define HTCHECKBOX
Definition: PropTree.h:84
CBitmap m_BackBuffer
Definition: PropTreeList.h:48
afx_msg void OnLButtonDown(UINT nFlags, CPoint point)
#define IDC_SPLITTER
#define PTN_ITEMEXPANDING
Definition: PropTree.h:103
CPropTreeItem * FocusFirst()
Definition: PropTree.cpp:691
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar)
void Expand(BOOL bExpand=TRUE)
long LONG
#define HTCOLUMN
Definition: PropTree.h:81
#define PROPTREEITEM_COLRNG
#define HTEXPAND
Definition: PropTree.h:82
#define PROPTREEITEM_DEFHEIGHT
#define FALSE
Definition: mprintf.c:70
CPropTreeItem * FindItem(const POINT &pt)
Definition: PropTree.cpp:620
#define TRUE
Definition: mprintf.c:69
void CheckVisibleFocus()
void UpdateMoveAllItems()
Definition: PropTree.cpp:810
void Activate(int activateType, CPoint point)
afx_msg void OnSize(UINT nType, int cx, int cy)
HINSTANCE ghInst
Definition: PropTree.cpp:38
CPropTreeItem * FocusLast()
Definition: PropTree.cpp:712
#define HTATTRIBUTE
Definition: PropTree.h:83
afx_msg void OnMouseMove(UINT nFlags, CPoint point)
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
BOOL Create(DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT nID)
LONG HitTest(const POINT &pt)
Definition: PropTree.cpp:586
BOOL IsDisableInput()
Definition: PropTree.cpp:665