Skip to content

Commit

Permalink
Add initial multi language support
Browse files Browse the repository at this point in the history
  • Loading branch information
Leapward-Koex committed Apr 24, 2024
1 parent 0a79a71 commit 851d83c
Show file tree
Hide file tree
Showing 10 changed files with 719 additions and 29 deletions.
3 changes: 3 additions & 0 deletions App.config
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
<setting name="FirstOpen" serializeAs="String">
<value>True</value>
</setting>
<setting name="UserLanguage" serializeAs="String">
<value />
</setting>
</WpfMaiTouchEmulator.Properties.Settings>
</userSettings>
</configuration>
42 changes: 24 additions & 18 deletions MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,44 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfMaiTouchEmulator"
mc:Ignorable="d"
Closing="MainWindow_Closing"
Title="MainWindow" Height="282" Width="800">
<Grid Background="Transparent">
<Button x:Name="ConnectToPortButton" Content="Connect to port" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Click="ConnectToPortButton_Click" Width="105"/>
Title="MainWindow" Height="360" Width="500" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
<Grid Background="Transparent" Height="317" VerticalAlignment="Top" >
<Button x:Name="ConnectToPortButton" Content="{Binding LbConnectToPort}" HorizontalAlignment="Left" Margin="10,95,0,0" VerticalAlignment="Top" Click="ConnectToPortButton_Click" />
<TextBox x:Name="RecievedLogBox"
IsReadOnly="True"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
AcceptsReturn="True"
AcceptsTab="True"
TextWrapping="Wrap" Margin="376,34,278,9" />
TextWrapping="Wrap" Margin="376,34,0,219" HorizontalAlignment="Left" Width="88" />
<TextBox x:Name="SentLogBox"
IsReadOnly="True"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
AcceptsReturn="True"
AcceptsTab="True"
TextWrapping="Wrap" Margin="552,34,102,9" />
<Label x:Name="label" Content="Recieved" HorizontalAlignment="Left" Margin="376,8,0,0" VerticalAlignment="Top" Width="88"/>
<Label x:Name="label_Copy" Content="Sent" HorizontalAlignment="Left" Margin="552,8,0,0" VerticalAlignment="Top" Width="88"/>
<Label x:Name="label_Copy1" Content="Button State" HorizontalAlignment="Left" Margin="698,8,0,0" VerticalAlignment="Top" Width="88"/>
<Label x:Name="buttonStateValue" Content="0" HorizontalAlignment="Left" Margin="698,34,0,0" VerticalAlignment="Top" RenderTransformOrigin="3.566,1.468" FontSize="10"/>
<CheckBox x:Name="debugMode" Content="Debug mode" HorizontalAlignment="Left" Margin="10,39,0,0" VerticalAlignment="Top" IsChecked="{Binding Path=IsDebugEnabled}" Click="debugMode_Click" Cursor="" Focusable="False" ToolTip="Show the touchpad with translucency and show inputs highlighted"/>
<CheckBox x:Name="automaticTouchPanelPositioning" HorizontalAlignment="Left" Margin="10,59,0,0" VerticalAlignment="Top" Height="17" Width="224" Content="Automatic sensor window positioning" IsChecked="{Binding Path=IsAutomaticPositioningEnabled}" Click="automaticTouchPanelPositioning_Click" ToolTip="Try and automatically move the touch sensor window into the correct position on top of Sinma.exe"/>
<CheckBox x:Name="automaticPortConnecting" HorizontalAlignment="Left" Margin="10,81,0,0" VerticalAlignment="Top" Height="17" Width="224" Content="Automatic port connecting" IsChecked="{Binding Path=IsAutomaticPortConnectingEnabled}" Click="automaticPortConnecting_Click" ToolTip="Try to automatically connect to COM23 to send touchsensor updates on app start"/>
<Label x:Name="label1" Content="Connection state" HorizontalAlignment="Left" Margin="238,8,0,0" VerticalAlignment="Top"/>
<Label x:Name="connectionStateLabel" Content="Not connected" HorizontalAlignment="Left" Margin="238,31,0,0" VerticalAlignment="Top" FontSize="10"/>
<CheckBox x:Name="exitWithSinmai" HorizontalAlignment="Left" Margin="10,103,0,0" VerticalAlignment="Top" Height="17" Width="224" Content="Exit when Sinmai exits" IsChecked="{Binding IsExitWithSinmaiEnabled}" Click="exitWithSinmai_Click" ToolTip="Try and detect when Sinmai.exe exits and exit this app alongside it"/>
<Button x:Name="buttonInstallComPort" Content="Install com port" HorizontalAlignment="Left" Margin="10,147,0,0" VerticalAlignment="Top" Click="buttonInstallComPort_Click"/>
<Button x:Name="buttonUninstallComPorts" Content="Uninstall com port" HorizontalAlignment="Left" Margin="10,172,0,0" VerticalAlignment="Top" Click="buttonUninstallComPorts_Click"/>
<Button x:Name="buttonListComPorts" Content="List installed com ports" HorizontalAlignment="Left" Margin="10,197,0,0" VerticalAlignment="Top" Click="buttonListComPorts_Click"/>
TextWrapping="Wrap" Margin="376,121,0,129" HorizontalAlignment="Left" Width="88" />
<Label x:Name="label" Content="{Binding LbRecievedData}" d:Content="Recieved Data" HorizontalAlignment="Left" Margin="376,8,0,0" VerticalAlignment="Top" Width="88"/>
<Label x:Name="label_Copy" Content="{Binding LbSentData}" d:Content="Sent Data" HorizontalAlignment="Left" Margin="376,95,0,0" VerticalAlignment="Top" Width="88"/>
<Label x:Name="label_Copy1" Content="{Binding LbButtonState}" d:Content="Button state" HorizontalAlignment="Left" Margin="238,56,0,0" VerticalAlignment="Top" Width="88"/>
<Label x:Name="buttonStateValue" Content="0" HorizontalAlignment="Left" Margin="238,82,0,0" VerticalAlignment="Top" RenderTransformOrigin="3.566,1.468" FontSize="10"/>
<CheckBox x:Name="debugMode" Content="{Binding LbDebugMode}" d:Content="Debug mode" HorizontalAlignment="Left" Margin="10,213,0,0" VerticalAlignment="Top" IsChecked="{Binding Path=IsDebugEnabled}" Click="debugMode_Click" Cursor="" Focusable="False" ToolTip="Show the touchpad with translucency and show inputs highlighted" Width="224"/>
<CheckBox x:Name="automaticTouchPanelPositioning" d:Content="Automatic touch panel positioning" HorizontalAlignment="Left" Margin="10,233,0,0" VerticalAlignment="Top" Height="17" Width="224" Content="{Binding LbAutoSensorPositioning}" IsChecked="{Binding Path=IsAutomaticPositioningEnabled}" Click="automaticTouchPanelPositioning_Click" ToolTip="Try and automatically move the touch sensor window into the correct position on top of Sinma.exe"/>
<CheckBox x:Name="automaticPortConnecting" d:Content="Automatic port connecting" HorizontalAlignment="Left" Margin="10,255,0,0" VerticalAlignment="Top" Height="17" Width="224" Content="{Binding LbAutoPortConnecting}" IsChecked="{Binding Path=IsAutomaticPortConnectingEnabled}" Click="automaticPortConnecting_Click" ToolTip="Try to automatically connect to COM23 to send touchsensor updates on app start"/>
<Label x:Name="label1" Content="{Binding LbConnectionState}" d:Content="Connection state" HorizontalAlignment="Left" Margin="238,8,0,0" VerticalAlignment="Top"/>
<Label x:Name="connectionStateLabel" Content="{Binding LbConnectionStateNotConnected}" d:Content="Not connected" HorizontalAlignment="Left" Margin="238,31,0,0" VerticalAlignment="Top" FontSize="10"/>
<CheckBox x:Name="exitWithSinmai" Content="{Binding LbExitWithSinmai}" d:Content="Exit with Sinmai" HorizontalAlignment="Left" Margin="10,277,0,0" VerticalAlignment="Top" Height="17" Width="224" IsChecked="{Binding IsExitWithSinmaiEnabled}" Click="exitWithSinmai_Click" ToolTip="Try and detect when Sinmai.exe exits and exit this app alongside it"/>
<Button x:Name="buttonInstallComPort" Content="{Binding LbInstallComPort}" d:Content="Install COM port" HorizontalAlignment="Left" Margin="10,9,0,0" VerticalAlignment="Top" Click="buttonInstallComPort_Click" Width="126"/>
<Button x:Name="buttonUninstallComPorts" Content="{Binding LbUninstallComPort}" d:Content="Uninstall COM port" HorizontalAlignment="Left" Margin="10,34,0,0" VerticalAlignment="Top" Click="buttonUninstallComPorts_Click" Width="126"/>
<Button x:Name="buttonListComPorts" Content="{Binding LbListComPorts}" d:Content="List installed COM ports" HorizontalAlignment="Left" Margin="10,59,0,0" VerticalAlignment="Top" Click="buttonListComPorts_Click"/>
<Separator HorizontalAlignment="Left" Margin="10,84,0,0" VerticalAlignment="Top" Height="6" Width="126"/>
<ComboBox x:Name="languageSelector" HorizontalAlignment="Left" Margin="10,186,0,0" VerticalAlignment="Top" Width="149" ItemsSource="{Binding SupportedLanguages}"
DisplayMemberPath="NativeName"
SelectedItem="{Binding SelectedLanguage, Mode=TwoWay}"/>
<Label x:Name="lagnuageLabel" Content="{Binding LbLanguageDropdown}" d:Content="Language" HorizontalAlignment="Left" Margin="10,155,0,0" VerticalAlignment="Top" Width="126"/>

</Grid>

Expand Down
23 changes: 13 additions & 10 deletions MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,21 @@ namespace WpfMaiTouchEmulator;
public partial class MainWindow : Window
{
private readonly MaiTouchSensorButtonStateManager buttonState;
private MaiTouchComConnector connector;
private readonly MaiTouchComConnector connector;
private readonly VirtualComPortManager comPortManager;
private TouchPanel _touchPanel;

public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel()
{
IsDebugEnabled = Properties.Settings.Default.IsDebugEnabled,
IsAutomaticPortConnectingEnabled = Properties.Settings.Default.IsAutomaticPortConnectingEnabled,
IsAutomaticPositioningEnabled = Properties.Settings.Default.IsAutomaticPositioningEnabled,
IsExitWithSinmaiEnabled = Properties.Settings.Default.IsExitWithSinmaiEnabled,
};

Title = "Mai Touch Emulator";
buttonState = new MaiTouchSensorButtonStateManager(buttonStateValue);
connector = new MaiTouchComConnector(buttonState);
Expand Down Expand Up @@ -53,22 +61,17 @@ public MainWindow()
Properties.Settings.Default.Save();
}


Loaded += (s, e) => {
Logger.Info("Main window loaded, creating touch panel");
_touchPanel = new TouchPanel();
_touchPanel.onTouch = (value) => { buttonState.PressButton(value); };
_touchPanel.onRelease = (value) => { buttonState.ReleaseButton(value); };
_touchPanel.Show();
_touchPanel.Owner = this;
DataContext = new MainWindowViewModel()
{
IsDebugEnabled = Properties.Settings.Default.IsDebugEnabled,
IsAutomaticPortConnectingEnabled = Properties.Settings.Default.IsAutomaticPortConnectingEnabled,
IsAutomaticPositioningEnabled = Properties.Settings.Default.IsAutomaticPositioningEnabled,
IsExitWithSinmaiEnabled = Properties.Settings.Default.IsExitWithSinmaiEnabled
};

var dataContext = (MainWindowViewModel)DataContext;

_touchPanel.SetDebugMode(dataContext.IsDebugEnabled);
if (Properties.Settings.Default.IsAutomaticPositioningEnabled)
{
Expand All @@ -81,7 +84,7 @@ public MainWindow()
};
}

private async void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
private async void MainWindow_Closing(object? sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
await connector.Disconnect();
Expand All @@ -90,7 +93,7 @@ private async void MainWindow_Closing(object sender, System.ComponentModel.Cance
childWindow.Close();
}
Closing -= MainWindow_Closing;
Close();
e.Cancel = false;
}

private async void ExitWithSinmaiLoop()
Expand Down
140 changes: 139 additions & 1 deletion MainWindowViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,107 @@
using System.ComponentModel;
using System.Globalization;
using System.Resources;
using System.Runtime.CompilerServices;

namespace WpfMaiTouchEmulator;

internal class MainWindowViewModel : INotifyPropertyChanged
public class MainWindowViewModel : INotifyPropertyChanged
{
// Language
public string LbAutoPortConnecting
{
get; set;
}
public string LbAutoSensorPositioning
{
get; set;
}
public string LbButtonState
{
get; set;
}
public string LbConnectionState
{
get; set;
}
public string LbConnectionStateNotConnected
{
get; set;
}
public string LbConnectToPort
{
get; set;
}
public string LbDebugMode
{
get; set;
}
public string LbExitWithSinmai
{
get; set;
}
public string LbInstallComPort
{
get; set;
}
public string LbLanguageDropdown
{
get; set;
}
public string LbListComPorts
{
get; set;
}
public string LbReceivedData
{
get; set;
}
public string LbRecievedData
{
get;
private set;
}
public string LbSentData
{
get; set;
}
public string LbUninstallComPort
{
get; set;
}


private bool _isAutomaticPortConnectingEnabled;
private bool _isDebugEnabled;
private bool _isAutomaticPositioningEnabled;
private bool _isExitWithSinmaiEnabled;
private CultureInfo _selectedLanguage;
private readonly ResourceManager resourceManager;
private readonly CultureInfo cultureInfo;

public List<CultureInfo> SupportedLanguages
{
get;
} =
[
new CultureInfo("en-US"), // English
new CultureInfo("zh-CN") // Chinese (Simplified)
];


public MainWindowViewModel()

Check warning on line 92 in MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Non-nullable property 'LbAutoPortConnecting' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 92 in MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Non-nullable property 'LbAutoSensorPositioning' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 92 in MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Non-nullable property 'LbButtonState' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 92 in MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Non-nullable property 'LbConnectionState' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 92 in MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Non-nullable property 'LbConnectionStateNotConnected' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 92 in MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Non-nullable property 'LbConnectToPort' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 92 in MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Non-nullable property 'LbDebugMode' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 92 in MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Non-nullable property 'LbExitWithSinmai' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
{
resourceManager = new ResourceManager("WpfMaiTouchEmulator.Properties.Resources", typeof(MainWindowViewModel).Assembly);
LoadLanguageSettings();
}

private void LoadLanguageSettings()
{
var savedLang = Properties.Settings.Default.UserLanguage;
var culture = string.IsNullOrEmpty(savedLang) ? CultureInfo.CurrentCulture : new CultureInfo(savedLang);

SelectedLanguage = SupportedLanguages.Contains(culture) ? culture : SupportedLanguages[0];
}

public bool IsDebugEnabled
{
Expand Down Expand Up @@ -50,6 +143,51 @@ public bool IsExitWithSinmaiEnabled
}
}

public CultureInfo SelectedLanguage
{
get => _selectedLanguage;
set
{
if (_selectedLanguage != value)
{
_selectedLanguage = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedLanguage)));
ChangeLanguage(value);
}
}
}

private void ChangeLanguage(CultureInfo culture)
{
Properties.Settings.Default.UserLanguage = culture.Name;
Properties.Settings.Default.Save();

Thread.CurrentThread.CurrentUICulture = culture;
ResourceManager rm = new ResourceManager(typeof(Resources.Strings));
UpdateLocalizedResources(rm);
}

private void UpdateLocalizedResources(ResourceManager resourceManager)
{
LbAutoPortConnecting = resourceManager.GetString("lbAutoPortConnecting");
LbAutoSensorPositioning = resourceManager.GetString("lbAutoSensorPositioning");
LbButtonState = resourceManager.GetString("lbButtonState");
LbConnectionState = resourceManager.GetString("lbConnectionState");
LbConnectionStateNotConnected = resourceManager.GetString("lbConnectionStateNotConnected");
LbConnectToPort = resourceManager.GetString("lbConnectToPort");
LbDebugMode = resourceManager.GetString("lbDebugMode");
LbExitWithSinmai = resourceManager.GetString("lbExitWithSinmai");
LbInstallComPort = resourceManager.GetString("lbInstallComPort");
LbLanguageDropdown = resourceManager.GetString("lbLanguageDropdown");
LbListComPorts = resourceManager.GetString("lbListComPorts");
LbReceivedData = resourceManager.GetString("lbReceivedData");
LbRecievedData = resourceManager.GetString("lbRecievedData");
LbSentData = resourceManager.GetString("lbSentData");
LbUninstallComPort = resourceManager.GetString("lbUninstallComPort");

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null));
}

public event PropertyChangedEventHandler? PropertyChanged;

protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
Expand Down
12 changes: 12 additions & 0 deletions Properties/Settings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Properties/Settings.settings
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@
<Setting Name="FirstOpen" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="UserLanguage" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings>
</SettingsFile>
Loading

0 comments on commit 851d83c

Please sign in to comment.