469 lines
18 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Windows.Forms.Design.Behavior;
namespace DevComponents.DotNetBar.Design
{
public class ComponentDesignerWithAction : ComponentDesigner
{
private Adorner _DesignerActionAdorner = null;
public override void Initialize(System.ComponentModel.IComponent component)
{
base.Initialize(component);
if (DesignerActionUIEnabled)
{
ISelectionService selectionService = (ISelectionService) GetService(typeof(ISelectionService));
if (selectionService != null)
selectionService.SelectionChanged += SelectionChanged;
_DesignerActionAdorner = new Adorner();
// If our component is removed we need to clean-up
IComponentChangeService cc = (IComponentChangeService) GetService(typeof(IComponentChangeService));
if (cc != null)
{
cc.ComponentRemoving += ComponentRemoving;
cc.ComponentRemoved += ComponentRemoved;
}
}
}
private void ComponentRemoved(object sender, ComponentEventArgs e)
{
if (e.Component is BaseItem)
{
BaseItem parent = this.Component as BaseItem;
BaseItem item = e.Component as BaseItem;
if (item != null && parent != null && parent.SubItems.Contains(item))
{
IComponentChangeService cc = (IComponentChangeService)GetService(typeof(IComponentChangeService));
if (cc != null)
cc.OnComponentChanging(parent, TypeDescriptor.GetProperties(parent)["SubItems"]);
parent.SubItems.Remove(item);
if (cc != null)
cc.OnComponentChanged(parent, TypeDescriptor.GetProperties(parent)["SubItems"], null, null);
this.RecalcLayout();
}
}
}
public virtual void RecalcLayout()
{
}
private void ComponentRemoving(object sender, ComponentEventArgs e)
{
if(e.Component == this.Component)
RemoveGlyph();
}
protected override void Dispose(bool disposing)
{
if (DesignerActionUIEnabled)
{
ISelectionService selectionService = (ISelectionService) GetService(typeof(ISelectionService));
if (selectionService != null)
selectionService.SelectionChanged -= SelectionChanged;
IComponentChangeService cc = (IComponentChangeService)GetService(typeof(IComponentChangeService));
if (cc != null)
{
cc.ComponentRemoving -= ComponentRemoving;
cc.ComponentRemoved -= ComponentRemoved;
}
}
base.Dispose(disposing);
}
public bool IsSelected = false;
private void SelectionChanged(object sender, EventArgs e)
{
bool selected = false;
ISelectionService selectionService = (ISelectionService) GetService(typeof(ISelectionService));
if (selectionService == null) return;
if (selectionService.PrimarySelection == this.Component)
selected = true;
else
{
ICollection selectedComponents = selectionService.GetSelectedComponents();
foreach (object o in selectedComponents)
{
if (o.Equals(this.Component))
{
selected = true;
break;
}
}
}
OnDesignerSelectionChanged(selected);
if (selected)
{
Control hostControl = GetContainerControl();
if (hostControl != null)
{
Rectangle itemScreenBounds = hostControl.RectangleToScreen(ComponentBounds);
_DesignerGlyph = CreateDesignerGlyphWrapper((Component) this.Component, GetParentControl(),
itemScreenBounds,
this.ActionLists);
}
}
else
{
RemoveGlyph();
}
IsSelected = selected;
}
protected virtual Rectangle ComponentBounds
{
get
{
BaseItem item = this.Component as BaseItem;
if (item != null)
return item.Bounds;
return Rectangle.Empty;
}
}
public virtual Control GetHostControl()
{
return GetParentControl();
}
protected virtual Control GetParentControl()
{
return GetContainerControl();
}
protected virtual Control GetContainerControl()
{
BaseItem item = this.Component as BaseItem;
if (item != null)
return (Control) item.ContainerControl;
return null;
}
protected virtual void OnDesignerSelectionChanged(bool isSelected)
{
}
protected virtual bool DesignerActionUIEnabled
{
get { return true; }
}
private Glyph _DesignerGlyph = null;
private void RemoveGlyph()
{
BehaviorService svc = (BehaviorService) this.GetService(typeof(BehaviorService));
if (svc == null) return;
_DesignerActionAdorner.Glyphs.Clear();
if (svc.Adorners.Contains(_DesignerActionAdorner))
svc.Adorners.Remove(_DesignerActionAdorner);
if (_ActionListToolStrip != null)
_ActionListToolStrip.LocationChanged -= HostLocationChanged;
_ActionListToolStrip = null;
InvalidateDesignerSurface();
}
private void InvalidateDesignerSurface()
{
BehaviorService behaviorService = (BehaviorService) GetService(typeof(BehaviorService));
if (behaviorService == null) return;
object actionUi = GetActionUI(behaviorService);
if (actionUi == null) return;
object mainParentWindow = ReflectionHelpers.GetValueField(actionUi, "mainParentWindow",
BindingFlags.Instance | BindingFlags.NonPublic);
if (mainParentWindow is IWin32Window)
{
WinApi.RedrawWindow(((IWin32Window) mainParentWindow).Handle, IntPtr.Zero, IntPtr.Zero,
(uint) (WinApi.RedrawWindowFlags.RDW_INVALIDATE | WinApi.RedrawWindowFlags.RDW_ALLCHILDREN));
}
}
private ToolStripDropDown _ActionListToolStrip = null;
private Glyph CreateDesignerGlyphWrapper(Component targetComponent, Control ownerControl,
Rectangle screenBounds, DesignerActionListCollection actionLists)
{
BehaviorService behaviorService = (BehaviorService) GetService(typeof(BehaviorService));
if (targetComponent != null && behaviorService != null && actionLists != null)
{
try
{
object actionUi = GetActionUI(behaviorService);
FieldInfo fieldInfo1 = ReflectionHelpers.GetFieldInfo(actionUi, "designerActionHost",
BindingFlags.Instance | BindingFlags.NonPublic);
ToolStripDropDown designerActionHost = null;
object mainParentWindow = ReflectionHelpers.GetValueField(actionUi, "mainParentWindow",
BindingFlags.Instance | BindingFlags.NonPublic);
if (!(fieldInfo1.GetValue(actionUi) is ToolStripDropDown))
{
ConstructorInfo constructorInfo = ReflectionHelpers.GetConstructorInfo(fieldInfo1.FieldType,
new Type[2]
{
actionUi.GetType(),
typeof(IWin32Window)
});
designerActionHost = constructorInfo.Invoke(new object[2]
{
actionUi,
mainParentWindow
}) as ToolStripDropDown;
designerActionHost.AutoSize = false;
designerActionHost.Padding = System.Windows.Forms.Padding.Empty;
designerActionHost.Renderer = (ToolStripRenderer) new NoBorderRenderer();
designerActionHost.Text = "DesignerActionTopLevelForm";
fieldInfo1.SetValue(actionUi, (object) designerActionHost);
}
else
{
designerActionHost = fieldInfo1.GetValue(actionUi) as ToolStripDropDown;
}
Glyph glyph = ReflectionHelpers.InvokeMethod(actionUi, "GetDesignerActionGlyph",
BindingFlags.Instance | BindingFlags.NonPublic, new object[2]
{
(object) targetComponent,
(object) actionLists
}) as Glyph;
if (glyph != null)
{
BarUtilities.InvokeDelayed(new MethodInvoker(delegate { SetGlyphBounds(glyph, screenBounds, behaviorService); }), 100);
if (designerActionHost != null)
{
designerActionHost.LocationChanged += HostLocationChanged;
Point p = new Point(glyph.Bounds.Right, glyph.Bounds.Y);
designerActionHost.Bounds =
new Rectangle(behaviorService.AdornerWindowPointToScreen(p), designerActionHost.Size);
}
FieldInfo fieldInfo2 = ReflectionHelpers.GetFieldInfo((object) glyph.Behavior,
"serviceProvider", BindingFlags.Instance | BindingFlags.NonPublic);
GlyphServiceProvider glyphServiceProvider =
new GlyphServiceProvider((IServiceProvider) fieldInfo2.GetValue((object) glyph.Behavior));
fieldInfo2.SetValue((object) glyph.Behavior, (object) glyphServiceProvider);
//SmartTagInfoCache.Default.Add(info.TargetComponent, new SmartTagCacheElement(glyph, info.TargetComponent, (Control)null, actionUi, info.BehaviorService));
behaviorService.Adorners.Add(_DesignerActionAdorner);
_DesignerActionAdorner.Glyphs.Add(glyph);
//TestGlyph testGlyph = new TestGlyph(behaviorService, this);
//_DesignerActionAdorner.Glyphs.Add(testGlyph);
if (mainParentWindow is Control) ((Control) mainParentWindow).Invalidate();
}
if (mainParentWindow is IWin32Window)
{
WinApi.RedrawWindow(((IWin32Window) mainParentWindow).Handle, IntPtr.Zero, IntPtr.Zero,
(uint) (WinApi.RedrawWindowFlags.RDW_INVALIDATE |
WinApi.RedrawWindowFlags.RDW_ALLCHILDREN));
}
if (_ActionListToolStrip != designerActionHost)
{
if (_ActionListToolStrip != null)
_ActionListToolStrip.LocationChanged -= HostLocationChanged;
_ActionListToolStrip = designerActionHost;
}
return glyph;
}
catch
{
return (Glyph) null;
}
}
return (Glyph) null;
}
private bool _SettingBounds = false;
private void HostLocationChanged(object sender, EventArgs e)
{
if (_SettingBounds) return;
ToolStripDropDown toolStripDropDown = sender as ToolStripDropDown;
BehaviorService svc = (BehaviorService) this.GetService(typeof(BehaviorService));
if (toolStripDropDown == null || _DesignerGlyph == null || svc == null)
return;
_SettingBounds = true;
Point p = new Point(_DesignerGlyph.Bounds.Right, _DesignerGlyph.Bounds.Y);
Rectangle r = new Rectangle(svc.AdornerWindowPointToScreen(p), toolStripDropDown.Size);
toolStripDropDown.Bounds = r;
_SettingBounds = false;
}
private void SetGlyphBounds(Glyph gl, Rectangle itemBounds, BehaviorService behaviorService)
{
Size glyphSize = GetGlyphSize();
Point adornerWindow = behaviorService.ScreenToAdornerWindow(new Point(itemBounds.Right - 6, itemBounds.Y));
Point p = behaviorService.ScreenToAdornerWindow(Point.Empty);
ReflectionHelpers.SetValueField((object) gl, "bounds",
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField,
(object) new Rectangle(adornerWindow, glyphSize));
InvalidateDesignerSurface();
}
private class NoBorderRenderer : ToolStripProfessionalRenderer
{
public NoBorderRenderer()
{
}
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
}
}
private object GetActionUI(BehaviorService behaviorService)
{
if (behaviorService == null)
return null;
return ReflectionHelpers.GetValueProperty((object) behaviorService, "DesignerActionUI",
BindingFlags.Instance | BindingFlags.NonPublic);
}
private Rectangle GetGlyphBounds(Rectangle componentBounds)
{
Size glyphSize = GetGlyphSize();
return new Rectangle(componentBounds.Right - glyphSize.Width, componentBounds.Y, glyphSize.Width,
glyphSize.Height);
}
private Size GetGlyphSize()
{
try
{
Type type = typeof(ControlDesigner).Assembly.GetType("System.Windows.Forms.DpiHelper");
if (type != (Type) null)
{
if ((bool) type.GetProperty("IsScalingRequired", BindingFlags.Static | BindingFlags.Public)
.GetValue((object) null, (object[]) null))
{
object[] parameters = new object[2]
{
(object) new Bitmap(10, 10),
(object) 0
};
type.GetMethod("ScaleBitmapLogicalToDevice", BindingFlags.Static | BindingFlags.Public)
.Invoke((object) null, parameters);
return ((Image) parameters[0]).Size;
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
return new Size(10, 10);
}
class TestBehavior : Behavior
{
}
class TestGlyph : Glyph
{
ComponentDesignerWithAction _Item;
BehaviorService _BehaviorSvc;
public TestGlyph(BehaviorService behaviorSvc, ComponentDesignerWithAction item)
:
base(new TestBehavior())
{
_BehaviorSvc = behaviorSvc;
_Item = item;
}
public ComponentDesignerWithAction Item
{
get { return _Item; }
}
public override Rectangle Bounds
{
get
{
// Glyph coordinates are in adorner window coordinates, so we must map using the behavior service.
Rectangle bounds = Rectangle.Empty;
if (_Item != null && _Item.GetHostControl() != null)
{
Point edge = _BehaviorSvc.ControlToAdornerWindow(_Item.GetHostControl());
bounds = _Item.ComponentBounds;
bounds.Offset(edge);
}
return bounds;
}
}
public override Cursor GetHitTest(Point p)
{
if (_Item != null && !_Item.IsSelected)
return null;
// GetHitTest is called to see if the point is
// within this glyph. This gives us a chance to decide
// what cursor to show. Returning null from here means
// the mouse pointer is not currently inside of the glyph.
// Returning a valid cursor here indicates the pointer is
// inside the glyph, and also enables our Behavior property
// as the active behavior.
if (Bounds.Contains(p))
{
return Cursors.SizeAll;
}
return null;
}
public Rectangle CompleteBounds
{
get
{
Rectangle bounds = Rectangle.Empty;
if (_Item != null && _Item.GetHostControl() != null)
{
Point edge = _BehaviorSvc.ControlToAdornerWindow(_Item.GetContainerControl());
bounds = _Item.ComponentBounds;
bounds.Offset(edge);
}
return bounds;
}
}
public override void Paint(PaintEventArgs pe)
{
// Draw our glyph
if (_Item != null)
{
if (_Item.IsSelected)
{
Rectangle r = CompleteBounds;
r.Width--;
r.Height--;
Graphics g = pe.Graphics;
using(SolidBrush brush=new SolidBrush(Color.FromArgb(129,Color.Red)))
{
g.FillRectangle(brush, r);
}
}
}
}
}
}
}