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 override Size MeasureOverride(Size availableSize) { if (!string.IsNullOrEmpty(caption)) { Size minButtonSize = new Size(caption.Length + 10, 2); return minButtonSize; } else return new Size(8, 2); }
/// <summary> /// Maximizes the terminal window size and terminal buffer size. /// Current size is stored. /// </summary> public void Maximize( ) { if ( usingLinux ) { // Doesn't work in Konsole Console.Write ("\x1B[9;1t"); return; } if ( maximized ) return; // savedBufferSize = new Size(Console.BufferWidth, Console.BufferHeight); Win32.SendMessage(getConsoleWindowHwnd(), Win32.WM_SYSCOMMAND, Win32.SC_MAXIMIZE, IntPtr.Zero); int maxWidth = Console.LargestWindowWidth; int maxHeight = Console.LargestWindowHeight; Console.SetWindowPosition( 0, 0 ); Console.SetBufferSize(maxWidth, maxHeight); Console.SetWindowSize(maxWidth, maxHeight); // Apply new sizes to Canvas CanvasSize = new Size(maxWidth, maxHeight); renderer.RootElementRect = new Rect(canvas.Size); renderer.UpdateLayout(); maximized = true; }
/// <summary> /// Размещает элементы вертикально, самым простым методом. /// </summary> /// <param name="availableSize"></param> /// <returns></returns> protected override Size MeasureOverride(Size availableSize) { if (orientation == Orientation.Vertical) { int totalHeight = 0; int maxWidth = 0; foreach (Control child in base.Children) { child.Measure(availableSize); totalHeight += child.DesiredSize.Height; if (child.DesiredSize.Width > maxWidth) { maxWidth = child.DesiredSize.Width; } } foreach (Control child in base.Children) { child.Measure(new Size(maxWidth, child.DesiredSize.Height)); } return new Size(maxWidth, totalHeight); } else { int totalWidth = 0; int maxHeight = 0; foreach (Control child in base.Children) { child.Measure(availableSize); totalWidth += child.DesiredSize.Width; if (child.DesiredSize.Height > maxHeight) maxHeight = child.DesiredSize.Height; } foreach (Control child in base.Children) child.Measure(new Size(child.DesiredSize.Width, maxHeight)); return new Size(totalWidth, maxHeight); } }
protected override Size ArrangeOverride(Size finalSize) { LastArrangeOverrideArgument = finalSize; LastArrangeOverrideResult = base.ArrangeOverride(finalSize); if (null != Content) { Content.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height)); } return LastArrangeOverrideResult.Value; }
protected override Size ArrangeOverride(Size finalSize) { if ( null == content) return finalSize; Rect contentRect = new Rect(1, 1, Math.Max( 0, finalSize.Width - 2), Math.Max(0, finalSize.Height - 2)); content.Arrange( contentRect ); return finalSize; }
public Rect(Point location, Size size) { if (size.IsEmpty) { this = s_empty; } else { this.x = location.x; this.y = location.y; this.width = size.width; this.height = size.height; } }
protected override Size MeasureOverride(Size availableSize) { LastMeasureOverrideArgument = availableSize; Size res; if (null != Content) { Content.Measure(availableSize); res = Content.DesiredSize; } else { res = base.MeasureOverride(availableSize); } LastMeasureOverrideResult = res; return res; }
protected override Size MeasureOverride(Size availableSize) { int windowsStartIndex = 0; if ( mainMenu != null ) { assert( Children[ 0 ] == mainMenu ); mainMenu.Measure( new Size(availableSize.Width, 1) ); windowsStartIndex++; } // Дочерние окна могут занимать сколько угодно пространства, // но при заданных Width/Height их размеры будут учтены // системой размещения автоматически for ( int index = windowsStartIndex; index < Children.Count; index++ ) { Control control = Children[ index ]; Window window = ( Window ) control; window.Measure( new Size( int.MaxValue, int.MaxValue ) ); } return availableSize; }
/// <summary> /// Maximizes the terminal window size and terminal buffer size. /// Current size is stored. /// </summary> public void Maximize( ) { if ( usingLinux ) { // Doesn't work in Konsole Console.Write ("\x1B[9;1t"); return; } if ( maximized ) return; // savedWindowRect = new Rect( new Point( Console.WindowLeft, Console.WindowTop ), new Size( Console.WindowWidth, Console.WindowHeight ) ); savedBufferSize = new Size(Console.BufferWidth, Console.BufferHeight); Win32.SendMessage(getConsoleWindowHwnd(), Win32.WM_SYSCOMMAND, Win32.SC_MAXIMIZE, IntPtr.Zero); int maxWidth = Console.LargestWindowWidth; int maxHeight = Console.LargestWindowHeight; Console.SetWindowPosition( 0, 0 ); Console.SetBufferSize(maxWidth, maxHeight); Console.SetWindowSize(maxWidth, maxHeight); // maximized = true; }
protected override Size ArrangeOverride( Size finalSize ) { int currentX = 0; for ( int x = 0; x < columnsWidths.Length; x++ ) { int currentY = 0; for ( int y = 0; y < rowsHeights.Length; y++ ) { Children[y * columnsWidths.Length + x].Arrange( new Rect( new Point(currentX, currentY), new Size(columnsWidths[x], rowsHeights[y]) ) ); currentY += rowsHeights[ y ]; } currentX += columnsWidths[ x ]; } return new Size(columnsWidths.Sum(), rowsHeights.Sum()); }
/// <summary> /// Оверлоад для оптимизированного наложения в случае, когда известно, что в дочернем /// контроле поменялась лишь часть, идентифицируемая параметром affectedRect. /// Будет обработана только эта часть дочернего контрола, и количество операций уменьшится. /// </summary> /// <param name="childBuffer"></param> /// <param name="actualOffset"></param> /// <param name="childRenderSize"></param> /// <param name="renderSlotRect"></param> /// <param name="layoutClip"></param> /// <param name="affectedRect">Прямоугольник в дочернем контроле, который был изменен.</param> public void ApplyChild(RenderingBuffer childBuffer, Vector actualOffset, Size childRenderSize, Rect renderSlotRect, Rect layoutClip, Rect? affectedRect) { // Считаем finalRect - прямоугольник относительно parent, который нужно закрасить Rect finalRect = layoutClip; if (affectedRect != null) finalRect.Intersect(affectedRect.Value); // Если child.RenderSlotRect больше child.RenderSize, а rendering buffer // дочернего контрола больше его RenderSize (такое бывает после уменьшения // размеров контрола - т.к. буфер может только увеличиваться, но не уменьшаться) - // то нам нужно либо передать в метод ApplyChild и child.RenderSize, либо // выполнить пересечение заранее finalRect.Intersect(new Rect(new Point(0, 0), childRenderSize)); // Because cannot call Offset() method of empty rect if ( finalRect.IsEmpty ) return; finalRect.Offset(actualOffset); finalRect.Intersect( renderSlotRect ); // Нужно также учесть размеры буфера текущего контрола finalRect.Intersect( new Rect(new Point(0, 0), new Size(this.width, this.height)) ); for ( int x = finalRect.Left; x < finalRect.Right; x++ ) { int parentX = x; int childX = parentX - actualOffset.x; for ( int y = finalRect.Top; y < finalRect.Bottom; y++ ) { int parentY = y; int childY = parentY - actualOffset.y; CHAR_INFO charInfo = childBuffer.buffer[childX, childY]; int opacity = childBuffer.opacityMatrix[childX, childY]; // Для полностью прозрачных пикселей родительского буфера - присваиваем и значение // пикселя, и значение opacity, дальше дело за следующим родителем if ( this.opacityMatrix[ parentX, parentY ] == 2 || this.opacityMatrix[ parentX, parentY ] == 6 ) { this.buffer[ parentX, parentY ] = charInfo; this.opacityMatrix[ parentX, parentY ] = opacity; } else { // В остальных случаях opacity родительского буфера остаётся, а // сам пиксель зависит от opacity дочернего элемента if ( opacity == 0 || opacity == 4 ) { this.buffer[ parentX, parentY ] = charInfo; } else if ( opacity == 1 || opacity == 5 ) { charInfo.Attributes = Colors.Blend( Color.DarkGray, Color.Black ); charInfo.UnicodeChar = buffer[ parentX, parentY ].UnicodeChar; buffer[ parentX, parentY ] = charInfo; } else if ( opacity == 3 || opacity == 7 ) { // берем фоновые атрибуты символа из родительского буфера Attr parentAttr = buffer[ parentX, parentY ].Attributes; if ( ( parentAttr & Attr.BACKGROUND_BLUE ) == Attr.BACKGROUND_BLUE ) { charInfo.Attributes |= Attr.BACKGROUND_BLUE; } else { charInfo.Attributes &= ~Attr.BACKGROUND_BLUE; } if ( ( parentAttr & Attr.BACKGROUND_GREEN ) == Attr.BACKGROUND_GREEN ) { charInfo.Attributes |= Attr.BACKGROUND_GREEN; } else { charInfo.Attributes &= ~Attr.BACKGROUND_GREEN; } if ( ( parentAttr & Attr.BACKGROUND_RED ) == Attr.BACKGROUND_RED ) { charInfo.Attributes |= Attr.BACKGROUND_RED; } else { charInfo.Attributes &= ~Attr.BACKGROUND_RED; } if ( ( parentAttr & Attr.BACKGROUND_INTENSITY ) == Attr.BACKGROUND_INTENSITY ) { charInfo.Attributes |= Attr.BACKGROUND_INTENSITY; } else { charInfo.Attributes &= ~Attr.BACKGROUND_INTENSITY; } buffer[ parentX, parentY ] = charInfo; } } } } }
/// <summary> /// Накладывает буфер дочернего элемента на текущий. Дочерний буфер виртуально накладывается на текущий /// в соответствии с переданным actualOffset, а потом та часть дочернего буфера, которая попадает в /// renderSlotRect, прорисовывается. renderSlotRect определен отн-но текущего буфера (а не дочернего). /// layoutClip определяет, какая часть дочернего буфера будет прорисована в текущий буфер (клиппинг, /// возникающий при применении Margin и Alignment'ов). /// </summary> /// <param name="childBuffer"></param> /// <param name="actualOffset">Смещение буфера дочернего элемента относительно текущего.</param> /// <param name="childRenderSize">Размер отрендеренного дочерним элементом контента - может /// быть меньше размера childBuffer, поэтому нужно передавать явно.</param> /// <param name="renderSlotRect">Размер и положение слота, выделенного дочернему элементу.</param> /// <param name="layoutClip">Часть дочернего буфера, которая будет отрисована - по размеру может быть /// меньше или равна RenderSlotRect.Size. По координатам соотносится с childBuffer.</param> public void ApplyChild(RenderingBuffer childBuffer, Vector actualOffset, Size childRenderSize, Rect renderSlotRect, Rect layoutClip) { ApplyChild( childBuffer, actualOffset, childRenderSize, renderSlotRect, layoutClip, null ); }
protected override Size MeasureOverride( Size availableSize ) { this.Children[0].Measure(availableSize); return this.Children[ 0 ].DesiredSize; }
protected override Size ArrangeOverride( Size finalSize ) { this.Children[0].Arrange( new Rect(new Point(0, 0), finalSize) ); return finalSize; }
public Rect(Size size) { if (size.IsEmpty) { this = s_empty; } else { this.x = this.y = 0; this.width = size.Width; this.height = size.Height; } }
protected override Size MeasureOverride(Size availableSize) { return new Size(1, 1); }
protected override Size MeasureOverride(Size availableSize) { int length = 2; if ( !string.IsNullOrEmpty( Title ) ) length += getTitleLength( Title ); if ( !string.IsNullOrEmpty( TitleRight ) ) length += TitleRight.Length; if ( !string.IsNullOrEmpty( Title ) && !string.IsNullOrEmpty( TitleRight ) ) length++; return new Size(length, 1); }
protected override Size MeasureOverride(Size availableSize) { if (Content == null) return new Size(0, 0); if ( shadow ) { // 1 строку и 1 столбец оставляем для прозрачного пространства, остальное занимает Content Content.Measure( new Size( availableSize.Width - 3, availableSize.Height - 4 ) ); // +2 for left empty space and right return new Size( Content.DesiredSize.Width + 3 + 2, Content.DesiredSize.Height + 4 ); } else { // 1 строку и 1 столбец оставляем для прозрачного пространства, остальное занимает Content Content.Measure(new Size(availableSize.Width - 2, availableSize.Height - 3)); // +2 for left empty space and right return new Size(Content.DesiredSize.Width + 2 + 2, Content.DesiredSize.Height + 3); } }
protected override Size ArrangeOverride(Size finalSize) { if (Content != null) { Content.Arrange(new Rect(1, 1, finalSize.width - 4, finalSize.height - 3)); } return finalSize; }
protected override Size ArrangeOverride(Size finalSize) { if ( Content == null ) return finalSize; int width = finalSize.Width; int height = finalSize.Height; Rect finalRect = new Rect( new Point( -deltaX, -deltaY ), new Size( deltaX + Math.Max( 0, verticalScrollVisible ? width - 1 : width ), deltaY + Math.Max( 0, horizontalScrollVisible ? height - 1 : height ) ) ); // если мы сдвинули окно просмотра, а потом размеры, доступные контролу, увеличились, // мы должны вернуть дочерний контрол в точку (0, 0) if (deltaX > Content.DesiredSize.Width - Math.Max(0, verticalScrollVisible ? width - 1 : width)) { deltaX = 0; finalRect = new Rect(new Point(-deltaX, -deltaY), new Size( deltaX + Math.Max(0, verticalScrollVisible ? width - 1 : width), deltaY + Math.Max(0, horizontalScrollVisible ? height - 1 : height)) ); } if (deltaY > Content.DesiredSize.Height - Math.Max(0, horizontalScrollVisible ? height - 1 : height)) { deltaY = 0; finalRect = new Rect(new Point(-deltaX, -deltaY), new Size( deltaX + Math.Max(0, verticalScrollVisible ? width - 1 : width), deltaY + Math.Max(0, horizontalScrollVisible ? height - 1 : height)) ); } Content.Arrange( finalRect ); int resultWidth = Math.Min(verticalScrollVisible ? 1 + finalRect.Width : finalRect.Width, width); int resultHeight = Math.Min(horizontalScrollVisible ? 1 + finalRect.Height : finalRect.Height, height); Size result = new Size(resultWidth, resultHeight); return result; }
protected override Size MeasureOverride( Size availableSize ) { listBox.Measure( availableSize ); return listBox.DesiredSize; }
public static Rect Inflate(Rect rect, Size size) { rect.Inflate(size.width, size.height); return rect; }
public void Inflate(Size size) { this.Inflate(size.width, size.height); }
protected override Size ArrangeOverride(Size finalSize) { int windowsStartIndex = 0; if ( mainMenu != null ) { assert( Children[ 0 ] == mainMenu ); mainMenu.Arrange( new Rect(0, 0, finalSize.Width, 1) ); windowsStartIndex++; } // сколько дочерние окна хотели - столько и получают for ( int index = windowsStartIndex; index < Children.Count; index++ ) { Control control = Children[ index ]; Window window = ( Window ) control; int x; if ( window.X.HasValue ) { x = window.X.Value; } else { x = ( finalSize.Width - window.DesiredSize.Width )/2; } int y; if ( window.Y.HasValue ) { y = window.Y.Value; } else { y = ( finalSize.Height - window.DesiredSize.Height )/2; } window.Arrange( new Rect( x, y, window.DesiredSize.Width, window.DesiredSize.Height ) ); } return finalSize; }
protected override Size ArrangeOverride(Size finalSize) { if ( Content != null ) { if ( shadow ) { // 1 pixel from all borders - for popup padding // 1 pixel from top - for transparent region // Additional pixel from right and bottom - for shadow Content.Arrange( new Rect( new Point( 2, 2 ), new Size( finalSize.Width - 5, finalSize.Height - 4 ) ) ); } else { // 1 pixel from all borders - for popup padding // 1 pixel from top - for transparent region Content.Arrange(new Rect(new Point(2, 2), new Size(finalSize.Width - 4, finalSize.Height - 3))); } } return finalSize; }
protected override Size MeasureOverride(Size availableSize) { Size desired = new Size( getSize( ) + 2, 1 ); return new Size( Math.Min( desired.Width, availableSize.Width ), Math.Min( desired.Height, availableSize.Height ) ); }
protected override Size MeasureOverride(Size availableSize) { if ( Content == null ) return new Size( Math.Min(availableSize.Width ,EMPTY_WINDOW_SIZE.Width + 4), Math.Min(availableSize.Height, EMPTY_WINDOW_SIZE.Height + 3)); if ( availableSize.Width != int.MaxValue && availableSize.Height != int.MaxValue ) { // reserve 2 pixels for frame and 2/1 pixels for shadow Content.Measure( new Size( availableSize.width - 4, availableSize.height - 3 ) ); } else { int width = availableSize.Width != int.MaxValue ? availableSize.Width - 4 : int.MaxValue; int height = availableSize.Height != int.MaxValue ? availableSize.Height - 3 : int.MaxValue; Content.Measure( new Size(width, height)); } var result = new Size(Content.DesiredSize.width + 4, Content.DesiredSize.height + 3); return result; }
protected override Size ArrangeOverride( Size finalSize ) { listBox.Arrange( new Rect(finalSize) ); return finalSize; }
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; }