/// <summary> /// Check if the selection direction is forward or backward.<br/> /// Is the selection start word is before the selection end word in DFS traversal. /// </summary> private void CheckSelectionDirection() { if (_selectionStart == _selectionEnd) { _backwardSelection = _selectionStartIndex > _selectionEndIndex; } else if (DomUtils.GetCssLineBoxByWord(_selectionStart) == DomUtils.GetCssLineBoxByWord(_selectionEnd)) { _backwardSelection = _selectionStart.Left > _selectionEnd.Left; } else { _backwardSelection = _selectionStart.Top >= _selectionEnd.Bottom; } }
/// <summary> /// Calculate the charecter index and offset by charecters for the given word and given offset. /// If the location is below the word line then set the selection to the end.<br/> /// If the location is to the right of the word then set the selection to the end.<br/> /// If the offset is to the left of the word set the selection to the begining.<br/> /// Otherwise calculate the width of each substring to find the char the location is on. /// </summary> /// <param name="control">used to create graphics to measure string</param> /// <param name="word">the word to calculate its index and offset</param> /// <param name="loc">the location to calculate for</param> /// <param name="selectionIndex">return the index of the char under the location</param> /// <param name="selectionOffset">return the offset of the char under the location</param> /// <param name="inclusive">is to include the first charecter in the calculation</param> private static void CalculateWordCharIndexAndOffset(Control control, CssRect word, Point loc, bool inclusive, out int selectionIndex, out float selectionOffset) { selectionIndex = 0; selectionOffset = 0.1f; var offset = loc.X - word.Left; if (word.Text == null) { // not a text word - set full selection selectionIndex = -1; selectionOffset = -1; } else if (offset > word.Width - word.OwnerBox.ActualWordSpacing || loc.Y > DomUtils.GetCssLineBoxByWord(word).LineBottom) { // mouse under the line, to the right of the word - set to the end of the word selectionIndex = word.Text.Length; selectionOffset = word.Width; } else if (offset > 0) { // calculate partial word selection selectionIndex = word.Text.Length; selectionOffset = word.OwnerBox.ActualWordSpacing / 2f; using (var g = control.CreateGraphics()) { for (int i = 1; i <= word.Text.Length; i++) { var sf = new StringFormat(); sf.SetMeasurableCharacterRanges(new[] { new CharacterRange(0, i) }); var regions = g.MeasureCharacterRanges(word.Text, word.OwnerBox.ActualFont, new RectangleF(0, 0, float.MaxValue, float.MaxValue), sf); SizeF s = regions[0].GetBounds(g).Size; if (!inclusive) { selectionOffset = s.Width + (s.Width / i / 15f); } if (s.Width > offset) { selectionIndex = i - (inclusive ? 1 : 0); break; } selectionOffset = s.Width + (s.Width / i / 15f); } } } }