in src/XmlNotepad/NodeTextView.cs [661:815]
private void DrawItem(Rectangle bounds, TreeNode tn, Graphics g)
{
//g.SmoothingMode = SmoothingMode.AntiAlias;
Color c = tn.ForeColor;
Brush myBrush = null;
bool focusSelected = false;
if (this.Focused && tn == this.SelectedNode)
{
focusSelected = true;
g.FillRectangle(SystemBrushes.Highlight, bounds);
myBrush = Brushes.HighlightTextBrush(c);
}
else
{
myBrush = new SolidBrush(c);
}
Font font = this.Font;
Rectangle inset = new Rectangle(bounds.Left + 3, bounds.Top, bounds.Width - 3, bounds.Height);
string value = null;
if (this._visibleTextCache.ContainsKey(tn))
{
value = this._visibleTextCache[tn];
}
else
{
value = GetNodeText(tn);
}
if (value == null && !focusSelected)
{
using (Brush b = new SolidBrush(_containerBackground))
{
g.FillRectangle(b, bounds);
}
}
if (value != null && value.Length > 0)
{
//inset.Inflate(-3, -2);
char ellipsis = Convert.ToChar(0x2026);
value = value.Trim();
int i = value.IndexOfAny(new char[] { '\r', '\n' });
if (i > 0)
{
value = value.Substring(0, i) + ellipsis;
}
// Figure out how much of the text we can display
int width = inset.Width; ;
//int height = inset.Height;
string s = value;
if (width < 0) return;
int length = value.Length;
SizeF size = SizeF.Empty;
bool measurable = false;
while (!measurable)
{
try
{
if (s.Length >= 65536)
{
// MeasureString tops out at 64kb strings.
s = s.Substring(0, 65535);
}
size = g.MeasureString(s, font, width + 1000, StringFormat.GenericTypographic);
measurable = true;
}
catch (Exception)
{
// perhaps the string is just too long!
s = s.Substring(0, s.Length / 2);
}
}
int j = s.Length;
int dy = (font.Height - (int)Math.Ceiling(size.Height)) / 2;
if (dy < 0) dy = 0;
char[] ws = new char[] { ' ', '\t' };
if ((int)size.Width > width && j > 1)
{ // line wrap?
int start = 0;
int w = 0;
int k = value.IndexOfAny(ws);
while (k > 0)
{
s = value.Substring(0, k) + ellipsis;
size = g.MeasureString(s, font, width + 1000, StringFormat.GenericTypographic);
if ((int)size.Width < width && k < length)
{
start = k;
w = (int)size.Width;
while (start < length && (value[start] == ' ' || value[start] == '\t'))
{
start++;
}
k = value.IndexOfAny(ws, start);
}
else
{
break;
}
}
j = start;
if (w < width / 2)
{
// if we have a really long word (e.g. binhex) then just take characters
// up to the end of the line.
while ((int)w < width && j < length)
{
j++;
s = value.Substring(0, j) + ellipsis;
size = g.MeasureString(s, font, width + 1000, StringFormat.GenericTypographic);
w = (int)size.Width;
}
}
if (j <= 0)
{
s = "";
}
else if (j < length)
{
s = value.Substring(0, j - 1) + ellipsis;
}
this._visibleTextCache[tn] = s;
}
// Draw the current item text based on the current Font and the custom brush settings.
g.DrawString(s, font, myBrush, inset.Left, dy + inset.Top, StringFormat.GenericTypographic);
}
// If the ListBox has focus, draw a focus rectangle around the selected item.
if (tn == this.SelectedNode)
{
g.SmoothingMode = SmoothingMode.Default;
Pen p = new Pen(Color.Black, 1);
p.DashStyle = DashStyle.Dot;
p.Alignment = PenAlignment.Inset;
p.LineJoin = LineJoin.Round;
bounds.Width--;
bounds.Height--;
g.DrawRectangle(p, bounds);
p.Dispose();
}
myBrush.Dispose();
}