/// <summary> /// Going through all the elements and looking for those that need to be re-rendered /// </summary> private void DetectVisualInvalidate(Control element, Point startPoint, ScreenDrawingContext bufferContext) { if (element == null) { return; } var wasRendered = false; if (!element.IsVisualValid) { element.BeforeRender(); wasRendered = true; } InvalidateScreenArea(element.DrawingContext, startPoint, bufferContext); if (element is ContentControl contentControl) { foreach (var control in contentControl) { if (wasRendered && (control.BackgroundIsTransparent || control.ForegroundIsTransparent)) { control.InvalidateVisual(); } var location = control.Location + startPoint; DetectVisualInvalidate(control, location, bufferContext); } } }
/// <summary> /// Going through all the elements and looking for those that need to be re-size /// and re-render /// </summary> private void CheckMeasureOrVisualInvalidate(WindowParameters wndParams) { if (wndParams?.Window == null || wndParams.Window.WasClosed) { return; } // 1-Check whether there is anything to re-size or re-render (run to the first // !IsMeasureValid or all trying to find at least one !IsVisualValid) var shouldRender = false; var shouldMeasure = DetectMeasureInvalidate(wndParams.Window, ref shouldRender); // 2- If it needed re-size, call Measure and Arrange var previousWndSize = wndParams.Window.Bounds; if (shouldMeasure) { PrepareWindow(wndParams); } // 3- if it needed re-render, or re-size was called, call ReleaseDrawingContext if (shouldMeasure || shouldRender) { pseudographicsProvider.CursorVisible = false; var bufferForRender = new ScreenDrawingContext(wndParams.Window.Bounds); bufferForRender.Release(Color.NotSet, Color.NotSet); // Run on all controls and for those who have !IsVisualValid calling BeforeRender DetectVisualInvalidate(wndParams.Window, Point.Empty, bufferForRender); TransferToScreen(wndParams, bufferForRender, wndParams.Window.Bounds != previousWndSize); SetFocusableBehavior(wndParams); } }
private void TransferToScreen(WindowParameters windowParameters, ScreenDrawingContext bufferForRender, bool shouldBackgroundRender) { var targetBuffer = shouldBackgroundRender ? windowParameters.ParentContext.Merge(windowParameters.Window.Location, bufferForRender) : bufferForRender; var targetLocation = shouldBackgroundRender ? Point.Empty : windowParameters.Window.Location; var strBuilder = new StringBuilder(targetBuffer.ContextBounds.Width); var colorPoint = targetBuffer.GetColorPoint(0, 0); for (var row = 0; row < targetBuffer.ContextBounds.Height; row++) { strBuilder.Clear(); pseudographicsProvider.SetCursorPosition(targetLocation.X, row + targetLocation.Y); for (var col = 0; col < targetBuffer.ContextBounds.Width; col++) { var currentPoint = targetBuffer.GetColorPoint(col, row); if (currentPoint == colorPoint) { strBuilder.Append(targetBuffer.Chars[col, row]); } else { if (strBuilder.Length > 0) { if (colorPoint.Background != Color.NotSet && colorPoint.Foreground != Color.NotSet) { pseudographicsProvider.BackgroundColor = colorPoint.Background; pseudographicsProvider.ForegroundColor = colorPoint.Foreground; pseudographicsProvider.Write(strBuilder.ToString()); } else { pseudographicsProvider.SetCursorPosition(col + targetLocation.X, row + targetLocation.Y); } strBuilder.Clear(); } colorPoint = currentPoint; strBuilder.Append(targetBuffer.Chars[col, row]); } } if (strBuilder.Length > 0) { if (colorPoint.Background != Color.NotSet && colorPoint.Foreground != Color.NotSet) { pseudographicsProvider.BackgroundColor = colorPoint.Background; pseudographicsProvider.ForegroundColor = colorPoint.Foreground; pseudographicsProvider.Write(strBuilder.ToString()); } } } pseudographicsProvider.SetCursorPosition(0, 0); windowParameters.CurrentBuffer = bufferForRender; }
internal static ScreenDrawingContext Merge(this ScreenDrawingContext parentContext, Point location, ScreenDrawingContext childContext) { var result = new ScreenDrawingContext(parentContext.ContextBounds); result.MergeWith(Point.Empty, parentContext); result.MergeWith(location, childContext); return(result); }
/// <summary> /// Redrawing a piece of the screen /// </summary> private void InvalidateScreenArea(IDrawingContext ctx, Point location, ScreenDrawingContext bufferContext) { if (ctx.ContextBounds.HasEmptyDimension()) { return; } var strBuilder = new StringBuilder(ctx.ContextBounds.Width); var colorPoint = ctx.GetColorPoint(0, 0); for (var row = 0; row < ctx.ContextBounds.Height; row++) { strBuilder.Clear(); bufferContext.SetCursorPos(new Point(location.X, row + location.Y)); for (var col = 0; col < ctx.ContextBounds.Width; col++) { var currentPoint = ctx.GetColorPoint(col, row); if (currentPoint == colorPoint) { strBuilder.Append(ctx.Chars[col, row]); } else { if (strBuilder.Length > 0) { bufferContext.DrawText(strBuilder.ToString(), colorPoint.Background, colorPoint.Foreground); strBuilder.Clear(); } colorPoint = currentPoint; strBuilder.Append(ctx.Chars[col, row]); } } if (strBuilder.Length > 0) { bufferContext.DrawText(strBuilder.ToString(), colorPoint.Background, colorPoint.Foreground); } } }
/// <summary> /// Initialize a new instance <see cref="WindowParameters"/> /// </summary> public WindowParameters(Window window, ScreenDrawingContext parentContext) { Window = window; ParentContext = parentContext; }