Skip to content
Open
Show file tree
Hide file tree
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
83 changes: 81 additions & 2 deletions src/Controls/src/Core/BoxView/BoxView.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#nullable disable
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Microsoft.Maui.Graphics;

Expand All @@ -11,12 +10,33 @@ namespace Microsoft.Maui.Controls
/// </summary>
public partial class BoxView : View, IColorElement, ICornerElement, IElementConfiguration<BoxView>, IShapeView, IShape
{
WeakBrushChangedProxy _fillProxy = null;
EventHandler _fillChanged;

/// <summary>Bindable property for <see cref="Color"/>.</summary>
public static readonly BindableProperty ColorProperty = ColorElement.ColorProperty;

/// <summary>Bindable property for <see cref="CornerRadius"/>.</summary>
public static readonly BindableProperty CornerRadiusProperty = CornerElement.CornerRadiusProperty;

/// <summary>Bindable property for <see cref="Fill"/>.</summary>
public static readonly BindableProperty FillProperty =
BindableProperty.Create(nameof(Fill), typeof(Brush), typeof(BoxView), null,
propertyChanging: (bindable, oldvalue, newvalue) =>
{
if (oldvalue != null)
{
(bindable as BoxView)?.StopNotifyingFillChanges();
}
},
propertyChanged: (bindable, oldvalue, newvalue) =>
{
if (newvalue != null)
{
(bindable as BoxView)?.NotifyFillChanges();
}
});

readonly Lazy<PlatformConfigurationRegistry<BoxView>> _platformConfigurationRegistry;

/// <summary>
Expand All @@ -27,6 +47,11 @@ public BoxView()
_platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<BoxView>>(() => new PlatformConfigurationRegistry<BoxView>(this));
}

~BoxView()
{
_fillProxy?.Unsubscribe();
}

/// <summary>
/// Gets or sets the color which will fill the rectangle. This is a bindable property.
/// </summary>
Expand All @@ -37,6 +62,19 @@ public Color Color
set => SetValue(ColorElement.ColorProperty, value);
}

/// <summary>
/// Gets or sets the brush that fills the interior of the BoxView.
/// </summary>
/// <value>
/// A <see cref="Brush"/> object that describes how the BoxView's interior is painted.
/// The default value is <see langword="null"/>.
/// </value>
public Brush Fill
{
get => (Brush)GetValue(FillProperty);
set => SetValue(FillProperty, value);
}

/// <summary>
/// Gets or sets the corner radius for the box view.
/// </summary>
Expand All @@ -60,6 +98,45 @@ protected override SizeRequest OnMeasure(double widthConstraint, double heightCo
return new SizeRequest(new Size(40, 40));
}

void NotifyFillChanges()
{
var fill = Fill;

if (fill is ImmutableBrush)
{
return;
}

if (fill is not null)
{
SetInheritedBindingContext(fill, BindingContext);
_fillChanged ??= (sender, e) => OnPropertyChanged(nameof(Fill));
_fillProxy ??= new();
_fillProxy.Subscribe(fill, _fillChanged);

OnParentResourcesChanged(this.GetMergedResources());
((IElementDefinition)this).AddResourcesChangedListener(fill.OnParentResourcesChanged);
}
}

void StopNotifyingFillChanges()
{
var fill = Fill;

if (fill is ImmutableBrush)
{
return;
}

if (fill is not null)
{
((IElementDefinition)this).RemoveResourcesChangedListener(fill.OnParentResourcesChanged);

SetInheritedBindingContext(fill, null);
_fillProxy?.Unsubscribe();
}
}

#nullable enable
// Todo these shuold be moved to a mapper
protected override void OnPropertyChanged([CallerMemberName] string? propertyName = null)
Expand All @@ -71,14 +148,16 @@ protected override void OnPropertyChanged([CallerMemberName] string? propertyNam
propertyName == IsVisibleProperty.PropertyName ||
propertyName == BackgroundProperty.PropertyName ||
propertyName == CornerRadiusProperty.PropertyName)
{
Handler?.UpdateValue(nameof(IShapeView.Shape));
}
}

IShape? IShapeView.Shape => this;

PathAspect IShapeView.Aspect => PathAspect.None;

Paint? IShapeView.Fill => Color?.AsPaint();
Paint? IShapeView.Fill => Fill ?? Color?.AsPaint();

Paint? IStroke.Stroke => null;

Expand Down
44 changes: 44 additions & 0 deletions src/Controls/src/Core/Internals/WeakEventProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,48 @@ public override void Unsubscribe()
base.Unsubscribe();
}
}

class WeakBrushChangedProxy : WeakEventProxy<Brush, EventHandler>
{
void OnBrushChanged(object? sender, EventArgs e)
{
if (TryGetHandler(out var handler))
{
handler(sender, e);
}
else
{
Unsubscribe();
}
}

public override void Subscribe(Brush source, EventHandler handler)
{
if (TryGetSource(out var s))
{
s.PropertyChanged -= OnBrushChanged;

if (s is GradientBrush g)
g.InvalidateGradientBrushRequested -= OnBrushChanged;
}

source.PropertyChanged += OnBrushChanged;
if (source is GradientBrush gradientBrush)
gradientBrush.InvalidateGradientBrushRequested += OnBrushChanged;

base.Subscribe(source, handler);
}

public override void Unsubscribe()
{
if (TryGetSource(out var s))
{
s.PropertyChanged -= OnBrushChanged;

if (s is GradientBrush g)
g.InvalidateGradientBrushRequested -= OnBrushChanged;
}
base.Unsubscribe();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -530,3 +530,7 @@ virtual Microsoft.Maui.Controls.Handlers.TabbedPageManager.UpdateTabIcons() -> v
~virtual Microsoft.Maui.Controls.Internals.EvaluateJavaScriptDelegate.Invoke(string script) -> System.Threading.Tasks.Task<string>
~virtual Microsoft.Maui.Controls.PropertyChangingEventHandler.Invoke(object sender, Microsoft.Maui.Controls.PropertyChangingEventArgs e) -> void
~virtual Microsoft.Maui.Controls.VisualElement.ComputeConstraintForView(Microsoft.Maui.Controls.View view) -> Microsoft.Maui.Controls.LayoutConstraint
Microsoft.Maui.Controls.BoxView.~BoxView() -> void
~Microsoft.Maui.Controls.BoxView.Fill.get -> Microsoft.Maui.Controls.Brush
~Microsoft.Maui.Controls.BoxView.Fill.set -> void
~static readonly Microsoft.Maui.Controls.BoxView.FillProperty -> Microsoft.Maui.Controls.BindableProperty
Original file line number Diff line number Diff line change
Expand Up @@ -498,3 +498,7 @@ virtual Microsoft.Maui.Controls.Platform.Compatibility.ShellPageRendererTracker.
~virtual Microsoft.Maui.Controls.Platform.Compatibility.ShellSectionRenderer.GetSecondaryToolbarMenuButtonImage() -> UIKit.UIImage
~virtual Microsoft.Maui.Controls.PropertyChangingEventHandler.Invoke(object sender, Microsoft.Maui.Controls.PropertyChangingEventArgs e) -> void
~virtual Microsoft.Maui.Controls.VisualElement.ComputeConstraintForView(Microsoft.Maui.Controls.View view) -> Microsoft.Maui.Controls.LayoutConstraint
Microsoft.Maui.Controls.BoxView.~BoxView() -> void
~Microsoft.Maui.Controls.BoxView.Fill.get -> Microsoft.Maui.Controls.Brush
~Microsoft.Maui.Controls.BoxView.Fill.set -> void
~static readonly Microsoft.Maui.Controls.BoxView.FillProperty -> Microsoft.Maui.Controls.BindableProperty
Original file line number Diff line number Diff line change
Expand Up @@ -498,3 +498,7 @@ virtual Microsoft.Maui.Controls.Platform.Compatibility.ShellPageRendererTracker.
~virtual Microsoft.Maui.Controls.Platform.Compatibility.ShellSectionRenderer.GetSecondaryToolbarMenuButtonImage() -> UIKit.UIImage
~virtual Microsoft.Maui.Controls.PropertyChangingEventHandler.Invoke(object sender, Microsoft.Maui.Controls.PropertyChangingEventArgs e) -> void
~virtual Microsoft.Maui.Controls.VisualElement.ComputeConstraintForView(Microsoft.Maui.Controls.View view) -> Microsoft.Maui.Controls.LayoutConstraint
Microsoft.Maui.Controls.BoxView.~BoxView() -> void
~Microsoft.Maui.Controls.BoxView.Fill.get -> Microsoft.Maui.Controls.Brush
~Microsoft.Maui.Controls.BoxView.Fill.set -> void
~static readonly Microsoft.Maui.Controls.BoxView.FillProperty -> Microsoft.Maui.Controls.BindableProperty
Original file line number Diff line number Diff line change
Expand Up @@ -298,4 +298,8 @@ override Microsoft.Maui.Controls.WebViewSourceTypeConverter.ConvertTo(System.Com
Microsoft.Maui.Controls.Xaml.IXamlDataTypeProvider
Microsoft.Maui.Controls.Xaml.IXamlDataTypeProvider.BindingDataType.get -> string!
~Microsoft.Maui.Controls.Binding.DataType.get -> System.Type
~Microsoft.Maui.Controls.Binding.DataType.set -> void
~Microsoft.Maui.Controls.Binding.DataType.set -> void
Microsoft.Maui.Controls.BoxView.~BoxView() -> void
~Microsoft.Maui.Controls.BoxView.Fill.get -> Microsoft.Maui.Controls.Brush
~Microsoft.Maui.Controls.BoxView.Fill.set -> void
~static readonly Microsoft.Maui.Controls.BoxView.FillProperty -> Microsoft.Maui.Controls.BindableProperty
Original file line number Diff line number Diff line change
Expand Up @@ -501,3 +501,7 @@ virtual Microsoft.Maui.Controls.BindableProperty.CreateDefaultValueDelegate<TDec
~virtual Microsoft.Maui.Controls.Internals.EvaluateJavaScriptDelegate.Invoke(string script) -> System.Threading.Tasks.Task<string>
~virtual Microsoft.Maui.Controls.PropertyChangingEventHandler.Invoke(object sender, Microsoft.Maui.Controls.PropertyChangingEventArgs e) -> void
~virtual Microsoft.Maui.Controls.VisualElement.ComputeConstraintForView(Microsoft.Maui.Controls.View view) -> Microsoft.Maui.Controls.LayoutConstraint
Microsoft.Maui.Controls.BoxView.~BoxView() -> void
~Microsoft.Maui.Controls.BoxView.Fill.get -> Microsoft.Maui.Controls.Brush
~Microsoft.Maui.Controls.BoxView.Fill.set -> void
~static readonly Microsoft.Maui.Controls.BoxView.FillProperty -> Microsoft.Maui.Controls.BindableProperty
4 changes: 4 additions & 0 deletions src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -472,3 +472,7 @@ virtual Microsoft.Maui.Controls.BindableProperty.CreateDefaultValueDelegate<TDec
~virtual Microsoft.Maui.Controls.Internals.EvaluateJavaScriptDelegate.Invoke(string script) -> System.Threading.Tasks.Task<string>
~virtual Microsoft.Maui.Controls.PropertyChangingEventHandler.Invoke(object sender, Microsoft.Maui.Controls.PropertyChangingEventArgs e) -> void
~virtual Microsoft.Maui.Controls.VisualElement.ComputeConstraintForView(Microsoft.Maui.Controls.View view) -> Microsoft.Maui.Controls.LayoutConstraint
Microsoft.Maui.Controls.BoxView.~BoxView() -> void
~Microsoft.Maui.Controls.BoxView.Fill.get -> Microsoft.Maui.Controls.Brush
~Microsoft.Maui.Controls.BoxView.Fill.set -> void
~static readonly Microsoft.Maui.Controls.BoxView.FillProperty -> Microsoft.Maui.Controls.BindableProperty
Original file line number Diff line number Diff line change
Expand Up @@ -472,3 +472,7 @@ virtual Microsoft.Maui.Controls.BindableProperty.CreateDefaultValueDelegate<TDec
~virtual Microsoft.Maui.Controls.Internals.EvaluateJavaScriptDelegate.Invoke(string script) -> System.Threading.Tasks.Task<string>
~virtual Microsoft.Maui.Controls.PropertyChangingEventHandler.Invoke(object sender, Microsoft.Maui.Controls.PropertyChangingEventArgs e) -> void
~virtual Microsoft.Maui.Controls.VisualElement.ComputeConstraintForView(Microsoft.Maui.Controls.View view) -> Microsoft.Maui.Controls.LayoutConstraint
Microsoft.Maui.Controls.BoxView.~BoxView() -> void
~Microsoft.Maui.Controls.BoxView.Fill.get -> Microsoft.Maui.Controls.Brush
~Microsoft.Maui.Controls.BoxView.Fill.set -> void
~static readonly Microsoft.Maui.Controls.BoxView.FillProperty -> Microsoft.Maui.Controls.BindableProperty
44 changes: 0 additions & 44 deletions src/Controls/src/Core/Shapes/Shape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -466,49 +466,5 @@ internal virtual double HeightForPathComputation
return height == -1 ? _fallbackHeight : height;
}
}

class WeakBrushChangedProxy : WeakEventProxy<Brush, EventHandler>
{
void OnBrushChanged(object? sender, EventArgs e)
{
if (TryGetHandler(out var handler))
{
handler(sender, e);
}
else
{
Unsubscribe();
}
}

public override void Subscribe(Brush source, EventHandler handler)
{
if (TryGetSource(out var s))
{
s.PropertyChanged -= OnBrushChanged;

if (s is GradientBrush g)
g.InvalidateGradientBrushRequested -= OnBrushChanged;
}

source.PropertyChanged += OnBrushChanged;
if (source is GradientBrush gradientBrush)
gradientBrush.InvalidateGradientBrushRequested += OnBrushChanged;

base.Subscribe(source, handler);
}

public override void Unsubscribe()
{
if (TryGetSource(out var s))
{
s.PropertyChanged -= OnBrushChanged;

if (s is GradientBrush g)
g.InvalidateGradientBrushRequested -= OnBrushChanged;
}
base.Unsubscribe();
}
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<!-- BoxView at top center -->
<BoxView Grid.Row="0"
Color="{Binding Color}"
Fill="{Binding Fill}"
WidthRequest="{Binding Width}"
Opacity="{Binding Opacity}"
HeightRequest="{Binding Height}"
Expand All @@ -39,7 +40,6 @@
<!-- Left Column - Entry Controls -->
<StackLayout Grid.Column="0"
Grid.Row="0"
Padding="20"
Spacing="10">
<Label FontAttributes="Bold"
AutomationId="CornerRadiusLabel"
Expand Down Expand Up @@ -69,23 +69,49 @@
<!-- Right Column - Controls -->
<StackLayout Grid.Column="1"
Grid.Row="0"
Padding="20"
Spacing="1">
<Label FontAttributes="Bold"
Text="Box Color"/>
<VerticalStackLayout>
<RadioButton Content="Red"
Value="Red"
GroupName="Colors"
AutomationId="RedRadioButton"
IsChecked="{Binding IsRedChecked, Mode=TwoWay}"/>
<HorizontalStackLayout>
<!-- Color -->
<VerticalStackLayout>
<Label FontAttributes="Bold"
Text="Box Color"/>
<RadioButton Content="Red"
Value="Red"
GroupName="Colors"
AutomationId="RedRadioButton"
IsChecked="{Binding IsRedChecked, Mode=TwoWay}"/>

<RadioButton Content="Blue"
Value="Blue"
GroupName="Colors"
AutomationId="BlueRadioButton"
IsChecked="{Binding IsBlueChecked, Mode=TwoWay}"/>
</VerticalStackLayout>

<!-- Fill -->
<VerticalStackLayout>
<Label FontAttributes="Bold"
HorizontalOptions="Center"
Text="Fill"/>
<RadioButton Content="Solid"
Value="Solid"
GroupName="Fill"
AutomationId="SolidRadioButton"
IsChecked="{Binding IsSolidChecked, Mode=TwoWay}"/>

<RadioButton Content="Linear"
Value="Linear"
GroupName="Fill"
AutomationId="LinearRadioButton"
IsChecked="{Binding IsLinearChecked, Mode=TwoWay}"/>
<RadioButton Content="Radial"
Value="Radial"
GroupName="Fill"
AutomationId="RadialRadioButton"
IsChecked="{Binding IsRadialChecked, Mode=TwoWay}"/>
</VerticalStackLayout>
</HorizontalStackLayout>

<RadioButton Content="Blue"
Value="Blue"
GroupName="Colors"
AutomationId="BlueRadioButton"
IsChecked="{Binding IsBlueChecked, Mode=TwoWay}"/>
</VerticalStackLayout>

<VerticalStackLayout Spacing="5">
<HorizontalStackLayout
Expand All @@ -104,17 +130,17 @@
</HorizontalStackLayout>

<Label Text="Flow Direction:"
FontAttributes="Bold"
FontSize="15"/>
FontAttributes="Bold"
FontSize="15"/>
<StackLayout Orientation="Horizontal"
Spacing="10">
Spacing="10">

<CheckBox x:Name="FlowDirectionRTLCheckBox"
AutomationId="FlowDirectionRTLCheckBox"
IsChecked="False"
CheckedChanged="OnFlowDirectionCheckBoxChanged"/>
<Label Text="RTL"
VerticalOptions="Center"/>
VerticalOptions="Center"/>
</StackLayout>

</VerticalStackLayout>
Expand Down
Loading
Loading