protected override Size MeasureOverride(Size availableSize) { if (Content == null) { return(new Size(0, 0)); } // Размещаем контрол так, как будто бы у него имеется сколько угодно пространства Content.Measure(new Size(int.MaxValue, int.MaxValue)); Size desiredSize = Content.DesiredSize; horizontalScrollVisible = HorizontalScrollEnabled && (desiredSize.Width > availableSize.Width); verticalScrollVisible = VerticalScrollEnabled && (desiredSize.Height > availableSize.Height); int width = Math.Min(verticalScrollVisible ? desiredSize.Width + 1 : desiredSize.Width, availableSize.Width); int height = Math.Min(horizontalScrollVisible ? desiredSize.Height + 1 : desiredSize.Height, availableSize.Height); // Если горизонтальная прокрутка отключена - то мы должны сообщить контролу, что по горизонтали он будет иметь не int.MaxValue // пространства, а ровно width. Таким образом мы даём возможность контролу приспособиться к тому, что прокрутки по горизонтали не будет. // Аналогично и с вертикальной прокруткой. Так как последний вызов Measure должен быть именно с такими размерами, которые реально // будут использоваться при размещении, то мы и должны выполнить Measure ещё раз. if (!HorizontalScrollEnabled || !VerticalScrollEnabled) { Content.Measure(new Size(HorizontalScrollEnabled ? int.MaxValue : width, VerticalScrollEnabled ? int.MaxValue : height)); } Size result = new Size(width, height); return(result); }
protected override Size MeasureOverride(Size availableSize) { // Get children max desired size to determine the tab content desired size Size childrenAvailableSize = new Size( Math.Max(availableSize.Width - 2, 0), Math.Max(availableSize.Height - 4, 0)); int maxDesiredWidth = 0; int maxDesiredHeight = 0; for (int i = 0; i < Math.Min(Children.Count, tabDefinitions.Count); i++) { Control child = Children[i]; child.Measure(childrenAvailableSize); if (child.DesiredSize.Width > maxDesiredWidth) { maxDesiredWidth = child.DesiredSize.Width; } if (child.DesiredSize.Height > maxDesiredHeight) { maxDesiredHeight = child.DesiredSize.Height; } } // Get tab header desired size var tabHeaderWidth = getTabHeaderWidth( ); // Calculate final size = min(availableSize, controlWithChildrenDesiredSize) Size controlWithChildrenDesiredSize = new Size( Math.Max(maxDesiredWidth + 2, tabHeaderWidth), maxDesiredHeight + 4 ); Size finalAvailableSize = new Size( Math.Min(availableSize.Width, controlWithChildrenDesiredSize.Width), Math.Min(availableSize.Height, controlWithChildrenDesiredSize.Height) ); // Invoke children.Measure() with final size for (int i = 0; i < Children.Count; i++) { Control child = Children[i]; if (activeTabIndex == i) { child.Measure(new Size( Math.Max(0, finalAvailableSize.Width - 2), Math.Max(0, finalAvailableSize.Height - 4) )); } else { child.Measure(Size.Empty); } } return(finalAvailableSize); }
void UpdateText() { if (Control == null) { return; } Label label = Element; if (label != null) { if (label.FormattedText == null) { Control.Text = label.Text; } else { FormattedString formattedText = label.FormattedText ?? label.Text; Control.Inlines.Clear(); // Have to implement a measure here, otherwise inline.ContentStart and ContentEnd will be null, when used in RecalculatePositions Control.Measure(new System.Windows.Size(double.MaxValue, double.MaxValue)); var heights = new List <double>(); for (var i = 0; i < formattedText.Spans.Count; i++) { var span = formattedText.Spans[i]; var run = span.ToRun(); heights.Add(Control.FindDefaultLineHeight(run)); Control.Inlines.Add(run); } _inlineHeights = heights; } } }
private static PngBitmapEncoder getImageFromControl(Control controlToConvert) { // save current canvas transform Transform transform = controlToConvert.LayoutTransform; // get size of control Size sizeOfControl = new Size(120, 120);//controlToConvert.ActualWidth, controlToConvert.ActualHeight); // measure and arrange the control controlToConvert.Measure(sizeOfControl); // arrange the surface controlToConvert.Arrange(new Rect(sizeOfControl)); // craete and render surface and push bitmap to it RenderTargetBitmap renderBitmap = new RenderTargetBitmap((Int32)sizeOfControl.Width, (Int32)sizeOfControl.Height, 96d, 96d, PixelFormats.Pbgra32); // now render surface to bitmap renderBitmap.Render(controlToConvert); // encode png data PngBitmapEncoder pngEncoder = new PngBitmapEncoder(); // puch rendered bitmap into it pngEncoder.Frames.Add(BitmapFrame.Create(renderBitmap)); // return encoder return(pngEncoder); }
public static void ScreenCapture(Control control, string filename) { try { // The BitmapSource that is rendered with a Visual. control.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); Size size = control.DesiredSize; int width = (int)size.Width; int height = (int)size.Height; control.Arrange(new Rect(0, 0, width, height)); var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32); rtb.Render(control); // Encoding the RenderBitmapTarget as a PNG file. var png = new PngBitmapEncoder(); png.Frames.Add(BitmapFrame.Create(rtb)); using (Stream stm = File.Create(filename)) { png.Save(stm); } } finally { } }
protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize) { if (Element == null || availableSize.Width * availableSize.Height == 0) { return(new System.Windows.Size(0, 0)); } Element.IsInNativeLayout = true; for (var i = 0; i < ElementController.LogicalChildren.Count; i++) { var child = ElementController.LogicalChildren[i] as VisualElement; if (child == null) { continue; } IVisualElementRenderer renderer = Platform.GetRenderer(child); if (renderer == null) { continue; } try { renderer.ContainerElement.Measure(availableSize); } catch (NullReferenceException) { if (!IsExpectedTabbedPageMeasurementException(renderer)) { throw; } } } double width = Math.Max(0, Element.Width); double height = Math.Max(0, Element.Height); var result = new System.Windows.Size(width, height); if (Control != null) { double w = Element.Width; double h = Element.Height; if (w == -1) { w = availableSize.Width; } if (h == -1) { h = availableSize.Height; } w = Math.Max(0, w); h = Math.Max(0, h); Control.Measure(new System.Windows.Size(w, h)); } Element.IsInNativeLayout = false; return(result); }
protected override void OnElementChanged(ElementChangedEventArgs <Editor> e) { base.OnElementChanged(e); if (Control == null) { return; } Control.Typeface = e.NewElement?.FontAttributes == FontAttributes.Bold ? Typefaces.FontBold : Typefaces.FontRegular; Control.Measure(0, 0); var height = Control.MeasuredHeight; var width = Control.MeasuredWidth; Control.Background = new FixedDrawable(height, width); Control.SetHintTextColor(new Android.Graphics.Color() { A = 255, R = 109, G = 197, B = 237 }); if (e.NewElement != null) { CitoEditor = e.NewElement; } }
public void AddScreen(Control screen) { // works //GameLog.Client.GameData.DebugFormat("GameScreenStack.cs: screen={0}", screen); if (screen == null) { throw new ArgumentNullException("screen"); } lock (_screens) { if (_screens.Contains(screen)) { return; } var wasEmpty = (_screens.Count == 0); _screens.Add(screen); _itemsContainer.Children.Add(screen); if (IsVisible) { screen.Measure(RenderSize); screen.Arrange(new Rect(RenderSize)); } screen.Visibility = Visibility.Hidden; if (wasEmpty) { FallbackScreen = screen; } } }
protected virtual Control GetMiniControl(Type t, double maxDimension) { Control c = (Control)Activator.CreateInstance(t); double uniformScaleAmount = c.UniformScaleAmount(maxDimension); if (double.IsNaN(uniformScaleAmount)) { c.Measure(new Size(maxDimension, maxDimension)); } TransformGroup tg = new TransformGroup(); ScaleTransform st = new ScaleTransform(); st.ScaleX = uniformScaleAmount; st.ScaleY = uniformScaleAmount; tg.Children.Add(st); c.RenderTransform = tg; double estimatedNewWidth = c.Width * uniformScaleAmount; double estimatedNewHeight = c.Height * uniformScaleAmount; double left = (85 / 2.0D) - (estimatedNewWidth / 2.0D); double top = (55.0 / 2.0D) - (estimatedNewHeight / 2.0D); c.SetValue(Canvas.LeftProperty, left); c.SetValue(Canvas.TopProperty, top); return(c); }
public static void Render(Control target, Size size, Stream stream, double dpi = 72, bool useDeferredRenderer = false) { using var managedWStream = new SKManagedWStream(stream); using var document = SKDocument.CreateXps(stream, (float)dpi); using var canvas = document.BeginPage((float)size.Width, (float)size.Height); target.Measure(size); target.Arrange(new Rect(size)); CanvasRenderer.Render(target, canvas, dpi, useDeferredRenderer); }
protected override Size MeasureOverride(Size constraint) { if (Placeholder != null && AdornedElement.IsMeasureValid && Placeholder.DesiredSize != AdornedElement.DesiredSize) { Placeholder.InvalidateMeasure(); } adornerHost.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); return((adornerHost).DesiredSize); }
protected override Size MeasureOverride(Size availableSize) { unchecked { MeasureCount++; } //TODO performance: setting Width and Height forces two Control.Measure passes Width = Column.Width; Control.Measure(availableSize); Height = Control.DesiredSize.Height; return(new Size(Width, Height)); }
public static void Render(Control target, Size size, Stream stream, double dpi = 96, bool useDeferredRenderer = false) { using var managedWStream = new SKManagedWStream(stream); var bounds = SKRect.Create(new SKSize((float)size.Width, (float)size.Height)); using var canvas = SKSvgCanvas.Create(bounds, managedWStream); target.Measure(size); target.Arrange(new Rect(size)); CanvasRenderer.Render(target, canvas, dpi, useDeferredRenderer); }
protected override Avalonia.Size MeasureOverride(Avalonia.Size availableSize) { if (Element == null || availableSize.Width * availableSize.Height == 0) { return(new Avalonia.Size(0, 0)); } Element.IsInNativeLayout = true; for (var i = 0; i < ElementController.LogicalChildren.Count; i++) { var child = ElementController.LogicalChildren[i] as VisualElement; if (child == null) { continue; } IVisualElementRenderer renderer = Platform.GetOrCreateRenderer(child); if (renderer == null) { continue; } Control control = renderer.GetNativeElement(); if (control.Bounds.Width != child.Width || control.Bounds.Height != child.Height) { double width = child.Width <= -1 ? Bounds.Width : child.Width; double height = child.Height <= -1 ? Bounds.Height : child.Height; control.Measure(new Avalonia.Size(width, height)); } } Avalonia.Size result; if (double.IsInfinity(availableSize.Width) || double.IsPositiveInfinity(availableSize.Height)) { Size request = Element.Measure(availableSize.Width, availableSize.Height, MeasureFlags.IncludeMargins).Request; result = new Avalonia.Size(request.Width, request.Height); } else { result = availableSize; } Element.IsInNativeLayout = false; if (Double.IsPositiveInfinity(result.Height)) { result.WithHeight(0.0); } if (Double.IsPositiveInfinity(result.Width)) { result.WithWidth(0.0); } return(result); }
protected override void OnElementChanged(ElementChangedEventArgs <Frame> e) { base.OnElementChanged(e); if (Control != null) { Control.Measure(0, 0); var height = Control.MeasuredHeight; var width = Control.MeasuredWidth; Control.Background = new FixedDrawable(height, width); } }
public static void Render(Control target, Size size, string path, double dpi = 96) { var pixelSize = new PixelSize((int)size.Width, (int)size.Height); var dpiVector = new Vector(dpi, dpi); using var bitmap = new RenderTargetBitmap(pixelSize, dpiVector); target.Measure(size); target.Arrange(new Rect(size)); bitmap.Render(target); bitmap.Save(path); }
public static void Render(Control target, Size size, Stream stream, double dpi = 96, bool useDeferredRenderer = false) { var bounds = SKRect.Create(new SKSize((float)size.Width, (float)size.Height)); using var pictureRecorder = new SKPictureRecorder(); using var canvas = pictureRecorder.BeginRecording(bounds); target.Measure(size); target.Arrange(new Rect(size)); CanvasRenderer.Render(target, canvas, dpi, useDeferredRenderer); using var picture = pictureRecorder.EndRecording(); picture.Serialize(stream); }
protected override Size MeasureOverride(Size availableSize) { Control child = ((IVisual)this).VisualChildren.SingleOrDefault() as Control; if (child != null) { child.Measure(availableSize); return(child.DesiredSize.Value); } return(new Size()); }
protected override void OnElementChanged(ElementChangedEventArgs <Entry> e) { base.OnElementChanged(e); if (Control == null) { return; } //Control.Background = ContextCompat.GetDrawable(Control.Context, Resource.Drawable.RoundedEntry); Control.Typeface = e.NewElement?.FontAttributes == FontAttributes.Bold ? Typefaces.FontBold : Typefaces.FontRegular; Control.Measure(0, 0); var height = Control.MeasuredHeight; var width = Control.MeasuredWidth; var textsize = Control.LineHeight + Control.LineSpacingExtra; const int roundedsize = 4; var padding = (height - (int)textsize - roundedsize) / 2; Control.SetPadding(Control.PaddingLeft + 20, padding, Control.PaddingRight, padding); Control.Background = new FixedDrawable(height, width); Control.Gravity = GravityFlags.CenterVertical | GravityFlags.CenterHorizontal; var newElement = (CitoEntry)e.NewElement; if (newElement != null) { Control.Focusable = newElement.HasFocusable; } if (newElement != null && newElement.IsFirstLetterUpperCase) { Control.InputType = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagNoSuggestions; } if (newElement != null && !newElement.IsAutoCorrectEnabled) { Control.InputType = InputTypes.ClassText | InputTypes.TextFlagNoSuggestions; } if (newElement?.NextView != null) { Control.ImeOptions = Android.Views.InputMethods.ImeAction.Next; Control.EditorAction += (sender, args) => { newElement.OnNext(); }; } }
public virtual SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint) { if (Control == null) { return(new SizeRequest()); } var constraint = new System.Windows.Size(widthConstraint, heightConstraint); Control.Measure(constraint); return(new SizeRequest(new Size(Math.Ceiling(Control.DesiredSize.Width), Math.Ceiling(Control.DesiredSize.Height)))); }
void SetLayout() { Control.Measure(AT_MOST, AT_MOST); Control.Measure(AT_MOST, MeasureSpec.MakeMeasureSpec(Control.MeasuredHeight + 200, Android.Views.MeasureSpecMode.Exactly)); Control.Layout(0, 0, Control.MeasuredWidth, Control.MeasuredHeight); Measure(MeasureSpec.MakeMeasureSpec(Control.MeasuredWidth, Android.Views.MeasureSpecMode.Exactly), MeasureSpec.MakeMeasureSpec(Control.MeasuredHeight, Android.Views.MeasureSpecMode.Exactly)); Layout(0, 0, MeasuredWidth, MeasuredHeight); Element.HeightRequest = MeasuredHeight / Context.Resources.DisplayMetrics.Density; Element.WidthRequest = MeasuredWidth / Context.Resources.DisplayMetrics.Density; }
//public MetryHolder(CTextBlock ctxt, int width = 400, int height = 1000) //{ // var reqSz = new Size(width, height); // // ctxt.Measure(reqSz); // ctxt.Arrange(new Rect(0, 0, width, ctxt.DesiredSize.Height == 0 ? height : ctxt.DesiredSize.Height)); // ctxt.Measure(reqSz); // // var newReqSz = new Size( // ctxt.DesiredSize.Width == 0 ? reqSz.Width : ctxt.DesiredSize.Width, // ctxt.DesiredSize.Height == 0 ? reqSz.Height : ctxt.DesiredSize.Height); // ctxt.Arrange(new Rect(0, 0, newReqSz.Width, newReqSz.Height)); // // var bitmap = new RenderTargetBitmap(PixelSize.FromSizeWithDpi(newReqSz, Dpi), Dpi); // // using (var icontext = bitmap.CreateDrawingContext(null)) // using (var context = new DrawingContext(icontext)) // { // ctxt.Render(context); // } // // Image = bitmap; //} public MetryHolder(Control ctxt, int width = 400, int height = 1000) { var reqSz = new Size(width, height); ctxt.Measure(reqSz); ctxt.Arrange(new Rect(0, 0, width, ctxt.DesiredSize.Height == 0 ? height : ctxt.DesiredSize.Height)); ctxt.Measure(reqSz); var newReqSz = new Size( ctxt.DesiredSize.Width == 0 ? reqSz.Width : ctxt.DesiredSize.Width, ctxt.DesiredSize.Height == 0 ? reqSz.Height : ctxt.DesiredSize.Height); ctxt.Arrange(new Rect(0, 0, newReqSz.Width, newReqSz.Height)); var bitmap = new RenderTargetBitmap(PixelSize.FromSizeWithDpi(newReqSz, Dpi), Dpi); using (var icontext = bitmap.CreateDrawingContext(null)) using (var context = new DrawingContext(icontext)) { RenderHelper(ctxt, context); } Image = bitmap; }
protected override Windows.Foundation.Size MeasureOverride(Windows.Foundation.Size availableSize) { if (Element == null || availableSize.Width * availableSize.Height == 0) { return(new Windows.Foundation.Size(0, 0)); } Element.IsInNativeLayout = true; for (var i = 0; i < ElementController.LogicalChildren.Count; i++) { var child = ElementController.LogicalChildren[i] as VisualElement; if (child == null) { continue; } IVisualElementRenderer renderer = Platform.GetRenderer(child); if (renderer == null) { continue; } renderer.ContainerElement.Measure(availableSize); } double width = Math.Max(0, Element.Width); double height = Math.Max(0, Element.Height); var result = new Windows.Foundation.Size(width, height); if (Control != null) { double w = Element.Width; double h = Element.Height; if (w == -1) { w = availableSize.Width; } if (h == -1) { h = availableSize.Height; } w = Math.Max(0, w); h = Math.Max(0, h); Control.Measure(new Windows.Foundation.Size(w, h)); } Element.IsInNativeLayout = false; return(result); }
public override Vector2 Measure() { if (Size.HasValue) { return(Size.Value); } if (left != null) { leftSize = left.Measure(); } if (right != null) { rightSize = right.Measure(); } if (top != null) { topSize = top.Measure(); } if (bottom != null) { bottomSize = bottom.Measure(); } if (center != null) { centerSize = center.Measure(); } float height = 0; float width = 0; if (Orientation == Orientation.Horizontal) { height = (new[] { leftSize.y, rightSize.y, centerSize.y }).Max(); width = leftSize.x + centerSize.x + rightSize.x; } else { height = topSize.y + centerSize.y + bottomSize.y; width = leftSize.x + centerSize.x + rightSize.x; } Size = new Vector2(width, height); return(Size.Value); }
protected async Task RenderToFile(Control target, [CallerMemberName] string testName = "") { if (!Directory.Exists(OutputPath)) { Directory.CreateDirectory(OutputPath); } var immediatePath = Path.Combine(OutputPath, testName + ".immediate.out.png"); var deferredPath = Path.Combine(OutputPath, testName + ".deferred.out.png"); var factory = AvaloniaLocator.Current.GetService <IPlatformRenderInterface>(); using (RenderTargetBitmap bitmap = new RenderTargetBitmap( (int)target.Width, (int)target.Height)) { Size size = new Size(target.Width, target.Height); target.Measure(size); target.Arrange(new Rect(size)); bitmap.Render(target); bitmap.Save(immediatePath); } using (var rtb = factory.CreateRenderTargetBitmap((int)target.Width, (int)target.Height, 96, 96)) using (var renderer = new DeferredRenderer(target, rtb)) { Size size = new Size(target.Width, target.Height); target.Measure(size); target.Arrange(new Rect(size)); renderer.UnitTestUpdateScene(); // Do the deferred render on a background thread to expose any threading errors in // the deferred rendering path. await Task.Run((Action)renderer.UnitTestRender); rtb.Save(deferredPath); } }
protected override Size MeasureOverride(Size availableSize) { Size contentSize = Size.Empty; if (content != null) { content.Measure(new Size(int.MaxValue, int.MaxValue)); contentSize = content.DesiredSize; } Size needSize = new Size( Math.Max(contentSize.Width + 2, (title ?? string.Empty).Length + 4), contentSize.Height + 2 ); if (fitSizeToContent) { return(needSize); } Size constrainedSize = new Size( Math.Min(needSize.Width, availableSize.Width), Math.Min(needSize.Height, availableSize.Height) ); if (needSize != constrainedSize && content != null) { // если контрол вместе с содержимым не помещается в availableSize, // то мы оставляем содержимому меньше места, чем ему хотелось бы, // и поэтому повторным вызовом Measure должны установить его реальные размеры, // которые будут использованы при размещении content.Measure(new Size( Math.Max(0, constrainedSize.Width - 2), Math.Max(0, constrainedSize.Height - 2) )); } return(constrainedSize); }
protected void RenderToFile(Control target, [CallerMemberName] string testName = "") { string path = Path.Combine(OutputPath, testName + ".out.png"); RenderTargetBitmap bitmap = new RenderTargetBitmap( (int)target.Width, (int)target.Height); Size size = new Size(target.Width, target.Height); target.Measure(size); target.Arrange(new Rect(size)); bitmap.Render(target); bitmap.Save(path); }
protected void RenderToFile(Control target, [CallerMemberName] string testName = "") { string path = Path.Combine(OutputPath, testName + ".out.png"); using (RenderTargetBitmap bitmap = new RenderTargetBitmap( (int)target.Width, (int)target.Height)) { Size size = new Size(target.Width, target.Height); target.Measure(size); target.Arrange(new Rect(size)); bitmap.Render(target); bitmap.Save(path); } }
internal static Stream Render(this Control control) { var stream = new MemoryStream(); var png = new PngBitmapEncoder(); control.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); control.Arrange(new Rect(0, 0, control.DesiredSize.Width, control.DesiredSize.Height)); var target = new RenderTargetBitmap(Math.Max(1, (int)control.ActualWidth), Math.Max(1, (int)control.ActualHeight), 96, 96, PixelFormats.Pbgra32); target.Render(control); png.Frames.Add(BitmapFrame.Create(target)); png.Save(stream); stream.Position = 0; return(stream); }
/// <summary> /// Measure adorner. /// </summary> protected override Size MeasureOverride(Size constraint) { Debug.Assert(child != null, "_child should not be null"); if (ReferenceElement != null && AdornedElement != null && AdornedElement.IsMeasureValid && !AreClose(ReferenceElement.DesiredSize, AdornedElement.DesiredSize)) { ReferenceElement.InvalidateMeasure(); } child.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); return(child.DesiredSize); }
protected override Windows.Foundation.Size MeasureOverride(Windows.Foundation.Size availableSize) { if (Element == null) { return(new Windows.Foundation.Size(0, 0)); } double width = Math.Max(0, Element.Width); double height = Math.Max(0, Element.Height); var result = new Windows.Foundation.Size(width, height); Control?.Measure(result); return(result); }
private RenderingBuffer processControl(Control control, List<Control> revalidatedControls) { RenderingBuffer buffer = getOrCreateBufferForControl(control); RenderingBuffer fullBuffer = getOrCreateFullBufferForControl(control); // LayoutInfo lastLayoutInfo = control.lastLayoutInfo; LayoutInfo layoutInfo = control.layoutInfo; // control.Measure(lastLayoutInfo.measureArgument); control.Arrange(lastLayoutInfo.renderSlotRect); // if lastLayoutInfo eq layoutInfo we can use last rendered buffer // if (layoutInfo.Equals(lastLayoutInfo) && lastLayoutInfo.validity == LayoutValidity.Render) { if (checkRenderingWasNotChangedRecursively(control)) { if (control.SetValidityToRender()) { revalidatedControls.Add(control); } return fullBuffer; } // replace buffers if control has grown if (layoutInfo.renderSize.width > buffer.Width || layoutInfo.renderSize.height > buffer.Height) { buffer = new RenderingBuffer(layoutInfo.renderSize.width, layoutInfo.renderSize.height); fullBuffer = new RenderingBuffer(layoutInfo.renderSize.width, layoutInfo.renderSize.height); buffers[control] = buffer; fullBuffers[control] = fullBuffer; } // otherwise we should assemble full rendered buffer using childs buffer.Clear(); if (control.RenderSize.Width != 0 && control.RenderSize.Height != 0) control.Render(buffer); // fullBuffer.CopyFrom(buffer); foreach (Control child in control.Children) { if (child.Visibility == Visibility.Visible) { RenderingBuffer fullChildBuffer = processControl(child, revalidatedControls); fullBuffer.ApplyChild(fullChildBuffer, child.ActualOffset, child.RenderSize, child.RenderSlotRect, child.LayoutClip); } else { // чтобы следующий Invalidate для этого контрола // перезаписал lastLayoutInfo if (child.SetValidityToRender()) { revalidatedControls.Add(child); } } } // Save overlappingRect for each control child refreshChildrenLastOverlappedRects( control, false ); if (control.SetValidityToRender()) { revalidatedControls.Add(control); } return fullBuffer; }
private void updateLayout(Control control, List<Control> revalidatedControls) { LayoutInfo lastLayoutInfo = control.lastLayoutInfo; // работаем с родительским элементом управления if (control.Parent != null) { bool needUpdateParentLayout = true; // если размер текущего контрола не изменился, то состояние ревалидации не распространяется // вверх по дереву элементов, и мы переходим к работе с дочерними элементами // в противном случае мы добавляем родительский элемент в конец очереди ревалидации, и // возвращаем управление if (lastLayoutInfo.validity != LayoutValidity.Nothing) { control.Measure(lastLayoutInfo.measureArgument); // if (lastLayoutInfo.unclippedDesiredSize == control.layoutInfo.unclippedDesiredSize) { if (checkDesiredSizeNotChangedRecursively(control)) { needUpdateParentLayout = false; } } if (needUpdateParentLayout) { // mark the parent control for invalidation too and enqueue them control.Parent.Invalidate(); // мы можем закончить с этим элементом, поскольку мы уже добавили // в конец очереди его родителя, и мы все равно вернемся к нему в след. раз return; } } // работаем с дочерними элементами управления // вызываем для текущего контрола Measure&Arrange с последними значениями аргументов if (lastLayoutInfo.validity == LayoutValidity.Nothing && control.Parent != null) { throw new InvalidOperationException("Assertion failed."); } // rootElement - особый случай if (control.Parent == null) { if (control != RootElement) { throw new InvalidOperationException("Control has no parent but is not known rootElement."); } control.Measure(RootElementRect.Size); control.Arrange(RootElementRect); } else { control.Measure(lastLayoutInfo.measureArgument); control.Arrange(lastLayoutInfo.renderSlotRect); } // update render buffers of current control and its children RenderingBuffer buffer = getOrCreateBufferForControl(control); RenderingBuffer fullBuffer = getOrCreateFullBufferForControl(control); // replace buffers if control has grown LayoutInfo layoutInfo = control.layoutInfo; if (layoutInfo.renderSize.width > buffer.Width || layoutInfo.renderSize.height > buffer.Height) { buffer = new RenderingBuffer(layoutInfo.renderSize.width, layoutInfo.renderSize.height); fullBuffer = new RenderingBuffer(layoutInfo.renderSize.width, layoutInfo.renderSize.height); buffers[control] = buffer; fullBuffers[control] = fullBuffer; } buffer.Clear(); if (control.RenderSize.Width != 0 && control.RenderSize.Height != 0) control.Render(buffer); // проверяем дочерние контролы - если их layoutInfo не изменился по сравнению с последним, // то мы можем взять их последний renderBuffer без обновления и применить к текущему контролу fullBuffer.CopyFrom(buffer); IList<Control> children = control.Children; foreach (Control child in children) { if (child.Visibility == Visibility.Visible) { RenderingBuffer fullChildBuffer = processControl(child, revalidatedControls); fullBuffer.ApplyChild(fullChildBuffer, child.ActualOffset, child.RenderSize, child.RenderSlotRect, child.LayoutClip); } else { // чтобы следующий Invalidate перезаписал lastLayoutInfo if (child.SetValidityToRender()) { revalidatedControls.Add(child); } } } // Save overlappingRect for each control child refreshChildrenLastOverlappedRects( control, false ); if (control.SetValidityToRender()) { revalidatedControls.Add(control); } addControlToRenderingUpdatedList(control); }