void CTreeWnd::BuildNodeShapes(mtNode* pNode,CRect& area,CRect& clientArea,int indent) { //if (m_pTree && m_pTree->numColumns() > 2) // int x=1; if (area.bottom > clientArea.bottom+DEF_NODE_HEIGHT) return; if (pNode == m_firstVisible->getmtNode()) m_rendering = true; // add shape for ourselves. if (m_rendering) { CRect colArea = area; for (int i = 0; i < m_pTree->numColumns(); i++) { // Shapes are positioned according to column widths. // The tree display column also has indents added // to indicate the hierarchy. // int pos = area.left; for (int col = 0; col < i; col++) pos += m_pHeader->GetPaneWidth(col); colArea.left = pos; colArea.right = colArea.left + m_pHeader->GetPaneWidth(i); // Create new shape object and populate it. CShape* pShape = new CShape(); pShape->border.SetPreset(BorderStyleNone); map<int,COLORREF>::iterator cpos = m_colColours.find(i); if (cpos != m_colColours.end()) { pShape->SetFgColour(cpos->second); } else pShape->SetFgColour(m_fgColour); pShape->SetBgColour(m_bgColour); LPCTSTR text = pNode->getText(i); pShape->SetText(text ? text : ""); // don't give NULL text to shapes. if (i == m_treeColumn) { CTreeNode* pTreeNode = NodeFromMTNode(pNode); colArea.left += DEF_LINE_SPACE; pShape->SetData(pNode->getData2()); colArea.left += indent; pShape->SetRect(colArea); colArea.right -= indent; SetNodeShapeIcon(pTreeNode,pShape); //pShape->SetBitmap(m_pImageList); if (pNode->hasChildren()) { CTreeNode* pTreeNode = NodeFromMTNode(pNode); pTreeNode->CalcExpandBoxArea(colArea); } // remove left margin if this is the tree col // pShape->SetMargins(0,0,5,0); } else { pShape->SetData(pNode->getData2()); pShape->SetRect(colArea); CTreeNode* pTreeNode = NodeFromMTNode(pNode); short iconIdx = -1;//pTreeNode->GetColumnIcon(i); if (iconIdx != -1) { pShape->RemoveAllImages(); pShape->AddImage(m_pImageList,iconIdx,CSize(16,16)); pShape->AddProperty(CShape::SP_ALIGN_LEFT); } } // Set shape alignment if we have one for this column. // map<int,DWORD>::iterator mpos = m_colAlignments.find(i); if (mpos != m_colAlignments.end()) { pShape->RemoveProperty( CShape::SP_ALIGN_LEFT | CShape::SP_ALIGN_RIGHT | CShape::SP_ALIGN_CENTRE ); pShape->AddProperty(mpos->second); } m_shapes.push_back(pShape); } } // do children only if expanded. mtNode* pChild = pNode->firstChild(); if (pChild && pNode->isExpanded()) { // Don't indent here is pNode is root and tree style is not MTS_SHOWROOT. // Otherwise tree will indent as if the root was there. We want to pretend // it isn't... indent += DEF_NODE_INDENT; if (m_rendering) area.OffsetRect(0,DEF_NODE_HEIGHT); BuildNodeShapes(pChild,area,clientArea,indent); indent -= DEF_NODE_INDENT; } // do first sibling only. rest will be done recursively. mtNode* pSib = pNode->nextSibling(); if (pSib) { if (m_rendering) area.OffsetRect(0,DEF_NODE_HEIGHT); BuildNodeShapes(pSib,area,clientArea,indent); } }
void CTreeWnd::Render(CDC* pDC,CRect& area) { //Timer t1; //t1.start(); // Create offscreen dc & bitmap for double buffering. All // tree m_rendering is done to this. CRect ca; GetClientRect(ca); int width = mymax(m_scrollExtents.cx,ca.Width()); CRect ur; GetUpdateRect(ur); //CDC memdc; //memdc.CreateCompatibleDC(pDC); //CBitmap membm; //membm.CreateCompatibleBitmap(pDC,width,ca.Height()); //CBitmap* pOldBM = memdc.SelectObject(&membm); //memdc.FillSolidRect(0,0,width,ca.Height(),m_bgColour); CDC* pDrawDC = pDC; //pDrawDC->FillSolidRect(area,m_bgColour); // After all the nodes have been drawn, we'll fill in the rest of the space in the // background colour. We use this point to track where we've drawn. CPoint bottomRight = CPoint(-1,-1); CFont* pOldFont = (CFont*)pDrawDC->SelectStockObject(DEFAULT_GUI_FONT); int nodesrendered=0; bool currNodeSelected = false; int xidx = 0; vector<CShape*>::iterator pos; CShape* pPrevShape = NULL; for (pos = m_shapes.begin(); pos != m_shapes.end(); ++pos) { CShape *pShape = *pos; CRect inter; if (inter.IntersectRect(area,*pShape)) { CTreeNode* pNode = NodeFromShape(pShape); if (pNode && pNode->isSelected() && ( (xidx % m_pTree->numColumns()) >= m_treeColumn) ) { // TODO: get from prefs sytem. if (GetFocus() == this) pShape->SetBgColour(GetSysColor(COLOR_HIGHLIGHT)); else pShape->SetBgColour(RGB(192,192,192)); pShape->SetFgColour(RGB(255,255,255)); } else { pShape->SetBgColour(m_bgColour); } if ( (xidx % m_pTree->numColumns()) == m_treeColumn) { // Fill the connecting lines area in, to make sure // we're drawing every single pixel. // TODO: prevent flickering here. CRect a = *pShape; //if (pPrevShape) // a.left = pPrevShape->right; //else a.left = area.left; pDrawDC->FillSolidRect(a,m_bgColour); OnSetNodeDisplayProperties(pDrawDC,pNode); SetNodeShapeIcon(pNode,pShape); if (!pNode->isSelected()) pShape->SetFgColour(pNode->GetFgColour()); pNode->Draw(pDrawDC,*pShape); if (pNode == m_selection.GetFocusItem()) { pShape->Draw(pDrawDC); // pShape->RemoveProperty(CShape::SP_FOCUS_BORDER); } else pShape->Draw(pDrawDC); } else // non-tree columns { pShape->Draw(pDrawDC); } if (pShape->right > bottomRight.x) bottomRight.x = pShape->right; if (pShape->bottom > bottomRight.y) bottomRight.y = pShape->bottom; nodesrendered++; } xidx++; pPrevShape = pShape; } // Now fill in the blank area CRect emptySpace; emptySpace.left = bottomRight.x; emptySpace.top = area.top; emptySpace.right = area.right; emptySpace.bottom = area.bottom; pDrawDC->FillSolidRect(emptySpace,m_bgColour); // right emptySpace.left = area.left; emptySpace.top = bottomRight.y; emptySpace.right = bottomRight.x; emptySpace.bottom = area.bottom; pDrawDC->FillSolidRect(emptySpace,m_bgColour); // right //t1.stop(); //TRACE("TREE %x: Rendered %d nodes in %s\n",this,nodesrendered,t1.format().c_str()); pDrawDC->SelectObject(pOldFont); //int desty = area.top; //if (m_style & MTS_HEADER) // desty += DEF_HDR_HEIGHT; // blt to screen //int sp = GetScrollPos(SB_HORZ); //pDC->BitBlt(area.left,area.top,area.Width(),area.Height(),&memdc,area.left+sp,area.top,SRCCOPY); // clean up //memdc.SelectObject(&pOldBM); //memdc.DeleteDC(); //membm.DeleteObject(); }