private CaretElement EnsureCaret(bool isBlinkEnabled, bool isSelectionActive, CaretScrollMethod scrollMethod) { TextEditorThreadLocalStore threadLocalStore = TextEditor._ThreadLocalStore; if (_caretElement == null) { // Create new caret _caretElement = new CaretElement(_textEditor, isBlinkEnabled); _caretElement.IsSelectionActive = isSelectionActive; // Check the current input language to draw the BiDi caret in case of BiDi language // like as Arabic or Hebrew input language. // if (IsBidiInputLanguage(InputLanguageManager.Current.CurrentInputLanguage)) { TextEditor._ThreadLocalStore.Bidi = true; } else { TextEditor._ThreadLocalStore.Bidi = false; } } else { // Please note that it is important to set the IsSelectionActive property before // calling SetBlinking. This is because SetBlinking calls Win32CreateCaret & // Win32DestroyCaret both of which meaningfully use this flag. _caretElement.IsSelectionActive = isSelectionActive; _caretElement.SetBlinking(isBlinkEnabled); } UpdateCaretState(scrollMethod); return _caretElement; }
// .............................................................. // // Caret Support // // .............................................................. // Shows/hides the caret and scrolls it into view if requested. // Called when the range is moved or layout is updated. internal void UpdateCaretState(CaretScrollMethod caretScrollMethod) { Invariant.Assert(caretScrollMethod != CaretScrollMethod.Unset); if (_pendingCaretNavigation) { caretScrollMethod = CaretScrollMethod.Navigation; _pendingCaretNavigation = false; } if (_caretScrollMethod == CaretScrollMethod.Unset) { _caretScrollMethod = caretScrollMethod; // Post a "Loaded" priority operation to the dispatcher queue. // Operations at Loaded priority are processed when layout and render is // done but just before items at input priority are serviced. // We want the update caret worker to run after layout is clean. if (_textEditor.TextView != null && _textEditor.TextView.IsValid) { UpdateCaretStateWorker(null); } else { _pendingUpdateCaretStateCallback = true; } } else if (caretScrollMethod != CaretScrollMethod.None) { _caretScrollMethod = caretScrollMethod; } }
// Token: 0x06002B1B RID: 11035 RVA: 0x000C472C File Offset: 0x000C292C internal void Update(bool visible, Rect caretRectangle, Brush caretBrush, double opacity, bool italic, CaretScrollMethod scrollMethod, double scrollToOriginPosition) { Invariant.Assert(caretBrush != null, "Assert: caretBrush != null"); this.EnsureAttachedToView(); bool flag = visible && !this._showCaret; if (this._showCaret != visible) { base.InvalidateVisual(); this._showCaret = visible; } this._caretBrush = caretBrush; this._opacity = opacity; double num; double num2; double num3; double num4; if (caretRectangle.IsEmpty || caretRectangle.Height <= 0.0) { num = 0.0; num2 = 0.0; num3 = 0.0; num4 = 0.0; } else { num = caretRectangle.X; num2 = caretRectangle.Y; num3 = caretRectangle.Height; num4 = SystemParameters.CaretWidth; } bool flag2 = flag || italic != this._italic; if (!DoubleUtil.AreClose(this._left, num)) { this._left = num; flag2 = true; } if (!DoubleUtil.AreClose(this._top, num2)) { this._top = num2; flag2 = true; } if (!caretRectangle.IsEmpty && this._interimWidth != caretRectangle.Width) { this._interimWidth = caretRectangle.Width; flag2 = true; } if (!DoubleUtil.AreClose(this._systemCaretWidth, num4)) { this._systemCaretWidth = num4; flag2 = true; } if (!DoubleUtil.AreClose(this._height, num3)) { this._height = num3; base.InvalidateMeasure(); } if (flag2 || !double.IsNaN(scrollToOriginPosition)) { this._scrolledToCurrentPositionYet = false; this.RefreshCaret(italic); } if (scrollMethod != CaretScrollMethod.None && !this._scrolledToCurrentPositionYet) { Rect rect = new Rect(this._left - 5.0, this._top, 10.0 + (this.IsInInterimState ? this._interimWidth : this._systemCaretWidth), this._height); if (!double.IsNaN(scrollToOriginPosition) && scrollToOriginPosition > 0.0) { rect.X += rect.Width; rect.Width = 0.0; } if (scrollMethod != CaretScrollMethod.Simple) { if (scrollMethod == CaretScrollMethod.Navigation) { this.DoNavigationalScrollToView(scrollToOriginPosition, rect); } } else { this.DoSimpleScrollToView(scrollToOriginPosition, rect); } this._scrolledToCurrentPositionYet = true; } this.SetBlinkAnimation(visible, flag2); }
//----------------------------------------------------- // // Internal Methods // //------------------------------------------------------ #region Internal Methods /// <summary> /// Invalidates the caret render. /// Used in TextSelection (for caret) and in TextEditor (for drag target) /// </summary> /// <param name="visible"> /// </param> /// <param name="caretRectangle"> /// Rectangle relative to AdornedElement (textview) where caret should be drawn. /// Width must be zero to apply the system caret width except the interim caret that has /// the interim caret width. /// </param> /// <param name="caretBrush"> /// Brush for drawing the caret /// </param> /// <param name="opacity"> /// Opacity factor to apply to RenderContext when drawing the caret. /// </param> /// <param name="italic"> /// Request to italic caret. /// </param> /// <param name="scrollMethod"> /// Determines how the caret is scrolled into view. /// </param> /// <param name="scrollToOriginPosition"> /// Request to scroll caret position with the scroll origin position. /// </param> internal void Update(bool visible, Rect caretRectangle, Brush caretBrush, double opacity, bool italic, CaretScrollMethod scrollMethod, double scrollToOriginPosition) { double newLeft; double newTop; double newHeight; double newWidth; bool positionChanged; Invariant.Assert(caretBrush != null, "Assert: caretBrush != null"); // Make sure we're attached to the view. We have to delay this work // until now because if we swap out a render scope on the fly, the // new one won't be hooked up to the visual tree until after its // style is rebuilt, which happens on an async layout update. EnsureAttachedToView(); // Enforce caret refresh for the case when it appears after invisible state bool justAppearing = visible && !_showCaret; if (_showCaret != visible) { InvalidateVisual(); _showCaret = visible; } // Update the caret brush. _caretBrush = caretBrush; _opacity = opacity; // Define new coordinates and dimensions of the caret. // We don't consider caret visibility here because even if the // caret is hidden, we need to calc the geometry info to scroll // the active edge of the selection into view. if (caretRectangle.IsEmpty || caretRectangle.Height <= 0) { newLeft = 0; newTop = 0; newHeight = 0; newWidth = 0; } else { newLeft = caretRectangle.X; newTop = caretRectangle.Y; newHeight = caretRectangle.Height; newWidth = SystemParameters.CaretWidth; } // Initialize flag requiring to refresh the caret positionChanged = justAppearing || italic != _italic; if (!DoubleUtil.AreClose(_left, newLeft)) { _left = newLeft; positionChanged = true; } if (!DoubleUtil.AreClose(_top, newTop)) { _top = newTop; positionChanged = true; } if (!caretRectangle.IsEmpty && _interimWidth != caretRectangle.Width) { _interimWidth = caretRectangle.Width; positionChanged = true; } if (!DoubleUtil.AreClose(_systemCaretWidth, newWidth)) { _systemCaretWidth = newWidth; positionChanged = true; } if (!DoubleUtil.AreClose(_height, newHeight)) { _height = newHeight; InvalidateMeasure(); } // Refresh caret and ensure the caret to the view if the caret position is changed or // caret is currently out of view area which scrollToOriginPosition is set. // scrollToOriginPosition will be set properly to view the caret correctly if caret is // currently out of view boundary. For example, typing bidi characters on LTR flow direction // or typing western characters on RTL flow direction from the out of view. if (positionChanged || !double.IsNaN(scrollToOriginPosition)) { _scrolledToCurrentPositionYet = false; RefreshCaret(italic); } if (scrollMethod != CaretScrollMethod.None && !_scrolledToCurrentPositionYet) { Rect scrollRectangle; //Set the interim width to show the interim caret in the interim mode. // We're providing enough space to also take care of an italic or bidi caret. scrollRectangle = new Rect(_left - CaretPaddingWidth, _top, CaretPaddingWidth * 2 + (IsInInterimState ? _interimWidth : _systemCaretWidth), _height); // If we're scrolling to one edge of the document or another, // - Going backward, we want to scroll into view the left edge // of the rect. This is the default. // - Going forward, we want to scroll into view the right edge // of the rect, which takes some adjustment. if (!double.IsNaN(scrollToOriginPosition) && scrollToOriginPosition > 0) { scrollRectangle.X += scrollRectangle.Width; scrollRectangle.Width = 0; } switch (scrollMethod) { case CaretScrollMethod.Simple: DoSimpleScrollToView(scrollToOriginPosition, scrollRectangle); break; case CaretScrollMethod.Navigation: DoNavigationalScrollToView(scrollToOriginPosition, scrollRectangle); break; } _scrolledToCurrentPositionYet = true; } // Skip the animation if the animation isn't set. E.g. DragDrop caret. SetBlinkAnimation(visible, positionChanged); }
private CaretElement EnsureCaret(bool isBlinkEnabled, CaretScrollMethod scrollMethod) { TextEditorThreadLocalStore threadLocalStore = TextEditor._ThreadLocalStore; if (_caretElement == null) { // Create new caret _caretElement = new CaretElement(_textEditor, isBlinkEnabled); // Check the current input language to draw the BiDi caret in case of BiDi language // like as Arabic or Hebrew input language. // if (IsBidiInputLanguage(InputLanguageManager.Current.CurrentInputLanguage)) { TextEditor._ThreadLocalStore.Bidi = true; } else { TextEditor._ThreadLocalStore.Bidi = false; } } else { _caretElement.SetBlinking(isBlinkEnabled); } UpdateCaretState(scrollMethod); return _caretElement; }