diff --git a/src/BetterControls.Design.Client/BetterControls.Design.Client.csproj b/src/BetterControls.Design.Client/BetterControls.Design.Client.csproj new file mode 100644 index 0000000..4b7be70 --- /dev/null +++ b/src/BetterControls.Design.Client/BetterControls.Design.Client.csproj @@ -0,0 +1,21 @@ + + + + net472 + true + 9.0 + enable + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/BetterControls.Design.Client/BetterToolbarTypeRoutingProvider.cs b/src/BetterControls.Design.Client/BetterToolbarTypeRoutingProvider.cs new file mode 100644 index 0000000..8d1d7b2 --- /dev/null +++ b/src/BetterControls.Design.Client/BetterToolbarTypeRoutingProvider.cs @@ -0,0 +1,45 @@ +using BetterControls.Design.Protocol; +using Microsoft.DotNet.DesignTools.Client.TypeRouting; +using System.Collections.Generic; + +namespace BetterControls.Design +{ + /// + /// Represents the toolbar type routing provider. + /// + [ExportTypeRoutingDefinitionProvider] + internal class BetterToolbarTypeRoutingProvider : TypeRoutingDefinitionProvider + { + /// + /// Initialize a new instance of . + /// + public BetterToolbarTypeRoutingProvider() { } + + /// + /// + /// + /// + public override IEnumerable GetDefinitions() + { + return new[] + { + new TypeRoutingDefinition( + TypeRoutingKinds.Editor, + nameof(EditorNames.BetterToolbarItemCollectionEditor), + typeof(BetterToolbarItemCollectionEditor)), + new TypeRoutingDefinition( + TypeRoutingKinds.Editor, + nameof(EditorNames.BetterMenuBarItemCollectionEditor), + typeof(BetterMenuBarItemCollectionEditor)), + new TypeRoutingDefinition( + TypeRoutingKinds.Editor, + nameof(EditorNames.BetterMenuItemCollectionEditor), + typeof(BetterMenuItemCollectionEditor)), + new TypeRoutingDefinition( + TypeRoutingKinds.Editor, + nameof(EditorNames.ImageIndexEditor), + typeof(ImageIndexEditor)), + }; + } + } +} \ No newline at end of file diff --git a/src/BetterControls.Design.Client/Editors/BetterCollectionEditor.cs b/src/BetterControls.Design.Client/Editors/BetterCollectionEditor.cs new file mode 100644 index 0000000..094d269 --- /dev/null +++ b/src/BetterControls.Design.Client/Editors/BetterCollectionEditor.cs @@ -0,0 +1,19 @@ +using Microsoft.DotNet.DesignTools.Client.Editors; +using System; + +namespace BetterControls.Design +{ + /// + /// Extend this class to create a collection editor. + /// + public abstract class BetterCollectionEditor : CollectionEditor + { + /// + /// Initialize a new instance of . + /// + /// The type that this collection editor is associated with. + public BetterCollectionEditor(Type collectionType) + : base(collectionType) + { } + } +} \ No newline at end of file diff --git a/src/BetterControls.Design.ClientServerProtocol/BetterControls.Design.ClientServerProtocol.csproj b/src/BetterControls.Design.ClientServerProtocol/BetterControls.Design.ClientServerProtocol.csproj new file mode 100644 index 0000000..e2092aa --- /dev/null +++ b/src/BetterControls.Design.ClientServerProtocol/BetterControls.Design.ClientServerProtocol.csproj @@ -0,0 +1,13 @@ + + + + net6.0-windows;net472 + disable + enable + 9.0 + + + + + + diff --git a/src/BetterControls.Design.ClientServerProtocol/CollectionEditorNames.cs b/src/BetterControls.Design.ClientServerProtocol/CollectionEditorNames.cs new file mode 100644 index 0000000..99f6757 --- /dev/null +++ b/src/BetterControls.Design.ClientServerProtocol/CollectionEditorNames.cs @@ -0,0 +1,9 @@ +namespace WinForms.Tiles.ClientServerProtocol +{ + public static class CollectionEditorNames + { + public const string BetterToolbarItemCollectionEditor = nameof(BetterToolbarItemCollectionEditor); + public const string BetterMenuBarItemCollectionEditor = nameof(BetterMenuBarItemCollectionEditor); + public const string BetterMenuItemCollectionEditor = nameof(BetterMenuItemCollectionEditor); + } +} \ No newline at end of file diff --git a/src/BetterControls.Design.ClientServerProtocol/EditorNames.cs b/src/BetterControls.Design.ClientServerProtocol/EditorNames.cs new file mode 100644 index 0000000..0808e94 --- /dev/null +++ b/src/BetterControls.Design.ClientServerProtocol/EditorNames.cs @@ -0,0 +1,10 @@ +namespace BetterControls.Design.Protocol +{ + public static class EditorNames + { + public const string BetterToolbarItemCollectionEditor = nameof(BetterToolbarItemCollectionEditor); + public const string BetterMenuBarItemCollectionEditor = nameof(BetterMenuBarItemCollectionEditor); + public const string BetterMenuItemCollectionEditor = nameof(BetterMenuItemCollectionEditor); + public const string ImageIndexEditor = nameof(ImageIndexEditor); + } +} \ No newline at end of file diff --git a/src/BetterControls.Design.Server/BetterControls.Design.Server.csproj b/src/BetterControls.Design.Server/BetterControls.Design.Server.csproj new file mode 100644 index 0000000..7e5248e --- /dev/null +++ b/src/BetterControls.Design.Server/BetterControls.Design.Server.csproj @@ -0,0 +1,21 @@ + + + + net6.0-windows + true + disable + disable + + + + + + + + + + + + + + diff --git a/src/BetterControls.Design.Server/BetterToolbarTypeRoutingProvider.cs b/src/BetterControls.Design.Server/BetterToolbarTypeRoutingProvider.cs new file mode 100644 index 0000000..bc012e2 --- /dev/null +++ b/src/BetterControls.Design.Server/BetterToolbarTypeRoutingProvider.cs @@ -0,0 +1,42 @@ +using Microsoft.DotNet.DesignTools.TypeRouting; +using System.Collections.Generic; + +namespace BetterControls.Design +{ + /// + /// Represents the toolbar type routing provider. + /// + [ExportTypeRoutingDefinitionProvider] + internal class BetterToolbarTypeRoutingProvider : TypeRoutingDefinitionProvider + { + /// + /// Initialize a new instance of . + /// + public BetterToolbarTypeRoutingProvider() { } + + /// + /// + /// + /// + public override IEnumerable GetDefinitions() + => new[] + { + new TypeRoutingDefinition( + TypeRoutingKinds.Designer, + nameof(BetterToolbarDesigner), + typeof(BetterToolbarDesigner)), + new TypeRoutingDefinition( + TypeRoutingKinds.Designer, + nameof(BetterToolbarItemDesigner), + typeof(BetterToolbarItemDesigner)), + new TypeRoutingDefinition( + TypeRoutingKinds.Designer, + nameof(BetterToolbarButtonDesigner), + typeof(BetterToolbarButtonDesigner)), + new TypeRoutingDefinition( + TypeRoutingKinds.Designer, + nameof(BetterMenuBarDesigner), + typeof(BetterMenuBarDesigner)) + }; + } +} \ No newline at end of file diff --git a/src/BetterControls.Design.Server/Designers/BetterComponentDesigner.cs b/src/BetterControls.Design.Server/Designers/BetterComponentDesigner.cs new file mode 100644 index 0000000..7f281a8 --- /dev/null +++ b/src/BetterControls.Design.Server/Designers/BetterComponentDesigner.cs @@ -0,0 +1,36 @@ +using Microsoft.DotNet.DesignTools.Designers; +using System.ComponentModel.Design; + +namespace BetterControls.Design +{ + /// + /// Extend this class to create a component designer. + /// + public abstract class BetterComponentDesigner : ComponentDesigner + { + /// + /// Initialize a new instance of . + /// + public BetterComponentDesigner() { } + + #region Private Member Fields + + private IDesignerHost _designerHost; + + #endregion + + /// + /// Gets the designer host associated with this component. + /// + protected IDesignerHost DesignerHost + { + get + { + if (_designerHost is null) + _designerHost = GetService(); + + return _designerHost; + } + } + } +} \ No newline at end of file diff --git a/src/BetterControls.Design.Server/Designers/BetterControlActionList.cs b/src/BetterControls.Design.Server/Designers/BetterControlActionList.cs new file mode 100644 index 0000000..e39c591 --- /dev/null +++ b/src/BetterControls.Design.Server/Designers/BetterControlActionList.cs @@ -0,0 +1,48 @@ +using Microsoft.DotNet.DesignTools.Designers; +using Microsoft.DotNet.DesignTools.Designers.Actions; +using System; +using System.ComponentModel.Design; + +namespace BetterControls.Design +{ + /// + /// Extend from this class to indicate that the implementing class is an action list. + /// + internal class BetterControlActionList : DesignerActionList + { + /// + /// Initialize a new instance of . + /// + /// The designer that is associated with this action list. + internal BetterControlActionList(Microsoft.DotNet.DesignTools.Designers.ControlDesigner designer) + : base(designer.Component) + { + Designer = designer ?? throw new ArgumentNullException(nameof(designer)); + } + + #region Private Member Fields + + private IDesignerHost _designerHost; + + #endregion + + /// + /// Gets the designer that is associated with this action list. + /// + protected Microsoft.DotNet.DesignTools.Designers.ControlDesigner Designer { get; } + + /// + /// Gets the designer host associated with this component. + /// + protected IDesignerHost DesignerHost + { + get + { + if(_designerHost is null) + _designerHost = GetService(); + + return _designerHost; + } + } + } +} \ No newline at end of file diff --git a/src/BetterControls.Design.Server/Designers/BetterControlDesigner.cs b/src/BetterControls.Design.Server/Designers/BetterControlDesigner.cs new file mode 100644 index 0000000..0de3593 --- /dev/null +++ b/src/BetterControls.Design.Server/Designers/BetterControlDesigner.cs @@ -0,0 +1,36 @@ +using Microsoft.DotNet.DesignTools.Designers; +using System.ComponentModel.Design; + +namespace BetterControls.Design +{ + /// + /// Extend this class to create a control designer. + /// + public abstract class BetterControlDesigner : ControlDesigner + { + /// + /// Initialize a new instance of . + /// + public BetterControlDesigner() { } + + #region Private Member Fields + + private IDesignerHost _designerHost; + + #endregion + + /// + /// Gets the designer host associated with this component. + /// + protected IDesignerHost DesignerHost + { + get + { + if (_designerHost is null) + _designerHost = GetService(); + + return _designerHost; + } + } + } +} \ No newline at end of file diff --git a/src/BetterControls.Design.Server/Designers/BetterToolbarButtonDesigner.cs b/src/BetterControls.Design.Server/Designers/BetterToolbarButtonDesigner.cs new file mode 100644 index 0000000..fa770ec --- /dev/null +++ b/src/BetterControls.Design.Server/Designers/BetterToolbarButtonDesigner.cs @@ -0,0 +1,37 @@ +using System.Collections; +using System.ComponentModel; + +namespace BetterControls.Design +{ + /// + /// Designer for . + /// + internal class BetterToolbarButtonDesigner : BetterToolbarItemDesigner + { + /// + /// Initialize a new instance of . + /// + public BetterToolbarButtonDesigner() { } + + /// + /// + /// + /// + public override void InitializeNewComponent(IDictionary defaultValues) + { + base.InitializeNewComponent(defaultValues); + + PropertyDescriptor nameProperty = TypeDescriptor.GetProperties(Component)["Name"]; + if (nameProperty != null && nameProperty.PropertyType == typeof(string)) + { + string itemText = (string)nameProperty.GetValue(Component); + + PropertyDescriptor textProperty = TypeDescriptor.GetProperties(Component)["Text"]; + if (textProperty != null) + { + textProperty.SetValue(Component, itemText); + } + } + } + } +} \ No newline at end of file diff --git a/src/BetterControls.Design.Server/Designers/BetterToolbarDesigner.ActionList.cs b/src/BetterControls.Design.Server/Designers/BetterToolbarDesigner.ActionList.cs new file mode 100644 index 0000000..cdf03b7 --- /dev/null +++ b/src/BetterControls.Design.Server/Designers/BetterToolbarDesigner.ActionList.cs @@ -0,0 +1,208 @@ +using Microsoft.DotNet.DesignTools.Designers.Actions; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Windows.Forms; + +namespace BetterControls.Design +{ + /// + /// Designer for . + /// + internal partial class BetterToolbarDesigner + { + /// + /// + /// + public override DesignerActionListCollection ActionLists => new DesignerActionListCollection() + { + new ActionList(this) + }; + + /// + /// Adds a to the toolbar. + /// + protected void AddPushButton() => AddItem(); + + /// + /// Adds a to the toolbar. + /// + protected void AddToggleButton() => AddItem(); + + /// + /// Adds a to the toolbar. + /// + protected void AddDropDownButton() => AddItem(); + + /// + /// Adds a to the toolbar. + /// + protected void AddSeparator() => AddItem(); + + /// + /// Adds a new to the toolbar. + /// + /// The type of item to add extending from . + private protected void AddItem() + where TItemType : BetterToolbarItem + { + DesignerTransaction transaction = null; + + try + { + transaction = DesignerHost.CreateTransaction("Inserting Item"); + + TItemType button = (TItemType)DesignerHost.CreateComponent(typeof(TItemType)); + + MemberDescriptor itemsMember = TypeDescriptor.GetProperties(Component!)[nameof(BetterToolbar.Items)]; + + RaiseComponentChanging(itemsMember); + + PropertyDescriptor nameProperty = TypeDescriptor.GetProperties(button)["Name"]; + if (nameProperty != null && nameProperty.PropertyType == typeof(string)) + { + string itemText = (string)nameProperty.GetValue(button); + + PropertyDescriptor textProperty = TypeDescriptor.GetProperties(button)["Text"]; + if (textProperty != null) + { + textProperty.SetValue(button, itemText); + } + } + + ((BetterToolbar)Component!).Items.Add(button); + + RaiseComponentChanged(itemsMember); + } + finally + { + transaction?.Commit(); + } + + Refresh(); + } + + /// + /// Action list for . + /// + private class ActionList : BetterControlActionList + { + /// + /// Initialize a new instance of . + /// + /// The designer that is associated with this action list. + public ActionList(BetterToolbarDesigner designer) + : base(designer) + { } + + /// + /// Invokes the property. + /// + public void InvokeItemsProperty() => Designer.InvokePropertyEditor("Items"); + + /// + /// Invokes the 'Add Push Button' action list item. + /// + public void InvokeAddPushButton() => ((BetterToolbarDesigner)Designer).AddPushButton(); + + /// + /// Invokes the 'Add Toggle Button' action list item. + /// + public void InvokeAddToggleButton() => ((BetterToolbarDesigner)Designer).AddToggleButton(); + + /// + /// Invokes the 'Add Drop-down Button' action list item. + /// + public void InvokeAddDropDownButton() => ((BetterToolbarDesigner)Designer).AddDropDownButton(); + + /// + /// Invokes the 'Add Separator' action list item. + /// + public void InvokeAddSeparator() => ((BetterToolbarDesigner)Designer).AddSeparator(); + + /// + /// Invokes the 'Dock in Parent Container'/'Undock in Parent Container' action list item. + /// + public void InvokeDock() + { + using DesignerTransaction transaction = DesignerHost.CreateTransaction(); + + PropertyDescriptor dockProperty = TypeDescriptor.GetProperties(Component)["Dock"]; + DockStyle dock = (DockStyle)dockProperty.GetValue(Component); + if (dock != DockStyle.None) + { + dockProperty.SetValue(Component, DockStyle.None); + } + else + { + dockProperty.SetValue(Component, DockStyle.Top); + } + + transaction.Commit(); + } + + /// + /// Gets the name of the dock action. + /// + /// The name of the dock action. + private string GetDockActionName() + { + PropertyDescriptor dockProperty = TypeDescriptor.GetProperties(Component)["Dock"]; + if (dockProperty != null && dockProperty.PropertyType == typeof(DockStyle)) + { + DockStyle dock = (DockStyle)dockProperty.GetValue(Component); + if (dock != DockStyle.None) + { + return "Undock in Parent Container"; + } + else + { + return "Dock in Parent Container"; + } + } + return null; + } + + /// + /// + /// + /// + public override DesignerActionItemCollection GetSortedActionItems() + { + DesignerActionItemCollection actionItems = new DesignerActionItemCollection(); + + actionItems.Add(new DesignerActionMethodItem( + this, + nameof(InvokeDock), + GetDockActionName(), + false)); + actionItems.Add(new DesignerActionMethodItem( + this, + nameof(InvokeItemsProperty), + "Edit Items...", + true)); + actionItems.Add(new DesignerActionMethodItem( + this, + nameof(InvokeAddPushButton), + "Add Push Button", + true)); + actionItems.Add(new DesignerActionMethodItem( + this, + nameof(InvokeAddToggleButton), + "Add Toggle Button", + true)); + actionItems.Add(new DesignerActionMethodItem( + this, + nameof(InvokeAddDropDownButton), + "Add Drop-down Button", + true)); + actionItems.Add(new DesignerActionMethodItem( + this, + nameof(InvokeAddSeparator), + "Add Separator", + true)); + + return actionItems; + } + } + } +} \ No newline at end of file diff --git a/src/BetterControls.Design.Server/Designers/BetterToolbarDesigner.cs b/src/BetterControls.Design.Server/Designers/BetterToolbarDesigner.cs new file mode 100644 index 0000000..6650dbb --- /dev/null +++ b/src/BetterControls.Design.Server/Designers/BetterToolbarDesigner.cs @@ -0,0 +1,120 @@ +using Microsoft.DotNet.DesignTools.Designers; +using Microsoft.DotNet.DesignTools.Designers.Actions; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Windows.Forms; + +namespace BetterControls.Design +{ + /// + /// Designer for . + /// + internal partial class BetterToolbarDesigner : BetterControlDesigner + { + /// + /// Initialize a new instance of . + /// + public BetterToolbarDesigner() { } + + /// + /// + /// + public override SelectionRules SelectionRules + { + get + { + SelectionRules selectionRules = base.SelectionRules; + + PropertyDescriptor dockProperty = TypeDescriptor.GetProperties(Component)["Dock"]; + PropertyDescriptor autoSizeProperty = TypeDescriptor.GetProperties(Component)["AutoSize"]; + if (dockProperty != null && autoSizeProperty != null) + { + DockStyle dock = (DockStyle)dockProperty.GetValue(Component); + bool autoSize = (bool)autoSizeProperty.GetValue(Component); + if (autoSize) + { + selectionRules &= ~(SelectionRules.TopSizeable | SelectionRules.BottomSizeable); + if (dock != DockStyle.None) + selectionRules &= ~SelectionRules.AllSizeable; + } + } + + return selectionRules; + } + } + + /// + /// + /// + /// + public override void InitializeNewComponent(IDictionary defaultValues) + { + base.InitializeNewComponent(defaultValues); + + PropertyDescriptor dockProperty = TypeDescriptor.GetProperties(Component)["Dock"]; + if (dockProperty != null && dockProperty.PropertyType == typeof(DockStyle)) + { + dockProperty.SetValue(Component, DockStyle.Top); + } + } + + protected override void OnMouseDragEnd(bool cancel, Keys modifierKeys) + { + base.OnMouseDragEnd(cancel, modifierKeys); + } + + + + /// + /// + /// + public override IReadOnlyCollection AssociatedComponents + { + get + { + if (Control is BetterToolbar toolbar) + { + List items = new List(); + + foreach (BetterToolbarItem item in toolbar.Items) + { + items.Add(item); + + if (item is BetterToolbarDropDownButton button) + { + if (button.DropDownMenu != null) + { + foreach (BetterMenuItem menuItem in button.DropDownMenu.Items) + { + items.Add(menuItem); + } + } + } + } + + return items.AsReadOnly(); + } + + return base.AssociatedComponents; + } + } + + protected override void OnMouseUp(MouseEventArgs e) + { + base.OnMouseUp(e); + + ((BetterToolbar)Component).UpdateItemDimensions(); + } + + + + protected void Refresh() + { + DesignerActionUIService das = GetService(); + das?.Refresh(Component!); + } + } +} diff --git a/src/BetterControls.Design.Server/Designers/BetterToolbarItemDesigner.cs b/src/BetterControls.Design.Server/Designers/BetterToolbarItemDesigner.cs new file mode 100644 index 0000000..284ba23 --- /dev/null +++ b/src/BetterControls.Design.Server/Designers/BetterToolbarItemDesigner.cs @@ -0,0 +1,16 @@ +using System.Collections; +using System.ComponentModel; + +namespace BetterControls.Design +{ + /// + /// Designer for . + /// + internal partial class BetterToolbarItemDesigner : BetterComponentDesigner + { + /// + /// Initialize a new instance of . + /// + public BetterToolbarItemDesigner() { } + } +} \ No newline at end of file diff --git a/src/BetterControls.Design.Server/Editors/BetterCollectionEditor.cs b/src/BetterControls.Design.Server/Editors/BetterCollectionEditor.cs new file mode 100644 index 0000000..f33a621 --- /dev/null +++ b/src/BetterControls.Design.Server/Editors/BetterCollectionEditor.cs @@ -0,0 +1,20 @@ +using Microsoft.DotNet.DesignTools.Editors; +using System; + +namespace BetterControls.Design +{ + /// + /// Extend this class to create a collection editor. + /// + public abstract class BetterCollectionEditor : CollectionEditor + { + /// + /// Initialize a new instance of . + /// + /// The service provider as an instance of . + /// The type that this collection editor is associated with. + public BetterCollectionEditor(IServiceProvider services, Type collectionType) + : base(services, collectionType) + { } + } +} \ No newline at end of file