mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-04 18:26:39 +02:00
[MouseJump][CQ]Refactor "common" classes into a separate project (#34333)
* [Mouse Jump] - moving common code to MouseJump.Common project - #25482 * [Mouse Jump] - fixing warnings in MouseJump.Common - #25482 * [MouseJump] - cherrypick 5653b4 - Exclude MouseJump Common tests from the checks # Conflicts: # src/modules/MouseUtils/MouseJump.Common.UnitTests/MouseJump.Common.UnitTests.csproj * [mOuSEjUMP] - cherry pick 61aab9 - Fix ci build issues # Conflicts: # src/modules/MouseUtils/MouseJump.Common.UnitTests/MouseJump.Common.UnitTests.csproj * [Mouse Jump] - remove project type guids - #25482 * [Mouse Jump] - simplify mousejump *.csproj files - #25482 * [Mouse Jump] - fixing broken tests - #25482 * [Mouse Jump] - fixing broken build - #25482 * [Mouse Jump] - editing MouseJump.Common.UnitTests.csproj - #25482 * [Mouse Jump] - editing MouseJump.Common.csproj (UseWindowsForms=true) - #25482 * [Mouse Jump] - fixing spellcheck - #25482 * [MouseJump] - enabled implicit usings - #25482 * [Mouse Jump] - re-add csproj attributes - #27511 * ci: Fix signing of Common dll --------- Co-authored-by: Clayton <mike.clayton@delinian.com>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace MouseJump.Common.Models.Drawing;
|
||||
|
||||
public sealed class BoxBounds
|
||||
{
|
||||
/*
|
||||
|
||||
see https://www.w3schools.com/css/css_boxmodel.asp
|
||||
|
||||
+--------------[bounds]---------------+
|
||||
|▒▒▒▒▒▒▒▒▒▒▒▒▒▒[margin]▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒|
|
||||
|▒▒▓▓▓▓▓▓▓▓▓▓▓▓[border]▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒|
|
||||
|▒▒▓▓░░░░░░░░░░[padding]░░░░░░░░░░▓▓▒▒|
|
||||
|▒▒▓▓░░ ░░▓▓▒▒|
|
||||
|▒▒▓▓░░ ░░▓▓▒▒|
|
||||
|▒▒▓▓░░ [content] ░░▓▓▒▒|
|
||||
|▒▒▓▓░░ ░░▓▓▒▒|
|
||||
|▒▒▓▓░░ ░░▓▓▒▒|
|
||||
|▒▒▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▒▒|
|
||||
|▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒|
|
||||
|▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒|
|
||||
+-------------------------------------+
|
||||
|
||||
*/
|
||||
|
||||
public BoxBounds(
|
||||
RectangleInfo outerBounds,
|
||||
RectangleInfo marginBounds,
|
||||
RectangleInfo borderBounds,
|
||||
RectangleInfo paddingBounds,
|
||||
RectangleInfo contentBounds)
|
||||
{
|
||||
this.OuterBounds = outerBounds ?? throw new ArgumentNullException(nameof(outerBounds));
|
||||
this.MarginBounds = marginBounds ?? throw new ArgumentNullException(nameof(marginBounds));
|
||||
this.BorderBounds = borderBounds ?? throw new ArgumentNullException(nameof(borderBounds));
|
||||
this.PaddingBounds = paddingBounds ?? throw new ArgumentNullException(nameof(paddingBounds));
|
||||
this.ContentBounds = contentBounds ?? throw new ArgumentNullException(nameof(contentBounds));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the outer bounds of this layout box.
|
||||
/// </summary>
|
||||
public RectangleInfo OuterBounds
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public RectangleInfo MarginBounds
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public RectangleInfo BorderBounds
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public RectangleInfo PaddingBounds
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bounds of the content area for this layout box.
|
||||
/// </summary>
|
||||
public RectangleInfo ContentBounds
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace MouseJump.Common.Models.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Immutable version of a System.Drawing.Point object with some extra utility methods.
|
||||
/// </summary>
|
||||
public sealed class PointInfo
|
||||
{
|
||||
public PointInfo(decimal x, decimal y)
|
||||
{
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
}
|
||||
|
||||
public PointInfo(Point point)
|
||||
: this(point.X, point.Y)
|
||||
{
|
||||
}
|
||||
|
||||
public decimal X
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Y
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves this PointInfo inside the specified RectangleInfo.
|
||||
/// </summary>
|
||||
public PointInfo Clamp(RectangleInfo outer)
|
||||
{
|
||||
return new(
|
||||
x: Math.Clamp(this.X, outer.X, outer.Right),
|
||||
y: Math.Clamp(this.Y, outer.Y, outer.Bottom));
|
||||
}
|
||||
|
||||
public PointInfo Scale(decimal scalingFactor) => new(this.X * scalingFactor, this.Y * scalingFactor);
|
||||
|
||||
public PointInfo Offset(PointInfo amount) => new(this.X + amount.X, this.Y + amount.Y);
|
||||
|
||||
public Point ToPoint() => new((int)this.X, (int)this.Y);
|
||||
|
||||
public SizeInfo ToSize()
|
||||
{
|
||||
return new((int)this.X, (int)this.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stretches the point to the same proportional position in targetBounds as
|
||||
/// it currently is in sourceBounds
|
||||
/// </summary>
|
||||
public PointInfo Stretch(RectangleInfo source, RectangleInfo target)
|
||||
{
|
||||
return new PointInfo(
|
||||
x: ((this.X - source.X) / source.Width * target.Width) + target.X,
|
||||
y: ((this.Y - source.Y) / source.Height * target.Height) + target.Y);
|
||||
}
|
||||
|
||||
public PointInfo Truncate() =>
|
||||
new(
|
||||
(int)this.X,
|
||||
(int)this.Y);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{" +
|
||||
$"{nameof(this.X)}={this.X}," +
|
||||
$"{nameof(this.Y)}={this.Y}" +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
using MouseJump.Common.Models.Styles;
|
||||
using BorderStyle = MouseJump.Common.Models.Styles.BorderStyle;
|
||||
|
||||
namespace MouseJump.Common.Models.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Immutable version of a System.Drawing.Rectangle object with some extra utility methods.
|
||||
/// </summary>
|
||||
public sealed class RectangleInfo
|
||||
{
|
||||
public static readonly RectangleInfo Empty = new(0, 0, 0, 0);
|
||||
|
||||
public RectangleInfo(decimal x, decimal y, decimal width, decimal height)
|
||||
{
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
this.Width = width;
|
||||
this.Height = height;
|
||||
}
|
||||
|
||||
public RectangleInfo(Rectangle rectangle)
|
||||
: this(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height)
|
||||
{
|
||||
}
|
||||
|
||||
public RectangleInfo(Point location, SizeInfo size)
|
||||
: this(location.X, location.Y, size.Width, size.Height)
|
||||
{
|
||||
}
|
||||
|
||||
public RectangleInfo(SizeInfo size)
|
||||
: this(0, 0, size.Width, size.Height)
|
||||
{
|
||||
}
|
||||
|
||||
public decimal X
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Y
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Width
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Height
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public decimal Left =>
|
||||
this.X;
|
||||
|
||||
[JsonIgnore]
|
||||
public decimal Top =>
|
||||
this.Y;
|
||||
|
||||
[JsonIgnore]
|
||||
public decimal Right =>
|
||||
this.X + this.Width;
|
||||
|
||||
[JsonIgnore]
|
||||
public decimal Bottom =>
|
||||
this.Y + this.Height;
|
||||
|
||||
[JsonIgnore]
|
||||
public decimal Area =>
|
||||
this.Width * this.Height;
|
||||
|
||||
[JsonIgnore]
|
||||
public PointInfo Location =>
|
||||
new(this.X, this.Y);
|
||||
|
||||
[JsonIgnore]
|
||||
public PointInfo Midpoint =>
|
||||
new(
|
||||
x: this.X + (this.Width / 2),
|
||||
y: this.Y + (this.Height / 2));
|
||||
|
||||
[JsonIgnore]
|
||||
public SizeInfo Size => new(this.Width, this.Height);
|
||||
|
||||
/// <summary>
|
||||
/// Centers the rectangle around a specified point.
|
||||
/// </summary>
|
||||
/// <param name="point">The <see cref="PointInfo"/> around which the rectangle will be centered.</param>
|
||||
/// <returns>A new <see cref="RectangleInfo"/> that is centered around the specified point.</returns>
|
||||
public RectangleInfo Center(PointInfo point) =>
|
||||
new(
|
||||
x: point.X - (this.Width / 2),
|
||||
y: point.Y - (this.Height / 2),
|
||||
width: this.Width,
|
||||
height: this.Height);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new <see cref="RectangleInfo"/> that is moved within the bounds of the specified outer rectangle.
|
||||
/// If the current rectangle is larger than the outer rectangle, an exception is thrown.
|
||||
/// </summary>
|
||||
/// <param name="outer">The outer <see cref="RectangleInfo"/> within which to confine this rectangle.</param>
|
||||
/// <returns>A new <see cref="RectangleInfo"/> that is the result of moving this rectangle within the bounds of the outer rectangle.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown when the current rectangle is larger than the outer rectangle.</exception>
|
||||
public RectangleInfo Clamp(RectangleInfo outer)
|
||||
{
|
||||
if ((this.Width > outer.Width) || (this.Height > outer.Height))
|
||||
{
|
||||
throw new ArgumentException($"Value cannot be larger than {nameof(outer)}.");
|
||||
}
|
||||
|
||||
return new(
|
||||
x: Math.Clamp(this.X, outer.X, outer.Right - this.Width),
|
||||
y: Math.Clamp(this.Y, outer.Y, outer.Bottom - this.Height),
|
||||
width: this.Width,
|
||||
height: this.Height);
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// Adapted from https://github.com/dotnet/runtime
|
||||
/// See https://github.com/dotnet/runtime/blob/dfd618dc648ba9b11dd0f8034f78113d69f223cd/src/libraries/System.Drawing.Primitives/src/System/Drawing/Rectangle.cs
|
||||
/// </remarks>
|
||||
public bool Contains(decimal x, decimal y) =>
|
||||
this.X <= x && x < this.X + this.Width && this.Y <= y && y < this.Y + this.Height;
|
||||
|
||||
/// <remarks>
|
||||
/// Adapted from https://github.com/dotnet/runtime
|
||||
/// See https://github.com/dotnet/runtime/blob/dfd618dc648ba9b11dd0f8034f78113d69f223cd/src/libraries/System.Drawing.Primitives/src/System/Drawing/Rectangle.cs
|
||||
/// </remarks>
|
||||
public bool Contains(PointInfo pt) =>
|
||||
this.Contains(pt.X, pt.Y);
|
||||
|
||||
/// <remarks>
|
||||
/// Adapted from https://github.com/dotnet/runtime
|
||||
/// See https://github.com/dotnet/runtime/blob/dfd618dc648ba9b11dd0f8034f78113d69f223cd/src/libraries/System.Drawing.Primitives/src/System/Drawing/Rectangle.cs
|
||||
/// </remarks>
|
||||
public bool Contains(RectangleInfo rect) =>
|
||||
(this.X <= rect.X) && (rect.X + rect.Width <= this.X + this.Width) &&
|
||||
(this.Y <= rect.Y) && (rect.Y + rect.Height <= this.Y + this.Height);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new <see cref="RectangleInfo"/> that is larger than the current rectangle.
|
||||
/// The dimensions of the new rectangle are calculated by enlarging the current rectangle's dimensions by the size of the border.
|
||||
/// </summary>
|
||||
/// <param name="border">The <see cref="BorderStyle"/> that specifies the amount to enlarge the rectangle on each side.</param>
|
||||
/// <returns>A new <see cref="RectangleInfo"/> that is larger than the current rectangle by the specified border amounts.</returns>
|
||||
public RectangleInfo Enlarge(BorderStyle border) =>
|
||||
new(
|
||||
this.X - border.Left,
|
||||
this.Y - border.Top,
|
||||
this.Width + border.Horizontal,
|
||||
this.Height + border.Vertical);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new <see cref="RectangleInfo"/> that is larger than the current rectangle.
|
||||
/// The dimensions of the new rectangle are calculated by enlarging the current rectangle's dimensions by the size of the margin.
|
||||
/// </summary>
|
||||
/// <param name="margin">The <see cref="MarginStyle"/> that specifies the amount to enlarge the rectangle on each side.</param>
|
||||
/// <returns>A new <see cref="RectangleInfo"/> that is larger than the current rectangle by the specified margin amounts.</returns>
|
||||
public RectangleInfo Enlarge(MarginStyle margin) =>
|
||||
new(
|
||||
this.X - margin.Left,
|
||||
this.Y - margin.Top,
|
||||
this.Width + margin.Horizontal,
|
||||
this.Height + margin.Vertical);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new <see cref="RectangleInfo"/> that is larger than the current rectangle.
|
||||
/// The dimensions of the new rectangle are calculated by enlarging the current rectangle's dimensions by the size of the padding.
|
||||
/// </summary>
|
||||
/// <param name="padding">The <see cref="PaddingStyle"/> that specifies the amount to enlarge the rectangle on each side.</param>
|
||||
/// <returns>A new <see cref="RectangleInfo"/> that is larger than the current rectangle by the specified padding amounts.</returns>
|
||||
public RectangleInfo Enlarge(PaddingStyle padding) =>
|
||||
new(
|
||||
this.X - padding.Left,
|
||||
this.Y - padding.Top,
|
||||
this.Width + padding.Horizontal,
|
||||
this.Height + padding.Vertical);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new <see cref="RectangleInfo"/> that is offset by the specified amount.
|
||||
/// </summary>
|
||||
/// <param name="amount">The <see cref="SizeInfo"/> representing the amount to offset in both the X and Y directions.</param>
|
||||
/// <returns>A new <see cref="RectangleInfo"/> that is offset by the specified amount.</returns>
|
||||
public RectangleInfo Offset(SizeInfo amount) =>
|
||||
this.Offset(amount.Width, amount.Height);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new <see cref="RectangleInfo"/> that is offset by the specified X and Y distances.
|
||||
/// </summary>
|
||||
/// <param name="dx">The distance to offset the rectangle along the X-axis.</param>
|
||||
/// <param name="dy">The distance to offset the rectangle along the Y-axis.</param>
|
||||
/// <returns>A new <see cref="RectangleInfo"/> that is offset by the specified X and Y distances.</returns>
|
||||
public RectangleInfo Offset(decimal dx, decimal dy) =>
|
||||
new(this.X + dx, this.Y + dy, this.Width, this.Height);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new <see cref="RectangleInfo"/> that is a scaled version of the current rectangle.
|
||||
/// The dimensions of the new rectangle are calculated by multiplying the current rectangle's dimensions by the scaling factor.
|
||||
/// </summary>
|
||||
/// <param name="scalingFactor">The factor by which to scale the rectangle's dimensions.</param>
|
||||
/// <returns>A new <see cref="RectangleInfo"/> that is a scaled version of the current rectangle.</returns>
|
||||
public RectangleInfo Scale(decimal scalingFactor) =>
|
||||
new(
|
||||
this.X * scalingFactor,
|
||||
this.Y * scalingFactor,
|
||||
this.Width * scalingFactor,
|
||||
this.Height * scalingFactor);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new <see cref="RectangleInfo"/> that is smaller than the current rectangle.
|
||||
/// The dimensions of the new rectangle are calculated by shrinking the current rectangle's dimensions by the size of the border.
|
||||
/// </summary>
|
||||
/// <param name="border">The <see cref="BorderStyle"/> that specifies the amount to shrink the rectangle on each side.</param>
|
||||
/// <returns>A new <see cref="RectangleInfo"/> that is smaller than the current rectangle by the specified border amounts.</returns>
|
||||
public RectangleInfo Shrink(BorderStyle border) =>
|
||||
new(
|
||||
this.X + border.Left,
|
||||
this.Y + border.Top,
|
||||
this.Width - border.Horizontal,
|
||||
this.Height - border.Vertical);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new <see cref="RectangleInfo"/> that is smaller than the current rectangle.
|
||||
/// The dimensions of the new rectangle are calculated by shrinking the current rectangle's dimensions by the size of the margin.
|
||||
/// </summary>
|
||||
/// <param name="margin">The <see cref="MarginStyle"/> that specifies the amount to shrink the rectangle on each side.</param>
|
||||
/// <returns>A new <see cref="RectangleInfo"/> that is smaller than the current rectangle by the specified margin amounts.</returns>
|
||||
public RectangleInfo Shrink(MarginStyle margin) =>
|
||||
new(
|
||||
this.X + margin.Left,
|
||||
this.Y + margin.Top,
|
||||
this.Width - margin.Horizontal,
|
||||
this.Height - margin.Vertical);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new <see cref="RectangleInfo"/> that is smaller than the current rectangle.
|
||||
/// The dimensions of the new rectangle are calculated by shrinking the current rectangle's dimensions by the size of the padding.
|
||||
/// </summary>
|
||||
/// <param name="padding">The <see cref="PaddingStyle"/> that specifies the amount to shrink the rectangle on each side.</param>
|
||||
/// <returns>A new <see cref="RectangleInfo"/> that is smaller than the current rectangle by the specified padding amounts.</returns>
|
||||
public RectangleInfo Shrink(PaddingStyle padding) =>
|
||||
new(
|
||||
this.X + padding.Left,
|
||||
this.Y + padding.Top,
|
||||
this.Width - padding.Horizontal,
|
||||
this.Height - padding.Vertical);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new <see cref="RectangleInfo"/> where the X, Y, Width, and Height properties of the current rectangle are truncated to integers.
|
||||
/// </summary>
|
||||
/// <returns>A new <see cref="RectangleInfo"/> with the X, Y, Width, and Height properties of the current rectangle truncated to integers.</returns>
|
||||
public RectangleInfo Truncate() =>
|
||||
new(
|
||||
(int)this.X,
|
||||
(int)this.Y,
|
||||
(int)this.Width,
|
||||
(int)this.Height);
|
||||
|
||||
/// <remarks>
|
||||
/// Adapted from https://github.com/dotnet/runtime
|
||||
/// See https://github.com/dotnet/runtime/blob/dfd618dc648ba9b11dd0f8034f78113d69f223cd/src/libraries/System.Drawing.Primitives/src/System/Drawing/Rectangle.cs
|
||||
/// </remarks>
|
||||
public RectangleInfo Union(RectangleInfo rect)
|
||||
{
|
||||
var x1 = Math.Min(this.X, rect.X);
|
||||
var x2 = Math.Max(this.X + this.Width, rect.X + rect.Width);
|
||||
var y1 = Math.Min(this.Y, rect.Y);
|
||||
var y2 = Math.Max(this.Y + this.Height, rect.Y + rect.Height);
|
||||
|
||||
return new RectangleInfo(x1, y1, x2 - x1, y2 - y1);
|
||||
}
|
||||
|
||||
public Rectangle ToRectangle() =>
|
||||
new(
|
||||
(int)this.X,
|
||||
(int)this.Y,
|
||||
(int)this.Width,
|
||||
(int)this.Height);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{" +
|
||||
$"{nameof(this.Left)}={this.Left}," +
|
||||
$"{nameof(this.Top)}={this.Top}," +
|
||||
$"{nameof(this.Width)}={this.Width}," +
|
||||
$"{nameof(this.Height)}={this.Height}" +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace MouseJump.Common.Models.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Immutable version of a System.Windows.Forms.Screen object so we don't need to
|
||||
/// take a dependency on WinForms just for screen info.
|
||||
/// </summary>
|
||||
public sealed class ScreenInfo
|
||||
{
|
||||
public ScreenInfo(int handle, bool primary, RectangleInfo displayArea, RectangleInfo workingArea)
|
||||
{
|
||||
this.Handle = handle;
|
||||
this.Primary = primary;
|
||||
this.DisplayArea = displayArea ?? throw new ArgumentNullException(nameof(displayArea));
|
||||
this.WorkingArea = workingArea ?? throw new ArgumentNullException(nameof(workingArea));
|
||||
}
|
||||
|
||||
public int Handle
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public bool Primary
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public RectangleInfo DisplayArea
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public RectangleInfo WorkingArea
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using MouseJump.Common.Models.Styles;
|
||||
using BorderStyle = MouseJump.Common.Models.Styles.BorderStyle;
|
||||
|
||||
namespace MouseJump.Common.Models.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Immutable version of a System.Drawing.Size object with some extra utility methods.
|
||||
/// </summary>
|
||||
public sealed class SizeInfo
|
||||
{
|
||||
public SizeInfo(decimal width, decimal height)
|
||||
{
|
||||
this.Width = width;
|
||||
this.Height = height;
|
||||
}
|
||||
|
||||
public SizeInfo(Size size)
|
||||
: this(size.Width, size.Height)
|
||||
{
|
||||
}
|
||||
|
||||
public decimal Width
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Height
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public SizeInfo Enlarge(BorderStyle border) =>
|
||||
new(
|
||||
this.Width + border.Horizontal,
|
||||
this.Height + border.Vertical);
|
||||
|
||||
public SizeInfo Enlarge(PaddingStyle padding) =>
|
||||
new(
|
||||
this.Width + padding.Horizontal,
|
||||
this.Height + padding.Vertical);
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the intersection of this size with another size, resulting in a size that represents
|
||||
/// the overlapping dimensions. Both sizes must be non-negative.
|
||||
/// </summary>
|
||||
/// <param name="size">The size to intersect with this instance.</param>
|
||||
/// <returns>A new <see cref="SizeInfo"/> instance representing the intersection of the two sizes.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown when either this size or the specified size has negative dimensions.</exception>
|
||||
public SizeInfo Intersect(SizeInfo size)
|
||||
{
|
||||
if ((this.Width < 0) || (this.Height < 0) || (size.Width < 0) || (size.Height < 0))
|
||||
{
|
||||
throw new ArgumentException("Sizes must be non-negative");
|
||||
}
|
||||
|
||||
return new(
|
||||
Math.Min(this.Width, size.Width),
|
||||
Math.Min(this.Height, size.Height));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="SizeInfo"/> instance with the width and height negated, effectively inverting its dimensions.
|
||||
/// </summary>
|
||||
/// <returns>A new <see cref="SizeInfo"/> instance with inverted dimensions.</returns>
|
||||
public SizeInfo Invert() =>
|
||||
new(-this.Width, -this.Height);
|
||||
|
||||
public SizeInfo Scale(decimal scalingFactor) => new(
|
||||
this.Width * scalingFactor,
|
||||
this.Height * scalingFactor);
|
||||
|
||||
public SizeInfo Shrink(BorderStyle border) =>
|
||||
new(this.Width - border.Horizontal, this.Height - border.Vertical);
|
||||
|
||||
public SizeInfo Shrink(MarginStyle margin) =>
|
||||
new(this.Width - margin.Horizontal, this.Height - margin.Vertical);
|
||||
|
||||
public SizeInfo Shrink(PaddingStyle padding) =>
|
||||
new(this.Width - padding.Horizontal, this.Height - padding.Vertical);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="RectangleInfo"/> instance representing a rectangle with this size,
|
||||
/// positioned at the specified coordinates.
|
||||
/// </summary>
|
||||
/// <param name="x">The x-coordinate of the upper-left corner of the rectangle.</param>
|
||||
/// <param name="y">The y-coordinate of the upper-left corner of the rectangle.</param>
|
||||
/// <returns>A new <see cref="RectangleInfo"/> instance representing the positioned rectangle.</returns>
|
||||
public RectangleInfo PlaceAt(decimal x, decimal y) =>
|
||||
new(x, y, this.Width, this.Height);
|
||||
|
||||
/// <summary>
|
||||
/// Scales this size to fit within the bounds of another size, while maintaining the aspect ratio.
|
||||
/// </summary>
|
||||
/// <param name="bounds">The size to fit this size into.</param>
|
||||
/// <returns>A new <see cref="SizeInfo"/> instance representing the scaled size.</returns>
|
||||
public SizeInfo ScaleToFit(SizeInfo bounds)
|
||||
{
|
||||
var widthRatio = bounds.Width / this.Width;
|
||||
var heightRatio = bounds.Height / this.Height;
|
||||
return widthRatio.CompareTo(heightRatio) switch
|
||||
{
|
||||
< 0 => new(bounds.Width, this.Height * widthRatio),
|
||||
0 => bounds,
|
||||
> 0 => new(this.Width * heightRatio, bounds.Height),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rounds down the width and height of this size to the nearest whole number.
|
||||
/// </summary>
|
||||
/// <returns>A new <see cref="SizeInfo"/> instance with floored dimensions.</returns>
|
||||
public SizeInfo Floor()
|
||||
{
|
||||
return new SizeInfo(
|
||||
Math.Floor(this.Width),
|
||||
Math.Floor(this.Height));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the scaling ratio needed to fit this size within the bounds of another size without distorting the aspect ratio.
|
||||
/// </summary>
|
||||
/// <param name="bounds">The size to fit this size into.</param>
|
||||
/// <returns>The scaling ratio as a decimal.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown if the width or height of the bounds is zero.</exception>
|
||||
public decimal ScaleToFitRatio(SizeInfo bounds)
|
||||
{
|
||||
if (bounds.Width == 0 || bounds.Height == 0)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(bounds.Width)} or {nameof(bounds.Height)} cannot be zero", nameof(bounds));
|
||||
}
|
||||
|
||||
var widthRatio = bounds.Width / this.Width;
|
||||
var heightRatio = bounds.Height / this.Height;
|
||||
var scalingRatio = Math.Min(widthRatio, heightRatio);
|
||||
|
||||
return scalingRatio;
|
||||
}
|
||||
|
||||
public Size ToSize() => new((int)this.Width, (int)this.Height);
|
||||
|
||||
public Point ToPoint() => new((int)this.Width, (int)this.Height);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{" +
|
||||
$"{nameof(this.Width)}={this.Width}," +
|
||||
$"{nameof(this.Height)}={this.Height}" +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
using MouseJump.Common.Models.Drawing;
|
||||
using MouseJump.Common.Models.Styles;
|
||||
|
||||
namespace MouseJump.Common.Models.Layout;
|
||||
|
||||
public sealed class PreviewLayout
|
||||
{
|
||||
public sealed class Builder
|
||||
{
|
||||
public Builder()
|
||||
{
|
||||
this.Screens = new();
|
||||
this.ScreenshotBounds = new();
|
||||
}
|
||||
|
||||
public PreviewStyle? PreviewStyle
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public RectangleInfo? VirtualScreen
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public List<RectangleInfo> Screens
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public int ActivatedScreenIndex
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public RectangleInfo? FormBounds
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public BoxBounds? PreviewBounds
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public List<BoxBounds> ScreenshotBounds
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public PreviewLayout Build()
|
||||
{
|
||||
return new PreviewLayout(
|
||||
previewStyle: this.PreviewStyle ?? throw new InvalidOperationException($"{nameof(this.PreviewStyle)} must be initialized before calling {nameof(this.Build)}."),
|
||||
virtualScreen: this.VirtualScreen ?? throw new InvalidOperationException($"{nameof(this.VirtualScreen)} must be initialized before calling {nameof(this.Build)}."),
|
||||
screens: this.Screens ?? throw new InvalidOperationException($"{nameof(this.Screens)} must be initialized before calling {nameof(this.Build)}."),
|
||||
activatedScreenIndex: this.ActivatedScreenIndex,
|
||||
formBounds: this.FormBounds ?? throw new InvalidOperationException($"{nameof(this.FormBounds)} must be initialized before calling {nameof(this.Build)}."),
|
||||
previewBounds: this.PreviewBounds ?? throw new InvalidOperationException($"{nameof(this.PreviewBounds)} must be initialized before calling {nameof(this.Build)}."),
|
||||
screenshotBounds: this.ScreenshotBounds ?? throw new InvalidOperationException($"{nameof(this.ScreenshotBounds)} must be initialized before calling {nameof(this.Build)}."));
|
||||
}
|
||||
}
|
||||
|
||||
public PreviewLayout(
|
||||
PreviewStyle previewStyle,
|
||||
RectangleInfo virtualScreen,
|
||||
List<RectangleInfo> screens,
|
||||
int activatedScreenIndex,
|
||||
RectangleInfo formBounds,
|
||||
BoxBounds previewBounds,
|
||||
List<BoxBounds> screenshotBounds)
|
||||
{
|
||||
this.PreviewStyle = previewStyle ?? throw new ArgumentNullException(nameof(previewStyle));
|
||||
this.VirtualScreen = virtualScreen ?? throw new ArgumentNullException(nameof(virtualScreen));
|
||||
this.Screens = (screens ?? throw new ArgumentNullException(nameof(screens)))
|
||||
.ToList().AsReadOnly();
|
||||
this.ActivatedScreenIndex = activatedScreenIndex;
|
||||
this.FormBounds = formBounds ?? throw new ArgumentNullException(nameof(formBounds));
|
||||
this.PreviewBounds = previewBounds ?? throw new ArgumentNullException(nameof(previewBounds));
|
||||
this.ScreenshotBounds = (screenshotBounds ?? throw new ArgumentNullException(nameof(screenshotBounds)))
|
||||
.ToList().AsReadOnly();
|
||||
}
|
||||
|
||||
public PreviewStyle PreviewStyle
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public RectangleInfo VirtualScreen
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<RectangleInfo> Screens
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public int ActivatedScreenIndex
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public RectangleInfo FormBounds
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public BoxBounds PreviewBounds
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<BoxBounds> ScreenshotBounds
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace MouseJump.Common.Models.Styles;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the background fill style for a drawing object.
|
||||
/// </summary>
|
||||
public sealed class BackgroundStyle
|
||||
{
|
||||
public static readonly BackgroundStyle Empty = new(
|
||||
Color.Transparent,
|
||||
Color.Transparent
|
||||
);
|
||||
|
||||
public BackgroundStyle(
|
||||
Color? color1,
|
||||
Color? color2)
|
||||
{
|
||||
this.Color1 = color1;
|
||||
this.Color2 = color2;
|
||||
}
|
||||
|
||||
public Color? Color1
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public Color? Color2
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{" +
|
||||
$"{nameof(this.Color1)}={this.Color1}," +
|
||||
$"{nameof(this.Color2)}={this.Color2}" +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace MouseJump.Common.Models.Styles;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the border style for a drawing object.
|
||||
/// </summary>
|
||||
public sealed class BorderStyle
|
||||
{
|
||||
public static readonly BorderStyle Empty = new(Color.Transparent, 0, 0);
|
||||
|
||||
public BorderStyle(Color color, decimal all, decimal depth)
|
||||
: this(color, all, all, all, all, depth)
|
||||
{
|
||||
}
|
||||
|
||||
public BorderStyle(Color color, decimal left, decimal top, decimal right, decimal bottom, decimal depth)
|
||||
{
|
||||
this.Color = color;
|
||||
this.Left = left;
|
||||
this.Top = top;
|
||||
this.Right = right;
|
||||
this.Bottom = bottom;
|
||||
this.Depth = depth;
|
||||
}
|
||||
|
||||
public Color Color
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Left
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Top
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Right
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Bottom
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the "depth" of the 3d highlight and shadow effect on the border.
|
||||
/// </summary>
|
||||
public decimal Depth
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Horizontal => this.Left + this.Right;
|
||||
|
||||
public decimal Vertical => this.Top + this.Bottom;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{" +
|
||||
$"{nameof(this.Color)}={this.Color}," +
|
||||
$"{nameof(this.Left)}={this.Left}," +
|
||||
$"{nameof(this.Top)}={this.Top}," +
|
||||
$"{nameof(this.Right)}={this.Right}," +
|
||||
$"{nameof(this.Bottom)}={this.Bottom}," +
|
||||
$"{nameof(this.Depth)}={this.Depth}" +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace MouseJump.Common.Models.Styles;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the styles to apply to a simple box-layout based drawing object.
|
||||
/// </summary>
|
||||
public sealed class BoxStyle
|
||||
{
|
||||
/*
|
||||
|
||||
see https://www.w3schools.com/css/css_boxmodel.asp
|
||||
|
||||
+--------------[bounds]---------------+
|
||||
|▒▒▒▒▒▒▒▒▒▒▒▒▒▒[margin]▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒|
|
||||
|▒▒▓▓▓▓▓▓▓▓▓▓▓▓[border]▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒|
|
||||
|▒▒▓▓░░░░░░░░░░[padding]░░░░░░░░░░▓▓▒▒|
|
||||
|▒▒▓▓░░ ░░▓▓▒▒|
|
||||
|▒▒▓▓░░ ░░▓▓▒▒|
|
||||
|▒▒▓▓░░ [content] ░░▓▓▒▒|
|
||||
|▒▒▓▓░░ ░░▓▓▒▒|
|
||||
|▒▒▓▓░░ ░░▓▓▒▒|
|
||||
|▒▒▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▒▒|
|
||||
|▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒|
|
||||
|▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒|
|
||||
+-------------------------------------+
|
||||
|
||||
*/
|
||||
|
||||
public static readonly BoxStyle Empty = new(MarginStyle.Empty, BorderStyle.Empty, PaddingStyle.Empty, BackgroundStyle.Empty);
|
||||
|
||||
public BoxStyle(
|
||||
MarginStyle marginStyle,
|
||||
BorderStyle borderStyle,
|
||||
PaddingStyle paddingStyle,
|
||||
BackgroundStyle backgroundStyle)
|
||||
{
|
||||
this.MarginStyle = marginStyle ?? throw new ArgumentNullException(nameof(marginStyle));
|
||||
this.BorderStyle = borderStyle ?? throw new ArgumentNullException(nameof(borderStyle));
|
||||
this.PaddingStyle = paddingStyle ?? throw new ArgumentNullException(nameof(paddingStyle));
|
||||
this.BackgroundStyle = backgroundStyle ?? throw new ArgumentNullException(nameof(backgroundStyle));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the margin style for this layout box.
|
||||
/// </summary>
|
||||
public MarginStyle MarginStyle
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the border style for this layout box.
|
||||
/// </summary>
|
||||
public BorderStyle BorderStyle
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the padding style for this layout box.
|
||||
/// </summary>
|
||||
public PaddingStyle PaddingStyle
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the background fill style for the content area of this layout box.
|
||||
/// </summary>
|
||||
public BackgroundStyle BackgroundStyle
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace MouseJump.Common.Models.Styles;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the margin style for a drawing object.
|
||||
/// </summary>
|
||||
public sealed class MarginStyle
|
||||
{
|
||||
public static readonly MarginStyle Empty = new(0);
|
||||
|
||||
public MarginStyle(decimal all)
|
||||
: this(all, all, all, all)
|
||||
{
|
||||
}
|
||||
|
||||
public MarginStyle(decimal left, decimal top, decimal right, decimal bottom)
|
||||
{
|
||||
this.Left = left;
|
||||
this.Top = top;
|
||||
this.Right = right;
|
||||
this.Bottom = bottom;
|
||||
}
|
||||
|
||||
public decimal Left
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Top
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Right
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Bottom
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Horizontal => this.Left + this.Right;
|
||||
|
||||
public decimal Vertical => this.Top + this.Bottom;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{" +
|
||||
$"{nameof(this.Left)}={this.Left}," +
|
||||
$"{nameof(this.Top)}={this.Top}," +
|
||||
$"{nameof(this.Right)}={this.Right}," +
|
||||
$"{nameof(this.Bottom)}={this.Bottom}" +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace MouseJump.Common.Models.Styles;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the margin style for a drawing object.
|
||||
/// </summary>
|
||||
public sealed class PaddingStyle
|
||||
{
|
||||
public static readonly PaddingStyle Empty = new(0);
|
||||
|
||||
public PaddingStyle(decimal all)
|
||||
: this(all, all, all, all)
|
||||
{
|
||||
}
|
||||
|
||||
public PaddingStyle(decimal left, decimal top, decimal right, decimal bottom)
|
||||
{
|
||||
this.Left = left;
|
||||
this.Top = top;
|
||||
this.Right = right;
|
||||
this.Bottom = bottom;
|
||||
}
|
||||
|
||||
public decimal Left
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Top
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Right
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Bottom
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Horizontal => this.Left + this.Right;
|
||||
|
||||
public decimal Vertical => this.Top + this.Bottom;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{" +
|
||||
$"{nameof(this.Left)}={this.Left}," +
|
||||
$"{nameof(this.Top)}={this.Top}," +
|
||||
$"{nameof(this.Right)}={this.Right}," +
|
||||
$"{nameof(this.Bottom)}={this.Bottom}" +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using MouseJump.Common.Models.Drawing;
|
||||
|
||||
namespace MouseJump.Common.Models.Styles;
|
||||
|
||||
public sealed class PreviewStyle
|
||||
{
|
||||
public PreviewStyle(
|
||||
SizeInfo canvasSize,
|
||||
BoxStyle canvasStyle,
|
||||
BoxStyle screenStyle)
|
||||
{
|
||||
this.CanvasSize = canvasSize ?? throw new ArgumentNullException(nameof(canvasSize));
|
||||
this.CanvasStyle = canvasStyle ?? throw new ArgumentNullException(nameof(canvasStyle));
|
||||
this.ScreenStyle = screenStyle ?? throw new ArgumentNullException(nameof(screenStyle));
|
||||
}
|
||||
|
||||
public SizeInfo CanvasSize
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public BoxStyle CanvasStyle
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public BoxStyle ScreenStyle
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user