/// <summary> /// Handle mouse move to handle hover cursor and text selection. /// </summary> /// <param name="parent">the control hosting the html to set cursor and invalidate</param> /// <param name="loc">the location of the mouse on the html</param> public void HandleMouseMove(RControl parent, RPoint loc) { if (_root.HtmlContainer.IsSelectionEnabled && _mouseDownInControl && parent.LeftMouseButton) { if (_mouseDownOnSelectedWord) { // make sure not to start drag-drop on click but when it actually moves as it f***s mouse-up if ((DateTime.Now - _lastMouseDown).TotalMilliseconds > 200) { StartDragDrop(parent); } } else { HandleSelection(parent, loc, !_isDoubleClickSelect); _inSelection = _selectionStart != null && _selectionEnd != null && (_selectionStart != _selectionEnd || _selectionStartIndex != _selectionEndIndex); } } else { // Handle mouse hover over the html to change the cursor depending if hovering word, link of other. var link = DomUtils.GetLinkBox(_root, loc); if (link != null) { _cursorChanged = true; parent.SetCursorHand(); if (link != _lastLink) { _root.HtmlContainer.HandleLinkHover(parent, loc, link); _lastLink = link; } } else if (_root.HtmlContainer.IsSelectionEnabled) { var word = DomUtils.GetCssBoxWord(_root, loc); _cursorChanged = word != null && !word.IsImage && !(word.Selected && (word.SelectedStartIndex < 0 || word.Left + word.SelectedStartOffset <= loc.X) && (word.SelectedEndOffset < 0 || word.Left + word.SelectedEndOffset >= loc.X)); if (_cursorChanged) { parent.SetCursorIBeam(); } else { parent.SetCursorDefault(); } _lastLink = null; } else if (_cursorChanged) { parent.SetCursorDefault(); _lastLink = null; } } }
/// <summary> /// Select the word at the given location if found. /// </summary> /// <param name="control">the control hosting the html to invalidate</param> /// <param name="loc">the location to select word at</param> public void SelectWord(RControl control, RPoint loc) { if (_root.HtmlContainer.IsSelectionEnabled) { var word = DomUtils.GetCssBoxWord(_root, loc); if (word != null) { word.Selection = this; _selectionStartPoint = loc; _selectionStart = _selectionEnd = word; control.Invalidate(); } } }
/// <summary> /// Handle mouse down to handle selection. /// </summary> /// <param name="parent">the control hosting the html to invalidate</param> /// <param name="loc">the location of the mouse on the html</param> /// <param name="isMouseInContainer"> </param> public void HandleMouseDown(RControl parent, RPoint loc, bool isMouseInContainer) { bool clear = !isMouseInContainer; if (isMouseInContainer) { _mouseDownInControl = true; _isDoubleClickSelect = (DateTime.Now - _lastMouseDown).TotalMilliseconds < 400; _lastMouseDown = DateTime.Now; _mouseDownOnSelectedWord = false; if (_root.HtmlContainer.IsSelectionEnabled && parent.LeftMouseButton) { var word = DomUtils.GetCssBoxWord(_root, loc); if (word != null && word.Selected) { _mouseDownOnSelectedWord = true; } else { clear = true; } } else if (parent.RightMouseButton) { var rect = DomUtils.GetCssBoxWord(_root, loc); var link = DomUtils.GetLinkBox(_root, loc); if (_root.HtmlContainer.IsContextMenuEnabled) { _contextMenuHandler.ShowContextMenu(parent, rect, link); } clear = rect == null || !rect.Selected; } } if (clear) { ClearSelection(); parent.Invalidate(); } }
/// <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(RControl control, RPoint loc, bool allowPartialSelect) { // get the line under the mouse or nearest from the top var lineBox = DomUtils.GetCssLineBox(_root, loc); if (lineBox != null) { // get the word under the mouse var 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.SetCursorIBeam(); control.Invalidate(); } } }