/// <summary> /// Paint the node in the expanded mode /// </summary> /// <param name="oNode"></param> /// <param name="nX"></param> /// <param name="nY"></param> /// <param name="oGraphics"></param> private void PaintNodeExpanded(Node oNode, Graphics oGraphics, ref int nX, ref int nY, int Width, ref Hashtable m_mapSubItemToRect, ref Hashtable m_mapRectToSubItem, ref Hashtable m_mapRectToItemBox, ref Hashtable m_mapItemBoxToRect, ref Hashtable m_mapRectToItemCheck, ref Hashtable m_mapItemCheckToRect, ref Hashtable m_mapRectToItemFlag, ref Hashtable m_mapItemFlagToRect) { int nXAdd = 0; //if (oNode.GetShowPlusMinus() == false) // nXAdd = 15; if (oNode.GetCheckBoxes() == true && oNode.CheckBoxVisible == true) nXAdd -= 18; int nodeSpace = 0; if (oNode.IndentLevel != 0) nodeSpace = m_oTreeView.Style.NodeSpaceHorizontal; int height = oNode.GetHeight(oGraphics); Rectangle oNodeRect = new Rectangle(nX - nXAdd +nodeSpace, nY, Width - nX - 5 + nXAdd - nodeSpace, height); if (m_oTreeView.Style.FullRowSelect == false && oNode.Panel == null) { oNodeRect = new Rectangle(nX - nXAdd + nodeSpace, nY, oNode.GetWidth(oGraphics), height); } // render the background if (oNode.BackgroundStyle != null && oNode.BackgroundStyle.Visible == true) { int width = oNode.GetTreeView().Width - oNodeRect.Left - nXAdd - m_oTreeView.GetScrollBarWidth() - oNode.IndentLevel - 4; AreaPainter.PaintRectangle(oGraphics, oNodeRect.Left + 1 + nXAdd, oNodeRect.Top - 1, width, oNode.GetFullHeight(oGraphics) - 1, oNode.BackgroundStyle.FillStyle, oNode.BackgroundStyle.BackColor, oNode.BackgroundStyle.FadeColor, BorderStyle.None, Color.White); } oNode.NodeOrder = m_nNodeOrder; m_nNodeOrder ++; // get the order of the actual group. calculate the bottom nY of the group, if the current nY is bigger than // this calculated nY, then skip the drawing and donot draw the object int nMaxY = oNode.TreeView.Height; int nGroupY = -height; // create the item rect and add it to maps try {m_mapSubItemToRect.Add(oNode, oNodeRect);} catch{} try {m_mapRectToSubItem.Add(oNodeRect, oNode);} catch{} oNode.Top = oNodeRect.Top + oNodeRect.Height + 1; oNode.Left = oNodeRect.Left; oNode.Width = oNodeRect.Width - m_oTreeView.GetScrollBarWidth(); SizeF oTextSize = oGraphics.MeasureString(oNode.GetText(), oNode.GetFont(), oNode.GetTreeView().GetDrawWidth() - nX - 8); if (m_oTreeView.Multiline == false) oTextSize = oGraphics.MeasureString(oNode.GetText(), oNode.GetFont()); oNode.Top = nY + (int)oTextSize.Height + 2; if ((nY >= nGroupY && nY < nMaxY) || oNode.TreeView.IsDesignMode == true) { // draw flag PaintNodeFlag(oNode, oGraphics, oNodeRect, ref m_mapRectToItemFlag, ref m_mapItemFlagToRect); // draw selected background PaintNodeBackground(oNode, oGraphics, oNodeRect); // draw design selection PaintNodeBackgroundDesignSelection(oNode, oGraphics, oNodeRect); // draw expand/collapse boxes if (oNode.GetShowPlusMinus() == true) PaintExpandBox(oNode, oGraphics, nX + nodeSpace, nY, ref m_mapRectToItemBox, ref m_mapItemBoxToRect); // draw lines between nodes PaintNodeLines(oNode, oGraphics, nX + nodeSpace, nY, m_mapItemBoxToRect, m_mapSubItemToRect); // draw item header PaintNodeText(oNode, oGraphics, nX + nodeSpace, nY, ref m_mapRectToItemCheck, ref m_mapItemCheckToRect); // check the design time highlight if (oNode.DesignHighlighted) { if (oNode.GetCheckBoxes() == false) { if (m_oTreeView.Style.FullRowSelect == true || oNode.Panel != null) { oGraphics.DrawRectangle(Pens.Black, oNodeRect.Left + 2, oNodeRect.Top - 1, Width - oNodeRect.Left - 7 - m_oTreeView.GetScrollBarWidth(), oNodeRect.Height - 2); } else { oGraphics.DrawRectangle(Pens.Black, oNodeRect.Left + 2, oNodeRect.Top - 1, (int)oNodeRect.Width, oNodeRect.Height - 2); } } else { if (oNode.CheckBoxVisible == true) { if (m_oTreeView.Style.FullRowSelect == true || oNode.Panel != null) { oGraphics.DrawRectangle(Pens.Black, oNodeRect.Left, oNodeRect.Top - 1, Width - oNodeRect.Left - 7 - m_oTreeView.GetScrollBarWidth() + 2, oNodeRect.Height - 2); } else { oGraphics.DrawRectangle(Pens.Black, oNodeRect.Left, oNodeRect.Top - 1, (int)oNodeRect.Width, oNodeRect.Height - 2); } } } } } // for the nodes being drawn before the visible area, but still needed for the // lines painting if (nY < nGroupY && oNode.TreeView.IsDesignMode == false) { // draw expand/collapse boxes PaintExpandBox(oNode, oGraphics, nX + nodeSpace, nY, ref m_mapRectToItemBox, ref m_mapItemBoxToRect); } // for the nodes being at the position under the drawing visible area, draw the lines // so it is visible that there are some other child nodes even they are not visible if (nY > nMaxY && oNode.TreeView.IsDesignMode == false) { // draw expand/collapse boxes PaintExpandBox(oNode, oGraphics, nX + nodeSpace, nY, ref m_mapRectToItemBox, ref m_mapItemBoxToRect); // draw lines between nodes PaintNodeLines(oNode, oGraphics, nX + nodeSpace, nY, m_mapItemBoxToRect, m_mapSubItemToRect); } nY += height; nY += m_oTreeView.Style.NodeSpaceVertical; // draw all subitems if (oNode.TreeView.Sorted == true) { ArrayList aList = new ArrayList(); foreach (Node oSubNode in oNode.Nodes) aList.Add(oSubNode); aList.Sort(); for (int nNode = 0; nNode < aList.Count; nNode ++) { Node oSubNode = aList[nNode] as Node; if (oSubNode == null || oSubNode.Visible == false) continue; int nOldNX = nX; nX += 12; nX += nodeSpace; PaintNode(oSubNode, oGraphics, ref nX, ref nY, Width, ref m_mapSubItemToRect, ref m_mapRectToSubItem, ref m_mapRectToItemBox, ref m_mapItemBoxToRect, ref m_mapRectToItemCheck, ref m_mapItemCheckToRect, ref m_mapRectToItemFlag, ref m_mapItemFlagToRect); nX = nOldNX; } } else { // sort the nodes by the m_nCollectionOrder // SortedList aList = new SortedList(); foreach (Node oSubNode in oNode.Nodes) { if (oSubNode.m_nCollectionOrder == -1) oSubNode.m_nCollectionOrder = oSubNode.Index; // try // { // aList.Add(oSubNode.m_nCollectionOrder, oSubNode); // } // catch // { // aList.Add(oSubNode.Index, oSubNode); // } } // for (int nNode = 0; nNode < aList.Count; nNode ++) Node [] aList = oNode.Nodes.GetNodesCollectionSorted(); for (int nNode = 0; nNode < aList.Length; nNode ++) { //Node oSubNode = aList.GetByIndex(nNode) as Node; Node oSubNode = aList[nNode] as Node; if (oSubNode.Visible == false) continue; int nOldNX = nX; nX += 12; nX += nodeSpace; PaintNode(oSubNode, oGraphics, ref nX, ref nY, Width, ref m_mapSubItemToRect, ref m_mapRectToSubItem, ref m_mapRectToItemBox, ref m_mapItemBoxToRect, ref m_mapRectToItemCheck, ref m_mapItemCheckToRect, ref m_mapRectToItemFlag, ref m_mapItemFlagToRect); nX = nOldNX; } } }
/// <summary> /// Paint the node text /// </summary> /// <param name="oNode"></param> /// <param name="oGraphics"></param> /// <param name="nX"></param> /// <param name="nY"></param> private void PaintNodeText(Node oNode, Graphics oGraphics, int nX, int nY, ref Hashtable m_mapRectToItemCheck, ref Hashtable m_mapItemCheckToRect) { int nAlpha = oNode.TreeView.GetNodeAlpha(oNode); Font oFont = oNode.GetFont(); if (oNode.Flash == true) nAlpha = 255; //if (oNode.GetShowPlusMinus() == false) // nX -= 15; SizeF oTextSize = oGraphics.MeasureString(oNode.GetText(), oNode.GetFont(), oNode.GetTreeView().GetDrawWidth() - nX - 8); if (m_oTreeView.Multiline == false) oTextSize = oGraphics.MeasureString(oNode.GetText(), oFont); oNode.Top = nY + (int)oTextSize.Height + 2; int nTextWidth = (int)oTextSize.Width; oNode.TextWidth = nTextWidth; if (oTextSize.Height == 0) { oTextSize.Height = oNode.GetFont().Height; } // draw check boxes if (oNode.GetCheckBoxes() == true && oNode.CheckBoxVisible == true) { Pen oPen = null; if (oNode.Flash == true) nAlpha = 255; #region draw check background if (oNode.GetCheckBackColor() != Color.Transparent) { if (oNode.Parent == null || oNode.Parent.SubNodesCheckExclusive == false) { Rectangle rectCheckBack = new Rectangle(nX + 4, nY + 2, 11, 11); Color backColor = Color.FromArgb(nAlpha, oNode.GetCheckBackColor()); Brush brush = new SolidBrush(backColor); if (oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.XP) { Color fadeColor = oNode.GetCheckBackColor(); if (fadeColor == Color.White) fadeColor = Color.LightGray; brush = new LinearGradientBrush ( rectCheckBack, Color.FromArgb(nAlpha == 255 ? 255 : 48, fadeColor), Color.White, LinearGradientMode.ForwardDiagonal ); } oGraphics.FillRectangle(brush, rectCheckBack); brush.Dispose(); brush = null; } else { Rectangle rectCheckBack = new Rectangle(nX + 4, nY + 2, 11, 11); Color backColor = Color.FromArgb(nAlpha, oNode.GetCheckBackColor()); Brush brush = new SolidBrush(backColor); if (oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.XP) { Color fadeColor = oNode.GetCheckBackColor(); if (fadeColor == Color.White) fadeColor = Color.LightGray; brush = new LinearGradientBrush ( rectCheckBack, Color.FromArgb(nAlpha == 255 ? 255 : 48, fadeColor), Color.White, LinearGradientMode.ForwardDiagonal ); } GraphicsPath path = new GraphicsPath(); path.AddEllipse(nX + 4, nY + 2, 10, 10); Region region = new Region(path); oGraphics.Clip = region; oGraphics.FillRectangle(brush, rectCheckBack); oGraphics.Clip = new Region(new Rectangle(0, 0, m_oTreeView.Width, m_oTreeView.Height)); brush.Dispose(); brush = null; } } #endregion oPen = new Pen(Color.FromArgb(nAlpha, oNode.GetCheckBorderColor()), 1); Rectangle rectCheck = new Rectangle(nX + 3, nY + 1, 12, 12); #region draw check rectangle if (oNode.Parent == null || oNode.Parent.SubNodesCheckExclusive == false) { if (oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.Solid || oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.XP) oGraphics.DrawRectangle(oPen, rectCheck); if (oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.Dot) { oPen.DashStyle = DashStyle.Dot; oGraphics.DrawRectangle(oPen, rectCheck); } } else { if (oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.Dot) oPen.DashStyle = DashStyle.Dot; if (oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.Solid || oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.XP || oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.Dot) oGraphics.DrawEllipse(oPen, nX + 4, nY + 2, 10, 10); } oPen.DashStyle = DashStyle.Solid; #endregion m_mapItemCheckToRect.Add(oNode, rectCheck); m_mapRectToItemCheck.Add(rectCheck, oNode); if (oNode.Checked == true) { if (oNode.Parent == null || oNode.Parent.SubNodesCheckExclusive == false) { oPen.Color = Color.FromArgb(nAlpha, oNode.GetCheckCheckColor()); oGraphics.DrawLine(oPen, nX + 6, nY + 6, nX + 6, nY + 8); oGraphics.DrawLine(oPen, nX + 7, nY + 7, nX + 7, nY + 9); oGraphics.DrawLine(oPen, nX + 8, nY + 8, nX + 8, nY + 10); oGraphics.DrawLine(oPen, nX + 9, nY + 7, nX + 9, nY + 9); oGraphics.DrawLine(oPen, nX + 10, nY + 6, nX + 10, nY + 8); oGraphics.DrawLine(oPen, nX + 11, nY + 5, nX + 11, nY + 7); oGraphics.DrawLine(oPen, nX + 12, nY + 4, nX + 12, nY + 6); } else { oPen.Color = Color.FromArgb(nAlpha, oNode.GetCheckCheckColor()); oGraphics.DrawEllipse(oPen, nX + 6, nY + 4, 6, 6); oGraphics.DrawEllipse(oPen, nX + 7, nY + 5, 4, 4); oGraphics.DrawEllipse(oPen, nX + 8, nY + 6, 2, 2); oGraphics.DrawEllipse(oPen, nX + 9, nY + 7, 1, 1); oGraphics.DrawRectangle(oPen, nX + 8, nY + 6, 2, 2); } } oPen.Dispose(); nX += 17; } // paint the picture first if needed then draw the text if (oNode.Image != null) { oGraphics.DrawImage(oNode.Image, nX + 4, nY + (int)(oTextSize.Height / 2.0) - (int)((float)oNode.Image.Height / 2.0) + 1, oNode.Image.Width, oNode.Image.Height); nX += oNode.Image.Width + 2; } else { if (oNode.ImageIndex != -1 && oNode.TreeView.ImageList != null && oNode.ImageIndex < oNode.TreeView.ImageList.Images.Count) { oNode.TreeView.ImageList.Draw(oGraphics, nX + 2, nY + (int)(oTextSize.Height / 2.0) - (int)((float)oNode.TreeView.ImageList.ImageSize.Height / 2.0), oNode.TreeView.ImageList.ImageSize.Width, oNode.TreeView.ImageList.ImageSize.Height, oNode.ImageIndex); nX += oNode.TreeView.ImageList.ImageSize.Width; } } // get the right side of the text. if it is more far away than the width of the TreeView, truncate the text string sText = oNode.GetText(); // render the text SolidBrush oTextBrush = new SolidBrush(Color.FromArgb(nAlpha, oNode.GetForeColor())); // when draging the mouse over nodes, test if the node is being highlighted if (oNode == oNode.TreeView.HighlightedNode) oTextBrush.Color = oNode.GetHighlightedForeColor(); Rectangle textRect = new Rectangle(nX + 2, nY, oNode.GetTreeView().GetDrawWidth() - nX - 15, (int)oNode.GetTreeView().Height); SizeF textSize = oGraphics.MeasureString(StringDrawUtils.GetInstance().GetTextFromFormattedString(sText), oFont, oNode.GetTreeView().GetDrawWidth() - nX - 15); // clear the truncated flag oNode.TextTruncated = false; if (m_oTreeView.Multiline) { if (oNode.UseFormatting == true) { CharacterFormat chrFormat = new CharacterFormat( oFont, oTextBrush, 0, HotkeyPrefix.None, true); ParagraphFormat paraFormat = new ParagraphFormat( ParagraphAlignment.Left, ParagraphVerticalAlignment.Top, true, true, StringTrimming.None, Brushes.Transparent); StringDrawUtils.GetInstance().DrawStringInRectangle(oGraphics, sText, textRect, chrFormat, paraFormat); } else oGraphics.DrawString(sText, oFont, oTextBrush, textRect); } else { sText = oNode.GetText(); oTextSize = oGraphics.MeasureString(StringDrawUtils.GetInstance().GetTextFromFormattedString(sText), oFont); nTextWidth = (int)oTextSize.Width; if (nX + 2 + nTextWidth > m_oTreeView.m_LastNX) m_oTreeView.m_LastNX = nX + 2 + nTextWidth; if (nX + nTextWidth > oNode.GetTreeView().GetDrawWidth() - 15) { sText = StringDrawUtils.GetInstance().GetTextFromFormattedString(sText); float fChar = oTextSize.Width / float.Parse(sText.Length.ToString()); int nChar = (int)((float)(nX + nTextWidth - oNode.GetTreeView().GetDrawWidth() + 15) / fChar) + 4; if (nChar < 0) nChar = 0; int nLength = sText.Length - nChar; if (nLength < 0) nLength = 0; sText = sText.Substring(0, nLength) + "..."; oNode.TextTruncated = true; } // draw string (text) of the node in the proper system, based on the information whether it has formatting or not if (oNode.UseFormatting == true) { CharacterFormat chrFormat = new CharacterFormat( oFont, oTextBrush, 0, HotkeyPrefix.None, true); StringDrawUtils.GetInstance().DrawString(oGraphics, sText, new PointF(nX + 2, nY), chrFormat, ParagraphAlignment.Left); } else oGraphics.DrawString(sText, oFont, oTextBrush, nX + 2, nY); } if (m_oTreeView.Multiline == false) textSize = oGraphics.MeasureString(StringDrawUtils.GetInstance().GetTextFromFormattedString(sText), oFont); oTextBrush.Dispose(); // create the expand icon if specified if (oNode.GetShowSubitemsIndicator() == true && oNode.Nodes.Count > 0 && oNode.IsExpanded == false) { int nIconX = (int)textRect.Left + (int)textSize.Width + 4; Pen oIndicatorPen = new Pen(Color.FromArgb(nAlpha, oNode.GetForeColor()), 1); oGraphics.DrawLine(oIndicatorPen, nIconX, nY + textSize.Height - 4, nIconX + 3, nY + textSize.Height - 4); oGraphics.DrawLine(oIndicatorPen, nIconX + 1, nY + textSize.Height - 5, nIconX + 3, nY + textSize.Height - 5); oGraphics.DrawLine(oIndicatorPen, nIconX + 2, nY + textSize.Height - 6, nIconX + 3, nY + textSize.Height - 6); oGraphics.DrawLine(oIndicatorPen, nIconX + 3, nY + textSize.Height - 6, nIconX + 3, nY + textSize.Height - 7); oIndicatorPen.Dispose(); } if (oNode.Underline == true) PaintNodeUnderline(oNode, sText, oGraphics, nX, nY); }