public HitTestResult HitTest(PointF point)
{
Debug.Assert(numColumns == 1);
HitTestResult result = new HitTestResult();
// Compensate for the margin.
point.X -= margin;
point.Y -= margin;
// Get total size, not including margin.
int width = (int) (WidthInCells() * cellSize);
int height = (int) (description.Length * cellSize);
if (point.X < 0 || point.X >= width || point.Y < 0 || point.Y >= height) {
// Outside the bounds of the description.
result.kind = HitTestKind.None;
result.firstLine = result.lastLine = -1;
result.box = -1;
result.rect = new RectangleF();
return result;
}
// What line, column are we on?
int iLine = (int) (point.Y / cellSize);
Debug.Assert(iLine >= 0 && iLine < description.Length);
int iCol = (int)(point.X / cellSize);
Debug.Assert(iCol >= 0 && iCol < WidthInCells());
result.firstLine = result.lastLine = iLine;
DescriptionLineKind lineKind = description[iLine].kind;
switch (lineKind) {
case DescriptionLineKind.Title:
result.kind = HitTestKind.Title;
result.box = 0;
LineBounds(iLine, out result.firstLine, out result.lastLine);
result.rect = new RectangleF(0, result.firstLine * cellSize, width, cellSize * (result.lastLine - result.firstLine + 1));
break;
case DescriptionLineKind.SecondaryTitle:
result.kind = HitTestKind.SecondaryTitle;
result.box = 0;
LineBounds(iLine, out result.firstLine, out result.lastLine);
result.rect = new RectangleF(0, result.firstLine * cellSize, width, cellSize * (result.lastLine - result.firstLine + 1));
break;
case DescriptionLineKind.Header2Box:
if (iCol < 3) {
result.kind = HitTestKind.Header;
result.box = 0;
result.rect = new RectangleF(0, iLine * cellSize, 3 * cellSize, cellSize);
}
else if (iCol < 8) {
result.kind = HitTestKind.Header;
result.box = 1;
result.rect = new RectangleF(3 * cellSize, iLine * cellSize, 5 * cellSize, cellSize);
}
else {
result.kind = HitTestKind.None;
result.box = -1;
result.rect = new RectangleF(8 * cellSize, iLine * cellSize, 5 * cellSize, cellSize);
}
break;
case DescriptionLineKind.Header3Box:
if (iCol < 3) {
result.kind = HitTestKind.Header;
result.box = 0;
result.rect = new RectangleF(0, iLine * cellSize, 3 * cellSize, cellSize);
}
else if (iCol < 6) {
result.kind = HitTestKind.Header;
result.box = 1;
result.rect = new RectangleF(3 * cellSize, iLine * cellSize, 3 * cellSize, cellSize);
}
else if (iCol < 8) {
result.kind = HitTestKind.Header;
result.box = 2;
result.rect = new RectangleF(6 * cellSize, iLine * cellSize, 2 * cellSize, cellSize);
}
else {
result.kind = HitTestKind.None;
result.box = -1;
result.rect = new RectangleF(8 * cellSize, iLine * cellSize, 5 * cellSize, cellSize);
}
break;
case DescriptionLineKind.Normal:
if (descriptionKind == DescriptionKind.SymbolsAndText && iCol >= 8) {
result.kind = HitTestKind.NormalText;
result.box = -1;
result.rect = new RectangleF(8 * cellSize, iLine * cellSize, 5 * cellSize, cellSize);
}
else if (descriptionKind == DescriptionKind.Text && iCol >= 2) {
result.kind = HitTestKind.NormalText;
result.box = -1;
result.rect = new RectangleF(2 * cellSize, iLine * cellSize, 6 * cellSize, cellSize);
}
else {
result.kind = HitTestKind.NormalBox;
result.box = iCol;
result.rect = new RectangleF(iCol * cellSize, iLine * cellSize, cellSize, cellSize);
}
break;
case DescriptionLineKind.Directive:
if (descriptionKind == DescriptionKind.SymbolsAndText && iCol >= 8) {
result.kind = HitTestKind.DirectiveText;
result.box = -1;
result.rect = new RectangleF(8 * cellSize, iLine * cellSize, 5 * cellSize, cellSize);
}
else if (descriptionKind == DescriptionKind.Text) {
result.kind = HitTestKind.DirectiveText;
result.box = -1;
result.rect = new RectangleF(0, iLine * cellSize, 8 * cellSize, cellSize);
}
else {
result.kind = HitTestKind.Directive;
result.box = 0;
result.rect = new RectangleF(0, iLine * cellSize, 8 * cellSize, cellSize);
}
break;
case DescriptionLineKind.Text:
result.kind = HitTestKind.OtherTextLine;
result.box = 0;
LineBounds(iLine, out result.firstLine, out result.lastLine);
result.rect = new RectangleF(0, result.firstLine * cellSize, width, cellSize * (result.lastLine - result.firstLine + 1));
break;
case DescriptionLineKind.Key:
result.kind = HitTestKind.Key;
result.box = 0;
result.rect = new RectangleF(0, iLine * cellSize, width, cellSize);
break;
default:
Debug.Fail("bad line kind");
return result;
}
result.rect.Offset(margin, margin); // recompensate for the margin.
return result;
}