Skip to content

Commit

Permalink
Merge pull request #1456 from picoe/curtis/mac-ui-glitches
Browse files Browse the repository at this point in the history
Mac: Fix a few UI glitches
  • Loading branch information
cwensley committed Jul 30, 2019
2 parents 6398401 + 0fd9e58 commit 3b88bdd
Show file tree
Hide file tree
Showing 11 changed files with 241 additions and 32 deletions.
64 changes: 48 additions & 16 deletions src/Eto.Mac/Forms/Controls/CheckBoxHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,33 +34,73 @@

namespace Eto.Mac.Forms.Controls
{
public class EtoCenteredButton : NSButtonCell

public abstract class EtoCenteredButtonCell : NSButtonCell
{
nfloat defaultHeight;
public EtoCenteredButton(nfloat defaultHeight)

protected abstract nfloat GetDefaultHeight();

protected virtual nfloat Offset => 0f;

public override void SetButtonType(NSButtonType aType)
{
base.SetButtonType(aType);
defaultHeight = GetDefaultHeight();
}

public override NSControlSize ControlSize
{
this.defaultHeight = defaultHeight;
get => base.ControlSize;
set
{
base.ControlSize = value;
defaultHeight = GetDefaultHeight();
}
}

nfloat ButtonOffset => (nfloat)Math.Max(0, Math.Ceiling((AttributedTitle.Size.Height - defaultHeight) / 2 - 1));

public override CGRect DrawingRectForBounds(CGRect theRect)
{
var rect = base.DrawingRectForBounds(theRect);
var titleSize = AttributedTitle.Size;
rect.Y += (nfloat)Math.Max(0, (titleSize.Height - defaultHeight) / 2);
rect.Y += ButtonOffset;
rect.Y += Offset;
return rect;
}

public override CGRect TitleRectForBounds(CGRect theRect)
{
var titleSize = AttributedTitle.Size;
var rect = base.TitleRectForBounds(theRect);
rect.Y -= (nfloat)Math.Max(0, (titleSize.Height - defaultHeight) / 2);
rect.Y -= ButtonOffset;
rect.Y -= Offset;
return rect;
}
}

public class CheckBoxHandler : MacButton<NSButton, CheckBox, CheckBox.ICallback>, CheckBox.IHandler
{
public class EtoCheckCenteredButtonCell : EtoCenteredButtonCell
{
// check boxes get clipped at the top in mini mode using the alignment rects. macOS 10.14.6
// see Eto.Test.Mac.UnitTests.CheckBoxTests.ButtonShouldNotBeClipped()
protected override nfloat Offset => ControlSize == NSControlSize.Mini ? 0.5f : 0;

protected override nfloat GetDefaultHeight()
{
switch (ControlSize)
{
default:
case NSControlSize.Regular:
return 14;
case NSControlSize.Small:
return 12;
case NSControlSize.Mini:
return 10;
}
}
}

public class EtoCheckBoxButton : NSButton, IMacControl
{
public WeakReference WeakHandler { get; set; }
Expand All @@ -71,17 +111,9 @@ public object Handler
set { WeakHandler = new WeakReference(value); }
}

static nfloat defaultHeight;
static EtoCheckBoxButton()
{
var b = new EtoCheckBoxButton();
b.SizeToFit();
defaultHeight = b.Frame.Height;
}

public EtoCheckBoxButton()
{
Cell = new EtoCenteredButton(defaultHeight);
Cell = new EtoCheckCenteredButtonCell();
Title = string.Empty;
SetButtonType(NSButtonType.Switch);
}
Expand Down
14 changes: 2 additions & 12 deletions src/Eto.Mac/Forms/Controls/MacLabel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public override CGRect DrawingRectForBounds(CGRect theRect)
var lineHeight = CellSizeForBounds(theRect).Height;
offset = (nfloat)Math.Round(theRect.Height - lineHeight);
}
offset = (nfloat)Math.Max(0, offset);
rect.Y += offset;
rect.Height -= offset;
return rect;
Expand Down Expand Up @@ -128,8 +129,6 @@ static class MacLabel
public static readonly object FontKey = new object();

public static readonly object TextColorKey = new object();

public static readonly bool SupportsSingleLine = ObjCExtensions.ClassInstancesRespondToSelector(Class.GetHandle("NSTextFieldCell"), Selector.GetHandle("setUsesSingleLineMode:"));
}

public abstract class MacLabel<TControl, TWidget, TCallback> : MacView<TControl, TWidget, TCallback>
Expand Down Expand Up @@ -210,9 +209,6 @@ protected MacLabel()

protected override void Initialize()
{
if (MacLabel.SupportsSingleLine)
Control.Cell.UsesSingleLineMode = false;

base.Initialize();
HandleEvent(Eto.Forms.Control.SizeChangedEvent);
}
Expand Down Expand Up @@ -248,7 +244,7 @@ public WrapMode Wrap
{
get
{
if (MacLabel.SupportsSingleLine && Control.Cell.UsesSingleLineMode)
if (paragraphStyle.LineBreakMode == NSLineBreakMode.Clipping)
return WrapMode.None;
if (paragraphStyle.LineBreakMode == NSLineBreakMode.ByWordWrapping)
return WrapMode.Word;
Expand All @@ -259,18 +255,12 @@ public WrapMode Wrap
switch (value)
{
case WrapMode.None:
if (MacLabel.SupportsSingleLine)
Control.Cell.UsesSingleLineMode = true;
paragraphStyle.LineBreakMode = NSLineBreakMode.Clipping;
break;
case WrapMode.Word:
if (MacLabel.SupportsSingleLine)
Control.Cell.UsesSingleLineMode = false;
paragraphStyle.LineBreakMode = NSLineBreakMode.ByWordWrapping;
break;
case WrapMode.Character:
if (MacLabel.SupportsSingleLine)
Control.Cell.UsesSingleLineMode = false;
paragraphStyle.LineBreakMode = NSLineBreakMode.CharWrapping;
break;
default:
Expand Down
25 changes: 22 additions & 3 deletions src/Eto.Mac/Forms/Controls/RadioButtonHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,27 @@ public void SetButtonStates(object newButton)
}
}

public class EtoRadioCenteredButtonCell : EtoCenteredButtonCell
{
// radio buttons get clipped at the top in small/mini mode using the alignment rects. macOS 10.14.6
// see Eto.Test.Mac.UnitTests.RadioButtonTests.ButtonShouldNotBeClipped()
protected override nfloat Offset => ControlSize != NSControlSize.Regular ? 0.5f : 0;

protected override nfloat GetDefaultHeight()
{
switch (ControlSize)
{
default:
case NSControlSize.Regular:
return 14;
case NSControlSize.Small:
return 12;
case NSControlSize.Mini:
return 10;
}
}
}

public class EtoRadioButton : NSButton, IMacControl
{
public WeakReference WeakHandler { get; set; }
Expand All @@ -88,11 +109,9 @@ static EtoRadioButton()
defaultHeight = b.Frame.Height;
}

static readonly Selector s_selClicked = new Selector("clicked");

public EtoRadioButton()
{
Cell = new EtoCenteredButton(defaultHeight);
Cell = new EtoRadioCenteredButtonCell();
Title = string.Empty;
SetButtonType(NSButtonType.Radio);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Eto.Mac/Forms/MacPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ protected override SizeF GetNaturalSize(SizeF availableSize)
{
var contentControl = content.GetMacControl();
if (contentControl != null && content.Visible)
return contentControl.GetPreferredSize(availableSize - Padding.Size) + Padding.Size;
return contentControl.GetPreferredSize(SizeF.Max(SizeF.Empty, availableSize - Padding.Size)) + Padding.Size;

return Padding.Size;
}
Expand Down
7 changes: 7 additions & 0 deletions test/Eto.Test.Mac/Eto.Test.XamMac.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,17 @@
<Reference Include="nunit.framework">
<HintPath>..\..\artifacts\packages\NUnit.3.11.0\lib\net45\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
</ItemGroup>
<ItemGroup>
<Compile Include="Startup.cs" />
<Compile Include="UnitTests\ButtonTests.cs" />
<Compile Include="UnitTests\CheckBoxTests.cs" />
<Compile Include="UnitTests\NativeParentWindowTests.cs" />
<Compile Include="UnitTests\RadioButtonTests.cs" />
<Compile Include="UnitTests\RichTextAreaHandlerTests.cs" />
<Compile Include="UnitTests\ScrollableTests.cs" />
<Compile Include="UnitTests\LabelTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Info.plist" />
Expand Down
6 changes: 6 additions & 0 deletions test/Eto.Test.Mac/Eto.Test.XamMac2-modern.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@
<ItemGroup>
<Compile Include="Startup.cs" />
<Compile Include="UnitTests\RichTextAreaHandlerTests.cs" />
<Compile Include="UnitTests\ButtonTests.cs" />
<Compile Include="UnitTests\CheckBoxTests.cs" />
<Compile Include="UnitTests\NativeParentWindowTests.cs" />
<Compile Include="UnitTests\RadioButtonTests.cs" />
<Compile Include="UnitTests\ScrollableTests.cs" />
<Compile Include="UnitTests\LabelTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Info.plist" />
Expand Down
3 changes: 3 additions & 0 deletions test/Eto.Test.Mac/Eto.Test.XamMac2-net461.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
<Compile Include="Startup.cs" />
<Compile Include="UnitTests\RichTextAreaHandlerTests.cs" />
<Compile Include="UnitTests\NativeParentWindowTests.cs" />
<Compile Include="UnitTests\RadioButtonTests.cs" />
<Compile Include="UnitTests\CheckBoxTests.cs" />
<Compile Include="UnitTests\LabelTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Info.plist" />
Expand Down
57 changes: 57 additions & 0 deletions test/Eto.Test.Mac/UnitTests/CheckBoxTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System;
using Eto.Drawing;
using Eto.Forms;
using Eto.Mac.Forms.Controls;
using Eto.Test.UnitTests;
using NUnit.Framework;
#if XAMMAC2
using AppKit;
using CoreGraphics;
#else
using MonoMac.AppKit;
using MonoMac.CoreGraphics;
#if SDCOMPAT
using CGSize = System.Drawing.SizeF;
using CGRect = System.Drawing.RectangleF;
using CGPoint = System.Drawing.PointF;
#endif
#endif

namespace Eto.Test.Mac.UnitTests
{
[TestFixture]
public class CheckBoxTests : TestBase
{
[Test, ManualTest]
public void ButtonShouldNotBeClipped()
{
ManualForm("All buttons should be fully visible without any clipping", form =>
{
form.Styles.Add<CheckBoxHandler>("small", c =>
{
c.Control.Cell.ControlSize = NSControlSize.Small;
c.Control.Font = NSFont.SystemFontOfSize(NSFont.SystemFontSizeForControlSize(NSControlSize.Small));
});
form.Styles.Add<CheckBoxHandler>("mini", c =>
{
c.Control.Cell.ControlSize = NSControlSize.Mini;
c.Control.Font = NSFont.SystemFontOfSize(NSFont.SystemFontSizeForControlSize(NSControlSize.Mini));
});
return new TableLayout
{
Rows =
{
new Panel { Height = 10, BackgroundColor = Colors.White },
new TableLayout(new TableRow(null, new CheckBox { Text = "Normal" }, null)),
new Panel { Height = 10, BackgroundColor = Colors.White },
new TableLayout(new TableRow(null, new CheckBox { Text = "Small", Style = "small" }, null)),
new Panel { Height = 10, BackgroundColor = Colors.White },
new TableLayout(new TableRow(null, new CheckBox { Text = "Mini", Style = "mini" }, null)),
new Panel { Height = 10, BackgroundColor = Colors.White },
}
};
});
}
}
}
33 changes: 33 additions & 0 deletions test/Eto.Test.Mac/UnitTests/LabelTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using Eto.Drawing;
using Eto.Forms;
using Eto.Test.UnitTests;
using NUnit.Framework;

namespace Eto.Test.Mac.UnitTests
{
[TestFixture]
public class LabelTests : TestBase
{
[Test, ManualTest]
public void LabelWithDifferentFontSizesShouldShowCorrectly()
{
ManualForm("Labels should show correctly.", form =>
{
return new TableLayout
{
Rows =
{
new Panel {BackgroundColor = Colors.White, Height = 10},
new TableLayout(new Label { Text = "Small Font", Wrap = WrapMode.None, Font = SystemFonts.Default(8) }),
new Panel {BackgroundColor = Colors.White, Height = 10},
new TableLayout(new Label { Text = "Normal Font", Wrap = WrapMode.None }),
new Panel {BackgroundColor = Colors.White, Height = 10},
new TableLayout(new Label { Text = "Large Font", Wrap = WrapMode.None, Font = SystemFonts.Default(48) }),
new Panel {BackgroundColor = Colors.White, Height = 10},
}
};
});
}
}
}
5 changes: 5 additions & 0 deletions test/Eto.Test.Mac/UnitTests/NativeParentWindowTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
#else
using MonoMac.AppKit;
using MonoMac.CoreGraphics;
#if SDCOMPAT
using CGSize = System.Drawing.SizeF;
using CGRect = System.Drawing.RectangleF;
using CGPoint = System.Drawing.PointF;
#endif
#endif

namespace Eto.Test.Mac.UnitTests
Expand Down

0 comments on commit 3b88bdd

Please sign in to comment.