mirror of
https://github.com/Hofknecht/SystemTrayMenu.git
synced 2024-06-02 10:34:42 +12:00
Merge pull request #136 from Hofknecht/feature/taskbar_orientation
Feature/taskbar orientation
This commit is contained in:
commit
cbdef123ba
|
@ -27,11 +27,6 @@ namespace SystemTrayMenu.Business
|
|||
private readonly BackgroundWorker workerMainMenu = new BackgroundWorker();
|
||||
private readonly List<BackgroundWorker> workersSubMenu = new List<BackgroundWorker>();
|
||||
|
||||
private readonly int screenHeight = Screen.PrimaryScreen.Bounds.Height;
|
||||
private readonly int screenWidth = Screen.PrimaryScreen.Bounds.Width;
|
||||
private readonly int screenRight = Screen.PrimaryScreen.Bounds.Right;
|
||||
private readonly int taskbarHeight = new WindowsTaskbar().Size.Height;
|
||||
|
||||
private readonly DgvMouseRow dgvMouseRow = new DgvMouseRow();
|
||||
private readonly WaitToLoadMenu waitToOpenMenu = new WaitToLoadMenu();
|
||||
private readonly KeyboardInput keyboardInput = null;
|
||||
|
@ -41,6 +36,7 @@ namespace SystemTrayMenu.Business
|
|||
private OpenCloseState openCloseState = OpenCloseState.Default;
|
||||
private RowData loadingRowData = null;
|
||||
private bool showingMessageBox = false;
|
||||
private TaskbarPosition taskbarPosition = new WindowsTaskbar().Position;
|
||||
|
||||
public Menus()
|
||||
{
|
||||
|
@ -513,7 +509,7 @@ namespace SystemTrayMenu.Business
|
|||
menus[0] = Create(
|
||||
GetData(workerMainMenu, Config.Path, 0),
|
||||
Path.GetFileName(Config.Path));
|
||||
menus[0].AdjustSizeAndLocation(screenHeight, screenRight, taskbarHeight);
|
||||
AdjustMenusSizeAndLocation();
|
||||
DisposeMenu(menus[0]);
|
||||
}
|
||||
|
||||
|
@ -859,34 +855,66 @@ namespace SystemTrayMenu.Business
|
|||
|
||||
private void AdjustMenusSizeAndLocation()
|
||||
{
|
||||
Menu menuPredecessor = menus[0];
|
||||
int widthPredecessors = -1; // -1 padding
|
||||
bool directionToRight = false;
|
||||
WindowsTaskbar taskbar = new WindowsTaskbar();
|
||||
Menu menuPredecessor = null;
|
||||
List<Menu> list = AsList;
|
||||
Menu menu;
|
||||
Rectangle screenBounds = Screen.PrimaryScreen.Bounds;
|
||||
Menu.StartLocation startLocation;
|
||||
|
||||
menus[0].AdjustSizeAndLocation(screenHeight, screenRight, taskbarHeight);
|
||||
// Only apply taskbar position change when no menu is currently open
|
||||
if (list.Count == 1)
|
||||
{
|
||||
taskbarPosition = taskbar.Position;
|
||||
}
|
||||
|
||||
foreach (Menu menu in AsEnumerable.Where(m => m.Level > 0))
|
||||
// Shrink the usable space depending on taskbar location
|
||||
switch (taskbarPosition)
|
||||
{
|
||||
case TaskbarPosition.Left:
|
||||
screenBounds.X += taskbar.Size.Width;
|
||||
screenBounds.Width -= taskbar.Size.Width;
|
||||
startLocation = Menu.StartLocation.BottomLeft;
|
||||
break;
|
||||
case TaskbarPosition.Right:
|
||||
screenBounds.Width -= taskbar.Size.Width;
|
||||
startLocation = Menu.StartLocation.BottomRight;
|
||||
break;
|
||||
case TaskbarPosition.Top:
|
||||
screenBounds.Y += taskbar.Size.Height;
|
||||
screenBounds.Height -= taskbar.Size.Height;
|
||||
startLocation = Menu.StartLocation.TopRight;
|
||||
break;
|
||||
case TaskbarPosition.Bottom:
|
||||
default:
|
||||
screenBounds.Height -= taskbar.Size.Height;
|
||||
startLocation = Menu.StartLocation.BottomRight;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
int newWith = menu.Width - menu.Padding.Horizontal + menuPredecessor.Width;
|
||||
if (directionToRight)
|
||||
menu = list[i];
|
||||
|
||||
// Only last one has to be updated as all previous one were already updated in the past
|
||||
if (list.Count - 1 == i)
|
||||
{
|
||||
if (widthPredecessors - menus[0].Width - menu.Width < 0)
|
||||
{
|
||||
directionToRight = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
widthPredecessors -= newWith;
|
||||
}
|
||||
}
|
||||
else if (screenWidth < widthPredecessors + menus[0].Width + menu.Width)
|
||||
{
|
||||
directionToRight = true;
|
||||
widthPredecessors -= newWith;
|
||||
menu.AdjustSizeAndLocation(screenBounds, menuPredecessor, startLocation);
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
const int overlapTolerance = 4;
|
||||
|
||||
// Remember width of the initial menu as we don't want to overlap with it
|
||||
if (taskbarPosition == TaskbarPosition.Left)
|
||||
{
|
||||
screenBounds.X += menu.Width - overlapTolerance;
|
||||
}
|
||||
|
||||
screenBounds.Width -= menu.Width - overlapTolerance;
|
||||
}
|
||||
|
||||
menu.AdjustSizeAndLocation(screenHeight, screenRight, taskbarHeight, menuPredecessor, directionToRight);
|
||||
widthPredecessors += menu.Width - menu.Padding.Left;
|
||||
menuPredecessor = menu;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,5 +39,5 @@ using System.Runtime.InteropServices;
|
|||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.15.1")]
|
||||
[assembly: AssemblyFileVersion("1.0.15.1")]
|
||||
[assembly: AssemblyVersion("1.0.16.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.16.0")]
|
||||
|
|
|
@ -154,6 +154,24 @@ namespace SystemTrayMenu.Properties
|
|||
SaveValuesToFile();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an empty user.config file...looks like the one MS creates.
|
||||
/// This could be overkill a simple key/value pairing would probably do.
|
||||
/// </summary>
|
||||
private static void CreateEmptyConfig()
|
||||
{
|
||||
var doc = new XDocument();
|
||||
var declaration = new XDeclaration("1.0", "utf-8", "true");
|
||||
var config = new XElement(Config);
|
||||
var userSettings = new XElement(UserSettings);
|
||||
var group = new XElement(typeof(Properties.Settings).FullName);
|
||||
userSettings.Add(group);
|
||||
config.Add(userSettings);
|
||||
doc.Add(config);
|
||||
doc.Declaration = declaration;
|
||||
doc.Save(UserConfigPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the values of the file into memory.
|
||||
/// </summary>
|
||||
|
@ -185,24 +203,6 @@ namespace SystemTrayMenu.Properties
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an empty user.config file...looks like the one MS creates.
|
||||
/// This could be overkill a simple key/value pairing would probably do.
|
||||
/// </summary>
|
||||
private void CreateEmptyConfig()
|
||||
{
|
||||
var doc = new XDocument();
|
||||
var declaration = new XDeclaration("1.0", "utf-8", "true");
|
||||
var config = new XElement(Config);
|
||||
var userSettings = new XElement(UserSettings);
|
||||
var group = new XElement(typeof(Properties.Settings).FullName);
|
||||
userSettings.Add(group);
|
||||
config.Add(userSettings);
|
||||
doc.Add(config);
|
||||
doc.Declaration = declaration;
|
||||
doc.Save(UserConfigPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the in memory dictionary to the user config file.
|
||||
/// </summary>
|
||||
|
|
|
@ -94,14 +94,14 @@ namespace SystemTrayMenu.Helper
|
|||
AppMoreInfo = versionInfo.LegalCopyright,
|
||||
};
|
||||
ab.AppMoreInfo += Environment.NewLine;
|
||||
ab.AppMoreInfo += "Markus Hofknecht (mailto:Markus@Hofknecht.eu)";
|
||||
ab.AppMoreInfo += Environment.NewLine;
|
||||
ab.AppMoreInfo += "Tanja Kauth (mailto:Tanja@Hofknecht.eu)";
|
||||
ab.AppMoreInfo += Environment.NewLine;
|
||||
ab.AppMoreInfo += "http://www.hofknecht.eu/systemtraymenu/";
|
||||
ab.AppMoreInfo += Environment.NewLine;
|
||||
ab.AppMoreInfo += "https://github.com/Hofknecht/SystemTrayMenu";
|
||||
ab.AppMoreInfo += Environment.NewLine;
|
||||
ab.AppMoreInfo += "Markus Hofknecht (mailto:Markus@Hofknecht.eu)" + Environment.NewLine;
|
||||
ab.AppMoreInfo += "Tanja Kauth (mailto:Tanja@Hofknecht.eu)" + Environment.NewLine;
|
||||
|
||||
// Thanks for letting me being part of this project and that I am allowed to be listed here :-)
|
||||
ab.AppMoreInfo += "Peter Kirmeier (mai" + "lto:top" + "ete" + "rk@f" + "reen" + "et." + "de)" + Environment.NewLine;
|
||||
|
||||
ab.AppMoreInfo += "http://www.hofknecht.eu/systemtraymenu/" + Environment.NewLine;
|
||||
ab.AppMoreInfo += "https://github.com/Hofknecht/SystemTrayMenu" + Environment.NewLine;
|
||||
ab.AppMoreInfo += Environment.NewLine;
|
||||
ab.AppMoreInfo += "GNU GENERAL PUBLIC LICENSE" + Environment.NewLine;
|
||||
ab.AppMoreInfo += "(Version 3, 29 June 2007)" + Environment.NewLine;
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
{
|
||||
private readonly Fading fading = new Fading();
|
||||
private bool isShowing = false;
|
||||
private bool directionToRight = false;
|
||||
|
||||
internal Menu()
|
||||
{
|
||||
|
@ -149,6 +150,14 @@ namespace SystemTrayMenu.UserInterface
|
|||
MaxReached,
|
||||
}
|
||||
|
||||
internal enum StartLocation
|
||||
{
|
||||
Predecessor,
|
||||
BottomLeft,
|
||||
BottomRight,
|
||||
TopRight,
|
||||
}
|
||||
|
||||
internal int Level { get; set; } = 0;
|
||||
|
||||
internal bool IsUsable => Visible && !fading.IsHiding &&
|
||||
|
@ -278,122 +287,107 @@ namespace SystemTrayMenu.UserInterface
|
|||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
internal void AdjustSizeAndLocation(
|
||||
int screenHeight,
|
||||
int screenRight,
|
||||
int taskbarHeight,
|
||||
Menu menuPredecessor = null,
|
||||
bool directionToRight = false)
|
||||
Rectangle bounds,
|
||||
Menu menuPredecessor,
|
||||
StartLocation startLocation)
|
||||
{
|
||||
CheckForAutoResizeRowDone();
|
||||
void CheckForAutoResizeRowDone()
|
||||
if (menuPredecessor != null)
|
||||
{
|
||||
double factor = 1;
|
||||
if (NativeMethods.IsTouchEnabled())
|
||||
{
|
||||
factor = 1.5;
|
||||
}
|
||||
|
||||
if (menuPredecessor == null)
|
||||
{
|
||||
if (dgv.Tag == null && dgv.Rows.Count > 0)
|
||||
{
|
||||
dgv.AutoResizeRows();
|
||||
dgv.RowTemplate.Height = (int)(dgv.Rows[0].Height * factor);
|
||||
foreach (DataGridViewRow row in dgv.Rows)
|
||||
{
|
||||
row.Height = dgv.RowTemplate.Height;
|
||||
}
|
||||
|
||||
dgv.Tag = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dgv.RowTemplate.Height = menuPredecessor.GetDataGridView().
|
||||
RowTemplate.Height;
|
||||
foreach (DataGridViewRow row in dgv.Rows)
|
||||
{
|
||||
row.Height = dgv.RowTemplate.Height;
|
||||
}
|
||||
|
||||
dgv.Tag = true;
|
||||
}
|
||||
}
|
||||
|
||||
int dgvHeightNeeded = dgv.Rows.GetRowsHeight(
|
||||
DataGridViewElementStates.None);
|
||||
int menuRestNeeded = Height - dgv.Height;
|
||||
|
||||
int dgvHeightMax = screenHeight - taskbarHeight -
|
||||
menuRestNeeded;
|
||||
|
||||
if (dgvHeightNeeded > dgvHeightMax)
|
||||
{
|
||||
dgvHeightNeeded = dgvHeightMax;
|
||||
}
|
||||
|
||||
DataTable data = (DataTable)dgv.DataSource;
|
||||
if (string.IsNullOrEmpty(data.DefaultView.RowFilter))
|
||||
{
|
||||
dgv.Height = dgvHeightNeeded;
|
||||
// Ignore start as we use predecessor
|
||||
startLocation = StartLocation.Predecessor;
|
||||
}
|
||||
|
||||
// Update the height and width
|
||||
AdjustDataGridViewHeight(menuPredecessor, bounds.Height);
|
||||
AdjustDataGridViewWidth();
|
||||
|
||||
// Calculate X position
|
||||
int x;
|
||||
if (menuPredecessor == null)
|
||||
switch (startLocation)
|
||||
{
|
||||
x = screenRight - Width;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (directionToRight)
|
||||
{
|
||||
x = menuPredecessor.Location.X +
|
||||
menuPredecessor.Width -
|
||||
(int)Math.Round(Scaling.Factor, 0, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = menuPredecessor.Location.X -
|
||||
Width +
|
||||
(int)Math.Round(Scaling.Factor, 0, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
}
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
x += menuPredecessor.Width;
|
||||
x += Width;
|
||||
case StartLocation.Predecessor:
|
||||
int scaling = (int)Math.Round(Scaling.Factor, 0, MidpointRounding.AwayFromZero);
|
||||
directionToRight = menuPredecessor.directionToRight; // try keeping same direction
|
||||
if (directionToRight)
|
||||
{
|
||||
x = menuPredecessor.Location.X + menuPredecessor.Width - scaling;
|
||||
|
||||
// Change direction when out of bounds
|
||||
if (bounds.X + bounds.Width <= x + Width - scaling)
|
||||
{
|
||||
x = menuPredecessor.Location.X - Width + scaling;
|
||||
directionToRight = !directionToRight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x = menuPredecessor.Location.X - Width + scaling;
|
||||
|
||||
// Change direction when out of bounds
|
||||
if (x < bounds.X)
|
||||
{
|
||||
x = menuPredecessor.Location.X + menuPredecessor.Width - scaling;
|
||||
directionToRight = !directionToRight;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case StartLocation.BottomLeft:
|
||||
x = bounds.X;
|
||||
directionToRight = true;
|
||||
break;
|
||||
case StartLocation.TopRight:
|
||||
case StartLocation.BottomRight:
|
||||
default:
|
||||
x = bounds.Width - Width;
|
||||
directionToRight = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate Y position
|
||||
int y;
|
||||
if (menuPredecessor == null)
|
||||
switch (startLocation)
|
||||
{
|
||||
y = screenHeight - taskbarHeight - Height;
|
||||
}
|
||||
else
|
||||
{
|
||||
RowData trigger = (RowData)Tag;
|
||||
DataGridView dgv = menuPredecessor.GetDataGridView();
|
||||
int distanceFromItemToDgvTop = 0;
|
||||
if (dgv.Rows.Count > trigger.RowIndex)
|
||||
{
|
||||
Rectangle cellRectangle = dgv.GetCellDisplayRectangle(
|
||||
0, trigger.RowIndex, false);
|
||||
distanceFromItemToDgvTop = cellRectangle.Top;
|
||||
}
|
||||
case StartLocation.Predecessor:
|
||||
RowData trigger = (RowData)Tag;
|
||||
DataGridView dgv = menuPredecessor.GetDataGridView();
|
||||
int distanceFromItemToDgvTop = 0;
|
||||
|
||||
y = menuPredecessor.Location.Y +
|
||||
menuPredecessor.dgv.Location.Y +
|
||||
distanceFromItemToDgvTop;
|
||||
if ((y + Height - tableLayoutPanelSearch.Height) > dgvHeightMax)
|
||||
{
|
||||
y = dgvHeightMax - Height + menuRestNeeded;
|
||||
}
|
||||
// Get offset of selected row from predecessor
|
||||
if (dgv.Rows.Count > trigger.RowIndex)
|
||||
{
|
||||
Rectangle cellRectangle = dgv.GetCellDisplayRectangle(0, trigger.RowIndex, false);
|
||||
distanceFromItemToDgvTop = cellRectangle.Top;
|
||||
}
|
||||
|
||||
// Set position on same height as the selected row from predecessor
|
||||
y = menuPredecessor.Location.Y + menuPredecessor.dgv.Location.Y + distanceFromItemToDgvTop;
|
||||
|
||||
// Move vertically when out of bounds
|
||||
if (bounds.Height < y + Height)
|
||||
{
|
||||
y = bounds.Y + bounds.Height - Height;
|
||||
}
|
||||
|
||||
break;
|
||||
case StartLocation.TopRight:
|
||||
y = bounds.Y;
|
||||
break;
|
||||
case StartLocation.BottomLeft:
|
||||
case StartLocation.BottomRight:
|
||||
default:
|
||||
y = bounds.Height - Height;
|
||||
break;
|
||||
}
|
||||
|
||||
// Update position
|
||||
Location = new Point(x, y);
|
||||
}
|
||||
|
||||
|
@ -439,6 +433,52 @@ namespace SystemTrayMenu.UserInterface
|
|||
CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
private void AdjustDataGridViewHeight(Menu menuPredecessor, int screenHeightMax)
|
||||
{
|
||||
double factor = 1;
|
||||
if (NativeMethods.IsTouchEnabled())
|
||||
{
|
||||
factor = 1.5;
|
||||
}
|
||||
|
||||
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;
|
||||
if (string.IsNullOrEmpty(data.DefaultView.RowFilter))
|
||||
{
|
||||
int dgvHeight = dgv.Rows.GetRowsHeight(DataGridViewElementStates.None); // Height of all rows
|
||||
int dgvHeightMax = screenHeightMax - (Height - dgv.Height); // except dgv
|
||||
if (dgvHeight > dgvHeightMax)
|
||||
{
|
||||
// Make all rows fit into the screen
|
||||
dgvHeight = dgvHeightMax;
|
||||
}
|
||||
|
||||
dgv.Height = dgvHeight;
|
||||
}
|
||||
}
|
||||
|
||||
private void AdjustDataGridViewWidth()
|
||||
{
|
||||
DataGridViewExtensions.FastAutoSizeColumns(dgv);
|
||||
|
|
Loading…
Reference in a new issue