using System.Collections.Generic;
using System.Windows.Forms.RibbonHelpers;
namespace System.Windows.Forms
{
///
/// Manages opened popups
///
public static class RibbonPopupManager
{
#region Subclasses
///
/// Specifies reasons why pop-ups can be dismissed
///
public enum DismissReason
{
///
/// An item has been clicked
///
ItemClicked,
///
/// The app has been clicked
///
AppClicked,
///
/// A new popup is showing and will hide sibling's popups
///
NewPopup,
///
/// The aplication window has been deactivated
///
AppFocusChanged,
///
/// User has pressed escape on the keyboard
///
EscapePressed
}
#endregion
#region Events
public static event EventHandler PopupRegistered;
public static event EventHandler PopupUnRegistered;
#endregion
#region Fields
private static readonly List pops;
#endregion
#region Ctor
static RibbonPopupManager()
{
pops = new List();
}
#endregion
#region Props
///
/// Gets the last pop-up of the collection
///
internal static RibbonPopup LastPopup
{
get
{
if (pops.Count > 0)
{
return pops[pops.Count - 1];
}
return null;
}
}
internal static int PopupCount => pops.Count;
#endregion
#region Methods
///
/// Registers a popup existance
///
///
internal static void Register(RibbonPopup p)
{
if (!pops.Contains(p))
{
pops.Add(p);
PopupRegistered(p, EventArgs.Empty);
}
}
///
/// Unregisters a popup from existance
///
///
internal static void Unregister(RibbonPopup p)
{
if (pops.Contains(p))
{
pops.Remove(p);
PopupUnRegistered(p, EventArgs.Empty);
}
}
///
/// Feeds a click generated on the mouse hook
///
///
internal static bool FeedHookClick(MouseEventArgs e)
{
//Al-74 fix (see GitHub issue #10):
//Starting from Windows 10 April 2018 Update (version 1803) with display scaling above 100%, e.Location is the physical mouse location,
//not scaled according to display scaling, so the Contains function fails check and no events fires when clicking RibbonButtons dropdown items.
//Use GetCursorPos api instead of e.Location seems to solve the problem.
WinApi.POINT pos;
if (WinApi.GetCursorPos(out pos))
{
foreach (RibbonPopup p in pops)
{
if (p.WrappedDropDown.Bounds.Contains(pos.x, pos.y))
//if (p.WrappedDropDown.Bounds.Contains(e.Location))
{
return true;
}
}
}
//If click was in no dropdown, let's go everyone
Dismiss(DismissReason.AppClicked);
return false;
}
///
/// Feeds mouse Wheel. If applied on a IScrollableItem it's sended to it
///
///
/// True if handled. False otherwise
internal static bool FeedMouseWheel(MouseEventArgs e)
{
RibbonDropDown dd = LastPopup as RibbonDropDown;
if (dd != null)
{
WinApi.POINT pos;
if (WinApi.GetCursorPos(out pos))
{
foreach (RibbonItem item in dd.Items)
{
if (dd.RectangleToScreen(item.Bounds).Contains(pos.x, pos.y))
//if (dd.RectangleToScreen(item.Bounds).Contains(e.Location))
{
IScrollableRibbonItem sc = item as IScrollableRibbonItem;
if (sc != null)
{
if (e.Delta < 0)
{
sc.ScrollDown();
}
else
{
sc.ScrollUp();
}
return true;
}
}
}
}
}
//kevin carbis - added scrollbar support to dropdowns so we need to feed the mouse wheel to the
//actual dropdown item if it was not intended for a child item.
if (dd != null)
{
if (e.Delta < 0)
{
dd.ScrollDown();
}
else
{
dd.ScrollUp();
}
return true;
}
return false;
}
///
/// Closes all children of specified pop-up
///
/// Pop-up of which children will be closed
/// Reason for dismissing
public static void DismissChildren(RibbonPopup parent, DismissReason reason)
{
int index = pops.IndexOf(parent);
if (index >= 0)
{
Dismiss(index + 1, reason);
}
}
///
/// Closes all currently registered pop-ups
///
///
public static void Dismiss(DismissReason reason)
{
Dismiss(0, reason);
}
///
/// Closes specified pop-up and all its descendants
///
/// Pop-up to close (and its descendants)
/// Reason for closing
public static void Dismiss(RibbonPopup startPopup, DismissReason reason)
{
int index = pops.IndexOf(startPopup);
if (index >= 0)
{
Dismiss(index, reason);
}
}
///
/// Closes pop-up of the specified index and all its descendants
///
/// Index of the pop-up to close
/// Reason for closing
private static void Dismiss(int startPopup, DismissReason reason)
{
for (int i = pops.Count - 1; i >= startPopup; i--)
{
pops[i].Close();
}
}
#endregion
}
}