1using Dreamine.MVVM.ViewModels;
2using System.Collections.ObjectModel;
3using System.Diagnostics;
5using System.Windows.Controls;
6using System.Windows.Input;
7using System.Windows.Media;
8using System.Windows.Media.Imaging;
9using System.Windows.Threading;
11using Dreamine.UI.Wpf.Localization;
35 Add(
new ButtonData { Content =
"LoginAsync" });
40 Add(
new ButtonData { Content =
"About", Visibility = Visibility.Hidden });
41 Add(
new ButtonData { Content =
"About", Visibility = Visibility.Hidden });
42 Add(
new ButtonData { Content =
"About", Visibility = Visibility.Hidden });
43 Add(
new ButtonData { Content =
"About", Visibility = Visibility.Hidden });
46 this[Count - 1].Margin =
new Thickness(0);
101 DependencyProperty.Register(
135 nav.ResetLogoutTimerIfNeeded();
147 private static readonly HashSet<DreamineNavigationBar>
_instances =
new();
210 if (e.StagingItem.Input is MouseEventArgs or KeyboardEventArgs or TouchEventArgs)
214 if (nav.AutoLogoutTimeout > 0)
215 nav.InitializeOrResetLogoutTimer();
270 _logoutTimer.Tick += (s, e) =>
314 foreach (Window window
in Application.Current.Windows)
316 if (window.Owner !=
null && window.IsVisible)
326 "You have been automatically logged out due to inactivity.",
329 MessageBoxImage.Information,
330 autoClick: MessageBoxResult.OK,
331 autoClickDelaySeconds: 5);
357 DependencyProperty.Register(
411 InitializeComponent();
414 ButtonDatas =
new ObservableCollection<ButtonData>();
418 Unloaded += (_, _) =>
_instances.Remove(
this);
423 var parentWindow = Window.GetWindow(
this);
424 if (parentWindow !=
null)
425 parentWindow.Closed += (_, _) =>
_instances.Remove(
this);
477 DependencyProperty.Register(
479 typeof(ObservableCollection<ButtonData>),
511 if (e.OldValue is ObservableCollection<ButtonData> oldList)
512 oldList.CollectionChanged -= nav.ButtonDatas_CollectionChanged;
514 if (e.NewValue is ObservableCollection<ButtonData> newList)
515 newList.CollectionChanged += nav.ButtonDatas_CollectionChanged;
517 nav.UpdateMarginAndAlignment();
573 DependencyProperty.Register(
606 nav.UpdateMarginAndAlignment();
619 Thickness defaultMargin =
Position switch
623 _ =>
new Thickness(0, 0, 4, 0)
625 Thickness lastMargin =
Position switch
629 _ =>
new Thickness(0)
665 .Select((btn, idx) =>
new { btn, idx })
666 .Where(x => x.btn.Visibility == Visibility.Visible)
670 if (visibleIndices.Count == 0)
675 btn.Margin = defaultMargin;
677 ButtonDatas[visibleIndices.Last()].Margin = lastMargin;
706 var navBars = Application.Current.Windows
708 .SelectMany(w => FindVisualChildren<DreamineNavigationBar>(w))
713 foreach (var nav
in navBars)
715 if (!nav.ButtonDatas.Contains(clickedButton))
718 foreach (var btn
in nav.ButtonDatas)
720 if (btn.IsSelected ==
true && btn.IsFocusableEx ==
true)
724 btn.IsSelected =
false;
726 if (clickedButton.IsFocusableEx)
728 clickedButton.IsSelected =
true;
732 foreach (var btn
in nav.ButtonDatas)
734 if (btn == buttonData)
736 btn.IsSelected =
true;
780 for (
int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
782 DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
788 yield
return childOfChild;
941 if (
string.IsNullOrWhiteSpace(
ImagePath))
return null!;
942 try {
return new BitmapImage(
new Uri(
ImagePath, UriKind.RelativeOrAbsolute)); }
943 catch (Exception ex) { Debug.WriteLine($
"[ButtonData] ImageSource 로드 실패({ImagePath}): {ex.Message}");
return null!; }
1097 public Thickness
Margin {
get;
set; } =
new Thickness(0, 0, 4, 0);
1325 ICommand? command =
null,
1327 string? imagePath =
null,
1328 bool isSelected =
false,
1329 bool isFocusable =
true,
1330 Visibility visibility = Visibility.Visible,
1337 MinimumGrade = minGrade,
1338 ImagePath = imagePath!,
1339 ImagePosition = imagePosition,
1340 FontWeight = FontWeights.Bold,
1343 ShineColorBottom = Brushes.White,
1344 BackgroundTop = Brushes.White,
1345 Background = Brushes.LightGray,
1346 IsSelected = isSelected,
1347 IsFocusableEx = isFocusable,
1348 Visibility = visibility
1394 return new SolidColorBrush((Color)ColorConverter.ConvertFromString(hex));
static void ShowAsync(string message, string title="Information", MessageBoxButton buttons=MessageBoxButton.OK, MessageBoxImage icon=MessageBoxImage.None, Action< MessageBoxResult >? callback=null, MessageBoxResult autoClick=MessageBoxResult.None, int autoClickDelaySeconds=0, int enableDelaySeconds=0)
void DreamineButton_Click(object sender, RoutedEventArgs e)
void ResetLogoutTimerIfNeeded()
ObservableCollection< ButtonData > ButtonDatas
void InitializeOrResetLogoutTimer()
static readonly DependencyProperty ButtonDatasProperty
static void NotifyButtonClicked(ButtonData clickedButton)
static void OnPositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
void ButtonDatas_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
static ? EventHandler AutoLogoutOccurred
static readonly HashSet< DreamineNavigationBar > _instances
static volatile bool _isInputHooked
void UpdateMarginAndAlignment()
static void OnButtonDatasChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
static readonly new DependencyProperty LanguageProperty
static readonly DependencyProperty PositionProperty
NavigationBarPosition Position
static void OnOnceLoginChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
DispatcherTimer? _logoutTimer
static void EnsureGlobalInputHook()
static IEnumerable< T > FindVisualChildren< T >(DependencyObject depObj)
static readonly DependencyProperty AutoLogoutTimeoutProperty
static void OnGlobalInputStatic(object sender, PreProcessInputEventArgs e)
void ApplyLastButtonMargin(Thickness defaultMargin, Thickness lastMargin)
static void OnAutoLogoutTimeoutChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
static readonly DependencyProperty OnceLoginProperty
IconPosition ImagePosition
IInputElement CommandTarget
static SolidColorBrush GetColor(string hex)
static ? object CurrentUser
static ButtonData Create(string content, ICommand? command=null, int minGrade=0, string? imagePath=null, bool isSelected=false, bool isFocusable=true, Visibility visibility=Visibility.Visible, IconPosition imagePosition=IconPosition.Top)
static bool IsOnceLoginEnabled