using System; using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; namespace Flow.Launcher.Plugin.WebSearch { /// /// Interaction logic for WebSearchesSetting.xaml /// public partial class SettingsControl : UserControl { private readonly Settings _settings; private readonly PluginInitContext _context; private Point _dragStartPoint; public SettingsControl(PluginInitContext context, SettingsViewModel viewModel) { InitializeComponent(); _context = context; _settings = viewModel.Settings; DataContext = viewModel; } private void OnAddSearchSearchClick(object sender, RoutedEventArgs e) { var setting = new SearchSourceSettingWindow(_settings.SearchSources, _context); setting.ShowDialog(); } private void OnDeleteSearchSearchClick(object sender, RoutedEventArgs e) { if (_settings.SelectedSearchSource != null) { var selected = _settings.SelectedSearchSource; var warning = _context.API.GetTranslation("flowlauncher_plugin_websearch_delete_warning"); var formated = string.Format(warning, selected.Title); var result = _context.API.ShowMsgBox(formated, string.Empty, MessageBoxButton.YesNo); if (result == MessageBoxResult.Yes) { var id = _context.CurrentPluginMetadata.ID; _context.API.RemoveActionKeyword(id, selected.ActionKeyword); _settings.SearchSources.Remove(selected); } } } private void OnEditSearchSourceClick(object sender, RoutedEventArgs e) { if (_settings.SelectedSearchSource != null) { var webSearch = new SearchSourceSettingWindow ( _settings.SearchSources, _context, _settings.SelectedSearchSource ); webSearch.ShowDialog(); } } GridViewColumnHeader _lastHeaderClicked = null; ListSortDirection _lastDirection = ListSortDirection.Ascending; private void SortByColumn(object sender, RoutedEventArgs e) { ListSortDirection direction; if (e.OriginalSource is not GridViewColumnHeader headerClicked) { return; } if (headerClicked.Role == GridViewColumnHeaderRole.Padding) { return; } if (headerClicked != _lastHeaderClicked) { direction = ListSortDirection.Ascending; } else { if (_lastDirection == ListSortDirection.Ascending) { direction = ListSortDirection.Descending; } else { direction = ListSortDirection.Ascending; } } var columnBinding = headerClicked.Column.DisplayMemberBinding as Binding; var sortBy = columnBinding?.Path.Path ?? headerClicked.Column.Header as string; if (sortBy != null) { Sort(sortBy, direction); if (direction == ListSortDirection.Ascending) { headerClicked.Column.HeaderTemplate = Resources["HeaderTemplateArrowUp"] as DataTemplate; } else { headerClicked.Column.HeaderTemplate = Resources["HeaderTemplateArrowDown"] as DataTemplate; } // Remove arrow from previously sorted header if (_lastHeaderClicked != null && _lastHeaderClicked != headerClicked) { _lastHeaderClicked.Column.HeaderTemplate = null; } _lastHeaderClicked = headerClicked; _lastDirection = direction; } } private void Sort(string sortBy, ListSortDirection direction) { ICollectionView dataView = CollectionViewSource.GetDefaultView(SearchSourcesListView.ItemsSource); dataView.SortDescriptions.Clear(); SortDescription sd = new(sortBy, direction); dataView.SortDescriptions.Add(sd); dataView.Refresh(); } private void MouseDoubleClickItem(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (((FrameworkElement)e.OriginalSource).DataContext is SearchSource && _settings.SelectedSearchSource != null) { var webSearch = new SearchSourceSettingWindow ( _settings.SearchSources, _context, _settings.SelectedSearchSource ); webSearch.ShowDialog(); } } private void ListView_SizeChanged(object sender, SizeChangedEventArgs e) { var listView = sender as ListView; var gView = listView.View as GridView; var workingWidth = listView.ActualWidth - SystemParameters.VerticalScrollBarWidth; // take into account vertical scrollbar if (workingWidth <= 0) return; var col1 = 0.08; var col2 = 0.24; var col3 = 0.26; var col4 = 0.20; var col5 = 0.22; gView.Columns[0].Width = workingWidth * col1; gView.Columns[1].Width = workingWidth * col2; gView.Columns[2].Width = workingWidth * col3; gView.Columns[3].Width = workingWidth * col4; gView.Columns[4].Width = workingWidth * col5; } private void ListView_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { _dragStartPoint = e.GetPosition(null); } private void ListView_PreviewMouseMove(object sender, MouseEventArgs e) { Point mousePos = e.GetPosition(null); Vector diff = _dragStartPoint - mousePos; if (e.LeftButton == MouseButtonState.Pressed && (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance || Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance)) { var listView = (ListView)sender; ListViewItem listViewItem = FindAncestor((DependencyObject)e.OriginalSource); if (listViewItem == null) return; SearchSource item = (SearchSource)listView.ItemContainerGenerator.ItemFromContainer(listViewItem); if (item == null) return; DragDrop.DoDragDrop(listViewItem, item, DragDropEffects.Move); } } private void ListView_Drop(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(typeof(SearchSource))) { SearchSource droppedData = e.Data.GetData(typeof(SearchSource)) as SearchSource; var listView = (ListView)sender; var target = GetNearestContainer(e.OriginalSource); if (target == null) return; SearchSource targetData = (SearchSource)listView.ItemContainerGenerator.ItemFromContainer(target); if (targetData == null) return; var items = _settings.SearchSources; int removedIdx = items.IndexOf(droppedData); int targetIdx = items.IndexOf(targetData); if (removedIdx == targetIdx) return; items.Move(removedIdx, targetIdx); } } private ListViewItem GetNearestContainer(object source) { var element = source as UIElement; while (element != null && !(element is ListViewItem)) element = VisualTreeHelper.GetParent(element) as UIElement; return element as ListViewItem; } private static T FindAncestor(DependencyObject current) where T : DependencyObject { while (current != null) { if (current is T) return (T)current; current = VisualTreeHelper.GetParent(current); } return null; } // This is used for NumberBox to force its value to be 1 when the user clears the value private void NumberBox_ValueChanged(iNKORE.UI.WPF.Modern.Controls.NumberBox sender, iNKORE.UI.WPF.Modern.Controls.NumberBoxValueChangedEventArgs args) { if (double.IsNaN(args.NewValue)) { sender.Value = 1; _settings.MaxSuggestions = (int)sender.Value; } } } }