/// <summary> /// Adds an appropriately sized highlight box for the range of characters on the given line. /// Does not take into account text clipping or text offset. /// </summary> private void AddHighlightBox(int line, int startCh, int endCh) { if (text[line].Count > 0) { if (startCh < 0 || endCh < 0 || startCh >= text[line].Count || endCh >= text[line].Count) { throw new Exception($"Char out of range. Line: {line} StartCh: {startCh}, EndCh: {endCh}, Count: {text[line].Count}"); } IRichChar left = text[line][startCh], right = text[line][endCh]; var highlightBox = new HighlightBox { size = new Vector2() { X = right.Offset.X - left.Offset.X + (left.Size.X + right.Size.X) * .5f, Y = text[line].Size.Y }, offset = new Vector2() { X = (right.Offset.X + left.Offset.X) * .5f - 2f, Y = text[line].VerticalOffset - text[line].Size.Y * .5f } }; if (highlightBox.size.X > 1f) { highlightBox.size.X += 4f; } highlightList.Add(highlightBox); } }
protected override void Draw() { if (ShowCaret) { bool isCharVisible = text.Count == 0 || text[0].Count == 0; CaretIndex = ClampIndex(CaretIndex); // If line visible if ((text.Count > 0 && text[0].Count > 0) && (CaretIndex.X >= text.VisibleLineRange.X && CaretIndex.X <= text.VisibleLineRange.Y)) { // Damned special cases Vector2I index = Vector2I.Max(CaretIndex, Vector2I.Zero); // Calculate visibilty on line IRichChar ch = text[index]; Vector2 size = ch.Size, pos = ch.Offset + text.TextOffset; BoundingBox2 textBounds = BoundingBox2.CreateFromHalfExtent(Vector2.Zero, .5f * text.Size), charBounds = BoundingBox2.CreateFromHalfExtent(pos, .5f * Vector2.Max(size, new Vector2(8f))); if (textBounds.Contains(charBounds) != ContainmentType.Disjoint) { isCharVisible = true; } } if (blink & isCharVisible) { UpdateOffset(); base.Draw(); } if (blinkTimer.ElapsedMilliseconds > 500) { blink = !blink; blinkTimer.Restart(); } } }