469 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			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);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |