3 // Copyright (C) 1998-2001 Scott Ramsay
5 // http://www.gonavi.com
7 // This material is provided "as is", with absolutely no warranty expressed
8 // or implied. Any use is at your own risk.
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.
16 // If you use this code, drop me an email. I'd like to know if you find the code
20 #include "../../../idlib/precompiled.h"
25 #include "PropTreeItem.h"
27 #define PROPTREEITEM_DEFHEIGHT 21 // default heigt of an item
28 #define PROPTREEITEM_SPACE 5 // default horz spacing
29 #define PROPTREEITEM_EXPANDBOX 9 // size of the expand box
30 #define PROPTREEITEM_CHECKBOX 14 // size of the check box
31 #define PROPTREEITEM_EXPANDCOLUMN 16 // width of the expand column
32 #define PNINDENT 16 // child level indent
34 #define PROPTREEITEM_EXPANDBOXHALF (PROPTREEITEM_EXPANDBOX/2)
37 /////////////////////////////////////////////////////////////////////////////
38 // drawing helper functions
41 // draw a dotted horizontal line
42 static void _DotHLine(HDC hdc, LONG x, LONG y, LONG w)
44 for (; w>0; w-=2, x+=2)
45 SetPixel(hdc, x, y, GetSysColor(COLOR_BTNSHADOW));
49 // draw the plus/minus button
50 static void _DrawExpand(HDC hdc, LONG x, LONG y, BOOL bExpand, BOOL bFill)
56 hPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
57 oPen = (HPEN)SelectObject(hdc, hPen);
58 oBrush = (HBRUSH)SelectObject(hdc, GetStockObject(bFill ? WHITE_BRUSH : NULL_BRUSH));
60 Rectangle(hdc, x, y, x + PROPTREEITEM_EXPANDBOX, y + PROPTREEITEM_EXPANDBOX);
61 SelectObject(hdc, GetStockObject(BLACK_PEN));
65 MoveToEx(hdc, x + PROPTREEITEM_EXPANDBOXHALF, y + 2, NULL);
66 LineTo(hdc, x + PROPTREEITEM_EXPANDBOXHALF, y + PROPTREEITEM_EXPANDBOX - 2);
69 MoveToEx(hdc, x + 2, y + PROPTREEITEM_EXPANDBOXHALF, NULL);
70 LineTo(hdc, x + PROPTREEITEM_EXPANDBOX - 2, y + PROPTREEITEM_EXPANDBOXHALF);
72 SelectObject(hdc, oPen);
73 SelectObject(hdc, oBrush);
77 /////////////////////////////////////////////////////////////////////////////
81 CPropTreeItem::CPropTreeItem() :
93 m_rcCheckbox(0,0,0,0),
103 CPropTreeItem::~CPropTreeItem()
108 BOOL CPropTreeItem::IsExpanded()
110 return (m_dwState & TreeItemExpanded) ? TRUE : FALSE;
114 BOOL CPropTreeItem::IsSelected()
116 return (m_dwState & TreeItemSelected) ? TRUE : FALSE;
120 BOOL CPropTreeItem::IsChecked()
122 return (m_dwState & TreeItemChecked) ? TRUE : FALSE;
126 BOOL CPropTreeItem::IsReadOnly()
128 return (m_dwState & TreeItemReadOnly) ? TRUE : FALSE;
132 BOOL CPropTreeItem::IsActivated()
134 return (m_dwState & TreeItemActivated) ? TRUE : FALSE;
138 void CPropTreeItem::Select(BOOL bSelect)
141 m_dwState |= TreeItemSelected;
143 m_dwState &= ~TreeItemSelected;
147 void CPropTreeItem::Expand(BOOL bExpand)
150 m_dwState |= TreeItemExpanded;
152 m_dwState &= ~TreeItemExpanded;
156 void CPropTreeItem::Check(BOOL bCheck)
159 m_dwState |= TreeItemChecked;
161 m_dwState &= ~TreeItemChecked;
165 void CPropTreeItem::ReadOnly(BOOL bReadOnly)
168 m_dwState |= TreeItemReadOnly;
170 m_dwState &= ~TreeItemReadOnly;
174 BOOL CPropTreeItem::IsCheckBox()
176 return (m_dwState & TreeItemCheckbox) ? TRUE : FALSE;
180 void CPropTreeItem::HasCheckBox(BOOL bCheckbox)
183 m_dwState |= TreeItemCheckbox;
185 m_dwState &= ~TreeItemCheckbox;
189 BOOL CPropTreeItem::HitExpand(const POINT& pt)
191 return m_rcExpand.PtInRect(pt);
195 BOOL CPropTreeItem::HitCheckBox(const POINT& pt)
197 return m_rcCheckbox.PtInRect(pt);
201 BOOL CPropTreeItem::IsRootLevel()
203 ASSERT(m_pProp!=NULL);
204 return GetParent() == m_pProp->GetRootItem();
208 LONG CPropTreeItem::GetTotalHeight()
210 CPropTreeItem* pItem;
213 nHeight = GetHeight();
217 for (pItem = GetChild(); pItem; pItem = pItem->GetSibling())
218 nHeight += pItem->GetTotalHeight();
225 void CPropTreeItem::SetLabelText(LPCTSTR sLabel)
231 LPCTSTR CPropTreeItem::GetLabelText()
237 void CPropTreeItem::SetInfoText(LPCTSTR sInfo)
243 LPCTSTR CPropTreeItem::GetInfoText()
249 void CPropTreeItem::SetCtrlID(UINT nCtrlID)
255 UINT CPropTreeItem::GetCtrlID()
261 LONG CPropTreeItem::GetHeight()
263 return PROPTREEITEM_DEFHEIGHT;
267 LPARAM CPropTreeItem::GetItemValue()
269 // no items are assocatied with this type
274 void CPropTreeItem::SetItemValue(LPARAM)
276 // no items are assocatied with this type
280 void CPropTreeItem::OnMove()
282 // no attributes, do nothing
286 void CPropTreeItem::OnRefresh()
288 // no attributes, do nothing
292 void CPropTreeItem::OnCommit()
294 // no attributes, do nothing
298 void CPropTreeItem::Activate(int activateType, CPoint point)
301 m_bCommitOnce = FALSE;
303 OnActivate(activateType, point);
307 void CPropTreeItem::CommitChanges()
309 m_bActivated = FALSE;
314 m_bCommitOnce = TRUE;
316 ASSERT(m_pProp!=NULL);
320 m_pProp->SendNotify(PTN_ITEMCHANGED, this);
321 m_pProp->RefreshItems(this);
325 void CPropTreeItem::OnActivate(int activateType, CPoint point)
327 // no attributes, do nothing
331 void CPropTreeItem::SetPropOwner(CPropTree* pProp)
337 const POINT& CPropTreeItem::GetLocation()
343 CPropTreeItem* CPropTreeItem::GetParent()
349 CPropTreeItem* CPropTreeItem::GetSibling()
355 CPropTreeItem* CPropTreeItem::GetChild()
361 CPropTreeItem* CPropTreeItem::GetNextVisible()
367 void CPropTreeItem::SetParent(CPropTreeItem* pParent)
373 void CPropTreeItem::SetSibling(CPropTreeItem* pSibling)
375 m_pSibling = pSibling;
379 void CPropTreeItem::SetChild(CPropTreeItem* pChild)
385 void CPropTreeItem::SetNextVisible(CPropTreeItem* pVis)
391 LONG CPropTreeItem::DrawItem(CDC* pDC, const RECT& rc, LONG x, LONG y)
394 LONG nTotal, nCol, ey;
397 ASSERT(m_pProp!=NULL);
399 // Add TreeItem the list of visble items
400 m_pProp->AddToVisibleList(this);
402 // store the item's location
403 m_loc = CPoint(x, y);
405 // store the items rectangle position
406 m_rc.SetRect(m_pProp->GetOrigin().x + PROPTREEITEM_SPACE, m_loc.y, rc.right, m_loc.y + GetHeight()-1);
407 m_rc.OffsetRect(0, -m_pProp->GetOrigin().y);
409 // init temp drawing variables
410 nTotal = GetHeight();
411 ey = (nTotal >> 1) - (PROPTREEITEM_EXPANDBOX >> 1) - 2;
415 // convert item coordinates to screen coordinates
417 pt.y -= m_pProp->GetOrigin().y;
418 nCol = m_pProp->GetOrigin().x;
421 drc.SetRect(pt.x + PROPTREEITEM_EXPANDCOLUMN, pt.y, rc.right, pt.y + nTotal);
423 drc.SetRect(pt.x + PROPTREEITEM_EXPANDCOLUMN, pt.y, nCol, pt.y + nTotal);
425 // root level items are shaded
428 HGDIOBJ hOld = pDC->SelectObject(GetSysColorBrush(COLOR_BTNFACE));
429 pDC->PatBlt(rc.left, drc.top, rc.right - rc.left + 1, drc.Height(), PATCOPY);
430 pDC->SelectObject(hOld);
433 // calc/draw expand box position
436 m_rcExpand.left = PROPTREEITEM_EXPANDCOLUMN/2 - PROPTREEITEM_EXPANDBOXHALF;
437 m_rcExpand.top = m_loc.y + ey;
438 m_rcExpand.right = m_rcExpand.left + PROPTREEITEM_EXPANDBOX - 1;
439 m_rcExpand.bottom = m_rcExpand.top + PROPTREEITEM_EXPANDBOX - 1;
442 ir.OffsetRect(0, -m_pProp->GetOrigin().y);
443 _DrawExpand(pDC->m_hDC, ir.left, ir.top, IsExpanded(), !IsRootLevel());
446 m_rcExpand.SetRectEmpty();
448 // calc/draw check box position
453 ir.left = drc.left + PROPTREEITEM_SPACE;
454 ir.top = m_loc.y + ey;
456 ir.right = ir.left + PROPTREEITEM_CHECKBOX;
457 ir.bottom = ir.top + PROPTREEITEM_CHECKBOX;
462 m_rcCheckbox.SetRectEmpty();
466 // create a clipping region for the label
469 hRgn = CreateRectRgn(drc.left, drc.top, drc.right, drc.bottom);
470 SelectClipRgn(pDC->m_hDC, hRgn);
473 // calc label position
475 ir.left += PROPTREEITEM_SPACE;
477 // offset the label text if item has a check box
479 OffsetRect(&ir, PROPTREEITEM_CHECKBOX + PROPTREEITEM_SPACE * 2, 0);
482 if (!m_sLabel.IsEmpty())
485 pDC->SelectObject(CPropTree::GetBoldFont());
487 pDC->SelectObject(CPropTree::GetNormalFont());
489 pDC->SetTextColor(GetSysColor(COLOR_BTNTEXT));
490 pDC->SetBkMode(TRANSPARENT);
491 pDC->DrawText(m_sLabel, &ir, DT_SINGLELINE|DT_VCENTER|DT_CALCRECT);
493 // draw the text highlighted if selected
496 HGDIOBJ oPen = pDC->SelectObject(GetStockObject(NULL_PEN));
497 HGDIOBJ oBrush = pDC->SelectObject(GetSysColorBrush(COLOR_HIGHLIGHT));
501 dr.left = PROPTREEITEM_EXPANDCOLUMN;
505 pDC->SelectObject(oPen);
506 pDC->SelectObject(oBrush);
508 pDC->SetTextColor(GetSysColor(COLOR_BTNHIGHLIGHT));
511 // check if we need to draw the text as disabled
512 if (!m_pProp->IsWindowEnabled())
513 pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
515 pDC->DrawText(m_sLabel, &ir, DT_SINGLELINE|DT_VCENTER);
518 // draw check box frame
522 ir.OffsetRect(0, -m_pProp->GetOrigin().y);
523 pDC->DrawFrameControl(&ir, DFC_BUTTON, DFCS_BUTTONCHECK | (IsChecked() ? DFCS_CHECKED : 0));
526 // remove clip region
529 SelectClipRgn(pDC->m_hDC, NULL);
533 // draw horzontal sep
534 _DotHLine(pDC->m_hDC, PROPTREEITEM_EXPANDCOLUMN, pt.y + nTotal - 1, rc.right - PROPTREEITEM_EXPANDCOLUMN + 1);
540 CPen pn1(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
543 pOld = pDC->SelectObject(&pn1);
544 pDC->MoveTo(nCol, drc.top);
545 pDC->LineTo(nCol, drc.bottom);
547 CPen pn2(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT));
548 pDC->SelectObject(&pn2);
549 pDC->MoveTo(nCol + 1, drc.top);
550 pDC->LineTo(nCol + 1, drc.bottom);
552 pDC->SelectObject(pOld);
558 // create clip region
559 hRgn = CreateRectRgn(m_rc.left, m_rc.top, m_rc.right, m_rc.bottom);
560 SelectClipRgn(pDC->m_hDC, hRgn);
562 DrawAttribute(pDC, m_rc);
564 SelectClipRgn(pDC->m_hDC, NULL);
569 if (GetChild() && IsExpanded())
573 CPropTreeItem* pNext;
575 for (pNext = GetChild(); pNext; pNext = pNext->GetSibling())
577 LONG nHeight = pNext->DrawItem(pDC, rc, x + (IsRootLevel() ? 0 : PNINDENT), y);
587 void CPropTreeItem::DrawAttribute(CDC*, const RECT&)
589 // no attributes are assocatied with this type