diff --git a/Plugins/Flow.Launcher.Plugin.Program/AddProgramSource.xaml b/Plugins/Flow.Launcher.Plugin.Program/AddProgramSource.xaml
index 9ee97e3e953..9848f51cfe0 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/AddProgramSource.xaml
+++ b/Plugins/Flow.Launcher.Plugin.Program/AddProgramSource.xaml
@@ -4,7 +4,10 @@
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:vm="clr-namespace:Flow.Launcher.Plugin.Program.ViewModels"
+ mc:Ignorable="d"
Title="{DynamicResource flowlauncher_plugin_program_directory}"
+ d:DataContext="{d:DesignInstance vm:AddProgramSourceViewModel}"
Width="Auto"
Height="276"
Background="{DynamicResource PopuBGColor}"
@@ -15,6 +18,9 @@
+
+
+
@@ -98,11 +104,14 @@
HorizontalAlignment="Stretch"
Click="BrowseButton_Click"
Content="{DynamicResource flowlauncher_plugin_program_browse}"
+ Visibility="{Binding IsCustomSource, Converter={StaticResource BooleanToVisibilityConverter}}"
DockPanel.Dock="Right" />
@@ -119,6 +128,7 @@
Grid.Row="1"
Grid.Column="1"
Margin="10,0"
+ IsChecked="{Binding Enabled, Mode=TwoWay}"
VerticalAlignment="Center" />
@@ -142,7 +152,7 @@
MinWidth="140"
Margin="5,0,10,0"
Click="BtnAdd_OnClick"
- Content="{DynamicResource flowlauncher_plugin_program_update}"
+ Content="{Binding AddBtnText}"
Style="{DynamicResource AccentButtonStyle}" />
diff --git a/Plugins/Flow.Launcher.Plugin.Program/AddProgramSource.xaml.cs b/Plugins/Flow.Launcher.Plugin.Program/AddProgramSource.xaml.cs
index e88c9b988d1..be8b768bd8f 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/AddProgramSource.xaml.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/AddProgramSource.xaml.cs
@@ -1,8 +1,5 @@
using System.Windows;
-using System.Windows.Forms;
-using Flow.Launcher.Plugin.Program.Views.Models;
-using Flow.Launcher.Plugin.Program.Views;
-using System.Linq;
+using Flow.Launcher.Plugin.Program.ViewModels;
namespace Flow.Launcher.Plugin.Program
{
@@ -11,41 +8,18 @@ namespace Flow.Launcher.Plugin.Program
///
public partial class AddProgramSource : Window
{
- private PluginInitContext _context;
- private ProgramSource _editing;
- private Settings _settings;
- private bool update;
+ private readonly AddProgramSourceViewModel ViewModel;
- public AddProgramSource(PluginInitContext context, Settings settings)
+ public AddProgramSource(AddProgramSourceViewModel viewModel)
{
+ ViewModel = viewModel;
+ DataContext = viewModel;
InitializeComponent();
- _context = context;
- _settings = settings;
- Directory.Focus();
- Chkbox.IsChecked = true;
- update = false;
- btnAdd.Content = _context.API.GetTranslation("flowlauncher_plugin_program_add");
- }
-
- public AddProgramSource(PluginInitContext context, Settings settings, ProgramSource source)
- {
- InitializeComponent();
- _context = context;
- _editing = source;
- _settings = settings;
- update = true;
- Chkbox.IsChecked = _editing.Enabled;
- Directory.Text = _editing.Location;
}
private void BrowseButton_Click(object sender, RoutedEventArgs e)
{
- var dialog = new FolderBrowserDialog();
- DialogResult result = dialog.ShowDialog();
- if (result == System.Windows.Forms.DialogResult.OK)
- {
- Directory.Text = dialog.SelectedPath;
- }
+ ViewModel.Browse();
}
private void BtnCancel_OnClick(object sender, RoutedEventArgs e)
@@ -55,51 +29,12 @@ private void BtnCancel_OnClick(object sender, RoutedEventArgs e)
private void BtnAdd_OnClick(object sender, RoutedEventArgs e)
{
- string path = Directory.Text;
- bool modified = false;
- if (!System.IO.Directory.Exists(path))
+ var (modified, msg) = ViewModel.AddOrUpdate();
+ if (modified == false && msg != null)
{
- System.Windows.MessageBox.Show(_context.API.GetTranslation("flowlauncher_plugin_program_invalid_path"));
+ MessageBox.Show(msg); // Invalid
return;
}
- if (!update)
- {
- if (!ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier.Equals(path, System.StringComparison.OrdinalIgnoreCase)))
- {
- var source = new ProgramSource(path);
- modified = true;
- _settings.ProgramSources.Insert(0, source);
- ProgramSetting.ProgramSettingDisplayList.Add(source);
- }
- else
- {
- System.Windows.MessageBox.Show(_context.API.GetTranslation("flowlauncher_plugin_program_duplicate_program_source"));
- return;
- }
- }
- else
- {
- // Separate checks to avoid changing UniqueIdentifier of UWP
- if (!_editing.Location.Equals(path, System.StringComparison.OrdinalIgnoreCase))
- {
- if (ProgramSetting.ProgramSettingDisplayList
- .Any(x => x.UniqueIdentifier.Equals(path, System.StringComparison.OrdinalIgnoreCase)))
- {
- // Check if the new location is used
- // No need to check win32 or uwp, just override them
- System.Windows.MessageBox.Show(_context.API.GetTranslation("flowlauncher_plugin_program_duplicate_program_source"));
- return;
- }
- modified = true;
- _editing.Location = path; // Changes UniqueIdentifier internally
- }
- if (_editing.Enabled != Chkbox.IsChecked)
- {
- modified = true;
- _editing.Enabled = Chkbox.IsChecked ?? true;
- }
- }
-
DialogResult = modified;
Close();
}
diff --git a/Plugins/Flow.Launcher.Plugin.Program/LocationConverter.cs b/Plugins/Flow.Launcher.Plugin.Program/LocationConverter.cs
deleted file mode 100644
index 41384aa8379..00000000000
--- a/Plugins/Flow.Launcher.Plugin.Program/LocationConverter.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Globalization;
-using System.Windows.Data;
-using System.Windows.Markup;
-
-namespace Flow.Launcher.Plugin.Program
-{
- public class LocationConverter : MarkupExtension, IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- var text = value as string;
- if (string.IsNullOrEmpty(text))
- {
- return string.Empty;
- }
- else
- {
- return text;
- }
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- throw new NotSupportedException();
- }
-
- public override object ProvideValue(IServiceProvider serviceProvider)
- {
- return this;
- }
- }
-}
diff --git a/Plugins/Flow.Launcher.Plugin.Program/ViewModels/AddProgramSourceViewModel.cs b/Plugins/Flow.Launcher.Plugin.Program/ViewModels/AddProgramSourceViewModel.cs
new file mode 100644
index 00000000000..1bb1ca13c80
--- /dev/null
+++ b/Plugins/Flow.Launcher.Plugin.Program/ViewModels/AddProgramSourceViewModel.cs
@@ -0,0 +1,131 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Windows.Forms;
+using Flow.Launcher.Plugin.Program.Views;
+using Flow.Launcher.Plugin.Program.Views.Models;
+
+namespace Flow.Launcher.Plugin.Program.ViewModels
+{
+ public class AddProgramSourceViewModel : BaseModel
+ {
+ private readonly Settings Settings;
+
+ private bool enabled = true;
+ public bool Enabled
+ {
+ get => enabled;
+ set
+ {
+ enabled = value;
+ StatusModified = true;
+ }
+ }
+
+ private string location = string.Empty;
+ public string Location
+ {
+ get => location;
+ set
+ {
+ location = value;
+ LocationModified = true;
+ OnPropertyChanged();
+ }
+ }
+
+ public ProgramSource Source { get; init; }
+ public IPublicAPI API { get; init; }
+ public string AddBtnText { get; init; }
+ private bool LocationModified = false;
+ private bool StatusModified = false;
+ public bool IsCustomSource { get; init; } = true;
+ public bool IsNotCustomSource => !IsCustomSource;
+
+ public AddProgramSourceViewModel(PluginInitContext context, Settings settings)
+ {
+ API = context.API;
+ Settings = settings;
+ AddBtnText = API.GetTranslation("flowlauncher_plugin_program_add");
+ }
+
+ public AddProgramSourceViewModel(PluginInitContext context, Settings settings, ProgramSource programSource) : this(context, settings)
+ {
+ Source = programSource;
+ enabled = Source.Enabled;
+ location = Source.Location;
+ AddBtnText = API.GetTranslation("flowlauncher_plugin_program_update");
+ IsCustomSource = Settings.ProgramSources.Any(x => x.UniqueIdentifier == Source.UniqueIdentifier);
+ }
+
+ public void Browse()
+ {
+ var dialog = new FolderBrowserDialog();
+ DialogResult result = dialog.ShowDialog();
+ if (result == DialogResult.OK)
+ {
+ Location = dialog.SelectedPath;
+ }
+ }
+
+ public (bool modified, string message) AddProgramSource()
+ {
+ if (!Directory.Exists(Location))
+ {
+ return (false, API.GetTranslation("flowlauncher_plugin_program_invalid_path"));
+ }
+ else if (DuplicateSource(Location))
+ {
+ return (false, API.GetTranslation("flowlauncher_plugin_program_duplicate_program_source"));
+ }
+ else
+ {
+ var source = new ProgramSource(Location, Enabled);
+ Settings.ProgramSources.Insert(0, source);
+ ProgramSetting.ProgramSettingDisplayList.Add(source);
+ return (true, null);
+ }
+ }
+
+ public (bool modified, string message) UpdateProgramSource()
+ {
+ if (LocationModified)
+ {
+ if (!Directory.Exists(Location))
+ {
+ return (false, API.GetTranslation("flowlauncher_plugin_program_invalid_path"));
+ }
+ else if (DuplicateSource(Location))
+ {
+ return (false, API.GetTranslation("flowlauncher_plugin_program_duplicate_program_source"));
+ }
+ else
+ {
+ Source.Location = Location; // Changes UniqueIdentifier internally
+ }
+ }
+ if (StatusModified)
+ {
+ Source.Enabled = Enabled;
+ }
+ return (StatusModified || LocationModified, null);
+ }
+
+ public (bool modified, string message) AddOrUpdate()
+ {
+ if (Source == null)
+ {
+ return AddProgramSource();
+ }
+ else
+ {
+ return UpdateProgramSource();
+ }
+ }
+
+ public static bool DuplicateSource(string location)
+ {
+ return ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier.Equals(location, StringComparison.OrdinalIgnoreCase));
+ }
+ }
+}
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/Models/ProgramSource.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/Models/ProgramSource.cs
index 571dc00174e..93c33e9ad18 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Views/Models/ProgramSource.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Views/Models/ProgramSource.cs
@@ -83,7 +83,7 @@ public bool Equals(IProgram program)
public override int GetHashCode()
{
- return HashCode.Combine(UniqueIdentifier);
+ return uniqueIdentifier.GetHashCode();
}
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml
index ab32dade270..957042de5d3 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml
+++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml
@@ -4,7 +4,6 @@
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:program="clr-namespace:Flow.Launcher.Plugin.Program"
Height="520"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d">
@@ -180,7 +179,7 @@
-
+
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs
index b14979337a2..7da224b698f 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs
@@ -9,7 +9,7 @@
using Flow.Launcher.Plugin.Program.Programs;
using System.ComponentModel;
using System.Windows.Data;
-using System;
+using Flow.Launcher.Plugin.Program.ViewModels;
namespace Flow.Launcher.Plugin.Program.Views
{
@@ -136,7 +136,8 @@ private async void ReIndexing()
private void btnAddProgramSource_OnClick(object sender, RoutedEventArgs e)
{
- var add = new AddProgramSource(context, _settings);
+ var vm = new AddProgramSourceViewModel(context, _settings);
+ var add = new AddProgramSource(vm);
if (add.ShowDialog() ?? false)
{
ReIndexing();
@@ -171,7 +172,12 @@ private void EditProgramSource(ProgramSource selectedProgramSource)
}
else
{
- var add = new AddProgramSource(context, _settings, selectedProgramSource);
+ var vm = new AddProgramSourceViewModel(context, _settings, selectedProgramSource);
+ var add = new AddProgramSource(vm);
+ int selectedIndex = programSourceView.SelectedIndex;
+ // https://stackoverflow.com/questions/16789360/wpf-listbox-items-with-changing-hashcode
+ // Or it can't be unselected after changing Location
+ programSourceView.UnselectAll();
if (add.ShowDialog() ?? false)
{
if (selectedProgramSource.Enabled)
@@ -186,6 +192,7 @@ private void EditProgramSource(ProgramSource selectedProgramSource)
}
ReIndexing();
}
+ programSourceView.SelectedIndex = selectedIndex;
}
}