diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 34f931ff41..46e8665945 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -18,7 +18,7 @@
- [ ] Added unit tests (if possible)?
- [ ] Added XML documentation to any related classes?
-- [ ] Consider submitting a PR to https://github.com/AvaloniaUI/Avaloniaui.net with user documentation
+- [ ] Consider submitting a PR to https://github.com/AvaloniaUI/Documentation with user documentation
## Breaking changes
diff --git a/native/Avalonia.Native/src/OSX/window.h b/native/Avalonia.Native/src/OSX/window.h
index b1f64bca88..6a4ca2b8d8 100644
--- a/native/Avalonia.Native/src/OSX/window.h
+++ b/native/Avalonia.Native/src/OSX/window.h
@@ -34,6 +34,7 @@ class WindowBaseImpl;
-(double) getScaling;
-(double) getExtendedTitleBarHeight;
-(void) setIsExtended:(bool)value;
+-(void) updateShadow;
@end
struct INSWindowHolder
diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm
index d7afbdaa3a..e7c144b2d3 100644
--- a/native/Avalonia.Native/src/OSX/window.mm
+++ b/native/Avalonia.Native/src/OSX/window.mm
@@ -124,7 +124,11 @@ public:
[Window setTitle:_lastTitle];
_shown = true;
-
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [Window updateShadow];
+ });
+
return S_OK;
}
}
@@ -1838,6 +1842,19 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
double _lastScaling;
}
+- (void)updateShadow
+{
+ // Common problem in Cocoa where [invalidateShadow] does work,
+ // This hack forces Cocoa to invalidate the shadow.
+
+ NSRect frame = [self frame];
+ NSRect updatedFrame = NSMakeRect(frame.origin.x, frame.origin.y, frame.size.width + 1.0, frame.size.height + 1.0);
+ [self setFrame:updatedFrame display:YES];
+ [self setFrame:frame display:YES];
+
+ [self invalidateShadow];
+}
+
-(void) setIsExtended:(bool)value;
{
_isExtended = value;
diff --git a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
index e4ff5e9e5b..d0cf772c01 100644
--- a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
+++ b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
@@ -8,7 +8,7 @@ using System.Globalization;
namespace Avalonia.Controls
{
///
- /// A control to allow the user to select a time
+ /// A control to allow the user to select a time.
///
[PseudoClasses(":hasnotime")]
public class TimePicker : TemplatedControl
diff --git a/src/Avalonia.Controls/Expander.cs b/src/Avalonia.Controls/Expander.cs
index 9ff2e41fa9..052b42a233 100644
--- a/src/Avalonia.Controls/Expander.cs
+++ b/src/Avalonia.Controls/Expander.cs
@@ -4,14 +4,35 @@ using Avalonia.Controls.Primitives;
namespace Avalonia.Controls
{
+ ///
+ /// Direction in which an control opens.
+ ///
public enum ExpandDirection
{
+ ///
+ /// Opens down.
+ ///
Down,
+
+ ///
+ /// Opens up.
+ ///
Up,
+
+ ///
+ /// Opens left.
+ ///
Left,
+
+ ///
+ /// Opens right.
+ ///
Right
}
+ ///
+ /// A control with a header that has a collapsible content section.
+ ///
[PseudoClasses(":expanded", ":up", ":down", ":left", ":right")]
public class Expander : HeaderedContentControl
{
diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs
index 105a2744e5..c7d598006d 100644
--- a/src/Avalonia.Controls/Grid.cs
+++ b/src/Avalonia.Controls/Grid.cs
@@ -17,7 +17,7 @@ using Avalonia.VisualTree;
namespace Avalonia.Controls
{
///
- /// Grid
+ /// Defines a flexible grid area that consists of columns and rows.
///
public class Grid : Panel
{
diff --git a/src/Avalonia.Controls/Primitives/ScrollBarVisibility.cs b/src/Avalonia.Controls/Primitives/ScrollBarVisibility.cs
index 90727a3505..e62e087140 100644
--- a/src/Avalonia.Controls/Primitives/ScrollBarVisibility.cs
+++ b/src/Avalonia.Controls/Primitives/ScrollBarVisibility.cs
@@ -1,10 +1,28 @@
namespace Avalonia.Controls.Primitives
{
+ ///
+ /// Specifies the visibility of a for scrollable content.
+ ///
public enum ScrollBarVisibility
{
+ ///
+ /// No scrollbars and no scrolling in this dimension.
+ ///
Disabled,
+
+ ///
+ /// The scrollbar should be visible only if there is more content than fits in the viewport.
+ ///
Auto,
+
+ ///
+ /// The scrollbar should never be visible. No space should ever be reserved for the scrollbar.
+ ///
Hidden,
+
+ ///
+ /// The scrollbar should always be visible. Space should always be reserved for the scrollbar.
+ ///
Visible,
}
}
diff --git a/src/Avalonia.Controls/RadioButton.cs b/src/Avalonia.Controls/RadioButton.cs
index 4bda241497..681278d247 100644
--- a/src/Avalonia.Controls/RadioButton.cs
+++ b/src/Avalonia.Controls/RadioButton.cs
@@ -8,6 +8,9 @@ using Avalonia.VisualTree;
namespace Avalonia.Controls
{
+ ///
+ /// Represents a button that allows a user to select a single option from a group of options.
+ ///
public class RadioButton : ToggleButton
{
private class RadioButtonGroupManager
diff --git a/src/Avalonia.Controls/RelativePanel.cs b/src/Avalonia.Controls/RelativePanel.cs
index 2305d8fb9e..c5de004f09 100644
--- a/src/Avalonia.Controls/RelativePanel.cs
+++ b/src/Avalonia.Controls/RelativePanel.cs
@@ -8,6 +8,9 @@ using Avalonia.Layout;
namespace Avalonia.Controls
{
+ ///
+ /// Defines an area within which you can position and align child objects in relation to each other or the parent panel.
+ ///
public partial class RelativePanel : Panel
{
private readonly Graph _childGraph;
diff --git a/src/Avalonia.Controls/RepeatButton.cs b/src/Avalonia.Controls/RepeatButton.cs
index fcd6607feb..ba770634d9 100644
--- a/src/Avalonia.Controls/RepeatButton.cs
+++ b/src/Avalonia.Controls/RepeatButton.cs
@@ -4,6 +4,9 @@ using Avalonia.Threading;
namespace Avalonia.Controls
{
+ ///
+ /// Represents a control that raises its event repeatedly when it is pressed and held.
+ ///
public class RepeatButton : Button
{
///
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index 15a954b462..3c221cbf27 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -17,6 +17,9 @@ using Avalonia.Controls.Metadata;
namespace Avalonia.Controls
{
+ ///
+ /// Represents a control that can be used to display or edit unformatted text.
+ ///
[PseudoClasses(":empty")]
public class TextBox : TemplatedControl, UndoRedoHelper.IUndoRedoHost
{
diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs
index 71359f733d..f716464d14 100644
--- a/src/Avalonia.Native/WindowImplBase.cs
+++ b/src/Avalonia.Native/WindowImplBase.cs
@@ -414,9 +414,7 @@ namespace Avalonia.Native
public Action Input { get; set; }
- Action ScalingChanged { get; set; }
-
- Action ITopLevelImpl.ScalingChanged { get; set; }
+ public Action ScalingChanged { get; set; }
public Action TransparencyLevelChanged { get; set; }
diff --git a/src/Avalonia.Visuals/Media/TextFormatting/ShapedTextCharacters.cs b/src/Avalonia.Visuals/Media/TextFormatting/ShapedTextCharacters.cs
index 723d5e81ab..b304b19910 100644
--- a/src/Avalonia.Visuals/Media/TextFormatting/ShapedTextCharacters.cs
+++ b/src/Avalonia.Visuals/Media/TextFormatting/ShapedTextCharacters.cs
@@ -109,7 +109,8 @@ namespace Avalonia.Media.TextFormatting
GlyphRun.GlyphAdvances.Take(glyphCount),
GlyphRun.GlyphOffsets.Take(glyphCount),
GlyphRun.Characters.Take(length),
- GlyphRun.GlyphClusters.Take(glyphCount));
+ GlyphRun.GlyphClusters.Take(glyphCount),
+ GlyphRun.BiDiLevel);
var firstTextRun = new ShapedTextCharacters(firstGlyphRun, Properties);
@@ -120,7 +121,8 @@ namespace Avalonia.Media.TextFormatting
GlyphRun.GlyphAdvances.Skip(glyphCount),
GlyphRun.GlyphOffsets.Skip(glyphCount),
GlyphRun.Characters.Skip(length),
- GlyphRun.GlyphClusters.Skip(glyphCount));
+ GlyphRun.GlyphClusters.Skip(glyphCount),
+ GlyphRun.BiDiLevel);
var secondTextRun = new ShapedTextCharacters(secondGlyphRun, Properties);
diff --git a/src/Avalonia.Visuals/Media/TextFormatting/TextCharacters.cs b/src/Avalonia.Visuals/Media/TextFormatting/TextCharacters.cs
index c6f524451b..0779716ec8 100644
--- a/src/Avalonia.Visuals/Media/TextFormatting/TextCharacters.cs
+++ b/src/Avalonia.Visuals/Media/TextFormatting/TextCharacters.cs
@@ -135,20 +135,20 @@ namespace Avalonia.Media.TextFormatting
count = 0;
var script = Script.Common;
- //var direction = BiDiClass.LeftToRight;
+ var direction = BiDiClass.LeftToRight;
var font = typeface.GlyphTypeface;
var defaultFont = defaultTypeface.GlyphTypeface;
-
+
var enumerator = new GraphemeEnumerator(text);
while (enumerator.MoveNext())
{
- var grapheme = enumerator.Current;
+ var currentGrapheme = enumerator.Current;
- var currentScript = grapheme.FirstCodepoint.Script;
+ var currentScript = currentGrapheme.FirstCodepoint.Script;
- //var currentDirection = grapheme.FirstCodepoint.BiDiClass;
+ var currentDirection = currentGrapheme.FirstCodepoint.BiDiClass;
//// ToDo: Implement BiDi algorithm
//if (currentScript.HorizontalDirection != direction)
@@ -161,36 +161,44 @@ namespace Avalonia.Media.TextFormatting
if (currentScript != script)
{
- if (currentScript != Script.Inherited && currentScript != Script.Common)
+ if (script == Script.Inherited || script == Script.Common)
{
- if (script == Script.Inherited || script == Script.Common)
- {
- script = currentScript;
- }
- else
+ script = currentScript;
+ }
+ else
+ {
+ if (currentScript != Script.Inherited && currentScript != Script.Common)
{
break;
}
}
}
- if (isFallback)
+ if (currentScript != Script.Common && currentScript != Script.Inherited)
{
- if (defaultFont.TryGetGlyph(grapheme.FirstCodepoint, out _))
+ if (isFallback && defaultFont.TryGetGlyph(currentGrapheme.FirstCodepoint, out _))
{
break;
}
- }
- if (!font.TryGetGlyph(grapheme.FirstCodepoint, out _))
- {
- if (!grapheme.FirstCodepoint.IsWhiteSpace)
+ if (!font.TryGetGlyph(currentGrapheme.FirstCodepoint, out _))
{
break;
}
}
- count += grapheme.Text.Length;
+ if (!currentGrapheme.FirstCodepoint.IsWhiteSpace && !font.TryGetGlyph(currentGrapheme.FirstCodepoint, out _))
+ {
+ break;
+ }
+
+ if (direction == BiDiClass.RightToLeft && currentDirection == BiDiClass.CommonSeparator)
+ {
+ break;
+ }
+
+ count += currentGrapheme.Text.Length;
+ direction = currentDirection;
}
return count > 0;
diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs
index 97af874238..9c2a1953f1 100644
--- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs
+++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs
@@ -125,6 +125,27 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
}
}
+ [Fact]
+ public void Should_Produce_A_Single_Fallback_Run()
+ {
+ using (Start())
+ {
+ var defaultProperties = new GenericTextRunProperties(Typeface.Default);
+
+ const string text = "👍 👍 👍 👍";
+
+ var textSource = new SingleBufferTextSource(text, defaultProperties);
+
+ var formatter = new TextFormatterImpl();
+
+ var textLine =
+ formatter.FormatLine(textSource, 0, double.PositiveInfinity,
+ new GenericTextParagraphProperties(defaultProperties));
+
+ Assert.Equal(1, textLine.TextRuns.Count);
+ }
+ }
+
[Fact]
public void Should_Split_Run_On_Script()
{