Skip to content

Commit

Permalink
Merge pull request #4241 from Splitwirez/feature/toggleswitch-dragging
Browse files Browse the repository at this point in the history
ToggleSwitch dragging
  • Loading branch information
danwalmsley authored Jul 8, 2020
2 parents 951e866 + 1da6fb4 commit b27c755
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 10 deletions.
118 changes: 118 additions & 0 deletions src/Avalonia.Controls/ToggleSwitch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,32 @@ namespace Avalonia.Controls
/// </summary>
public class ToggleSwitch : ToggleButton
{
private Panel _knobsPanel;
private Panel _switchKnob;
private bool _knobsPanelPressed = false;
private Point _switchStartPoint = new Point();
private double _initLeft = -1;
private bool _isDragging = false;

static ToggleSwitch()
{
OffContentProperty.Changed.AddClassHandler<ToggleSwitch>((x, e) => x.OffContentChanged(e));
OnContentProperty.Changed.AddClassHandler<ToggleSwitch>((x, e) => x.OnContentChanged(e));
IsCheckedProperty.Changed.AddClassHandler<ToggleSwitch>((x, e) =>
{
if ((e.NewValue != null) && (e.NewValue is bool val))
{
x.UpdateKnobPos(val);
}
});

BoundsProperty.Changed.AddClassHandler<ToggleSwitch>((x, e) =>
{
if (x.IsChecked != null)
{
x.UpdateKnobPos(x.IsChecked.Value);
}
});
}

/// <summary>
Expand Down Expand Up @@ -131,6 +153,102 @@ protected override bool RegisterContentPresenter(IContentPresenter presenter)

return result;
}


protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);

_switchKnob = e.NameScope.Find<Panel>("SwitchKnob");
_knobsPanel = e.NameScope.Find<Panel>("MovingKnobs");

_knobsPanel.PointerPressed += KnobsPanel_PointerPressed;
_knobsPanel.PointerReleased += KnobsPanel_PointerReleased;
_knobsPanel.PointerMoved += KnobsPanel_PointerMoved;

if (IsChecked.HasValue)
{
UpdateKnobPos(IsChecked.Value);
}
}

private void KnobsPanel_PointerPressed(object sender, Input.PointerPressedEventArgs e)
{
_switchStartPoint = e.GetPosition(_switchKnob);
_initLeft = Canvas.GetLeft(_knobsPanel);
_isDragging = false;
_knobsPanelPressed = true;
}

private void KnobsPanel_PointerReleased(object sender, Input.PointerReleasedEventArgs e)
{
if (_isDragging)
{
bool shouldBecomeChecked = Canvas.GetLeft(_knobsPanel) >= (_switchKnob.Bounds.Width / 2);
_knobsPanel.ClearValue(Canvas.LeftProperty);

PseudoClasses.Set(":dragging", false);

if (shouldBecomeChecked == IsChecked)
{
UpdateKnobPos(shouldBecomeChecked);
}
else
{
IsChecked = shouldBecomeChecked;
}
}
else
{
base.Toggle();
}

_isDragging = false;

_knobsPanelPressed = false;
}

private void KnobsPanel_PointerMoved(object sender, Input.PointerEventArgs e)
{
if (_knobsPanelPressed)
{
var difference = e.GetPosition(_switchKnob) - _switchStartPoint;

if ((!_isDragging) && (System.Math.Abs(difference.X) > 3))
{
_isDragging = true;
PseudoClasses.Set(":dragging", true);
}

if (_isDragging)
{
Canvas.SetLeft(_knobsPanel, System.Math.Min(_switchKnob.Bounds.Width, System.Math.Max(0, (_initLeft + difference.X))));
}
}
}

protected override void Toggle()
{
if ((_switchKnob != null) && (!_switchKnob.IsPointerOver))
{
base.Toggle();
}
}

protected void UpdateKnobPos(bool value)
{
if ((_switchKnob != null) && (_knobsPanel != null))
{
if (value)
{
Canvas.SetLeft(_knobsPanel, _switchKnob.Bounds.Width);
}
else
{
Canvas.SetLeft(_knobsPanel, 0);
}
}
}
}
}

11 changes: 1 addition & 10 deletions src/Avalonia.Themes.Fluent/ToggleSwitch.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,7 @@
<Setter Property="Stroke" Value="{DynamicResource ToggleSwitchKnobStrokeOff}"/>
</Style>

<Style Selector="ToggleSwitch /template/ Grid#MovingKnobs">
<Setter Property="Canvas.Left" Value="{DynamicResource KnobOffPosition}"/>
<Style Selector="ToggleSwitch:not(:dragging) /template/ Grid#MovingKnobs">
<Setter Property="Transitions">
<Transitions>
<DoubleTransition Property="Canvas.Left" Duration="0:0:0.2" Easing="CubicEaseOut"/>
Expand Down Expand Up @@ -234,10 +233,6 @@
</Style>

<!-- CheckedState -->
<Style Selector="ToggleSwitch:checked /template/ Grid#MovingKnobs">
<Setter Property="Canvas.Left" Value="{DynamicResource KnobOnPosition}"/>
</Style>

<Style Selector="ToggleSwitch:checked /template/ Border#OuterBorder">
<Setter Property="Opacity" Value="0"/>
</Style>
Expand All @@ -263,10 +258,6 @@
</Style>

<!--UncheckedState -->
<Style Selector="ToggleSwitch:unchecked /template/ Grid#MovingKnobs">
<Setter Property="Canvas.Left" Value="{DynamicResource KnobOffPosition}"/>
</Style>

<Style Selector="ToggleSwitch:unchecked /template/ Border#OuterBorder">
<Setter Property="Opacity" Value="1"/>
</Style>
Expand Down

0 comments on commit b27c755

Please sign in to comment.