// *********************************
// Message from Original Author:
//
// 2008 Jose Menendez Poo
// Please give me credit if you use this code. It's all I ask.
// Contact me for more info: menendezpoo@gmail.com
// *********************************
//
// Original project from http://ribbon.codeplex.com/
// Continue to support and maintain by http://officeribbon.codeplex.com/
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms.Design;
using System.Windows.Forms.Design.Behavior;
using System.Windows.Forms.RibbonHelpers;
namespace System.Windows.Forms
{
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
public class RibbonDesigner
: ControlDesigner
{
#region Static
internal static RibbonDesigner Current;
#endregion
#region Fields
private IRibbonElement _selectedElement;
private Adorner _quickAccessAdorner;
private Adorner _orbAdorner;
private Adorner _tabAdorner;
#endregion
#region Ctor
public RibbonDesigner()
{
Current = this;
}
///
/// Clean up any resources being used.
///
/// true if managed resources should be disposed; otherwise, false.
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (Current == this)
{
Current = null;
}
}
//Finalize is called by base class "System.ComponentModel.Design.ComponentDesigner"
#endregion
#region Properties
///
/// Gets or sets the currently selected RibbonElement
///
public IRibbonElement SelectedElement
{
get => _selectedElement;
set
{
if (Ribbon == null) return;
_selectedElement = value;
if (GetService(typeof(ISelectionService)) is ISelectionService selector && value != null)
selector.SetSelectedComponents(new[] { value as Component }, SelectionTypes.Primary);
if (value is RibbonButton button)
{
button.ShowDropDown();
}
Ribbon.Refresh();
}
}
///
/// Gets the Ribbon of the designer
///
public Ribbon Ribbon => Control as Ribbon;
#endregion
#region Methods
public virtual void CreateItem(Ribbon ribbon, RibbonItemCollection collection, Type t)
{
if (GetService(typeof(IDesignerHost)) is IDesignerHost host && collection != null && ribbon != null)
{
DesignerTransaction transaction = host.CreateTransaction("AddRibbonItem_" + Component.Site.Name);
MemberDescriptor member = TypeDescriptor.GetProperties(Component)["Items"];
RaiseComponentChanging(member);
RibbonItem item = host.CreateComponent(t) as RibbonItem;
if (!(item is RibbonSeparator)) item.Text = item.Site.Name;
collection.Add(item);
ribbon.OnRegionsChanged();
RaiseComponentChanged(member, null, null);
transaction.Commit();
}
}
private void CreateOrbItem(string collectionName, RibbonItemCollection collection, Type t)
{
if (Ribbon == null) return;
IDesignerHost host = GetService(typeof(IDesignerHost)) as IDesignerHost;
DesignerTransaction transaction = host.CreateTransaction("AddRibbonOrbItem_" + Component.Site.Name);
MemberDescriptor member = TypeDescriptor.GetProperties(Ribbon.OrbDropDown)[collectionName];
RaiseComponentChanging(member);
RibbonItem item = host.CreateComponent(t) as RibbonItem;
if (!(item is RibbonSeparator)) item.Text = item.Site.Name;
collection.Add(item);
Ribbon.OrbDropDown.OnRegionsChanged();
RaiseComponentChanged(member, null, null);
transaction.Commit();
Ribbon.OrbDropDown.SelectOnDesigner(item);
Ribbon.OrbDropDown.WrappedDropDown.Size = Ribbon.OrbDropDown.Size;
}
///
/// Creates an Orb's MenuItem
///
///
public void CreateOrbMenuItem(Type t)
{
CreateOrbItem("MenuItems", Ribbon.OrbDropDown.MenuItems, t);
}
///
/// Creates an Orb's RecentItem
///
///
public void CreateOrbRecentItem(Type t)
{
CreateOrbItem("RecentItems", Ribbon.OrbDropDown.RecentItems, t);
}
///
/// Creates an Orb's OptionItem
///
///
public void CreateOrbOptionItem(Type t)
{
CreateOrbItem("OptionItems", Ribbon.OrbDropDown.OptionItems, t);
}
private void AssignEventHandler()
{
//TODO: Didn't work
//if (SelectedElement == null) return;
//IEventBindingService binder = GetService(typeof(IEventBindingService)) as IEventBindingService;
//EventDescriptorCollection evts = TypeDescriptor.GetEvents(SelectedElement);
////string id = binder.CreateUniqueMethodName(SelectedElement as Component, evts["Click"]);
//binder.ShowCode(SelectedElement as Component, evts["Click"]);
}
private void SelectRibbon()
{
if (GetService(typeof(ISelectionService)) is ISelectionService selector)
selector.SetSelectedComponents(new Component[] { Ribbon }, SelectionTypes.Primary);
}
public override DesignerVerbCollection Verbs
{
get
{
DesignerVerbCollection verbs = new DesignerVerbCollection();
verbs.Add(new DesignerVerb("Add Tab", AddTabVerb));
verbs.Add(new DesignerVerb("Add Context", AddContextVerb));
return verbs;
}
}
public void AddTabVerb(object sender, EventArgs e)
{
if (Control is Ribbon r)
{
IDesignerHost host = GetService(typeof(IDesignerHost)) as IDesignerHost;
RibbonTab tab = host?.CreateComponent(typeof(RibbonTab)) as RibbonTab;
if (tab == null) return;
tab.Text = tab.Site.Name;
Ribbon.Tabs.Add(tab);
r.Refresh();
}
}
public void AddContextVerb(object sender, EventArgs e)
{
if (Control is Ribbon r)
{
IDesignerHost host = GetService(typeof(IDesignerHost)) as IDesignerHost;
RibbonContext context = host?.CreateComponent(typeof(RibbonContext)) as RibbonContext;
if (context == null) return;
context.Text = context.Site.Name;
Random rnd1 = new Random();
context.GlowColor = Color.FromArgb(rnd1.Next(155, 255), rnd1.Next(155, 255), rnd1.Next(155, 255));
Ribbon.Contexts.Add(context);
r.Refresh();
}
}
protected override void WndProc(ref Message m)
{
if (m.HWnd == Control.Handle)
{
switch (m.Msg)
{
case 0x203: //WM_LBUTTONDBLCLK
AssignEventHandler();
break;
case 0x201: //WM_LBUTTONDOWN
case 0x204: //WM_RBUTTONDOWN
return;
case 0x202: //WM_LBUTTONUP
case 0x205: //WM_RBUTTONUP
HitOn(WinApi.LoWord((int)m.LParam), WinApi.HiWord((int)m.LParam));
return;
default:
break;
}
}
base.WndProc(ref m);
}
private void HitOn(int x, int y)
{
if (Ribbon.Tabs.Count == 0 || Ribbon.ActiveTab == null)
{
SelectRibbon();
return;
}
if (Ribbon != null)
{
if (Ribbon.TabHitTest(x, y))
{
SelectedElement = Ribbon.ActiveTab;
}
else if (Ribbon.ContextHitTest(x, y))
{
foreach (RibbonContext context in Ribbon.Contexts)
{
if (context.Bounds.Contains(x, y))
{
SelectedElement = context;
break;
}
}
}
else
{
#region Tab ScrollTest
if (Ribbon.ActiveTab.TabContentBounds.Contains(x, y))
{
if (Ribbon.ActiveTab.ScrollLeftBounds.Contains(x, y) && Ribbon.ActiveTab.ScrollLeftVisible)
{
Ribbon.ActiveTab.ScrollLeft();
SelectedElement = Ribbon.ActiveTab;
return;
}
if (Ribbon.ActiveTab.ScrollRightBounds.Contains(x, y) && Ribbon.ActiveTab.ScrollRightVisible)
{
Ribbon.ActiveTab.ScrollRight();
SelectedElement = Ribbon.ActiveTab;
return;
}
}
#endregion
//Check Panel
if (Ribbon.ActiveTab.TabContentBounds.Contains(x, y))
{
RibbonPanel hittedPanel = null;
foreach (RibbonPanel panel in Ribbon.ActiveTab.Panels)
if (panel.Bounds.Contains(x, y))
{
hittedPanel = panel;
break;
}
if (hittedPanel != null)
{
//Check item
RibbonItem hittedItem = null;
foreach (RibbonItem item in hittedPanel.Items)
if (item.Bounds.Contains(x, y))
{
hittedItem = item;
break;
}
if (hittedItem != null && hittedItem is IContainsSelectableRibbonItems)
{
//Check subitem
RibbonItem hittedSubItem = null;
foreach (RibbonItem subItem in (hittedItem as IContainsSelectableRibbonItems).GetItems())
if (subItem.Bounds.Contains(x, y))
{
hittedSubItem = subItem;
break;
}
if (hittedSubItem != null)
{
SelectedElement = hittedSubItem;
}
else
{
SelectedElement = hittedItem;
}
}
else if (hittedItem != null)
{
SelectedElement = hittedItem;
}
else
{
SelectedElement = hittedPanel;
}
}
else
{
SelectedElement = Ribbon.ActiveTab;
}
}
else if (Ribbon.QuickAccessToolbar.SuperBounds.Contains(x, y))
{
bool itemHitted = false;
foreach (RibbonItem item in Ribbon.QuickAccessToolbar.Items)
{
if (item.Bounds.Contains(x, y))
{
itemHitted = true;
SelectedElement = item;
break;
}
}
if (!itemHitted)
SelectedElement = Ribbon.QuickAccessToolbar;
}
else if (Ribbon.OrbBounds.Contains(x, y))
{
Ribbon.OrbMouseDown();
}
else
{
SelectRibbon();
Ribbon.ForceOrbMenu = false;
if (Ribbon.OrbDropDown.Visible) Ribbon.OrbDropDown.Close();
}
}
}
}
protected override void OnPaintAdornments(PaintEventArgs pe)
{
base.OnPaintAdornments(pe);
using (Pen p = new Pen(Color.Black))
{
p.DashStyle = DashStyle.Dot;
if (GetService(typeof(ISelectionService)) is ISelectionService host)
{
foreach (IComponent comp in host.GetSelectedComponents())
{
if (comp is RibbonContext)
{
if (comp is RibbonContext item)
{
Rectangle selection = (item.ContextualTabsCount > 0) ? item.HeaderBounds : item.Bounds;
selection.Inflate(-1, -1);
pe.Graphics.DrawRectangle(p, selection);
}
}
else if (comp is RibbonTab)
{
if (comp is RibbonTab item)
{
Rectangle selection = item.Bounds;
selection.Inflate(-1, -1);
pe.Graphics.DrawRectangle(p, selection);
}
}
else if (comp is RibbonPanel)
{
if (comp is RibbonPanel item)
{
Rectangle selection = item.Bounds;
selection.Inflate(-1, -1);
pe.Graphics.DrawRectangle(p, selection);
}
}
else if (comp is RibbonItem)
{
if (comp is RibbonItem item && !Ribbon.OrbDropDown.AllItems.Contains(item))
{
Rectangle selection = item.Bounds;
selection.Inflate(1, 1);
pe.Graphics.DrawRectangle(p, selection);
}
}
}
}
}
}
#endregion
#region Site
public BehaviorService GetBehaviorService()
{
return BehaviorService;
}
public override void Initialize(IComponent component)
{
base.Initialize(component);
IComponentChangeService changeService = GetService(typeof(IComponentChangeService)) as IComponentChangeService;
IDesignerEventService desigerEvt = GetService(typeof(IDesignerEventService)) as IDesignerEventService;
if (changeService != null) changeService.ComponentRemoved += changeService_ComponentRemoved;
_orbAdorner = new Adorner();
_tabAdorner = new Adorner();
if (BehaviorService != null)
{
BehaviorService.Adorners.AddRange(new[] { _orbAdorner, _tabAdorner });
if (Ribbon.QuickAccessToolbar.Visible)
{
_quickAccessAdorner = new Adorner();
BehaviorService.Adorners.Add(_quickAccessAdorner);
_quickAccessAdorner.Glyphs.Add(new RibbonQuickAccessToolbarGlyph(BehaviorService, this, Ribbon));
}
else
{
_quickAccessAdorner = null;
}
//orbAdorner.Glyphs.Add(new RibbonOrbAdornerGlyph(BehaviorService, this, Ribbon));
_tabAdorner.Glyphs.Add(new RibbonTabGlyph(BehaviorService, this, Ribbon));
}
}
///
/// Catches the event of a component on the ribbon being removed
///
///
///
public void changeService_ComponentRemoved(object sender, ComponentEventArgs e)
{
RibbonTab tab = e.Component as RibbonTab;
RibbonContext context = e.Component as RibbonContext;
RibbonPanel panel = e.Component as RibbonPanel;
RibbonItem item = e.Component as RibbonItem;
IDesignerHost designerService = GetService(typeof(IDesignerHost)) as IDesignerHost;
RemoveRecursive(e.Component as IContainsRibbonComponents, designerService);
if (tab != null && Ribbon != null)
{
Ribbon.Tabs.Remove(tab);
}
else if (context != null)
{
Ribbon.Contexts.Remove(context);
}
else if (panel != null)
{
panel.OwnerTab.Panels.Remove(panel);
}
else if (item != null)
{
if (item.Canvas is RibbonOrbDropDown)
{
Ribbon.OrbDropDown.HandleDesignerItemRemoved(item);
}
else if (item.OwnerItem is RibbonItemGroup @group)
{
@group.Items.Remove(item);
}
else if (item.OwnerPanel != null)
{
item.OwnerPanel.Items.Remove(item);
}
else if (Ribbon != null && Ribbon.QuickAccessToolbar.Items.Contains(item))
{
Ribbon.QuickAccessToolbar.Items.Remove(item);
}
}
SelectedElement = null;
Ribbon?.OnRegionsChanged();
}
public void RemoveRecursive(IContainsRibbonComponents item, IDesignerHost service)
{
if (item == null || service == null) return;
foreach (Component c in item.GetAllChildComponents())
{
if (c is IContainsRibbonComponents components)
{
RemoveRecursive(components, service);
}
service.DestroyComponent(c);
}
}
#endregion
}
}