Browse Source

Merge branch 'master' into fixes/5924-copy-from-readonly-textbox

pull/5935/head
Max Katz 6 years ago
committed by GitHub
parent
commit
1ddbb1270f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .github/PULL_REQUEST_TEMPLATE.md
  2. 1
      native/Avalonia.Native/src/OSX/window.h
  3. 19
      native/Avalonia.Native/src/OSX/window.mm
  4. 2
      src/Avalonia.Controls/DateTimePickers/TimePicker.cs
  5. 21
      src/Avalonia.Controls/Expander.cs
  6. 2
      src/Avalonia.Controls/Grid.cs
  7. 18
      src/Avalonia.Controls/Primitives/ScrollBarVisibility.cs
  8. 3
      src/Avalonia.Controls/RadioButton.cs
  9. 3
      src/Avalonia.Controls/RelativePanel.cs
  10. 3
      src/Avalonia.Controls/RepeatButton.cs
  11. 3
      src/Avalonia.Controls/TextBox.cs
  12. 4
      src/Avalonia.Native/WindowImplBase.cs
  13. 6
      src/Avalonia.Visuals/Media/TextFormatting/ShapedTextCharacters.cs
  14. 44
      src/Avalonia.Visuals/Media/TextFormatting/TextCharacters.cs
  15. 21
      tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs

2
.github/PULL_REQUEST_TEMPLATE.md

@ -18,7 +18,7 @@
- [ ] Added unit tests (if possible)? - [ ] Added unit tests (if possible)?
- [ ] Added XML documentation to any related classes? - [ ] 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 ## Breaking changes
<!--- List any breaking changes here. When the PR is merged please add an entry to https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes --> <!--- List any breaking changes here. When the PR is merged please add an entry to https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes -->

1
native/Avalonia.Native/src/OSX/window.h

@ -34,6 +34,7 @@ class WindowBaseImpl;
-(double) getScaling; -(double) getScaling;
-(double) getExtendedTitleBarHeight; -(double) getExtendedTitleBarHeight;
-(void) setIsExtended:(bool)value; -(void) setIsExtended:(bool)value;
-(void) updateShadow;
@end @end
struct INSWindowHolder struct INSWindowHolder

19
native/Avalonia.Native/src/OSX/window.mm

@ -124,7 +124,11 @@ public:
[Window setTitle:_lastTitle]; [Window setTitle:_lastTitle];
_shown = true; _shown = true;
dispatch_async(dispatch_get_main_queue(), ^{
[Window updateShadow];
});
return S_OK; return S_OK;
} }
} }
@ -1838,6 +1842,19 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
double _lastScaling; 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; -(void) setIsExtended:(bool)value;
{ {
_isExtended = value; _isExtended = value;

2
src/Avalonia.Controls/DateTimePickers/TimePicker.cs

@ -8,7 +8,7 @@ using System.Globalization;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
/// <summary> /// <summary>
/// A control to allow the user to select a time /// A control to allow the user to select a time.
/// </summary> /// </summary>
[PseudoClasses(":hasnotime")] [PseudoClasses(":hasnotime")]
public class TimePicker : TemplatedControl public class TimePicker : TemplatedControl

21
src/Avalonia.Controls/Expander.cs

@ -4,14 +4,35 @@ using Avalonia.Controls.Primitives;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
/// <summary>
/// Direction in which an <see cref="Expander"/> control opens.
/// </summary>
public enum ExpandDirection public enum ExpandDirection
{ {
/// <summary>
/// Opens down.
/// </summary>
Down, Down,
/// <summary>
/// Opens up.
/// </summary>
Up, Up,
/// <summary>
/// Opens left.
/// </summary>
Left, Left,
/// <summary>
/// Opens right.
/// </summary>
Right Right
} }
/// <summary>
/// A control with a header that has a collapsible content section.
/// </summary>
[PseudoClasses(":expanded", ":up", ":down", ":left", ":right")] [PseudoClasses(":expanded", ":up", ":down", ":left", ":right")]
public class Expander : HeaderedContentControl public class Expander : HeaderedContentControl
{ {

2
src/Avalonia.Controls/Grid.cs

@ -17,7 +17,7 @@ using Avalonia.VisualTree;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
/// <summary> /// <summary>
/// Grid /// Defines a flexible grid area that consists of columns and rows.
/// </summary> /// </summary>
public class Grid : Panel public class Grid : Panel
{ {

18
src/Avalonia.Controls/Primitives/ScrollBarVisibility.cs

@ -1,10 +1,28 @@
namespace Avalonia.Controls.Primitives namespace Avalonia.Controls.Primitives
{ {
/// <summary>
/// Specifies the visibility of a <see cref="ScrollBar"/> for scrollable content.
/// </summary>
public enum ScrollBarVisibility public enum ScrollBarVisibility
{ {
/// <summary>
/// No scrollbars and no scrolling in this dimension.
/// </summary>
Disabled, Disabled,
/// <summary>
/// The scrollbar should be visible only if there is more content than fits in the viewport.
/// </summary>
Auto, Auto,
/// <summary>
/// The scrollbar should never be visible. No space should ever be reserved for the scrollbar.
/// </summary>
Hidden, Hidden,
/// <summary>
/// The scrollbar should always be visible. Space should always be reserved for the scrollbar.
/// </summary>
Visible, Visible,
} }
} }

3
src/Avalonia.Controls/RadioButton.cs

@ -8,6 +8,9 @@ using Avalonia.VisualTree;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
/// <summary>
/// Represents a button that allows a user to select a single option from a group of options.
/// </summary>
public class RadioButton : ToggleButton public class RadioButton : ToggleButton
{ {
private class RadioButtonGroupManager private class RadioButtonGroupManager

3
src/Avalonia.Controls/RelativePanel.cs

@ -8,6 +8,9 @@ using Avalonia.Layout;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
/// <summary>
/// Defines an area within which you can position and align child objects in relation to each other or the parent panel.
/// </summary>
public partial class RelativePanel : Panel public partial class RelativePanel : Panel
{ {
private readonly Graph _childGraph; private readonly Graph _childGraph;

3
src/Avalonia.Controls/RepeatButton.cs

@ -4,6 +4,9 @@ using Avalonia.Threading;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
/// <summary>
/// Represents a control that raises its <see cref="Button.Click"/> event repeatedly when it is pressed and held.
/// </summary>
public class RepeatButton : Button public class RepeatButton : Button
{ {
/// <summary> /// <summary>

3
src/Avalonia.Controls/TextBox.cs

@ -17,6 +17,9 @@ using Avalonia.Controls.Metadata;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
/// <summary>
/// Represents a control that can be used to display or edit unformatted text.
/// </summary>
[PseudoClasses(":empty")] [PseudoClasses(":empty")]
public class TextBox : TemplatedControl, UndoRedoHelper<TextBox.UndoRedoState>.IUndoRedoHost public class TextBox : TemplatedControl, UndoRedoHelper<TextBox.UndoRedoState>.IUndoRedoHost
{ {

4
src/Avalonia.Native/WindowImplBase.cs

@ -414,9 +414,7 @@ namespace Avalonia.Native
public Action<RawInputEventArgs> Input { get; set; } public Action<RawInputEventArgs> Input { get; set; }
Action<double> ScalingChanged { get; set; } public Action<double> ScalingChanged { get; set; }
Action<double> ITopLevelImpl.ScalingChanged { get; set; }
public Action<WindowTransparencyLevel> TransparencyLevelChanged { get; set; } public Action<WindowTransparencyLevel> TransparencyLevelChanged { get; set; }

6
src/Avalonia.Visuals/Media/TextFormatting/ShapedTextCharacters.cs

@ -109,7 +109,8 @@ namespace Avalonia.Media.TextFormatting
GlyphRun.GlyphAdvances.Take(glyphCount), GlyphRun.GlyphAdvances.Take(glyphCount),
GlyphRun.GlyphOffsets.Take(glyphCount), GlyphRun.GlyphOffsets.Take(glyphCount),
GlyphRun.Characters.Take(length), GlyphRun.Characters.Take(length),
GlyphRun.GlyphClusters.Take(glyphCount)); GlyphRun.GlyphClusters.Take(glyphCount),
GlyphRun.BiDiLevel);
var firstTextRun = new ShapedTextCharacters(firstGlyphRun, Properties); var firstTextRun = new ShapedTextCharacters(firstGlyphRun, Properties);
@ -120,7 +121,8 @@ namespace Avalonia.Media.TextFormatting
GlyphRun.GlyphAdvances.Skip(glyphCount), GlyphRun.GlyphAdvances.Skip(glyphCount),
GlyphRun.GlyphOffsets.Skip(glyphCount), GlyphRun.GlyphOffsets.Skip(glyphCount),
GlyphRun.Characters.Skip(length), GlyphRun.Characters.Skip(length),
GlyphRun.GlyphClusters.Skip(glyphCount)); GlyphRun.GlyphClusters.Skip(glyphCount),
GlyphRun.BiDiLevel);
var secondTextRun = new ShapedTextCharacters(secondGlyphRun, Properties); var secondTextRun = new ShapedTextCharacters(secondGlyphRun, Properties);

44
src/Avalonia.Visuals/Media/TextFormatting/TextCharacters.cs

@ -135,20 +135,20 @@ namespace Avalonia.Media.TextFormatting
count = 0; count = 0;
var script = Script.Common; var script = Script.Common;
//var direction = BiDiClass.LeftToRight; var direction = BiDiClass.LeftToRight;
var font = typeface.GlyphTypeface; var font = typeface.GlyphTypeface;
var defaultFont = defaultTypeface.GlyphTypeface; var defaultFont = defaultTypeface.GlyphTypeface;
var enumerator = new GraphemeEnumerator(text); var enumerator = new GraphemeEnumerator(text);
while (enumerator.MoveNext()) 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 //// ToDo: Implement BiDi algorithm
//if (currentScript.HorizontalDirection != direction) //if (currentScript.HorizontalDirection != direction)
@ -161,36 +161,44 @@ namespace Avalonia.Media.TextFormatting
if (currentScript != script) 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;
{ }
script = currentScript; else
} {
else if (currentScript != Script.Inherited && currentScript != Script.Common)
{ {
break; break;
} }
} }
} }
if (isFallback) if (currentScript != Script.Common && currentScript != Script.Inherited)
{ {
if (defaultFont.TryGetGlyph(grapheme.FirstCodepoint, out _)) if (isFallback && defaultFont.TryGetGlyph(currentGrapheme.FirstCodepoint, out _))
{ {
break; break;
} }
}
if (!font.TryGetGlyph(grapheme.FirstCodepoint, out _)) if (!font.TryGetGlyph(currentGrapheme.FirstCodepoint, out _))
{
if (!grapheme.FirstCodepoint.IsWhiteSpace)
{ {
break; 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; return count > 0;

21
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] [Fact]
public void Should_Split_Run_On_Script() public void Should_Split_Run_On_Script()
{ {

Loading…
Cancel
Save