Skip to content

Commit

Permalink
Fix broken radio buttons (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
chkr1011 authored Oct 26, 2022
1 parent b309035 commit 0224099
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 83 deletions.
1 change: 1 addition & 0 deletions Source/App.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<StyleInclude Source="/Styles/NumericUpDown.axaml" />
<StyleInclude Source="/Styles/ComboBox.axaml" />
<StyleInclude Source="/Styles/CheckBox.axaml" />
<StyleInclude Source="/Styles/RadioButton.axaml" />

<StyleInclude Source="/Styles/Text.axaml" />

Expand Down
42 changes: 42 additions & 0 deletions Source/Common/BaseSingleSelectionViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using ReactiveUI;

namespace MQTTnetApp.Common;

public abstract class BaseSingleSelectionViewModel : BaseViewModel
{
readonly bool[] _states;

protected BaseSingleSelectionViewModel(int count)
{
_states = new bool[count];
}

protected bool GetState(int index)
{
return _states[index];
}

protected void UpdateStates(int changedStateIndex, bool changedStateValue)
{
if (!changedStateValue)
{
// Do not allow "unchecking" the value.
return;
}

for (var i = 0; i < _states.Length; i++)
{
if (i == changedStateIndex)
{
_states[i] = changedStateValue;
}
else
{
_states[i] = !changedStateValue;
}
}

// Notify all properties!
this.RaisePropertyChanged(string.Empty);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,17 @@
d:DataContext="{d:DesignInstance controls:QualityOfServiceLevelSelectorViewModel}"
x:Class="MQTTnetApp.Controls.QualityOfServiceLevelSelectorView">
<StackPanel Orientation="Horizontal">
<StackPanel.Styles>
<Style Selector="RadioButton">
<Setter Property="Margin"
Value="0,0,10,0" />
</Style>
</StackPanel.Styles>
<CheckBox Content="At most once - 0"
Classes="radio-button"
IsChecked="{Binding Path=IsLevel0, Mode=TwoWay}" />

<RadioButton GroupName="QoS"
Content="At most once (0)"
IsChecked="{Binding Path=IsLevel0, Mode=TwoWay}" />
<CheckBox Margin="10,0"
Content="At lease once - 1"
Classes="radio-button"
IsChecked="{Binding Path=IsLevel1, Mode=TwoWay}" />

<RadioButton GroupName="QoS"
Content="At lease once (1)"
IsChecked="{Binding Path=IsLevel1, Mode=TwoWay}" />

<RadioButton GroupName="QoS"
Content="Exactly once (2)"
IsChecked="{Binding Path=IsLevel2, Mode=TwoWay}" />
<CheckBox Content="Exactly once - 2"
Classes="radio-button"
IsChecked="{Binding Path=IsLevel2, Mode=TwoWay}" />
</StackPanel>
</UserControl>
Original file line number Diff line number Diff line change
@@ -1,37 +1,32 @@
using System;
using MQTTnet.Protocol;
using MQTTnetApp.Common;
using ReactiveUI;

namespace MQTTnetApp.Controls;

public sealed class QualityOfServiceLevelSelectorViewModel : BaseViewModel
public sealed class QualityOfServiceLevelSelectorViewModel : BaseSingleSelectionViewModel
{
bool _isLevel0 = true;
bool _isLevel1;
bool _isLevel2;

public QualityOfServiceLevelSelectorViewModel()
public QualityOfServiceLevelSelectorViewModel() : base(3)
{
Value = MqttQualityOfServiceLevel.AtMostOnce;
}

public bool IsLevel0
{
get => _isLevel0;
set => this.RaiseAndSetIfChanged(ref _isLevel0, value);
get => GetState(0);
set => UpdateStates(0, value);
}

public bool IsLevel1
{
get => _isLevel1;
set => this.RaiseAndSetIfChanged(ref _isLevel1, value);
get => GetState(1);
set => UpdateStates(1, value);
}

public bool IsLevel2
{
get => _isLevel2;
set => this.RaiseAndSetIfChanged(ref _isLevel2, value);
get => GetState(2);
set => UpdateStates(2, value);
}

public MqttQualityOfServiceLevel Value
Expand Down
26 changes: 10 additions & 16 deletions Source/Controls/RetainHandling/RetainHandlingSelectorView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,17 @@
d:DataContext="{d:DesignInstance controls:RetainHandlingSelectorViewModel}"
x:Class="MQTTnetApp.Controls.RetainHandlingSelectorView">
<StackPanel Orientation="Horizontal">
<StackPanel.Styles>
<Style Selector="RadioButton">
<Setter Property="Margin"
Value="0,0,10,0" />
</Style>
</StackPanel.Styles>
<CheckBox IsChecked="{Binding IsSendAtSubscribe, Mode=TwoWay}"
Classes="radio-button"
Content="Send at subscribe (0)" />

<RadioButton IsChecked="{Binding IsSendAtSubscribe, Mode=TwoWay}"
GroupName="RetainHandling"
Content="Send at subscribe (0)" />
<CheckBox Margin="10,0"
IsChecked="{Binding IsSendAtSubscribeIfNewSubscriptionOnly, Mode=TwoWay}"
Classes="radio-button"
Content="Send at subscribe if new subscription only (1)" />

<RadioButton IsChecked="{Binding IsSendAtSubscribeIfNewSubscriptionOnly, Mode=TwoWay}"
GroupName="RetainHandling"
Content="Send at subscribe if new subscription only (1)" />

<RadioButton GroupName="RetainHandling"
IsChecked="{Binding IsDoNotSendOnSubscribe, Mode=TwoWay}"
Content="Do not send on subscribe (2)" />
<CheckBox Classes="radio-button"
IsChecked="{Binding IsDoNotSendOnSubscribe, Mode=TwoWay}"
Content="Do not send on subscribe (2)" />
</StackPanel>
</UserControl>
35 changes: 17 additions & 18 deletions Source/Controls/RetainHandling/RetainHandlingSelectorViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,54 +1,53 @@
using System;
using MQTTnet.Protocol;
using MQTTnetApp.Common;
using ReactiveUI;

namespace MQTTnetApp.Controls;

public sealed class RetainHandlingSelectorViewModel : BaseViewModel
public sealed class RetainHandlingSelectorViewModel : BaseSingleSelectionViewModel
{
bool _doNotSendOnSubscribe;
bool _isSendAtSubscribe;
bool _sendAtSubscribeIfNewSubscriptionOnly;
const int DoNotSendOnSubscribeIndex = 0;
const int SendAtSubscribeIndex = 1;
const int SendAtSubscribeIfNewSubscriptionOnly = 2;

public RetainHandlingSelectorViewModel()
public RetainHandlingSelectorViewModel() : base(3)
{
Value = MqttRetainHandling.SendAtSubscribe;
}

public bool IsDoNotSendOnSubscribe
{
get => _doNotSendOnSubscribe;
set => this.RaiseAndSetIfChanged(ref _doNotSendOnSubscribe, value);
get => GetState(DoNotSendOnSubscribeIndex);
set => UpdateStates(DoNotSendOnSubscribeIndex, value);
}

public bool IsSendAtSubscribe
{
get => _isSendAtSubscribe;
set => this.RaiseAndSetIfChanged(ref _isSendAtSubscribe, value);
get => GetState(SendAtSubscribeIndex);
set => UpdateStates(SendAtSubscribeIndex, value);
}

public bool IsSendAtSubscribeIfNewSubscriptionOnly
{
get => _sendAtSubscribeIfNewSubscriptionOnly;
set => this.RaiseAndSetIfChanged(ref _sendAtSubscribeIfNewSubscriptionOnly, value);
get => GetState(SendAtSubscribeIfNewSubscriptionOnly);
set => UpdateStates(SendAtSubscribeIfNewSubscriptionOnly, value);
}

public MqttRetainHandling Value
{
get
{
if (_isSendAtSubscribe)
if (IsSendAtSubscribe)
{
return MqttRetainHandling.SendAtSubscribe;
}

if (_sendAtSubscribeIfNewSubscriptionOnly)
if (IsSendAtSubscribeIfNewSubscriptionOnly)
{
return MqttRetainHandling.SendAtSubscribeIfNewSubscriptionOnly;
}

if (_doNotSendOnSubscribe)
if (IsDoNotSendOnSubscribe)
{
return MqttRetainHandling.DoNotSendOnSubscribe;
}
Expand All @@ -58,9 +57,9 @@ public MqttRetainHandling Value

set
{
_isSendAtSubscribe = value == MqttRetainHandling.SendAtSubscribe;
_doNotSendOnSubscribe = value == MqttRetainHandling.DoNotSendOnSubscribe;
_sendAtSubscribeIfNewSubscriptionOnly = value == MqttRetainHandling.SendAtSubscribeIfNewSubscriptionOnly;
IsSendAtSubscribe = value == MqttRetainHandling.SendAtSubscribe;
IsDoNotSendOnSubscribe = value == MqttRetainHandling.DoNotSendOnSubscribe;
IsSendAtSubscribeIfNewSubscriptionOnly = value == MqttRetainHandling.SendAtSubscribeIfNewSubscriptionOnly;
}
}
}
20 changes: 12 additions & 8 deletions Source/Pages/Publish/PayloadFormatIndicatorSelectorViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
using System;
using MQTTnet.Protocol;
using MQTTnetApp.Common;
using ReactiveUI;

namespace MQTTnetApp.Pages.Publish;

public sealed class PayloadFormatIndicatorSelectorViewModel : BaseViewModel
public sealed class PayloadFormatIndicatorSelectorViewModel : BaseSingleSelectionViewModel
{
bool _isCharacterData;
bool _isUnspecified = true;
const int CharacterDataIndex = 0;
const int UnspecifiedIndex = 1;

public PayloadFormatIndicatorSelectorViewModel() : base(2)
{
IsUnspecified = true;
}

public bool IsCharacterData
{
get => _isCharacterData;
set => this.RaiseAndSetIfChanged(ref _isCharacterData, value);
get => GetState(CharacterDataIndex);
set => UpdateStates(CharacterDataIndex, value);
}

public bool IsUnspecified
{
get => _isUnspecified;
set => this.RaiseAndSetIfChanged(ref _isUnspecified, value);
get => GetState(UnspecifiedIndex);
set => UpdateStates(UnspecifiedIndex, value);
}

public MqttPayloadFormatIndicator Value
Expand Down
22 changes: 10 additions & 12 deletions Source/Pages/Publish/PublishItemView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,14 @@
Classes="value"
Grid.Column="1"
Orientation="Horizontal">
<StackPanel.Styles>
<Style Selector="RadioButton">
<Setter Property="Margin"
Value="0,0,10,0" />
</Style>
</StackPanel.Styles>
<RadioButton Content="Unspecified"
IsChecked="{Binding PayloadFormatIndicator.IsUnspecified}" />
<RadioButton Content="Character data"
IsChecked="{Binding PayloadFormatIndicator.IsCharacterData}" />

<CheckBox Classes="radio-button"
Content="Unspecified"
IsChecked="{Binding PayloadFormatIndicator.IsUnspecified}" />
<CheckBox Classes="radio-button"
Margin="10,0,0,0"
Content="Character data"
IsChecked="{Binding PayloadFormatIndicator.IsCharacterData}" />
</StackPanel>

<!-- The payload -->
Expand Down Expand Up @@ -108,8 +106,8 @@
Grid.Row="0"
Content="Quality of service (QoS) level" />
<controls:QualityOfServiceLevelSelectorView Grid.Column="1"
Grid.Row="0"
DataContext="{Binding QualityOfServiceLevel}" />
Grid.Row="0"
DataContext="{Binding QualityOfServiceLevel}" />
<!-- Retain -->
<Label Classes="caption"
Grid.Column="0"
Expand Down
6 changes: 6 additions & 0 deletions Source/Styles/CheckBox.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@
Value="26" />
</Style>

<!-- This is a fake radio button because the radio button from avalonia has binding bugs! -->
<Style Selector="CheckBox.radio-button">
<Setter Property="CornerRadius"
Value="50" />
</Style>

</Styles>
14 changes: 14 additions & 0 deletions Source/Styles/RadioButton.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Design.PreviewWith>
<Border Padding="20">
<!-- Add Controls for Previewer Here -->
</Border>
</Design.PreviewWith>

<Style Selector="RadioButton">
<Setter Property="MinHeight"
Value="26" />
</Style>

</Styles>

0 comments on commit 0224099

Please sign in to comment.