//
// Copyright (c) PlaceholderCompany. All rights reserved.
//
namespace SystemTrayMenu.UserInterface
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using SystemTrayMenu.Business;
using SystemTrayMenu.DataClasses;
using SystemTrayMenu.DllImports;
using SystemTrayMenu.Properties;
using SystemTrayMenu.Utilities;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
///
/// Logic of Menu window.
///
public partial class Menu : Window
{
private const int CornerRadius = 10;
private static readonly RoutedEvent FadeToTransparentEvent = EventManager.RegisterRoutedEvent(
nameof(FadeToTransparent), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Menu));
private static readonly RoutedEvent FadeInEvent = EventManager.RegisterRoutedEvent(
nameof(FadeIn), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Menu));
private static readonly RoutedEvent FadeOutEvent = EventManager.RegisterRoutedEvent(
nameof(FadeOut), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Menu));
private readonly DispatcherTimer timerUpdateIcons = new (DispatcherPriority.Background, Dispatcher.CurrentDispatcher);
private readonly string folderPath;
#if TODO // SEARCH
public const string RowFilterShowAll = "[SortIndex] LIKE '%0%'";
#endif
private bool isFading;
private bool directionToRight;
private bool mouseDown;
private Point lastLocation;
#if TODO // SEARCH
private bool isSetSearchText;
#endif
internal Menu(MenuData menuData, string path)
{
timerUpdateIcons.Tick += TimerUpdateIcons_Tick;
Closed += (_, _) =>
{
timerUpdateIcons.Stop();
IsClosed = true; // TODO WPF Replace Forms wrapper
};
InitializeComponent();
if (!Config.ShowDirectoryTitleAtTop)
{
txtTitle.Visibility = Visibility.Hidden;
}
if (!Config.ShowSearchBar)
{
searchPanel.Visibility = Visibility.Collapsed;
}
if (!Config.ShowFunctionKeyOpenFolder)
{
buttonOpenFolder.Visibility = Visibility.Collapsed;
}
if (!Config.ShowFunctionKeyPinMenu)
{
buttonMenuAlwaysOpen.Visibility = Visibility.Collapsed;
}
if (!Config.ShowFunctionKeySettings)
{
buttonSettings.Visibility = Visibility.Collapsed;
}
if (!Config.ShowFunctionKeyRestart)
{
buttonRestart.Visibility = Visibility.Collapsed;
}
folderPath = path;
RowDataParent = menuData.RowDataParent;
if (RowDataParent == null)
{
// This will be a main menu
Level = 0;
// Use Main Menu DPI for all further calculations
Scaling.CalculateFactorByDpi(this);
}
else
{
// This will be a sub menu
Level = RowDataParent.Level + 1;
RowDataParent.SubMenu = this;
buttonOpenFolder.Visibility = Visibility.Collapsed;
buttonSettings.Visibility = Visibility.Collapsed;
buttonRestart.Visibility = Visibility.Collapsed;
labelStatus.Content = Translator.GetText("loading");
// Todo: use embedded resources that we can assign image in XAML already
pictureBoxLoading.Source = SystemTrayMenu.Resources.StaticResources.LoadingIcon.ToImageSource();
pictureBoxLoading.Visibility = Visibility.Visible;
}
string title = new DirectoryInfo(path).Name;
if (title.Length > MenuDefines.LengthMax)
{
title = $"{title[..MenuDefines.LengthMax]}...";
}
txtTitle.Text = Title = title;
foreach (FrameworkElement control in
new List()
{
buttonMenuAlwaysOpen,
buttonOpenFolder,
buttonSettings,
buttonRestart,
pictureBoxSearch,
pictureBoxMenuAlwaysOpen,
pictureBoxOpenFolder,
pictureBoxSettings,
pictureBoxRestart,
pictureBoxLoading,
})
{
control.Width = Scaling.Scale(control.Width);
control.Height = Scaling.Scale(control.Height);
}
labelTitle.FontSize = Scaling.ScaleFontByPoints(8.25F);
textBoxSearch.FontSize = Scaling.ScaleFontByPoints(8.25F);
labelStatus.FontSize = Scaling.ScaleFontByPoints(7F);
dgv.FontSize = Scaling.ScaleFontByPoints(9F);
MouseDown += Menu_MouseDown;
MouseUp += Menu_MouseUp;
MouseMove += Menu_MouseMove;
textBoxSearch.TextChanged += (_, _) => TextBoxSearch_TextChanged(false);
textBoxSearch.ContextMenu = new()
{
Background = SystemColors.ControlBrush,
};
textBoxSearch.ContextMenu.Items.Add(new MenuItem()
{
Header = Translator.GetText("Cut"),
Command = new ActionCommand((_) => textBoxSearch.Cut()),
});
textBoxSearch.ContextMenu.Items.Add(new MenuItem()
{
Header = Translator.GetText("Copy"),
Command = new ActionCommand((_) => Clipboard.SetData(DataFormats.Text, textBoxSearch.SelectedText)),
});
textBoxSearch.ContextMenu.Items.Add(new MenuItem()
{
Header = Translator.GetText("Paste"),
Command = new ActionCommand((_) =>
{
if (Clipboard.ContainsText(TextDataFormat.Text))
{
textBoxSearch.SelectedText = Clipboard.GetData(DataFormats.Text).ToString();
}
}),
});
textBoxSearch.ContextMenu.Items.Add(new MenuItem()
{
Header = Translator.GetText("Undo"),
Command = new ActionCommand((_) => textBoxSearch.Undo()),
});
textBoxSearch.ContextMenu.Items.Add(new MenuItem()
{
Header = Translator.GetText("Select All"),
Command = new ActionCommand((_) => textBoxSearch.SelectAll()),
});
SolidColorBrush foreColor = new(Colors.Black);
SolidColorBrush backColor = AppColors.Background.ToSolidColorBrush();
SolidColorBrush backColorSearch = AppColors.SearchField.ToSolidColorBrush();
SolidColorBrush backgroundBorder = AppColors.BackgroundBorder.ToSolidColorBrush();
if (Config.IsDarkMode())
{
foreColor = new (Colors.White);
backColor = AppColors.DarkModeBackground.ToSolidColorBrush();
backColorSearch = AppColors.DarkModeSearchField.ToSolidColorBrush();
backgroundBorder = AppColors.DarkModeBackgroundBorder.ToSolidColorBrush();
Resources["ic_fluent_svgColor"] = WPFExtensions.SolidColorBrushFromString(Settings.Default.ColorDarkModeIcons);
}
else
{
Resources["ic_fluent_svgColor"] = WPFExtensions.SolidColorBrushFromString(Settings.Default.ColorIcons);
}
labelTitle.Foreground = foreColor;
textBoxSearch.Foreground = foreColor;
dgv.Foreground = foreColor;
labelStatus.Foreground = MenuDefines.ColorIcons.ToSolidColorBrush();
windowFrame.BorderBrush = backgroundBorder;
windowFrame.Background = backColor;
searchPanel.Background = backColorSearch;
panelLine.Background = AppColors.Icons.ToSolidColorBrush();
dgv.GotFocus += (_, _) => FocusTextBox();
#if TODO // Misc MouseEvents
dgv.MouseEnter += ControlsMouseEnter;
labelTitle.MouseEnter += ControlsMouseEnter;
textBoxSearch.MouseEnter += ControlsMouseEnter;
pictureBoxOpenFolder.MouseEnter += ControlsMouseEnter;
pictureBoxMenuAlwaysOpen.MouseEnter += ControlsMouseEnter;
pictureBoxSettings.MouseEnter += ControlsMouseEnter;
pictureBoxRestart.MouseEnter += ControlsMouseEnter;
pictureBoxSearch.MouseEnter += ControlsMouseEnter;
tableLayoutPanelMenu.MouseEnter += ControlsMouseEnter;
dgv.MouseEnter += ControlsMouseEnter;
tableLayoutPanelBottom.MouseEnter += ControlsMouseEnter;
labelStatus.MouseEnter += ControlsMouseEnter;
void ControlsMouseEnter(object sender, EventArgs e)
{
MouseEnter?.Invoke();
}
dgv.MouseLeave += ControlsMouseLeave;
labelTitle.MouseLeave += ControlsMouseLeave;
textBoxSearch.MouseLeave += ControlsMouseLeave;
pictureBoxMenuAlwaysOpen.MouseLeave += ControlsMouseLeave;
pictureBoxOpenFolder.MouseLeave += ControlsMouseLeave;
pictureBoxSettings.MouseLeave += ControlsMouseLeave;
pictureBoxRestart.MouseLeave += ControlsMouseLeave;
pictureBoxSearch.MouseLeave += ControlsMouseLeave;
tableLayoutPanelMenu.MouseLeave += ControlsMouseLeave;
dgv.MouseLeave += ControlsMouseLeave;
tableLayoutPanelBottom.MouseLeave += ControlsMouseLeave;
labelStatus.MouseLeave += ControlsMouseLeave;
void ControlsMouseLeave(object sender, EventArgs e)
{
MouseLeave?.Invoke();
}
#endif
#if TODO // Misc MouseEvents
bool isTouchEnabled = NativeMethods.IsTouchEnabled();
if ((isTouchEnabled && Settings.Default.DragDropItemsEnabledTouch) ||
(!isTouchEnabled && Settings.Default.DragDropItemsEnabled))
{
AllowDrop = true;
DragEnter += DragDropHelper.DragEnter;
DragDrop += DragDropHelper.DragDrop;
}
#endif
Loaded += (_, _) =>
{
NativeMethods.HideFromAltTab(this);
RaiseEvent(new(routedEvent: FadeInEvent));
};
Closed += (_, _) =>
{
foreach (ListViewItemData item in dgv.Items)
{
item.data.SubMenu?.Close();
}
};
AddItemsToMenu(menuData.RowDatas, null, false);
}
internal event Action? MenuScrolled;
#if TODO // Misc MouseEvents
internal new event Action MouseEnter;
internal new event Action MouseLeave;
#endif
internal event Action