2020-07-07 09:37:55 +12:00
|
|
|
|
// <copyright file="Menu.cs" company="PlaceholderCompany">
|
|
|
|
|
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
|
|
|
// </copyright>
|
|
|
|
|
|
|
|
|
|
namespace SystemTrayMenu.UserInterface
|
2020-06-08 00:28:59 +12:00
|
|
|
|
{
|
2020-07-07 07:15:45 +12:00
|
|
|
|
using System;
|
|
|
|
|
using System.Data;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
using SystemTrayMenu.DataClasses;
|
|
|
|
|
using SystemTrayMenu.DllImports;
|
2021-10-26 08:45:49 +13:00
|
|
|
|
using SystemTrayMenu.Helper;
|
2020-07-07 07:15:45 +12:00
|
|
|
|
using SystemTrayMenu.Utilities;
|
|
|
|
|
|
2020-06-08 00:28:59 +12:00
|
|
|
|
internal partial class Menu : Form
|
|
|
|
|
{
|
2021-12-10 08:00:33 +13:00
|
|
|
|
private const int CornerRadius = 20;
|
2021-11-17 12:13:46 +13:00
|
|
|
|
private readonly Fading fading = new();
|
2021-04-17 12:39:48 +12:00
|
|
|
|
private bool isShowing;
|
|
|
|
|
private bool directionToRight;
|
2021-10-04 07:24:22 +13:00
|
|
|
|
private int rotationAngle;
|
2021-11-25 07:01:59 +13:00
|
|
|
|
private bool mouseDown;
|
|
|
|
|
private Point lastLocation;
|
2020-06-06 21:47:19 +12:00
|
|
|
|
|
2020-06-08 00:28:59 +12:00
|
|
|
|
internal Menu()
|
|
|
|
|
{
|
|
|
|
|
fading.ChangeOpacity += Fading_ChangeOpacity;
|
|
|
|
|
void Fading_ChangeOpacity(object sender, double newOpacity)
|
|
|
|
|
{
|
2020-07-04 08:02:16 +12:00
|
|
|
|
if (!IsDisposed && !Disposing)
|
2020-06-21 06:11:25 +12:00
|
|
|
|
{
|
2021-12-10 08:00:33 +13:00
|
|
|
|
Opacity = newOpacity;
|
2020-06-21 06:11:25 +12:00
|
|
|
|
}
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-08 00:28:59 +12:00
|
|
|
|
fading.Show += Fading_Show;
|
|
|
|
|
void Fading_Show()
|
|
|
|
|
{
|
2021-05-29 06:48:17 +12:00
|
|
|
|
try
|
2020-06-08 00:28:59 +12:00
|
|
|
|
{
|
2021-05-29 06:48:17 +12:00
|
|
|
|
isShowing = true;
|
|
|
|
|
Visible = true;
|
|
|
|
|
isShowing = false;
|
2021-09-24 08:53:46 +12:00
|
|
|
|
timerUpdateIcons.Start();
|
2021-05-29 06:48:17 +12:00
|
|
|
|
}
|
|
|
|
|
catch (ObjectDisposedException)
|
|
|
|
|
{
|
|
|
|
|
Visible = false;
|
|
|
|
|
isShowing = false;
|
|
|
|
|
Log.Info($"Could not open menu, old menu was disposing," +
|
|
|
|
|
$" IsDisposed={IsDisposed}");
|
|
|
|
|
}
|
2020-06-08 00:28:59 +12:00
|
|
|
|
|
2021-05-29 06:48:17 +12:00
|
|
|
|
if (Visible)
|
|
|
|
|
{
|
|
|
|
|
if (Level == 0)
|
2020-06-08 00:28:59 +12:00
|
|
|
|
{
|
|
|
|
|
Activate();
|
2021-11-02 01:32:06 +13:00
|
|
|
|
textBoxSearch.SelectAll();
|
2020-06-08 00:28:59 +12:00
|
|
|
|
textBoxSearch.Focus();
|
|
|
|
|
NativeMethods.User32ShowInactiveTopmost(this);
|
|
|
|
|
NativeMethods.ForceForegroundWindow(Handle);
|
|
|
|
|
}
|
2021-05-29 06:48:17 +12:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NativeMethods.User32ShowInactiveTopmost(this);
|
2021-11-02 01:32:06 +13:00
|
|
|
|
textBoxSearch.SelectAll();
|
2021-05-29 06:48:17 +12:00
|
|
|
|
textBoxSearch.Focus();
|
|
|
|
|
}
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-08 00:28:59 +12:00
|
|
|
|
fading.Hide += Hide;
|
|
|
|
|
|
|
|
|
|
InitializeComponent();
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-08 00:28:59 +12:00
|
|
|
|
SetDoubleBuffer(dgv, true);
|
|
|
|
|
|
2020-08-08 01:24:25 +12:00
|
|
|
|
Color foreColor = Color.Black;
|
2021-05-05 07:59:55 +12:00
|
|
|
|
Color backColor = AppColors.Background;
|
|
|
|
|
Color backColorSearch = AppColors.SearchField;
|
2021-07-04 07:50:59 +12:00
|
|
|
|
Color backgroundBorder = AppColors.BackgroundBorder;
|
2021-06-26 23:24:56 +12:00
|
|
|
|
|
2020-08-08 01:24:25 +12:00
|
|
|
|
if (Config.IsDarkMode())
|
|
|
|
|
{
|
|
|
|
|
foreColor = Color.White;
|
|
|
|
|
labelTitle.ForeColor = foreColor;
|
|
|
|
|
textBoxSearch.ForeColor = foreColor;
|
2021-05-05 07:59:55 +12:00
|
|
|
|
backColor = AppColors.DarkModeBackground;
|
|
|
|
|
backColorSearch = AppColors.DarkModeSearchField;
|
2021-07-04 07:50:59 +12:00
|
|
|
|
backgroundBorder = AppColors.DarkModeBackgroundBorder;
|
2020-08-08 01:24:25 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-11-17 12:13:46 +13:00
|
|
|
|
ColorConverter colorConverter = new();
|
2021-12-10 08:00:33 +13:00
|
|
|
|
labelItems.ForeColor = MenuDefines.ColorIcons;
|
2021-06-28 01:42:34 +12:00
|
|
|
|
|
2021-06-06 23:15:01 +12:00
|
|
|
|
if (backColor.R == 0)
|
|
|
|
|
{
|
|
|
|
|
backColor = Color.White;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-04 07:50:59 +12:00
|
|
|
|
BackColor = backgroundBorder;
|
2021-12-10 08:00:33 +13:00
|
|
|
|
labelTitle.BackColor = backColor;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
tableLayoutPanelDgvAndScrollbar.BackColor = backColor;
|
2021-12-10 08:00:33 +13:00
|
|
|
|
tableLayoutPanelBottom.BackColor = backColor;
|
|
|
|
|
tableLayoutPanelMenu.BackColor = backColor;
|
2021-05-05 02:18:19 +12:00
|
|
|
|
dgv.BackgroundColor = backColor;
|
|
|
|
|
textBoxSearch.BackColor = backColorSearch;
|
2021-12-10 08:00:33 +13:00
|
|
|
|
panelLine.BackColor = AppColors.Icons;
|
2021-05-05 02:18:19 +12:00
|
|
|
|
pictureBoxSearch.BackColor = backColorSearch;
|
|
|
|
|
tableLayoutPanelSearch.BackColor = backColorSearch;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
dgv.DefaultCellStyle = new DataGridViewCellStyle
|
2020-06-08 00:28:59 +12:00
|
|
|
|
{
|
2020-08-08 01:24:25 +12:00
|
|
|
|
SelectionForeColor = foreColor,
|
|
|
|
|
ForeColor = foreColor,
|
|
|
|
|
BackColor = backColor,
|
2020-06-08 00:28:59 +12:00
|
|
|
|
};
|
|
|
|
|
|
2021-11-02 01:32:06 +13:00
|
|
|
|
dgv.GotFocus += (sender, e) => FocusTextBox();
|
|
|
|
|
customScrollbar.GotFocus += (sender, e) => FocusTextBox();
|
2021-06-03 22:52:47 +12:00
|
|
|
|
|
|
|
|
|
customScrollbar.Margin = new Padding(0);
|
|
|
|
|
customScrollbar.Scroll += CustomScrollbar_Scroll;
|
|
|
|
|
void CustomScrollbar_Scroll(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
decimal firstIndex = customScrollbar.Value * dgv.Rows.Count / (decimal)customScrollbar.Maximum;
|
2021-06-26 23:24:56 +12:00
|
|
|
|
int firstIndexRounded = (int)Math.Ceiling(firstIndex);
|
2021-06-03 22:52:47 +12:00
|
|
|
|
if (firstIndexRounded > -1 && firstIndexRounded < dgv.RowCount)
|
|
|
|
|
{
|
|
|
|
|
dgv.FirstDisplayedScrollingRowIndex = firstIndexRounded;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
customScrollbar.MouseEnter += ControlsMouseEnter;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
dgv.MouseEnter += ControlsMouseEnter;
|
|
|
|
|
labelTitle.MouseEnter += ControlsMouseEnter;
|
2021-10-29 03:29:04 +13:00
|
|
|
|
textBoxSearch.MouseEnter += ControlsMouseEnter;
|
|
|
|
|
pictureBoxOpenFolder.MouseEnter += ControlsMouseEnter;
|
2021-11-22 05:24:01 +13:00
|
|
|
|
pictureBoxMenuAlwaysOpen.MouseEnter += ControlsMouseEnter;
|
|
|
|
|
pictureBoxSettings.MouseEnter += ControlsMouseEnter;
|
|
|
|
|
pictureBoxRestart.MouseEnter += ControlsMouseEnter;
|
2021-10-29 03:29:04 +13:00
|
|
|
|
pictureBoxSearch.MouseEnter += ControlsMouseEnter;
|
2021-12-10 08:00:33 +13:00
|
|
|
|
tableLayoutPanelMenu.MouseEnter += ControlsMouseEnter;
|
|
|
|
|
tableLayoutPanelDgvAndScrollbar.MouseEnter += ControlsMouseEnter;
|
|
|
|
|
tableLayoutPanelBottom.MouseEnter += ControlsMouseEnter;
|
|
|
|
|
labelItems.MouseEnter += ControlsMouseEnter;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
void ControlsMouseEnter(object sender, EventArgs e)
|
|
|
|
|
{
|
2020-06-29 06:57:03 +12:00
|
|
|
|
MouseEnter?.Invoke();
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2021-06-03 22:52:47 +12:00
|
|
|
|
customScrollbar.MouseLeave += ControlsMouseLeave;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
dgv.MouseLeave += ControlsMouseLeave;
|
|
|
|
|
labelTitle.MouseLeave += ControlsMouseLeave;
|
2021-10-29 03:29:04 +13:00
|
|
|
|
textBoxSearch.MouseLeave += ControlsMouseLeave;
|
|
|
|
|
pictureBoxMenuAlwaysOpen.MouseLeave += ControlsMouseLeave;
|
|
|
|
|
pictureBoxOpenFolder.MouseLeave += ControlsMouseLeave;
|
2021-11-22 05:24:01 +13:00
|
|
|
|
pictureBoxSettings.MouseLeave += ControlsMouseLeave;
|
|
|
|
|
pictureBoxRestart.MouseLeave += ControlsMouseLeave;
|
2021-10-29 03:29:04 +13:00
|
|
|
|
pictureBoxSearch.MouseLeave += ControlsMouseLeave;
|
2021-12-10 08:00:33 +13:00
|
|
|
|
tableLayoutPanelMenu.MouseLeave += ControlsMouseLeave;
|
|
|
|
|
tableLayoutPanelDgvAndScrollbar.MouseLeave += ControlsMouseLeave;
|
|
|
|
|
tableLayoutPanelBottom.MouseLeave += ControlsMouseLeave;
|
|
|
|
|
labelItems.MouseLeave += ControlsMouseLeave;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
void ControlsMouseLeave(object sender, EventArgs e)
|
|
|
|
|
{
|
2020-06-29 06:57:03 +12:00
|
|
|
|
MouseLeave?.Invoke();
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
2021-06-26 23:24:56 +12:00
|
|
|
|
|
|
|
|
|
AllowDrop = true;
|
|
|
|
|
DragEnter += DragDropHelper.DragEnter;
|
|
|
|
|
DragDrop += DragDropHelper.DragDrop;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 09:37:55 +12:00
|
|
|
|
internal new event EventHandlerEmpty MouseWheel;
|
|
|
|
|
|
|
|
|
|
internal new event EventHandlerEmpty MouseEnter;
|
|
|
|
|
|
|
|
|
|
internal new event EventHandlerEmpty MouseLeave;
|
|
|
|
|
|
|
|
|
|
internal event EventHandlerEmpty UserClickedOpenFolder;
|
|
|
|
|
|
|
|
|
|
internal event EventHandler<Keys> CmdKeyProcessed;
|
|
|
|
|
|
|
|
|
|
internal event EventHandlerEmpty SearchTextChanging;
|
|
|
|
|
|
|
|
|
|
internal event EventHandler SearchTextChanged;
|
|
|
|
|
|
2021-11-25 07:01:59 +13:00
|
|
|
|
internal event EventHandlerEmpty UserDragsMenu;
|
|
|
|
|
|
2020-07-07 09:37:55 +12:00
|
|
|
|
internal enum MenuType
|
|
|
|
|
{
|
|
|
|
|
Main,
|
|
|
|
|
Sub,
|
|
|
|
|
Empty,
|
|
|
|
|
NoAccess,
|
|
|
|
|
MaxReached,
|
2021-10-04 07:24:22 +13:00
|
|
|
|
Loading,
|
2020-07-07 09:37:55 +12:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-21 05:19:21 +12:00
|
|
|
|
internal enum StartLocation
|
|
|
|
|
{
|
|
|
|
|
Predecessor,
|
|
|
|
|
BottomLeft,
|
|
|
|
|
BottomRight,
|
|
|
|
|
TopRight,
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-17 12:39:48 +12:00
|
|
|
|
internal int Level { get; set; }
|
2020-07-08 03:05:19 +12:00
|
|
|
|
|
2021-12-10 08:00:33 +13:00
|
|
|
|
internal bool IsUsable => Visible && !fading.IsHiding && !IsDisposed && !Disposing;
|
2020-07-07 09:37:55 +12:00
|
|
|
|
|
2022-01-09 01:39:19 +13:00
|
|
|
|
internal bool ScrollbarVisible { get; private set; }
|
|
|
|
|
|
2020-07-08 03:05:19 +12:00
|
|
|
|
protected override CreateParams CreateParams
|
2020-06-08 00:28:59 +12:00
|
|
|
|
{
|
2020-07-08 03:05:19 +12:00
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
CreateParams createparams = base.CreateParams;
|
2021-12-10 08:00:33 +13:00
|
|
|
|
createparams.ExStyle |= 0x80; // do not show when user presses alt + tab
|
|
|
|
|
createparams.ClassStyle |= 0x00020000; // CS_DROPSHADOW
|
2021-12-06 05:04:48 +13:00
|
|
|
|
|
2020-07-08 03:05:19 +12:00
|
|
|
|
return createparams;
|
|
|
|
|
}
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-11-11 11:39:52 +13:00
|
|
|
|
internal void ResetSearchText()
|
|
|
|
|
{
|
|
|
|
|
textBoxSearch.Text = string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-08 03:05:19 +12:00
|
|
|
|
internal void FocusTextBox()
|
2020-06-08 00:28:59 +12:00
|
|
|
|
{
|
2021-11-02 01:32:06 +13:00
|
|
|
|
textBoxSearch.SelectAll();
|
2020-07-08 03:05:19 +12:00
|
|
|
|
textBoxSearch.Focus();
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void SetTypeSub()
|
|
|
|
|
{
|
|
|
|
|
SetType(MenuType.Sub);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void SetTypeEmpty()
|
|
|
|
|
{
|
|
|
|
|
SetType(MenuType.Empty);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void SetTypeNoAccess()
|
|
|
|
|
{
|
|
|
|
|
SetType(MenuType.NoAccess);
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-04 07:24:22 +13:00
|
|
|
|
internal void SetTypeLoading()
|
|
|
|
|
{
|
|
|
|
|
SetType(MenuType.Loading);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 00:28:59 +12:00
|
|
|
|
internal void SetType(MenuType type)
|
|
|
|
|
{
|
2021-06-26 23:24:56 +12:00
|
|
|
|
if (type != MenuType.Main)
|
|
|
|
|
{
|
2021-11-22 05:24:01 +13:00
|
|
|
|
pictureBoxSettings.Visible = false;
|
|
|
|
|
pictureBoxRestart.Visible = false;
|
2021-06-26 23:24:56 +12:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 00:28:59 +12:00
|
|
|
|
switch (type)
|
|
|
|
|
{
|
2021-10-04 07:24:22 +13:00
|
|
|
|
case MenuType.Main:
|
|
|
|
|
break;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
case MenuType.Sub:
|
2021-12-10 08:00:33 +13:00
|
|
|
|
pictureBoxMenuAlwaysOpen.Visible = false;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
break;
|
|
|
|
|
case MenuType.Empty:
|
2021-12-10 08:00:33 +13:00
|
|
|
|
pictureBoxSearch.Visible = true;
|
|
|
|
|
textBoxSearch.Visible = true;
|
|
|
|
|
tableLayoutPanelSearch.Visible = true;
|
|
|
|
|
labelItems.Text = Translator.GetText("Folder empty");
|
|
|
|
|
pictureBoxMenuAlwaysOpen.Visible = false;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
break;
|
|
|
|
|
case MenuType.NoAccess:
|
2021-12-10 08:00:33 +13:00
|
|
|
|
pictureBoxSearch.Visible = true;
|
|
|
|
|
textBoxSearch.Visible = true;
|
|
|
|
|
tableLayoutPanelSearch.Visible = true;
|
|
|
|
|
labelItems.Text = Translator.GetText("Folder inaccessible");
|
|
|
|
|
pictureBoxMenuAlwaysOpen.Visible = false;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
break;
|
2021-10-04 07:24:22 +13:00
|
|
|
|
case MenuType.Loading:
|
2021-12-10 08:00:33 +13:00
|
|
|
|
pictureBoxSearch.Visible = true;
|
|
|
|
|
textBoxSearch.Visible = true;
|
|
|
|
|
tableLayoutPanelSearch.Visible = true;
|
|
|
|
|
labelItems.Text = Translator.GetText("loading");
|
|
|
|
|
pictureBoxMenuAlwaysOpen.Visible = true;
|
|
|
|
|
textBoxSearch.TextChanged -= TextBoxSearch_TextChanged;
|
2021-10-04 07:24:22 +13:00
|
|
|
|
pictureBoxOpenFolder.Visible = false;
|
|
|
|
|
pictureBoxMenuAlwaysOpen.Paint -= PictureBoxMenuAlwaysOpen_Paint;
|
|
|
|
|
pictureBoxMenuAlwaysOpen.Paint += LoadingMenu_Paint;
|
|
|
|
|
timerUpdateIcons.Tick -= TimerUpdateIcons_Tick;
|
2021-11-22 05:24:01 +13:00
|
|
|
|
timerUpdateIcons.Tick += (sender, e) => pictureBoxMenuAlwaysOpen.Invalidate();
|
2021-10-04 07:24:22 +13:00
|
|
|
|
timerUpdateIcons.Interval = 15;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-10 08:00:33 +13:00
|
|
|
|
internal string GetSearchText()
|
|
|
|
|
{
|
|
|
|
|
return textBoxSearch.Text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void SetSearchText(string userSearchText)
|
|
|
|
|
{
|
|
|
|
|
textBoxSearch.Text = userSearchText;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 00:28:59 +12:00
|
|
|
|
internal bool IsMouseOn(Point mousePosition)
|
|
|
|
|
{
|
|
|
|
|
bool isMouseOn = Visible && ClientRectangle.Contains(
|
|
|
|
|
PointToClient(mousePosition));
|
|
|
|
|
return isMouseOn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal DataGridView GetDataGridView()
|
|
|
|
|
{
|
|
|
|
|
return dgv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void SetTitle(string title)
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrEmpty(title))
|
|
|
|
|
{
|
|
|
|
|
if (title.Length > MenuDefines.LengthMax)
|
|
|
|
|
{
|
2021-12-12 02:34:28 +13:00
|
|
|
|
title = $"{title[..MenuDefines.LengthMax]}...";
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-08 00:28:59 +12:00
|
|
|
|
labelTitle.Text = title;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void ShowWithFadeOrTransparent(bool formActiveFormIsMenu)
|
|
|
|
|
{
|
|
|
|
|
if (formActiveFormIsMenu)
|
|
|
|
|
{
|
|
|
|
|
ShowWithFade();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ShowTransparent();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void ShowWithFade()
|
|
|
|
|
{
|
|
|
|
|
fading.Fade(Fading.FadingState.Show);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void ShowTransparent()
|
|
|
|
|
{
|
|
|
|
|
fading.Fade(Fading.FadingState.ShowTransparent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void HideWithFade()
|
|
|
|
|
{
|
|
|
|
|
if (!isShowing)
|
|
|
|
|
{
|
|
|
|
|
fading.Fade(Fading.FadingState.Hide);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-21 07:47:46 +12:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Update the position and size of the menu.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="bounds">Screen coordinates where the menu is allowed to be drawn in.</param>
|
|
|
|
|
/// <param name="menuPredecessor">Predecessor menu (when available).</param>
|
|
|
|
|
/// <param name="startLocation">Defines where the first menu is drawn (when no predecessor is set).</param>
|
2021-12-28 00:22:52 +13:00
|
|
|
|
/// <param name="isCustomLocationOutsideOfScreen">isCustomLocationOutsideOfScreen.</param>
|
2020-07-07 07:15:45 +12:00
|
|
|
|
internal void AdjustSizeAndLocation(
|
2020-09-21 03:26:45 +12:00
|
|
|
|
Rectangle bounds,
|
|
|
|
|
Menu menuPredecessor,
|
2021-12-28 00:22:52 +13:00
|
|
|
|
StartLocation startLocation,
|
|
|
|
|
bool isCustomLocationOutsideOfScreen)
|
2020-06-08 00:28:59 +12:00
|
|
|
|
{
|
2021-05-29 09:23:05 +12:00
|
|
|
|
// Update the height and width
|
|
|
|
|
AdjustDataGridViewHeight(menuPredecessor, bounds.Height);
|
|
|
|
|
AdjustDataGridViewWidth();
|
|
|
|
|
|
2021-11-25 07:01:59 +13:00
|
|
|
|
bool useCustomLocation = Properties.Settings.Default.UseCustomLocation || lastLocation.X > 0;
|
2021-12-28 00:22:52 +13:00
|
|
|
|
bool changeDirectionWhenOutOfBounds = true;
|
2021-11-25 07:01:59 +13:00
|
|
|
|
|
2020-09-21 05:19:21 +12:00
|
|
|
|
if (menuPredecessor != null)
|
|
|
|
|
{
|
2020-09-21 06:45:12 +12:00
|
|
|
|
// Ignore start as we use predecessor
|
2020-09-21 05:19:21 +12:00
|
|
|
|
startLocation = StartLocation.Predecessor;
|
|
|
|
|
}
|
2021-12-28 00:22:52 +13:00
|
|
|
|
else if (useCustomLocation && !isCustomLocationOutsideOfScreen)
|
2021-11-25 07:01:59 +13:00
|
|
|
|
{
|
|
|
|
|
// Do not adjust location again because Cursor.Postion changed
|
|
|
|
|
if (Tag != null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Use this menu as predecessor and overwrite location with CustomLocation
|
|
|
|
|
menuPredecessor = this;
|
|
|
|
|
Tag = new RowData();
|
|
|
|
|
Location = new Point(
|
|
|
|
|
Properties.Settings.Default.CustomLocationX,
|
|
|
|
|
Properties.Settings.Default.CustomLocationY);
|
|
|
|
|
directionToRight = true;
|
|
|
|
|
startLocation = StartLocation.Predecessor;
|
2021-12-28 00:22:52 +13:00
|
|
|
|
changeDirectionWhenOutOfBounds = false;
|
2021-11-25 07:01:59 +13:00
|
|
|
|
}
|
2021-04-29 08:58:33 +12:00
|
|
|
|
else if (Properties.Settings.Default.AppearAtMouseLocation)
|
|
|
|
|
{
|
2021-06-27 22:24:05 +12:00
|
|
|
|
// Do not adjust location again because Cursor.Postion changed
|
|
|
|
|
if (Tag != null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Use this menu as predecessor and overwrite location with Cursor.Postion
|
2021-04-29 08:58:33 +12:00
|
|
|
|
menuPredecessor = this;
|
|
|
|
|
Tag = new RowData();
|
|
|
|
|
Location = new Point(Cursor.Position.X, Cursor.Position.Y - labelTitle.Height);
|
|
|
|
|
directionToRight = true;
|
|
|
|
|
startLocation = StartLocation.Predecessor;
|
2021-12-28 00:22:52 +13:00
|
|
|
|
changeDirectionWhenOutOfBounds = false;
|
2021-04-29 08:58:33 +12:00
|
|
|
|
}
|
2020-09-21 05:19:21 +12:00
|
|
|
|
|
|
|
|
|
// Calculate X position
|
2020-06-08 00:28:59 +12:00
|
|
|
|
int x;
|
2020-09-21 05:19:21 +12:00
|
|
|
|
switch (startLocation)
|
2020-06-08 00:28:59 +12:00
|
|
|
|
{
|
2020-09-21 05:19:21 +12:00
|
|
|
|
case StartLocation.Predecessor:
|
2020-09-21 06:45:12 +12:00
|
|
|
|
int scaling = (int)Math.Round(Scaling.Factor, 0, MidpointRounding.AwayFromZero);
|
|
|
|
|
directionToRight = menuPredecessor.directionToRight; // try keeping same direction
|
2020-09-21 05:19:21 +12:00
|
|
|
|
if (directionToRight)
|
|
|
|
|
{
|
2020-09-21 06:45:12 +12:00
|
|
|
|
x = menuPredecessor.Location.X + menuPredecessor.Width - scaling;
|
|
|
|
|
|
2021-12-28 00:22:52 +13:00
|
|
|
|
if (changeDirectionWhenOutOfBounds &&
|
|
|
|
|
bounds.X + bounds.Width <= x + Width - scaling)
|
2020-09-21 06:45:12 +12:00
|
|
|
|
{
|
|
|
|
|
x = menuPredecessor.Location.X - Width + scaling;
|
|
|
|
|
directionToRight = !directionToRight;
|
|
|
|
|
}
|
2020-09-21 05:19:21 +12:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-09-21 06:45:12 +12:00
|
|
|
|
x = menuPredecessor.Location.X - Width + scaling;
|
|
|
|
|
|
2021-12-28 00:22:52 +13:00
|
|
|
|
if (changeDirectionWhenOutOfBounds &&
|
|
|
|
|
x < bounds.X)
|
2020-09-21 06:45:12 +12:00
|
|
|
|
{
|
|
|
|
|
x = menuPredecessor.Location.X + menuPredecessor.Width - scaling;
|
|
|
|
|
directionToRight = !directionToRight;
|
|
|
|
|
}
|
2020-09-21 05:19:21 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case StartLocation.BottomLeft:
|
|
|
|
|
x = bounds.X;
|
2020-09-21 06:45:12 +12:00
|
|
|
|
directionToRight = true;
|
2020-09-21 05:19:21 +12:00
|
|
|
|
break;
|
|
|
|
|
case StartLocation.TopRight:
|
|
|
|
|
case StartLocation.BottomRight:
|
|
|
|
|
default:
|
|
|
|
|
x = bounds.Width - Width;
|
2020-09-21 06:45:12 +12:00
|
|
|
|
directionToRight = false;
|
2020-09-21 05:19:21 +12:00
|
|
|
|
break;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-29 08:58:33 +12:00
|
|
|
|
// X position for click, remove width of this menu as it is used as predecessor
|
|
|
|
|
if (menuPredecessor == this && directionToRight)
|
|
|
|
|
{
|
|
|
|
|
x -= Width;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-16 02:44:56 +13:00
|
|
|
|
if (Level != 0 &&
|
|
|
|
|
!Properties.Settings.Default.AppearNextToPreviousMenu &&
|
|
|
|
|
menuPredecessor.Width > Properties.Settings.Default.OverlappingOffsetPixels)
|
|
|
|
|
{
|
|
|
|
|
if (directionToRight)
|
|
|
|
|
{
|
|
|
|
|
x = x - menuPredecessor.Width + Properties.Settings.Default.OverlappingOffsetPixels;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
x = x + menuPredecessor.Width - Properties.Settings.Default.OverlappingOffsetPixels;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-21 05:19:21 +12:00
|
|
|
|
// Calculate Y position
|
2020-06-08 00:28:59 +12:00
|
|
|
|
int y;
|
2020-09-21 05:19:21 +12:00
|
|
|
|
switch (startLocation)
|
2020-06-08 00:28:59 +12:00
|
|
|
|
{
|
2020-09-21 05:19:21 +12:00
|
|
|
|
case StartLocation.Predecessor:
|
|
|
|
|
RowData trigger = (RowData)Tag;
|
|
|
|
|
DataGridView dgv = menuPredecessor.GetDataGridView();
|
|
|
|
|
int distanceFromItemToDgvTop = 0;
|
2020-09-21 06:45:12 +12:00
|
|
|
|
|
|
|
|
|
// Get offset of selected row from predecessor
|
2020-09-21 05:19:21 +12:00
|
|
|
|
if (dgv.Rows.Count > trigger.RowIndex)
|
|
|
|
|
{
|
|
|
|
|
Rectangle cellRectangle = dgv.GetCellDisplayRectangle(0, trigger.RowIndex, false);
|
|
|
|
|
distanceFromItemToDgvTop = cellRectangle.Top;
|
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-09-21 06:45:12 +12:00
|
|
|
|
// Set position on same height as the selected row from predecessor
|
|
|
|
|
y = menuPredecessor.Location.Y + menuPredecessor.dgv.Location.Y + distanceFromItemToDgvTop;
|
|
|
|
|
|
2021-06-28 01:42:34 +12:00
|
|
|
|
// when warning the title should appear in same height as selected row
|
|
|
|
|
if (!tableLayoutPanelSearch.Visible)
|
2021-06-26 23:24:56 +12:00
|
|
|
|
{
|
2021-12-10 08:00:33 +13:00
|
|
|
|
TableLayoutPanelCellPosition pos = tableLayoutPanelMenu.GetCellPosition(labelTitle);
|
|
|
|
|
int height = tableLayoutPanelMenu.GetRowHeights()[pos.Row];
|
|
|
|
|
y += height;
|
2021-06-26 23:24:56 +12:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-21 06:45:12 +12:00
|
|
|
|
// Move vertically when out of bounds
|
2020-09-27 22:24:58 +13:00
|
|
|
|
if (bounds.Y + bounds.Height < y + Height)
|
2020-09-21 05:19:21 +12:00
|
|
|
|
{
|
2020-09-21 06:45:12 +12:00
|
|
|
|
y = bounds.Y + bounds.Height - Height;
|
2020-09-21 05:19:21 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case StartLocation.TopRight:
|
|
|
|
|
y = bounds.Y;
|
|
|
|
|
break;
|
|
|
|
|
case StartLocation.BottomLeft:
|
|
|
|
|
case StartLocation.BottomRight:
|
|
|
|
|
default:
|
|
|
|
|
y = bounds.Height - Height;
|
|
|
|
|
break;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-21 05:19:21 +12:00
|
|
|
|
// Update position
|
2020-06-08 00:28:59 +12:00
|
|
|
|
Location = new Point(x, y);
|
2021-11-14 07:44:32 +13:00
|
|
|
|
|
|
|
|
|
if (Properties.Settings.Default.RoundCorners)
|
|
|
|
|
{
|
2021-12-11 08:35:00 +13:00
|
|
|
|
if (NativeMethods.GetRegionRoundCorners(Width + 1, Height + 1, CornerRadius, CornerRadius, out Region regionOutline))
|
2021-11-19 09:12:03 +13:00
|
|
|
|
{
|
|
|
|
|
Region = regionOutline;
|
|
|
|
|
}
|
2021-12-11 08:35:00 +13:00
|
|
|
|
|
|
|
|
|
if (NativeMethods.GetRegionRoundCorners(Width - 1, Height - 1, CornerRadius, CornerRadius, out Region region))
|
|
|
|
|
{
|
|
|
|
|
tableLayoutPanelMenu.Region = region;
|
|
|
|
|
}
|
2021-11-14 07:44:32 +13:00
|
|
|
|
}
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-08 03:05:19 +12:00
|
|
|
|
internal void KeyPressedSearch(string letter)
|
|
|
|
|
{
|
|
|
|
|
textBoxSearch.Text += letter;
|
|
|
|
|
textBoxSearch.SelectionStart = textBoxSearch.Text.Length;
|
|
|
|
|
textBoxSearch.SelectionLength = 0;
|
|
|
|
|
textBoxSearch.Focus();
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-03 22:52:47 +12:00
|
|
|
|
internal void AdjustScrollbar()
|
|
|
|
|
{
|
|
|
|
|
customScrollbar.Value = (int)Math.Round(
|
|
|
|
|
dgv.FirstDisplayedScrollingRowIndex * (decimal)customScrollbar.Maximum / dgv.Rows.Count,
|
|
|
|
|
0,
|
|
|
|
|
MidpointRounding.AwayFromZero);
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-28 01:42:34 +12:00
|
|
|
|
internal void SetCounts(int foldersCount, int filesCount)
|
|
|
|
|
{
|
2021-12-10 08:00:33 +13:00
|
|
|
|
int filesAndFoldersCount = foldersCount + filesCount;
|
2021-12-11 08:35:00 +13:00
|
|
|
|
string elements = filesAndFoldersCount == 1 ? "element" : "elements";
|
|
|
|
|
labelItems.Text = $"{filesAndFoldersCount} {Translator.GetText(elements)}";
|
2021-06-28 01:42:34 +12:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-08 03:05:19 +12:00
|
|
|
|
protected override bool ProcessCmdKey(ref Message msg, Keys keys)
|
|
|
|
|
{
|
|
|
|
|
switch (keys)
|
|
|
|
|
{
|
|
|
|
|
case Keys.Enter:
|
2022-02-05 02:37:37 +13:00
|
|
|
|
case Keys.Home:
|
|
|
|
|
case Keys.End:
|
2020-07-08 03:05:19 +12:00
|
|
|
|
case Keys.Up:
|
|
|
|
|
case Keys.Down:
|
|
|
|
|
case Keys.Left:
|
|
|
|
|
case Keys.Right:
|
|
|
|
|
case Keys.Escape:
|
|
|
|
|
case Keys.Control | Keys.F:
|
|
|
|
|
case Keys.Tab:
|
|
|
|
|
case Keys.Tab | Keys.Shift:
|
|
|
|
|
case Keys.Apps:
|
|
|
|
|
CmdKeyProcessed.Invoke(this, keys);
|
|
|
|
|
return true;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return base.ProcessCmdKey(ref msg, keys);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void SetDoubleBuffer(Control ctl, bool doubleBuffered)
|
|
|
|
|
{
|
|
|
|
|
typeof(Control).InvokeMember(
|
|
|
|
|
"DoubleBuffered",
|
|
|
|
|
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
|
|
|
|
|
null,
|
|
|
|
|
ctl,
|
|
|
|
|
new object[] { doubleBuffered },
|
|
|
|
|
CultureInfo.InvariantCulture);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-21 07:47:46 +12:00
|
|
|
|
private void AdjustDataGridViewHeight(Menu menuPredecessor, int screenHeightMax)
|
|
|
|
|
{
|
2021-11-14 04:52:55 +13:00
|
|
|
|
double factor = Properties.Settings.Default.RowHeighteInPercentage / 100f;
|
2020-09-21 07:47:46 +12:00
|
|
|
|
if (NativeMethods.IsTouchEnabled())
|
|
|
|
|
{
|
2021-11-14 04:52:55 +13:00
|
|
|
|
factor = Properties.Settings.Default.RowHeighteInPercentageTouch / 100f;
|
2020-09-21 07:47:46 +12:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-23 03:43:44 +13:00
|
|
|
|
double factorIconSizeInPercent = Properties.Settings.Default.IconSizeInPercent / 100f;
|
|
|
|
|
|
|
|
|
|
if (factor < factorIconSizeInPercent)
|
|
|
|
|
{
|
|
|
|
|
factor = factorIconSizeInPercent;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-21 07:47:46 +12:00
|
|
|
|
if (menuPredecessor == null)
|
|
|
|
|
{
|
|
|
|
|
if (dgv.Tag == null && dgv.Rows.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
// Find row size based on content and apply factor
|
|
|
|
|
dgv.AutoResizeRows();
|
|
|
|
|
dgv.RowTemplate.Height = (int)(dgv.Rows[0].Height * factor);
|
|
|
|
|
dgv.Tag = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Take over the height from predecessor menu
|
|
|
|
|
dgv.RowTemplate.Height = menuPredecessor.GetDataGridView().RowTemplate.Height;
|
|
|
|
|
dgv.Tag = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Patch size of each row
|
|
|
|
|
foreach (DataGridViewRow row in dgv.Rows)
|
|
|
|
|
{
|
|
|
|
|
row.Height = dgv.RowTemplate.Height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DataTable data = (DataTable)dgv.DataSource;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
int dgvHeightNew = dgv.Rows.GetRowsHeight(DataGridViewElementStates.None); // Height of all rows
|
|
|
|
|
int dgvHeightMax = screenHeightMax - (Height - dgv.Height); // except dgv
|
|
|
|
|
|
|
|
|
|
if (dgvHeightMax > Properties.Settings.Default.MaximumMenuHeight)
|
2020-09-21 07:47:46 +12:00
|
|
|
|
{
|
2021-06-03 22:52:47 +12:00
|
|
|
|
dgvHeightMax = Properties.Settings.Default.MaximumMenuHeight;
|
|
|
|
|
}
|
2021-05-29 19:46:54 +12:00
|
|
|
|
|
2021-06-03 22:52:47 +12:00
|
|
|
|
if (dgvHeightNew > dgvHeightMax)
|
|
|
|
|
{
|
|
|
|
|
// Make all rows fit into the screen
|
|
|
|
|
customScrollbar.PaintEnable();
|
|
|
|
|
if (customScrollbar.Maximum != dgvHeightNew)
|
2021-05-29 19:46:54 +12:00
|
|
|
|
{
|
2021-06-03 22:52:47 +12:00
|
|
|
|
customScrollbar.Reset();
|
|
|
|
|
customScrollbar.Height = dgvHeightMax;
|
|
|
|
|
customScrollbar.Minimum = 0;
|
|
|
|
|
customScrollbar.Maximum = dgvHeightNew;
|
2021-06-05 21:52:33 +12:00
|
|
|
|
customScrollbar.LargeChange = dgvHeightMax;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
customScrollbar.SmallChange = dgv.RowTemplate.Height;
|
2021-05-29 19:46:54 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-03 22:52:47 +12:00
|
|
|
|
dgvHeightNew = dgvHeightMax;
|
2021-12-31 00:36:00 +13:00
|
|
|
|
ScrollbarVisible = true;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
customScrollbar.PaintDisable();
|
2021-12-31 00:36:00 +13:00
|
|
|
|
ScrollbarVisible = false;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
2020-09-21 07:47:46 +12:00
|
|
|
|
|
2021-06-03 22:52:47 +12:00
|
|
|
|
if (string.IsNullOrEmpty(data.DefaultView.RowFilter))
|
|
|
|
|
{
|
|
|
|
|
dgv.Height = dgvHeightNew;
|
2020-09-21 07:47:46 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 00:28:59 +12:00
|
|
|
|
private void AdjustDataGridViewWidth()
|
|
|
|
|
{
|
|
|
|
|
DataGridViewExtensions.FastAutoSizeColumns(dgv);
|
2021-06-03 22:52:47 +12:00
|
|
|
|
|
|
|
|
|
if (dgv.Columns[1].Width < 60)
|
2020-06-08 00:28:59 +12:00
|
|
|
|
{
|
2021-06-03 22:52:47 +12:00
|
|
|
|
dgv.Columns[1].Width = 60;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-03 22:52:47 +12:00
|
|
|
|
int widthIcon = dgv.Columns[0].Width;
|
|
|
|
|
int widthText = dgv.Columns[1].Width;
|
|
|
|
|
int widthScrollbar = 0;
|
|
|
|
|
if (customScrollbar.Enabled)
|
2020-06-08 00:28:59 +12:00
|
|
|
|
{
|
2021-06-03 22:52:47 +12:00
|
|
|
|
widthScrollbar = customScrollbar.Width;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-10 08:00:33 +13:00
|
|
|
|
if (tableLayoutPanelBottom.Width > (widthIcon + widthText + widthScrollbar))
|
2021-06-03 22:52:47 +12:00
|
|
|
|
{
|
2021-12-10 08:00:33 +13:00
|
|
|
|
dgv.Width = tableLayoutPanelBottom.Width - widthScrollbar;
|
|
|
|
|
dgv.Columns[1].Width = tableLayoutPanelBottom.Width - widthIcon - widthScrollbar;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-06-03 22:52:47 +12:00
|
|
|
|
dgv.Width = widthIcon + widthText;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-12 08:48:11 +13:00
|
|
|
|
tableLayoutPanelSearch.MinimumSize = new Size(dgv.Width + widthScrollbar, 0);
|
|
|
|
|
|
2020-07-07 07:15:45 +12:00
|
|
|
|
// Only scaling correct with Sans Serif for textBoxSearch. Workaround:
|
|
|
|
|
textBoxSearch.Font = new Font(
|
|
|
|
|
"Segoe UI",
|
|
|
|
|
8.25F * Scaling.Factor,
|
|
|
|
|
FontStyle.Regular,
|
|
|
|
|
GraphicsUnit.Point,
|
|
|
|
|
0);
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 02:46:47 +12:00
|
|
|
|
private void DgvMouseWheel(object sender, MouseEventArgs e)
|
2020-06-08 00:28:59 +12:00
|
|
|
|
{
|
|
|
|
|
((HandledMouseEventArgs)e).Handled = true;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
customScrollbar.CustomScrollbar_MouseWheel(sender, e);
|
2020-06-29 06:57:03 +12:00
|
|
|
|
MouseWheel?.Invoke();
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 02:46:47 +12:00
|
|
|
|
private void TextBoxSearch_TextChanged(object sender, EventArgs e)
|
2020-06-08 00:28:59 +12:00
|
|
|
|
{
|
2021-06-03 22:52:47 +12:00
|
|
|
|
customScrollbar.Value = 0;
|
|
|
|
|
|
2020-06-08 00:28:59 +12:00
|
|
|
|
DataTable data = (DataTable)dgv.DataSource;
|
|
|
|
|
string filterField = dgv.Columns[1].Name;
|
2020-06-29 06:56:03 +12:00
|
|
|
|
SearchTextChanging?.Invoke();
|
2020-06-08 00:28:59 +12:00
|
|
|
|
|
2022-01-07 01:49:07 +13:00
|
|
|
|
// Expression reference: https://docs.microsoft.com/en-us/dotnet/api/system.data.datacolumn.expression?view=net-6.0
|
|
|
|
|
|
|
|
|
|
// Instead implementing in-string wildcards, simply split into multiple search patters
|
2021-06-28 00:44:12 +12:00
|
|
|
|
string searchString = textBoxSearch.Text.Trim()
|
|
|
|
|
.Replace("%", " ")
|
|
|
|
|
.Replace("*", " ");
|
2022-01-07 01:49:07 +13:00
|
|
|
|
|
|
|
|
|
// Replace special characters
|
2022-02-06 00:47:27 +13:00
|
|
|
|
string tmp = new(searchString);
|
2022-01-07 01:49:07 +13:00
|
|
|
|
searchString = string.Empty;
|
|
|
|
|
foreach (char ch in tmp)
|
|
|
|
|
{
|
2022-02-06 00:47:27 +13:00
|
|
|
|
searchString += ch switch
|
2022-01-07 01:49:07 +13:00
|
|
|
|
{
|
2022-02-06 00:47:27 +13:00
|
|
|
|
'[' => "[[]",
|
|
|
|
|
']' => "[]]",
|
|
|
|
|
_ => ch,
|
|
|
|
|
};
|
2022-01-07 01:49:07 +13:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-15 09:12:14 +12:00
|
|
|
|
string like = string.Empty;
|
|
|
|
|
string[] splittedParts = searchString.Split(" ");
|
|
|
|
|
if (splittedParts.Length > 1)
|
|
|
|
|
{
|
|
|
|
|
foreach (string splittedPart in splittedParts)
|
|
|
|
|
{
|
|
|
|
|
string and = string.Empty;
|
|
|
|
|
if (!string.IsNullOrEmpty(like))
|
|
|
|
|
{
|
|
|
|
|
and = $" AND [{filterField}]";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
like += $"{and} LIKE '%{splittedPart}%'";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
like = $"LIKE '%{searchString}%'";
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-31 04:52:42 +13:00
|
|
|
|
bool isSearchStringEmpty = string.IsNullOrEmpty(searchString);
|
|
|
|
|
|
2021-04-15 09:12:14 +12:00
|
|
|
|
try
|
|
|
|
|
{
|
2022-01-08 23:39:23 +13:00
|
|
|
|
if (Properties.Settings.Default.ShowOnlyAsSearchResult &&
|
2022-01-31 04:52:42 +13:00
|
|
|
|
isSearchStringEmpty)
|
2022-01-08 23:39:23 +13:00
|
|
|
|
{
|
|
|
|
|
data.DefaultView.RowFilter = "[SortIndex] LIKE '%0%'";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
data.DefaultView.RowFilter = $"[{filterField}] {like}";
|
|
|
|
|
}
|
2021-04-15 09:12:14 +12:00
|
|
|
|
}
|
2021-04-17 04:39:21 +12:00
|
|
|
|
catch (Exception ex)
|
2021-04-15 09:12:14 +12:00
|
|
|
|
{
|
2021-04-17 04:39:21 +12:00
|
|
|
|
if (ex is EvaluateException ||
|
|
|
|
|
ex is SyntaxErrorException)
|
|
|
|
|
{
|
|
|
|
|
Log.Warn($"searchString \"{searchString}\" is a invalid", ex);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
throw;
|
|
|
|
|
}
|
2021-04-15 09:12:14 +12:00
|
|
|
|
}
|
2021-04-15 07:06:54 +12:00
|
|
|
|
|
2022-01-08 23:39:23 +13:00
|
|
|
|
string columnSortIndex = "SortIndex";
|
2022-01-31 04:52:42 +13:00
|
|
|
|
if (isSearchStringEmpty)
|
2020-06-08 00:28:59 +12:00
|
|
|
|
{
|
2022-01-31 01:51:23 +13:00
|
|
|
|
foreach (DataRow row in data.Rows)
|
2022-01-08 23:39:23 +13:00
|
|
|
|
{
|
2022-01-31 01:51:23 +13:00
|
|
|
|
RowData rowData = (RowData)row[2];
|
|
|
|
|
if (Properties.Settings.Default.ShowOnlyAsSearchResult &&
|
|
|
|
|
rowData.ShowOnlyWhenSearch)
|
2022-01-08 23:39:23 +13:00
|
|
|
|
{
|
2022-01-31 01:51:23 +13:00
|
|
|
|
row[columnSortIndex] = 99;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
row[columnSortIndex] = 0;
|
2022-01-08 23:39:23 +13:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-31 01:51:23 +13:00
|
|
|
|
|
|
|
|
|
data.DefaultView.Sort = string.Empty;
|
|
|
|
|
data.AcceptChanges();
|
2021-04-15 07:06:54 +12:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
foreach (DataRow row in data.Rows)
|
|
|
|
|
{
|
|
|
|
|
if (row[1].ToString().StartsWith(
|
2021-04-15 09:12:14 +12:00
|
|
|
|
searchString,
|
2021-04-15 07:06:54 +12:00
|
|
|
|
StringComparison.InvariantCultureIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
row[columnSortIndex] = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
row[columnSortIndex] = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data.DefaultView.Sort = columnSortIndex;
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-28 00:44:12 +12:00
|
|
|
|
int foldersCount = 0;
|
|
|
|
|
int filesCount = 0;
|
2021-10-22 08:28:58 +13:00
|
|
|
|
bool anyIconNotUpdated = false;
|
2021-06-28 00:44:12 +12:00
|
|
|
|
|
2021-04-17 09:14:39 +12:00
|
|
|
|
foreach (DataGridViewRow row in dgv.Rows)
|
|
|
|
|
{
|
|
|
|
|
RowData rowData = (RowData)row.Cells[2].Value;
|
2021-06-28 00:44:12 +12:00
|
|
|
|
|
2022-01-31 04:52:42 +13:00
|
|
|
|
if (!isSearchStringEmpty || !rowData.ShowOnlyWhenSearch)
|
2021-06-28 00:44:12 +12:00
|
|
|
|
{
|
2022-01-08 23:39:23 +13:00
|
|
|
|
rowData.RowIndex = row.Index;
|
2021-10-22 08:28:58 +13:00
|
|
|
|
|
2022-01-08 23:39:23 +13:00
|
|
|
|
if (rowData.ContainsMenu)
|
|
|
|
|
{
|
|
|
|
|
foldersCount++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
filesCount++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rowData.IconLoading)
|
|
|
|
|
{
|
|
|
|
|
anyIconNotUpdated = true;
|
|
|
|
|
}
|
2021-10-22 08:28:58 +13:00
|
|
|
|
}
|
2021-04-17 09:14:39 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-28 00:44:12 +12:00
|
|
|
|
SetCounts(foldersCount, filesCount);
|
|
|
|
|
|
2020-06-08 00:28:59 +12:00
|
|
|
|
SearchTextChanged.Invoke(this, null);
|
2021-10-22 08:28:58 +13:00
|
|
|
|
|
|
|
|
|
if (anyIconNotUpdated)
|
|
|
|
|
{
|
|
|
|
|
timerUpdateIcons.Start();
|
|
|
|
|
}
|
2022-01-31 04:52:42 +13:00
|
|
|
|
|
|
|
|
|
if (isSearchStringEmpty)
|
|
|
|
|
{
|
|
|
|
|
dgv.FirstDisplayedScrollingRowIndex = 0;
|
|
|
|
|
}
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
2021-06-26 23:24:56 +12:00
|
|
|
|
|
|
|
|
|
private void PictureBox_MouseEnter(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
PictureBox pictureBox = (PictureBox)sender;
|
|
|
|
|
pictureBox.BackColor = MenuDefines.ColorSelectedItem;
|
|
|
|
|
pictureBox.Tag = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void PictureBox_MouseLeave(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
PictureBox pictureBox = (PictureBox)sender;
|
|
|
|
|
pictureBox.BackColor = Color.Transparent;
|
|
|
|
|
pictureBox.Tag = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void PictureBox_Resize(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
PictureBox pictureBox = (PictureBox)sender;
|
|
|
|
|
pictureBox.Invalidate();
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-22 05:24:01 +13:00
|
|
|
|
private void PictureBoxOpenFolder_Paint(object sender, PaintEventArgs e)
|
2021-06-26 23:24:56 +12:00
|
|
|
|
{
|
2021-06-27 21:35:07 +12:00
|
|
|
|
PictureBox pictureBox = (PictureBox)sender;
|
2021-06-26 23:24:56 +12:00
|
|
|
|
|
2021-11-22 05:24:01 +13:00
|
|
|
|
e.Graphics.DrawImage(AppColors.BitmapOpenFolder, new Rectangle(Point.Empty, pictureBox.ClientSize));
|
|
|
|
|
|
|
|
|
|
if (pictureBox.Tag != null && (bool)pictureBox.Tag)
|
|
|
|
|
{
|
|
|
|
|
Rectangle rowBounds = new(0, 0, pictureBox.Width, pictureBox.Height);
|
|
|
|
|
ControlPaint.DrawBorder(e.Graphics, rowBounds, MenuDefines.ColorSelectedItemBorder, ButtonBorderStyle.Solid);
|
|
|
|
|
}
|
2021-06-28 00:44:12 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-11-22 05:24:01 +13:00
|
|
|
|
private void PictureBoxOpenFolder_Click(object sender, MouseEventArgs e)
|
2021-06-28 00:44:12 +12:00
|
|
|
|
{
|
2021-11-22 05:24:01 +13:00
|
|
|
|
if (e.Button == MouseButtons.Left)
|
|
|
|
|
{
|
|
|
|
|
UserClickedOpenFolder?.Invoke();
|
|
|
|
|
}
|
2021-06-28 00:44:12 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-26 23:24:56 +12:00
|
|
|
|
private void PictureBoxMenuAlwaysOpen_Paint(object sender, PaintEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
PictureBox pictureBox = (PictureBox)sender;
|
|
|
|
|
|
|
|
|
|
if (Config.AlwaysOpenByPin)
|
|
|
|
|
{
|
2021-08-16 21:48:35 +12:00
|
|
|
|
e.Graphics.DrawImage(AppColors.BitmapPinActive, new Rectangle(Point.Empty, pictureBox.ClientSize));
|
2021-06-26 23:24:56 +12:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-08-16 21:48:35 +12:00
|
|
|
|
e.Graphics.DrawImage(AppColors.BitmapPin, new Rectangle(Point.Empty, pictureBox.ClientSize));
|
2021-06-26 23:24:56 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pictureBox.Tag != null && (bool)pictureBox.Tag)
|
|
|
|
|
{
|
2021-11-17 12:13:46 +13:00
|
|
|
|
Rectangle rowBounds = new(0, 0, pictureBox.Width, pictureBox.Height);
|
2021-06-26 23:24:56 +12:00
|
|
|
|
ControlPaint.DrawBorder(e.Graphics, rowBounds, MenuDefines.ColorSelectedItemBorder, ButtonBorderStyle.Solid);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-22 05:24:01 +13:00
|
|
|
|
private void PictureBoxMenuAlwaysOpen_Click(object sender, EventArgs e)
|
2021-10-04 07:24:22 +13:00
|
|
|
|
{
|
|
|
|
|
PictureBox pictureBox = (PictureBox)sender;
|
2021-11-22 05:24:01 +13:00
|
|
|
|
Config.AlwaysOpenByPin = !Config.AlwaysOpenByPin;
|
|
|
|
|
pictureBox.Invalidate();
|
2021-10-04 07:24:22 +13:00
|
|
|
|
}
|
|
|
|
|
|
2021-11-22 05:24:01 +13:00
|
|
|
|
private void PictureBoxSettings_Paint(object sender, PaintEventArgs e)
|
2021-06-26 23:24:56 +12:00
|
|
|
|
{
|
|
|
|
|
PictureBox pictureBox = (PictureBox)sender;
|
|
|
|
|
|
2021-11-22 05:24:01 +13:00
|
|
|
|
e.Graphics.DrawImage(AppColors.BitmapSettings, new Rectangle(Point.Empty, pictureBox.ClientSize));
|
2021-06-26 23:24:56 +12:00
|
|
|
|
|
|
|
|
|
if (pictureBox.Tag != null && (bool)pictureBox.Tag)
|
|
|
|
|
{
|
2021-11-17 12:13:46 +13:00
|
|
|
|
Rectangle rowBounds = new(0, 0, pictureBox.Width, pictureBox.Height);
|
2021-06-26 23:24:56 +12:00
|
|
|
|
ControlPaint.DrawBorder(e.Graphics, rowBounds, MenuDefines.ColorSelectedItemBorder, ButtonBorderStyle.Solid);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-22 05:24:01 +13:00
|
|
|
|
private void PictureBoxSettings_MouseClick(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (e.Button == MouseButtons.Left)
|
|
|
|
|
{
|
2022-01-10 02:17:00 +13:00
|
|
|
|
if (Properties.Settings.Default.CacheMainMenu)
|
|
|
|
|
{
|
|
|
|
|
SettingsForm.ShowSingleInstance(this);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SettingsForm.ShowSingleInstance(null);
|
|
|
|
|
}
|
2021-11-22 05:24:01 +13:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void PictureBoxRestart_Paint(object sender, PaintEventArgs e)
|
2021-06-26 23:24:56 +12:00
|
|
|
|
{
|
|
|
|
|
PictureBox pictureBox = (PictureBox)sender;
|
2021-11-22 05:24:01 +13:00
|
|
|
|
|
|
|
|
|
e.Graphics.DrawImage(AppColors.BitmapRestart, new Rectangle(Point.Empty, pictureBox.ClientSize));
|
|
|
|
|
|
|
|
|
|
if (pictureBox.Tag != null && (bool)pictureBox.Tag)
|
|
|
|
|
{
|
|
|
|
|
Rectangle rowBounds = new(0, 0, pictureBox.Width, pictureBox.Height);
|
|
|
|
|
ControlPaint.DrawBorder(e.Graphics, rowBounds, MenuDefines.ColorSelectedItemBorder, ButtonBorderStyle.Solid);
|
|
|
|
|
}
|
2021-06-26 23:24:56 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-11-22 05:24:01 +13:00
|
|
|
|
private void PictureBoxRestart_MouseClick(object sender, MouseEventArgs e)
|
2021-06-26 23:24:56 +12:00
|
|
|
|
{
|
|
|
|
|
if (e.Button == MouseButtons.Left)
|
|
|
|
|
{
|
2021-11-22 05:24:01 +13:00
|
|
|
|
AppRestart.ByMenuButton();
|
2021-06-26 23:24:56 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-09-24 08:53:46 +12:00
|
|
|
|
|
2021-11-22 05:24:01 +13:00
|
|
|
|
private void PictureBoxSearch_Paint(object sender, PaintEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
PictureBox pictureBox = (PictureBox)sender;
|
|
|
|
|
e.Graphics.DrawImage(AppColors.BitmapSearch, new Rectangle(Point.Empty, pictureBox.ClientSize));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void LoadingMenu_Paint(object sender, PaintEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
PictureBox pictureBox = (PictureBox)sender;
|
|
|
|
|
rotationAngle += 5;
|
|
|
|
|
e.Graphics.DrawImage(
|
|
|
|
|
ImagingHelper.RotateImage(Resources.StaticResources.LoadingIcon.ToBitmap(), rotationAngle),
|
|
|
|
|
new Rectangle(Point.Empty, new Size(pictureBox.ClientSize.Width - 2, pictureBox.ClientSize.Height - 2)));
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-24 08:53:46 +12:00
|
|
|
|
private void TimerUpdateIcons_Tick(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
int iconsToUpdate = 0;
|
|
|
|
|
|
|
|
|
|
foreach (DataGridViewRow row in dgv.Rows)
|
|
|
|
|
{
|
|
|
|
|
RowData rowData = (RowData)row.Cells[2].Value;
|
|
|
|
|
rowData.RowIndex = row.Index;
|
|
|
|
|
|
|
|
|
|
if (rowData.IconLoading)
|
|
|
|
|
{
|
|
|
|
|
iconsToUpdate++;
|
2021-09-25 01:37:58 +12:00
|
|
|
|
row.Cells[0].Value = rowData.ReadLoadedIcon();
|
2021-09-24 08:53:46 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (iconsToUpdate < 1)
|
|
|
|
|
{
|
|
|
|
|
timerUpdateIcons.Stop();
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-11-25 07:01:59 +13:00
|
|
|
|
|
|
|
|
|
private void Menu_MouseDown(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
2021-12-10 08:00:33 +13:00
|
|
|
|
if (Level == 0)
|
|
|
|
|
{
|
|
|
|
|
mouseDown = true;
|
|
|
|
|
lastLocation = e.Location;
|
|
|
|
|
UserDragsMenu.Invoke();
|
|
|
|
|
}
|
2021-11-25 07:01:59 +13:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Menu_MouseMove(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (mouseDown)
|
|
|
|
|
{
|
|
|
|
|
Location = new Point(
|
|
|
|
|
Location.X - lastLocation.X + e.X,
|
|
|
|
|
Location.Y - lastLocation.Y + e.Y);
|
|
|
|
|
|
|
|
|
|
Properties.Settings.Default.CustomLocationX = Location.X;
|
|
|
|
|
Properties.Settings.Default.CustomLocationY = Location.Y;
|
|
|
|
|
|
|
|
|
|
Update();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Menu_MouseUp(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
mouseDown = false;
|
2021-12-27 18:31:23 +13:00
|
|
|
|
if (Properties.Settings.Default.UseCustomLocation)
|
|
|
|
|
{
|
|
|
|
|
if (!SettingsForm.IsOpen())
|
|
|
|
|
{
|
|
|
|
|
Properties.Settings.Default.Save();
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-11-25 07:01:59 +13:00
|
|
|
|
}
|
2020-06-08 00:28:59 +12:00
|
|
|
|
}
|
2019-07-05 05:04:14 +12:00
|
|
|
|
}
|