Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Drawing;
using System.Windows.Forms.ButtonInternal;

namespace System.Windows.Forms.Tests;

public class CheckBoxBaseAdapterTests : IDisposable
{
private TestCheckBox? _checkBox;

private (TestCheckBoxBaseAdapter, TestCheckBox) CreateAdapter(CheckState checkState)
{
_checkBox = new TestCheckBox
{
CheckState = checkState
};

TestCheckBoxBaseAdapter adapter = new(_checkBox);

return (adapter, _checkBox);
}

public void Dispose() => _checkBox?.Dispose();

private class TestCheckBox : CheckBox
{
public new bool Enabled
{
get => base.Enabled;
set => base.Enabled = value;
}

public new CheckState CheckState
{
get => base.CheckState;
set => base.CheckState = value;
}
}

private class TestCheckBoxBaseAdapter : CheckBoxBaseAdapter
{
public TestCheckBoxBaseAdapter(ButtonBase control) : base(control) { }

public void CallDrawCheckFlat(
PaintEventArgs e,
LayoutData layout,
Color checkColor,
Color checkBackground,
Color checkBorder,
ColorData colors)
=> DrawCheckFlat(e, layout, checkColor, checkBackground, checkBorder, colors);

protected override LayoutOptions Layout(PaintEventArgs e)
=> new LayoutOptions();

protected override ButtonBaseAdapter CreateButtonAdapter()
=> new StubButtonBaseAdapter(Control);

private class StubButtonBaseAdapter : ButtonBaseAdapter
{
public StubButtonBaseAdapter(ButtonBase control) : base(control) { }
internal override void PaintUp(PaintEventArgs e, CheckState state) { }
internal override void PaintDown(PaintEventArgs e, CheckState state) { }
internal override void PaintOver(PaintEventArgs e, CheckState state) { }
protected override LayoutOptions Layout(PaintEventArgs e) => new LayoutOptions();
}

internal override void PaintOver(PaintEventArgs e, CheckState state)
{
}

internal override void PaintDown(PaintEventArgs e, CheckState state)
{
}

internal override void PaintUp(PaintEventArgs e, CheckState state)
{
}
}

private static ButtonBaseAdapter.LayoutData CreateLayoutData(bool dotNetOneButtonCompat = false)
{
ButtonBaseAdapter.LayoutData layout = new(
new ButtonBaseAdapter.LayoutOptions
{
DotNetOneButtonCompat = dotNetOneButtonCompat
})
{
CheckBounds = new Rectangle(2, 2, 11, 11)
};

return layout;
}

private static ButtonBaseAdapter.ColorData CreateColorData(Graphics graphics)
{
ButtonBaseAdapter.ColorOptions options = new(
graphics,
Color.Black,
Color.White
);

ButtonBaseAdapter.ColorData colorData = new(options)
{
ButtonFace = Color.LightGray,
ButtonShadow = Color.Gray,
Highlight = Color.Yellow
};

return colorData;
}

[WinFormsTheory]
[InlineData(CheckState.Unchecked, false)]
[InlineData(CheckState.Checked, false)]
[InlineData(CheckState.Indeterminate, false)]
[InlineData(CheckState.Unchecked, true)]
[InlineData(CheckState.Checked, true)]
[InlineData(CheckState.Indeterminate, true)]
public void DrawCheckFlat_DoesNotThrow(CheckState checkState, bool dotNetOneButtonCompat)
{
(TestCheckBoxBaseAdapter adapter, TestCheckBox checkBox) = CreateAdapter(checkState);
using Bitmap bitmap = new(20, 20);
using Graphics graphics = Graphics.FromImage(bitmap);
using PaintEventArgs e = new(graphics, new Rectangle(0, 0, 20, 20));
ButtonBaseAdapter.LayoutData layout = CreateLayoutData(dotNetOneButtonCompat);
Color checkColor = Color.Black;
Color checkBackground = Color.White;
Color checkBorder = Color.Blue;
ButtonBaseAdapter.ColorData colors = CreateColorData(graphics);

Exception? ex = Record.Exception(() =>
adapter.CallDrawCheckFlat(e, layout, checkColor, checkBackground, checkBorder, colors));

ex.Should().BeNull();
}

[WinFormsTheory]
[InlineData(false, CheckState.Unchecked, false, 0)]
[InlineData(false, CheckState.Unchecked, true, 1)]
[InlineData(true, CheckState.Indeterminate, true, 2)]
public void DrawCheckBackground_CoversAllBranches(
bool controlEnabled,
CheckState checkState,
bool disabledColors,
int expectedBranch)
{
Rectangle bounds = new(1, 2, 3, 4);
using Bitmap bitmap = new(10, 10);
using Graphics graphics = Graphics.FromImage(bitmap);
Color checkBackground = expectedBranch == 2 ? SystemColors.Window : Color.Red;

Exception? ex = Record.Exception(() =>
CheckBoxBaseAdapter.DrawCheckBackground(
controlEnabled,
checkState,
graphics,
bounds,
checkBackground,
disabledColors));

ex.Should().BeNull();
}

[WinFormsTheory]
[InlineData(CheckState.Checked, true, true)]
[InlineData(CheckState.Checked, false, true)]
[InlineData(CheckState.Indeterminate, true, true)]
[InlineData(CheckState.Indeterminate, false, true)]
[InlineData(CheckState.Unchecked, true, false)]
public void DrawCheckOnly_Protected_DoesNotThrow(
CheckState checkState,
bool enabled,
bool isChecked)
{
(TestCheckBoxBaseAdapter adapter, TestCheckBox checkBox) = CreateAdapter(checkState);
checkBox.Enabled = enabled;
checkBox.Checked = isChecked;

using Bitmap bitmap = new(20, 20);
using Graphics graphics = Graphics.FromImage(bitmap);
using PaintEventArgs e = new(graphics, new Rectangle(0, 0, 20, 20));
ButtonBaseAdapter.LayoutData layout = CreateLayoutData();
ButtonBaseAdapter.ColorData colors = CreateColorData(graphics);
Color checkColor = Color.Black;

Exception? ex = Record.Exception(() =>
adapter.TestAccessor().Dynamic.DrawCheckOnly(
e,
layout,
colors,
checkColor));

ex.Should().BeNull();
}

[WinFormsFact]
public void DrawPopupBorder_DoesNotThrow_AndInflatesRectangle()
{
using Bitmap bitmap = new(20, 20);
using Graphics graphics = Graphics.FromImage(bitmap);
Rectangle original = new(2, 2, 10, 10);

ButtonBaseAdapter.ColorData colors = CreateColorData(graphics);

Rectangle result = CheckBoxBaseAdapter.DrawPopupBorder(graphics, original, colors);

Rectangle expected = original;
expected.Inflate(-1, -1);

result.Should().Be(expected);
}

[WinFormsFact]
public void DrawPopupBorder_PaintEventArgs_DoesNotThrow_AndInflatesRectangle()
{
using Bitmap bitmap = new(20, 20);
using Graphics graphics = Graphics.FromImage(bitmap);
Rectangle original = new(3, 3, 8, 8);

ButtonBaseAdapter.ColorData colors = CreateColorData(graphics);

using PaintEventArgs e = new(graphics, new Rectangle(0, 0, 20, 20));
Rectangle result = CheckBoxBaseAdapter.DrawPopupBorder(e, original, colors);

Rectangle expected = original;
expected.Inflate(-1, -1);

result.Should().Be(expected);
}

[WinFormsFact]
public void DrawPopupBorder_HDC_DoesNotThrow_AndInflatesRectangle()
{
using Bitmap bitmap = new(20, 20);
using Graphics graphics = Graphics.FromImage(bitmap);
Rectangle original = new(4, 4, 6, 6);

ButtonBaseAdapter.ColorData colors = CreateColorData(graphics);

IntPtr hdcPtr = graphics.GetHdc();
try
{
Rectangle result = CheckBoxBaseAdapter.DrawPopupBorder(
new HDC(hdcPtr),
original,
colors);

Rectangle expected = original;
expected.Inflate(-1, -1);

result.Should().Be(expected);
}
finally
{
graphics.ReleaseHdc(hdcPtr);
}
}

[Theory]
[InlineData(null, true, 2, 2, 10, 10)]
[InlineData("", true, 2, 2, 10, 10)]
[InlineData(null, false, 2, 2, 10, 10)]
[InlineData("", false, 2, 2, 10, 10)]
public void AdjustFocusRectangle_SetsFocusAsExpected(
string? text,
bool autoSize,
int checkX, int checkY, int checkW, int checkH)
{
(TestCheckBoxBaseAdapter adapter, TestCheckBox checkBox) = CreateAdapter(CheckState.Unchecked);
checkBox.Text = text;
checkBox.AutoSize = autoSize;

ButtonBaseAdapter.LayoutData layout = new(new ButtonBaseAdapter.LayoutOptions())
{
CheckBounds = new Rectangle(checkX, checkY, checkW, checkH),
Field = new Rectangle(5, 5, 20, 20)
};

adapter.TestAccessor().Dynamic.AdjustFocusRectangle(layout);

if (string.IsNullOrEmpty(text))
{
if (autoSize)
{
Rectangle expected = Rectangle.Inflate(layout.CheckBounds, -2, -2);
layout.Focus.Should().Be(expected);
}
else
{
layout.Focus.Should().Be(new Rectangle(5, 5, 20, 20));
}
}
else
{
layout.Focus.Should().Be(default);
}
}
}