Skip to content

Commit

Permalink
Stepper Handlers (#517)
Browse files Browse the repository at this point in the history
* StepperHandlers

* Fixed Stepper handler broken tests

* Remove duplicate searchbar

* Add IStepper interface

Co-authored-by: E.Z. Hart <hartez@gmail.com>
  • Loading branch information
jsuarezruiz and hartez committed Mar 17, 2021
1 parent 7c3a94c commit 2aee03f
Show file tree
Hide file tree
Showing 22 changed files with 551 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public StepperRenderer(Context context) : base(context)
AutoPackage = false;
}

[PortHandler]
protected override LinearLayout CreateNativeControl()
{
return new LinearLayout(Context)
Expand All @@ -26,6 +27,7 @@ protected override LinearLayout CreateNativeControl()
};
}

[PortHandler]
protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
{
base.OnElementChanged(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
{
[PortHandler]
public static class StepperRendererManager
{
public static void CreateStepperButtons<TButton>(IStepperRenderer renderer, out TButton downButton, out TButton upButton)
Expand Down
1 change: 1 addition & 0 deletions src/Compatibility/Core/src/AppHostBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public static IAppHostBuilder RegisterCompatibilityRenderers(this IAppHostBuilde
typeof(Page) ,
typeof(Label) ,
typeof(Slider),
typeof(Stepper),
typeof(Switch)
};

Expand Down
5 changes: 5 additions & 0 deletions src/Compatibility/Core/src/iOS/Renderers/StepperRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,26 +65,31 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE
UpdateIncrement();
}

[PortHandler]
void OnValueChanged(object sender, EventArgs e)
{
((IElementController)Element).SetValueFromRenderer(Stepper.ValueProperty, Control.Value);
}

[PortHandler]
void UpdateIncrement()
{
Control.StepValue = Element.Increment;
}

[PortHandler]
void UpdateMaximum()
{
Control.MaximumValue = Element.Maximum;
}

[PortHandler]
void UpdateMinimum()
{
Control.MinimumValue = Element.Minimum;
}

[PortHandler]
void UpdateValue()
{
if (Control.Value != Element.Value)
Expand Down
8 changes: 4 additions & 4 deletions src/Controls/samples/Controls.Sample/Pages/MainPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,16 +109,16 @@ void SetupMauiLayout()
searchBar.Text = "A search query";
verticalStack.Add(searchBar);

var searchBar = new SearchBar();
searchBar.Text = "A search query";
verticalStack.Add(searchBar);

var placeholderSearchBar = new SearchBar();
placeholderSearchBar.Placeholder = "Placeholder";
verticalStack.Add(placeholderSearchBar);

verticalStack.Add(new Slider());

verticalStack.Add(new Stepper());
verticalStack.Add(new Stepper { BackgroundColor = Color.IndianRed });
verticalStack.Add(new Stepper { Minimum = 0, Maximum = 10, Value = 5 });

verticalStack.Add(new Switch());
verticalStack.Add(new Switch() { OnColor = Color.Green });
verticalStack.Add(new Switch() { ThumbColor = Color.Yellow });
Expand Down
2 changes: 1 addition & 1 deletion src/Controls/src/Core/Stepper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Microsoft.Maui.Controls
{
public class Stepper : View, IElementConfiguration<Stepper>
public class Stepper : View, IElementConfiguration<Stepper>, IStepper
{
public static readonly BindableProperty MaximumProperty = BindableProperty.Create(nameof(Maximum), typeof(double), typeof(Stepper), 100.0,
validateValue: (bindable, value) => (double)value > ((Stepper)bindable).Minimum,
Expand Down
23 changes: 23 additions & 0 deletions src/Core/src/Core/IRange.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace Microsoft.Maui
{
/// <summary>
/// Provides functionality to select a value from a range of values.
/// </summary>
public interface IRange : IView
{
/// <summary>
/// Gets or sets the minimum selectable value.
/// </summary>
double Minimum { get; }

/// <summary>
/// Gets or sets the maximum selectable value.
/// </summary>
double Maximum { get; }

/// <summary>
/// Gets or sets the current value.
/// </summary>
double Value { get; set; }
}
}
17 changes: 1 addition & 16 deletions src/Core/src/Core/ISlider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,8 @@ namespace Microsoft.Maui
/// <summary>
/// Represents a View that inputs a linear value.
/// </summary>
public interface ISlider : IView
public interface ISlider : IView, IRange
{
/// <summary>
/// Gets or sets the minimum selectable value for the Slider.
/// </summary>
double Minimum { get; }

/// <summary>
/// Gets or sets the maximum selectable value for the Slider.
/// </summary>
double Maximum { get; }

/// <summary>
/// Gets or sets the current value.
/// </summary>
double Value { get; set; }

/// <summary>
/// Gets or sets the color of the portion of the slider track that contains the minimum value of the slider.
/// </summary>
Expand Down
14 changes: 14 additions & 0 deletions src/Core/src/Core/IStepper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Microsoft.Maui
{
/// <summary>
/// Represents a View that consists of two buttons labeled with minus and plus signs.
/// Use a Stepper for selecting a numeric value from a range of values.
/// </summary>
public interface IStepper : IView, IRange
{
/// <summary>
/// Gets the increment by which Value is increased or decreased.
/// </summary>
double Increment { get; }
}
}
70 changes: 70 additions & 0 deletions src/Core/src/Handlers/Stepper/StepperHandler.Android.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System;
using Android.Widget;
using Android.Views;
using AButton = Android.Widget.Button;
using AOrientation = Android.Widget.Orientation;

namespace Microsoft.Maui.Handlers
{
public partial class StepperHandler : AbstractViewHandler<IStepper, LinearLayout>, IStepperHandler
{
AButton? _downButton;
AButton? _upButton;

IStepper? IStepperHandler.VirtualView => VirtualView;

AButton? IStepperHandler.UpButton => _upButton;

AButton? IStepperHandler.DownButton => _downButton;

protected override LinearLayout CreateNativeView()
{
var stepperLayout = new LinearLayout(Context)
{
Orientation = AOrientation.Horizontal,
Focusable = true,
DescendantFocusability = DescendantFocusability.AfterDescendants
};

StepperHandlerManager.CreateStepperButtons(this, out _downButton, out _upButton);

if (_downButton != null)
stepperLayout.AddView(_downButton, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.MatchParent));

if (_upButton != null)
stepperLayout.AddView(_upButton, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.MatchParent));

return stepperLayout;
}

public static void MapMinimum(StepperHandler handler, IStepper stepper)
{
handler.TypedNativeView?.UpdateMinimum(stepper);
}

public static void MapMaximum(StepperHandler handler, IStepper stepper)
{
handler.TypedNativeView?.UpdateMaximum(stepper);
}

public static void MapIncrement(StepperHandler handler, IStepper stepper)
{
handler.TypedNativeView?.UpdateIncrement(stepper);
}

public static void MapValue(StepperHandler handler, IStepper stepper)
{
handler.TypedNativeView?.UpdateValue(stepper);
}

AButton IStepperHandler.CreateButton()
{
if (Context == null)
throw new ArgumentException("Context is null or empty", nameof(Context));

var button = new AButton(Context);
button.SetHeight((int)Context.ToPixels(10.0));
return button;
}
}
}
14 changes: 14 additions & 0 deletions src/Core/src/Handlers/Stepper/StepperHandler.Standard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace Microsoft.Maui.Handlers
{
public partial class StepperHandler : AbstractViewHandler<IStepper, object>
{
protected override object CreateNativeView() => throw new NotImplementedException();

public static void MapMinimum(IViewHandler handler, IStepper stepper) { }
public static void MapMaximum(IViewHandler handler, IStepper stepper) { }
public static void MapIncrement(IViewHandler handler, IStepper stepper) { }
public static void MapValue(IViewHandler handler, IStepper stepper) { }
}
}
23 changes: 23 additions & 0 deletions src/Core/src/Handlers/Stepper/StepperHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace Microsoft.Maui.Handlers
{
public partial class StepperHandler
{
public static PropertyMapper<IStepper, StepperHandler> StepperMapper = new PropertyMapper<IStepper, StepperHandler>(ViewHandler.ViewMapper)
{
[nameof(IStepper.Minimum)] = MapMinimum,
[nameof(IStepper.Maximum)] = MapMaximum,
[nameof(IStepper.Increment)] = MapIncrement,
[nameof(IStepper.Value)] = MapValue
};

public StepperHandler() : base(StepperMapper)
{

}

public StepperHandler(PropertyMapper mapper) : base(mapper ?? StepperMapper)
{

}
}
}
52 changes: 52 additions & 0 deletions src/Core/src/Handlers/Stepper/StepperHandler.iOS.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using System.Drawing;
using UIKit;

namespace Microsoft.Maui.Handlers
{
public partial class StepperHandler : AbstractViewHandler<IStepper, UIStepper>
{
protected override UIStepper CreateNativeView()
{
return new UIStepper(RectangleF.Empty);
}

protected override void ConnectHandler(UIStepper nativeView)
{
nativeView.ValueChanged += OnValueChanged;
}

protected override void DisconnectHandler(UIStepper nativeView)
{
nativeView.ValueChanged -= OnValueChanged;
}

public static void MapMinimum(StepperHandler handler, IStepper stepper)
{
handler.TypedNativeView?.UpdateMinimum(stepper);
}

public static void MapMaximum(StepperHandler handler, IStepper stepper)
{
handler.TypedNativeView?.UpdateMaximum(stepper);
}

public static void MapIncrement(StepperHandler handler, IStepper stepper)
{
handler.TypedNativeView?.UpdateIncrement(stepper);
}

public static void MapValue(StepperHandler handler, IStepper stepper)
{
handler.TypedNativeView?.UpdateValue(stepper);
}

void OnValueChanged(object? sender, EventArgs e)
{
if (TypedNativeView == null || VirtualView == null)
return;

VirtualView.Value = TypedNativeView.Value;
}
}
}
1 change: 1 addition & 0 deletions src/Core/src/Hosting/AppHostBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public static IAppHostBuilder UseMauiHandlers(this IAppHostBuilder builder)
{ typeof(ILabel), typeof(LabelHandler) },
{ typeof(IProgress), typeof(ProgressBarHandler) },
{ typeof(ISlider), typeof(SliderHandler) },
{ typeof(IStepper), typeof(StepperHandler) },
{ typeof(ISwitch), typeof(SwitchHandler) },
{ typeof(ITimePicker), typeof(TimePickerHandler) }
});
Expand Down
52 changes: 52 additions & 0 deletions src/Core/src/Platform/Android/StepperExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using Android.Widget;
using AButton = Android.Widget.Button;

namespace Microsoft.Maui
{
public static class StepperExtensions
{
public static void UpdateMinimum(this LinearLayout linearLayout, IStepper stepper)
{
UpdateButtons(linearLayout, stepper);
}

public static void UpdateMaximum(this LinearLayout linearLayout, IStepper stepper)
{
UpdateButtons(linearLayout, stepper);
}

public static void UpdateIncrement(this LinearLayout linearLayout, IStepper stepper)
{
UpdateButtons(linearLayout, stepper);
}

public static void UpdateValue(this LinearLayout linearLayout, IStepper stepper)
{
UpdateButtons(linearLayout, stepper);
}

public static void UpdateIsEnabled(this LinearLayout linearLayout, IStepper stepper)
{
UpdateButtons(linearLayout, stepper);
}

internal static void UpdateButtons(this LinearLayout linearLayout, IStepper stepper)
{
AButton? downButton = null;
AButton? upButton = null;

for (int i = 0; i < linearLayout?.ChildCount; i++)
{
var childButton = linearLayout.GetChildAt(i) as AButton;

if (childButton?.Text == "")
downButton = childButton;

if (childButton?.Text == "")
upButton = childButton;
}

StepperHandlerManager.UpdateButtons(stepper, downButton, upButton);
}
}
}
Loading

0 comments on commit 2aee03f

Please sign in to comment.