/// <summary> /// Get css word box under the given sub-tree at the given x,y location.<br/> /// the location must be in correct scroll offset. /// </summary> /// <param name="lineBox">the line box to search in</param> /// <param name="location">the location to find the box at</param> /// <returns>css word box if exists or null</returns> public static CssRect GetCssBoxWord(CssLineBox lineBox, RPoint location) { foreach (var rects in lineBox.Rectangles) { foreach (var word in rects.Key.Words) { // add word spacing to word width so sentence won't have hols in it when moving the mouse var rect = word.Rectangle; rect.Width += word.OwnerBox.ActualWordSpacing; if (rect.Contains(location)) { return(word); } } } return(null); }
public void PaintSelection(PaintVisitor p, CssLineBox line) { if (this.Kind == SelectionSegmentKind.FullLine) { p.FillRectangle(p.CssBoxSelectionColor, //should be configurable 0, 0, line.CachedLineContentWidth, line.CacheLineHeight); } else { p.FillRectangle( p.CssBoxSelectionColor, this.BeginAtPx, 0, this.WidthPx, (int)line.CacheLineHeight); } }
internal static float CalculateInnerContentHeight(this CssBox startBox) { //calculate inner content height if (startBox.LineBoxCount > 0) { CssLineBox lastLine = startBox.GetLastLineBox(); return(lastLine.CachedLineBottom); } else { float maxBottom = 0; foreach (CssBox childBox in startBox.GetChildBoxIter()) { float top = childBox.LocalY; float contentH = CalculateInnerContentHeight(childBox); if ((top + contentH) > maxBottom) { maxBottom = top + contentH; } } return(maxBottom); } }
/// <summary> /// Get css line box under the given sub-tree at the given y location or the nearest line from the top.<br/> /// the location must be in correct scroll offset. /// </summary> /// <param name="box">the box to start search from</param> /// <param name="location">the location to find the box at</param> /// <returns>css word box if exists or null</returns> public static CssLineBox GetCssLineBox(CssBox box, RPoint location) { CssLineBox line = null; if (box != null) { if (box.LineBoxes.Count > 0) { if (box.HtmlTag == null || box.HtmlTag.Name != "td" || box.Bounds.Contains(location)) { foreach (var lineBox in box.LineBoxes) { foreach (var rect in lineBox.Rectangles) { if (rect.Value.Top <= location.Y) { line = lineBox; } if (rect.Value.Top > location.Y) { return(line); } } } } } foreach (var childBox in box.Boxes) { line = GetCssLineBox(childBox, location) ?? line; } } return(line); }
/// <summary> /// Handle html text selection by mouse move over the html with left mouse button pressed.<br/> /// Calculate the words in the selected range and set their selected property. /// </summary> /// <param name="control">the control hosting the html to invalidate</param> /// <param name="loc">the mouse location</param> /// <param name="allowPartialSelect">true - partial word selection allowed, false - only full words selection</param> private void HandleSelection(Control control, Point loc, bool allowPartialSelect) { // get the line under the mouse or nearest from the top CssLineBox lineBox = DomUtils.GetCssLineBox(_root, loc); if (lineBox != null) { // get the word under the mouse CssRect word = DomUtils.GetCssBoxWord(lineBox, loc); // if no word found under the mouse use the last or the first word in the line if (word == null && lineBox.Words.Count > 0) { if (loc.Y > lineBox.LineBottom) { // under the line word = lineBox.Words[lineBox.Words.Count - 1]; } else if (loc.X < lineBox.Words[0].Left) { // before the line word = lineBox.Words[0]; } else if (loc.X > lineBox.Words[lineBox.Words.Count - 1].Right) { // at the end of the line word = lineBox.Words[lineBox.Words.Count - 1]; } } // if there is matching word if (word != null) { if (_selectionStart == null) { // on start set the selection start word _selectionStartPoint = loc; _selectionStart = word; if (allowPartialSelect) { CalculateWordCharIndexAndOffset(control, word, loc, true); } } // always set selection end word _selectionEnd = word; if (allowPartialSelect) { CalculateWordCharIndexAndOffset(control, word, loc, false); } ClearSelection(_root); if (CheckNonEmptySelection(loc, allowPartialSelect)) { CheckSelectionDirection(); SelectWordsInRange(_root, _backwardSelection ? _selectionEnd : _selectionStart, _backwardSelection ? _selectionStart : _selectionEnd); } else { _selectionEnd = null; } _cursorChanged = true; control.Cursor = Cursors.IBeam; control.Invalidate(); } } }