using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; using Explorer.Presentation.ViewModels; namespace Explorer.App; public partial class ExplorerAddressBar : UserControl { private bool _suppressLostFocus; public ExplorerAddressBar() { InitializeComponent(); DataContextChanged += OnDataContextChanged; IsVisibleChanged += (_, _) => { if (IsVisible && DataContext is ExplorerPaneViewModel { IsEditingPath: true }) { FocusEditor(); } }; } public void FocusEditor() { Dispatcher.BeginInvoke(() => { PathCombo.ApplyTemplate(); if (PathCombo.Template.FindName("PART_EditableTextBox", PathCombo) is TextBox box) { box.Focus(); box.SelectAll(); } else { PathCombo.Focus(); } }, DispatcherPriority.Loaded); } private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e) { if (e.OldValue is ExplorerPaneViewModel previous) { previous.PropertyChanged -= OnPanePropertyChanged; } if (e.NewValue is ExplorerPaneViewModel pane) { pane.PropertyChanged += OnPanePropertyChanged; if (pane.IsEditingPath) { FocusEditor(); } } } private void OnPanePropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == nameof(ExplorerPaneViewModel.IsEditingPath) && sender is ExplorerPaneViewModel { IsEditingPath: true }) { FocusEditor(); } } private void OnBreadcrumbMouseDown(object sender, MouseButtonEventArgs e) { if (e.OriginalSource is DependencyObject origin && IsInsideButton(origin)) { return; } if (DataContext is not ExplorerPaneViewModel pane) { return; } pane.BeginEditPath(); e.Handled = true; } private void OnPathKeyDown(object sender, KeyEventArgs e) { if (DataContext is not ExplorerPaneViewModel pane) { return; } if (e.Key == Key.Enter) { CommitPath(); e.Handled = true; return; } if (e.Key == Key.Escape) { _suppressLostFocus = true; pane.CancelEditPath(); e.Handled = true; } } private void OnPathHistorySelected(object sender, SelectionChangedEventArgs e) { if (sender is not ComboBox combo || e.AddedItems.Count == 0 || e.AddedItems[0] is not string path) { return; } if (DataContext is not ExplorerPaneViewModel pane) { return; } if (NavigationTreeViewModel.PathsEqual(path, pane.CurrentPath)) { return; } if (combo.IsDropDownOpen || combo.IsKeyboardFocusWithin) { pane.PathEditText = path; CommitPath(); } } private void OnPathLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { Dispatcher.BeginInvoke(() => { if (_suppressLostFocus) { _suppressLostFocus = false; return; } if (PathCombo.IsDropDownOpen || PathCombo.IsKeyboardFocusWithin) { return; } if (DataContext is ExplorerPaneViewModel pane) { pane.CancelEditPath(); } }, DispatcherPriority.Input); } private void CommitPath() { if (Window.GetWindow(this)?.DataContext is MainViewModel vm) { vm.GoCommand.Execute(null); } } private static bool IsInsideButton(DependencyObject origin) { for (var current = origin; current is not null;) { if (current is Button) { return true; } current = current is Visual ? VisualTreeHelper.GetParent(current) : LogicalTreeHelper.GetParent(current); } return false; } }