diff --git a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Images/Delete.png b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Images/Delete.png new file mode 100644 index 0000000000..824d938dd6 Binary files /dev/null and b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Images/Delete.png differ diff --git a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/StandaloneDesigner.csproj b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/StandaloneDesigner.csproj index 8fef61a195..948580cdde 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/StandaloneDesigner.csproj +++ b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/StandaloneDesigner.csproj @@ -48,6 +48,7 @@ App.xaml + Code Window1.xaml @@ -64,5 +65,6 @@ + \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Toolbox.cs b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Toolbox.cs new file mode 100644 index 0000000000..8dbeeb06c4 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Toolbox.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using ICSharpCode.WpfDesign; +using ICSharpCode.WpfDesign.Designer.Services; + +namespace StandaloneDesigner +{ + public partial class Toolbox : ListBox + { + public Toolbox() + { + this.SelectionMode = SelectionMode.Single; + } + + IToolService toolService; + + public IToolService ToolService { + get { return toolService; } + set { + if (toolService != null) { + toolService.CurrentToolChanged -= OnCurrentToolChanged; + } + toolService = value; + this.Items.Clear(); + if (toolService != null) { + AddTool("Pointer", toolService.PointerTool); + AddTool(typeof(Button)); + AddTool(typeof(TextBox)); + AddTool(typeof(CheckBox)); + + toolService.CurrentToolChanged += OnCurrentToolChanged; + OnCurrentToolChanged(null, null); + } + } + } + + void AddTool(Type componentType) + { + AddTool(componentType.Name, new CreateComponentTool(componentType)); + } + + void AddTool(string title, ITool tool) + { + ListBoxItem item = new ListBoxItem(); + item.Content = title; + item.Tag = tool; + this.Items.Add(item); + } + + void OnCurrentToolChanged(object sender, EventArgs e) + { + Debug.WriteLine("Toolbox.OnCurrentToolChanged"); + for (int i = 0; i < this.Items.Count; i++) { + if (((ListBoxItem)this.Items[i]).Tag == toolService.CurrentTool) { + this.SelectedIndex = i; + return; + } + } + this.SelectedIndex = -1; + } + + protected override void OnSelectionChanged(SelectionChangedEventArgs e) + { + base.OnSelectionChanged(e); + + Debug.WriteLine("Toolbox.OnSelectionChanged"); + if (toolService != null && this.SelectedItem is ListBoxItem) { + toolService.CurrentTool = (ITool)(this.SelectedItem as ListBoxItem).Tag; + } + } + + Point startPos; + bool canStartDrag; + + protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) + { + startPos = e.GetPosition(this); + canStartDrag = true; + + base.OnPreviewMouseLeftButtonDown(e); + } + + protected override void OnMouseMove(MouseEventArgs e) + { + if (canStartDrag && e.LeftButton == MouseButtonState.Pressed) { + if ((e.GetPosition(this) - startPos).LengthSquared > 4) { + canStartDrag = false; + + if (this.SelectedItem == null) + return; + + if (toolService != null && this.SelectedItem is ListBoxItem) { + ITool tool = (ITool)(this.SelectedItem as ListBoxItem).Tag; + if (tool is CreateComponentTool) { + DragDrop.DoDragDrop((ListBoxItem)this.SelectedItem, tool, DragDropEffects.Copy); + } + } + } + } + + base.OnMouseMove(e); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml index 31daad2eec..eb2dc22405 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml +++ b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml @@ -2,12 +2,14 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:designer="clr-namespace:ICSharpCode.WpfDesign.Designer;assembly=ICSharpCode.WpfDesign.Designer" + xmlns:my="clr-namespace:StandaloneDesigner" Title="StandaloneDesigner" Height="500" Width="700" > + @@ -47,7 +49,16 @@ - + + + + + + + + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml.cs index 90939d7d27..1a7b351bd5 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Collections.Generic; using System.IO; using System.Windows; @@ -8,6 +9,8 @@ using System.Xml; using ICSharpCode.WpfDesign; using ICSharpCode.WpfDesign.Designer; using ICSharpCode.WpfDesign.PropertyEditor; +using System.Threading; +using System.Windows.Threading; namespace StandaloneDesigner { @@ -37,6 +40,7 @@ namespace StandaloneDesigner DesignSurface designSurface; PropertyEditor propertyEditor; ToolBar toolBar; + Toolbox toolbox; #endif void tabControlSelectionChanged(object sender, RoutedEventArgs e) @@ -45,6 +49,7 @@ namespace StandaloneDesigner if (tabControl.SelectedItem == designTab) { designSurface.LoadDesigner(new XmlTextReader(new StringReader(CodeTextBox.Text))); designSurface.DesignContext.Services.Selection.SelectionChanged += OnSelectionChanged; + toolbox.ToolService = designSurface.DesignContext.Services.Tool; } else { if (designSurface.DesignContext != null) { propertyEditor.EditedObject = null; @@ -58,6 +63,7 @@ namespace StandaloneDesigner } } designSurface.UnloadDesigner(); + toolbox.ToolService = null; } } @@ -68,7 +74,8 @@ namespace StandaloneDesigner ISelectionService selectionService = designSurface.DesignContext.Services.Selection; ICollection items = selectionService.SelectedItems; if (!IsCollectionWithSameElements(items, oldItems)) { - propertyEditor.EditedObject = DesignItemDataSource.GetDataSourceForDesignItems(items); + IPropertyEditorDataSource dataSource = DesignItemDataSource.GetDataSourceForDesignItems(items); + propertyEditor.EditedObject = dataSource; oldItems = items; } } @@ -86,5 +93,19 @@ namespace StandaloneDesigner } return true; } + + void TestButtonClick(object sender, EventArgs e) + { + DesignItem[] c = new List(designSurface.DesignContext.Services.Selection.SelectedItems).ToArray(); + if (c.Length < 2) return; + int index = 0; + DispatcherTimer timer = new DispatcherTimer(); + timer.Interval = new TimeSpan(0, 0, 0, 0, 100); + timer.Tick += delegate { + index++; + designSurface.DesignContext.Services.Selection.SetSelectedComponents(new DesignItem[] { c[index % c.Length] }); + }; + timer.Start(); + } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/PropertyEditor.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/PropertyEditor.cs index 042a24bb73..8a0aea7933 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/PropertyEditor.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/PropertyEditor.cs @@ -117,13 +117,13 @@ namespace ICSharpCode.WpfDesign.Designer } } else { PropertyGridView grid = new PropertyGridView(); + contentStackPanel.Children.Add(grid); foreach (IPropertyEditorDataProperty p in Func.Sort(dataSource.Properties, ComparePropertyNames)) { if (p.Name == "Name") { continue; } grid.AddProperty(p); } - contentStackPanel.Children.Add(grid); } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/PropertyNameTextBlock.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/PropertyNameTextBlock.cs index a6b36523cb..c4417f5323 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/PropertyNameTextBlock.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/PropertyNameTextBlock.cs @@ -18,8 +18,8 @@ namespace ICSharpCode.WpfDesign.Designer.Controls sealed class PropertyNameTextBlock : TextBlock { readonly IPropertyEditorDataProperty property; - readonly TextBlock toolTipTextBlock; - bool toolTipTextBlockInitialized; + readonly DockPanel toolTipDockPanel; + bool toolTipInitialized; internal DependencyPropertyDotButton ContextMenuProvider; public PropertyNameTextBlock(IPropertyEditorDataProperty property) @@ -29,7 +29,7 @@ namespace ICSharpCode.WpfDesign.Designer.Controls this.TextAlignment = TextAlignment.Right; this.TextTrimming = TextTrimming.CharacterEllipsis; - this.ToolTip = toolTipTextBlock = new TextBlock(); + this.ToolTip = toolTipDockPanel = new DockPanel(); } protected override void OnToolTipOpening(ToolTipEventArgs e) @@ -48,17 +48,22 @@ namespace ICSharpCode.WpfDesign.Designer.Controls void CreateToolTip() { - if (toolTipTextBlockInitialized) + if (toolTipInitialized) return; - toolTipTextBlockInitialized = true; - toolTipTextBlock.TextAlignment = TextAlignment.Left; - toolTipTextBlock.Inlines.Add(new Bold(new Run(property.Name))); + toolTipInitialized = true; + TextBlock textBlock = new TextBlock(); + textBlock.TextAlignment = TextAlignment.Left; + textBlock.Inlines.Add(new Bold(new Run(property.Name))); if (property.ReturnType != null) { - toolTipTextBlock.Inlines.Add(" (" + property.ReturnType.Name + ")"); + textBlock.Inlines.Add(" (" + property.ReturnType.Name + ")"); } - if (!string.IsNullOrEmpty(property.Description)) { - toolTipTextBlock.Inlines.Add(new LineBreak()); - toolTipTextBlock.Inlines.Add(property.Description); + DockPanel.SetDock(textBlock, Dock.Top); + toolTipDockPanel.Children.Add(textBlock); + object description = property.GetDescription(); + if (description != null) { + ContentControl cc = new ContentControl(); + cc.Content = description; + toolTipDockPanel.Children.Add(cc); } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs index fac7e555ce..c93533c0b5 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs @@ -145,9 +145,11 @@ namespace ICSharpCode.WpfDesign.Designer this.Focusable = true; this.VerticalAlignment = VerticalAlignment.Top; this.HorizontalAlignment = HorizontalAlignment.Left; + this.AllowDrop = true; DesignerProperties.SetIsInDesignMode(this, true); _eatAllHitTestRequests = new EatAllHitTestRequests(); + _eatAllHitTestRequests.AllowDrop = true; _adornerLayer = new AdornerLayer(this); _markerCanvas = new Canvas(); _markerCanvas.IsHitTestVisible = false; @@ -170,10 +172,6 @@ namespace ICSharpCode.WpfDesign.Designer } } - public Canvas MarkerCanvas { - get { return _markerCanvas; } - } - /// /// Gets/Sets if the design content is visible for hit-testing purposes. /// diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.cs index 193e0225b1..6ccd6ed7b8 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.cs @@ -40,54 +40,58 @@ namespace ICSharpCode.WpfDesign.Designer this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Undo, OnUndoExecuted, OnUndoCanExecute)); this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Redo, OnRedoExecuted, OnRedoCanExecute)); + this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Delete, OnDeleteExecuted, OnDeleteCanExecute)); } - #region Undo/Redo - UndoService _undoService; - - private UndoService UndoService { - get { return _undoService; } - set { - if (_undoService != null) { - _undoService.UndoStackChanged -= OnUndoStackChanged; - } - _undoService = value; - if (_undoService != null) { - _undoService.UndoStackChanged += OnUndoStackChanged; - } - CommandManager.InvalidateRequerySuggested(); - } + T GetService() where T : class + { + if (_designContext != null) + return _designContext.Services.GetService(); + else + return null; } + #region Command: Undo/Redo void OnUndoExecuted(object sender, ExecutedRoutedEventArgs e) { - IUndoAction action = Func.First(_undoService.UndoActions); + UndoService undoService = GetService(); + IUndoAction action = Func.First(undoService.UndoActions); Debug.WriteLine("Undo " + action.Title); - _undoService.Undo(); + undoService.Undo(); _designContext.Services.Selection.SetSelectedComponents(action.AffectedElements); } void OnUndoCanExecute(object sender, CanExecuteRoutedEventArgs e) { - e.CanExecute = _undoService != null && _undoService.CanUndo; + UndoService undoService = GetService(); + e.CanExecute = undoService != null && undoService.CanUndo; } void OnRedoExecuted(object sender, ExecutedRoutedEventArgs e) { - IUndoAction action = Func.First(_undoService.RedoActions); + UndoService undoService = GetService(); + IUndoAction action = Func.First(undoService.RedoActions); Debug.WriteLine("Redo " + action.Title); - _undoService.Redo(); + undoService.Redo(); _designContext.Services.Selection.SetSelectedComponents(action.AffectedElements); } void OnRedoCanExecute(object sender, CanExecuteRoutedEventArgs e) { - e.CanExecute = _undoService != null && _undoService.CanRedo; + UndoService undoService = GetService(); + e.CanExecute = undoService != null && undoService.CanRedo; } + #endregion - void OnUndoStackChanged(object sender, EventArgs e) + #region Command: Delete + void OnDeleteExecuted(object sender, ExecutedRoutedEventArgs e) { - CommandManager.InvalidateRequerySuggested(); + + } + + void OnDeleteCanExecute(object sender, CanExecuteRoutedEventArgs e) + { + } #endregion @@ -125,7 +129,13 @@ namespace ICSharpCode.WpfDesign.Designer designPanelBorder.Padding = new Thickness(10); _designPanel.Child = designPanelBorder; designPanelBorder.Child = context.RootItem.View; - UndoService = context.Services.GetService(); + context.Services.RunWhenAvailable( + delegate (UndoService undoService) { + CommandManager.InvalidateRequerySuggested(); + }); + context.Services.Selection.SelectionChanged += delegate { + CommandManager.InvalidateRequerySuggested(); + }; } /// @@ -133,12 +143,16 @@ namespace ICSharpCode.WpfDesign.Designer /// public void UnloadDesigner() { + if (_designContext != null) { + foreach (object o in _designContext.Services.AllServices) { + IDisposable d = o as IDisposable; + if (d != null) d.Dispose(); + } + } _designContext = null; _designPanel.Context = null; _designPanel.Child = null; _designPanel.Adorners.Clear(); - _designPanel.MarkerCanvas.Children.Clear(); - UndoService = null; } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasChildResizeSupport.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasChildResizeSupport.cs index b7b9a1dc3a..6432ad59a8 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasChildResizeSupport.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasChildResizeSupport.cs @@ -34,7 +34,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions /// public bool CanPlace(ICollection child, PlacementType type, PlacementAlignment position) { - return type == PlacementType.Resize || type == PlacementType.Move; + return type == PlacementType.Resize || type == PlacementType.Move || type == PlacementType.Delete; } /// diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PanelSelectionHandler.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PanelSelectionHandler.cs index 41ade54be5..7ca1faf419 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PanelSelectionHandler.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PanelSelectionHandler.cs @@ -54,7 +54,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions this.positionRelativeTo = container.View; } - protected override void OnDragStarted() + protected override void OnDragStarted(MouseEventArgs e) { adornerPanel = new AdornerPanel(); adornerPanel.SetAdornedElement(container.View, container); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/ClickOrDragMouseGesture.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/ClickOrDragMouseGesture.cs index 181b03be37..57cd33d388 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/ClickOrDragMouseGesture.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/ClickOrDragMouseGesture.cs @@ -34,9 +34,11 @@ namespace ICSharpCode.WpfDesign.Designer.Services { if (!hasDragStarted) { Vector v = e.GetPosition(positionRelativeTo) - startPoint; - if (v.LengthSquared >= MinimumDragDistance * MinimumDragDistance) { + if (Math.Abs(v.X) >= SystemParameters.MinimumHorizontalDragDistance + || Math.Abs(v.Y) >= SystemParameters.MinimumVerticalDragDistance) + { hasDragStarted = true; - OnDragStarted(); + OnDragStarted(e); } } } @@ -46,6 +48,6 @@ namespace ICSharpCode.WpfDesign.Designer.Services hasDragStarted = false; } - protected virtual void OnDragStarted() {} + protected virtual void OnDragStarted(MouseEventArgs e) {} } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/CreateComponentTool.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/CreateComponentTool.cs new file mode 100644 index 0000000000..4232da0fad --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/CreateComponentTool.cs @@ -0,0 +1,182 @@ +// +// +// +// +// $Revision$ +// + +using System.Windows; +using System; +using System.Diagnostics; +using System.Windows.Input; +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Designer.Controls; + +namespace ICSharpCode.WpfDesign.Designer.Services +{ + /// + /// A tool that creates a component when used. + /// + public class CreateComponentTool : ITool + { + readonly Type componentType; + + /// + /// Creates a new CreateComponentTool instance. + /// + public CreateComponentTool(Type componentType) + { + if (componentType == null) + throw new ArgumentNullException("componentType"); + this.componentType = componentType; + } + + /// + /// Gets the type of the component to be created. + /// + public Type ComponentType { + get { return componentType; } + } + + /// + public Cursor Cursor { + get { return null; } + } + + /// + public void Activate(IDesignPanel designPanel) + { + designPanel.MouseDown += OnMouseDown; + designPanel.DragOver += OnDragOver; + designPanel.Drop += OnDrop; + } + + /// + public void Deactivate(IDesignPanel designPanel) + { + designPanel.MouseDown -= OnMouseDown; + designPanel.DragOver -= OnDragOver; + designPanel.Drop -= OnDrop; + } + + /// + /// Is called to create the item used by the CreateComponentTool. + /// + protected virtual DesignItem CreateItem(DesignContext context) + { + object newInstance = Activator.CreateInstance(componentType); + return context.Services.Component.RegisterComponentForDesigner(newInstance); + } + + void OnDragOver(object sender, DragEventArgs e) + { + if (e.Data.GetData(typeof(CreateComponentTool)) == this) { + e.Effects = DragDropEffects.Copy; + e.Handled = true; + } else { + e.Effects = DragDropEffects.None; + } + } + + void OnDrop(object sender, DragEventArgs e) + { + if (e.Data.GetData(typeof(CreateComponentTool)) != this) + return; + e.Handled = true; + MessageBox.Show("Not implemented"); + } + + void OnMouseDown(object sender, MouseButtonEventArgs e) + { + if (e.ChangedButton == MouseButton.Left && MouseGestureBase.IsOnlyButtonPressed(e, MouseButton.Left)) { + e.Handled = true; + IDesignPanel designPanel = (IDesignPanel)sender; + DesignPanelHitTestResult result = designPanel.HitTest(e, false, true); + if (result.ModelHit != null) { + IPlacementBehavior behavior = result.ModelHit.GetBehavior(); + if (behavior != null) { + // ensure the design panel has the focus - otherwise pressing Escape to abort creating doesn't work + designPanel.Focus(); + + DesignItem createdItem = CreateItem(designPanel.Context); + + new CreateComponentMouseGesture(result.ModelHit, createdItem).Start(designPanel, e); + } + } + } + } + } + + sealed class CreateComponentMouseGesture : ClickOrDragMouseGesture + { + DesignItem createdItem; + PlacementOperation operation; + DesignItem container; + + public CreateComponentMouseGesture(DesignItem clickedOn, DesignItem createdItem) + { + this.container = clickedOn; + this.createdItem = createdItem; + this.positionRelativeTo = clickedOn.View; + } + +// GrayOutDesignerExceptActiveArea grayOut; +// SelectionFrame frame; +// AdornerPanel adornerPanel; + + Rect GetStartToEndRect(MouseEventArgs e) + { + Point endPoint = e.GetPosition(positionRelativeTo); + return new Rect( + Math.Min(startPoint.X, endPoint.X), + Math.Min(startPoint.Y, endPoint.Y), + Math.Abs(startPoint.X - endPoint.X), + Math.Abs(startPoint.Y - endPoint.Y) + ); + } + + protected override void OnDragStarted(MouseEventArgs e) + { + operation = PlacementOperation.TryStartInsertNewComponents(container, + new DesignItem[] { createdItem }, + new Rect[] { GetStartToEndRect(e) }, + PlacementType.Resize); + if (operation != null) { + services.Selection.SetSelectedComponents(new DesignItem[] { createdItem }); + } + } + + protected override void OnMouseMove(object sender, MouseEventArgs e) + { + base.OnMouseMove(sender, e); + if (operation != null) { + foreach (PlacementInformation info in operation.PlacedItems) { + info.Bounds = GetStartToEndRect(e); + operation.CurrentContainerBehavior.SetPosition(info); + } + } + } + + protected override void OnMouseUp(object sender, MouseButtonEventArgs e) + { + if (hasDragStarted) { + if (operation != null) { + operation.Commit(); + operation = null; + } + } else { + + } + base.OnMouseUp(sender, e); + } + + protected override void OnStopped() + { + if (operation != null) { + operation.Abort(); + operation = null; + } + base.OnStopped(); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/DragMoveMouseGesture.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/DragMoveMouseGesture.cs index 2a36b1d81b..4276d56c70 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/DragMoveMouseGesture.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/DragMoveMouseGesture.cs @@ -19,7 +19,7 @@ namespace ICSharpCode.WpfDesign.Designer.Services /// sealed class DragMoveMouseGesture : ClickOrDragMouseGesture { - DesignItem clickedOn; + readonly DesignItem clickedOn; PlacementOperation operation; ICollection selectedItems; @@ -39,7 +39,7 @@ namespace ICSharpCode.WpfDesign.Designer.Services selectedItems = new DesignItem[0]; } - protected override void OnDragStarted() + protected override void OnDragStarted(MouseEventArgs e) { IPlacementBehavior b = PlacementOperation.GetPlacementBehavior(selectedItems); if (b != null && b.CanPlace(selectedItems, PlacementType.Move, PlacementAlignments.TopLeft)) { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/MouseGestureBase.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/MouseGestureBase.cs new file mode 100644 index 0000000000..969a64f607 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/MouseGestureBase.cs @@ -0,0 +1,114 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Diagnostics; +using System.Windows.Input; + +namespace ICSharpCode.WpfDesign.Designer.Services +{ + /// + /// Base class for classes handling mouse gestures on the design surface. + /// + abstract class MouseGestureBase + { + /// + /// Checks if is the only button that is currently pressed. + /// + internal static bool IsOnlyButtonPressed(MouseEventArgs e, MouseButton button) + { + return e.LeftButton == (button == MouseButton.Left ? MouseButtonState.Pressed : MouseButtonState.Released) + && e.MiddleButton == (button == MouseButton.Middle ? MouseButtonState.Pressed : MouseButtonState.Released) + && e.RightButton == (button == MouseButton.Right ? MouseButtonState.Pressed : MouseButtonState.Released) + && e.XButton1 == (button == MouseButton.XButton1 ? MouseButtonState.Pressed : MouseButtonState.Released) + && e.XButton2 == (button == MouseButton.XButton2 ? MouseButtonState.Pressed : MouseButtonState.Released); + } + + protected IDesignPanel designPanel; + protected ServiceContainer services; + protected bool canAbortWithEscape = true; + bool isStarted; + + public void Start(IDesignPanel designPanel, MouseButtonEventArgs e) + { + if (designPanel == null) + throw new ArgumentNullException("designPanel"); + if (e == null) + throw new ArgumentNullException("e"); + if (isStarted) + throw new InvalidOperationException("Gesture already was started"); + + isStarted = true; + this.designPanel = designPanel; + this.services = designPanel.Context.Services; + designPanel.IsAdornerLayerHitTestVisible = false; + if (designPanel.CaptureMouse()) { + RegisterEvents(); + OnStarted(e); + } else { + Stop(); + } + } + + void RegisterEvents() + { + designPanel.LostMouseCapture += OnLostMouseCapture; + designPanel.MouseDown += OnMouseDown; + designPanel.MouseMove += OnMouseMove; + designPanel.MouseUp += OnMouseUp; + designPanel.KeyDown += OnKeyDown; + } + + void UnRegisterEvents() + { + designPanel.LostMouseCapture -= OnLostMouseCapture; + designPanel.MouseDown -= OnMouseDown; + designPanel.MouseMove -= OnMouseMove; + designPanel.MouseUp -= OnMouseUp; + designPanel.KeyDown -= OnKeyDown; + } + + void OnKeyDown(object sender, KeyEventArgs e) + { + if (canAbortWithEscape && e.Key == Key.Escape) { + e.Handled = true; + Stop(); + } + } + + void OnLostMouseCapture(object sender, MouseEventArgs e) + { + Stop(); + } + + protected virtual void OnMouseDown(object sender, MouseButtonEventArgs e) + { + } + + protected virtual void OnMouseMove(object sender, MouseEventArgs e) + { + } + + protected virtual void OnMouseUp(object sender, MouseButtonEventArgs e) + { + Stop(); + } + + protected void Stop() + { + if (!isStarted) return; + isStarted = false; + designPanel.ReleaseMouseCapture(); + UnRegisterEvents(); + designPanel.IsAdornerLayerHitTestVisible = true; + OnStopped(); + } + + protected virtual void OnStarted(MouseButtonEventArgs e) {} + protected virtual void OnStopped() {} + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/PointerTool.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/PointerTool.cs new file mode 100644 index 0000000000..acc13d6fac --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/PointerTool.cs @@ -0,0 +1,52 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Windows.Input; + +namespace ICSharpCode.WpfDesign.Designer.Services +{ + sealed class PointerTool : ITool + { + internal static readonly PointerTool Instance = new PointerTool(); + + public Cursor Cursor { + get { return null; } + } + + public void Activate(IDesignPanel designPanel) + { + designPanel.MouseDown += OnMouseDown; + } + + public void Deactivate(IDesignPanel designPanel) + { + designPanel.MouseDown -= OnMouseDown; + } + + void OnMouseDown(object sender, MouseButtonEventArgs e) + { + if (e.ChangedButton == MouseButton.Left && MouseGestureBase.IsOnlyButtonPressed(e, MouseButton.Left)) { + e.Handled = true; + IDesignPanel designPanel = (IDesignPanel)sender; + DesignPanelHitTestResult result = designPanel.HitTest(e, false, true); + if (result.ModelHit != null) { + IHandlePointerToolMouseDown b = result.ModelHit.GetBehavior(); + if (b != null) { + b.HandleSelectionMouseDown(designPanel, e, result); + } else { + ISelectionService selectionService = designPanel.Context.Services.Selection; + selectionService.SetSelectedComponents(new DesignItem[] { result.ModelHit }, SelectionTypes.Auto); + if (selectionService.IsComponentSelected(result.ModelHit)) { + new DragMoveMouseGesture(result.ModelHit).Start(designPanel, e); + } + } + } + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/ToolService.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/ToolService.cs index 0a529a7d15..91047d96ef 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/ToolService.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/ToolService.cs @@ -11,15 +11,14 @@ using System.Windows.Input; namespace ICSharpCode.WpfDesign.Designer.Services { // See IToolService for description. - sealed class DefaultToolService : IToolService + sealed class DefaultToolService : IToolService, IDisposable { - PointerTool _pointerTool; ITool _currentTool; IDesignPanel _designPanel; public DefaultToolService(DesignContext context) { - _currentTool = _pointerTool = new PointerTool(); + _currentTool = this.PointerTool; context.Services.RunWhenAvailable( delegate(IDesignPanel designPanel) { _designPanel = designPanel; @@ -27,8 +26,16 @@ namespace ICSharpCode.WpfDesign.Designer.Services }); } + public void Dispose() + { + if (_designPanel != null) { + _currentTool.Deactivate(_designPanel); + _designPanel = null; + } + } + public ITool PointerTool { - get { return _pointerTool; } + get { return Services.PointerTool.Instance; } } public ITool CurrentTool { @@ -37,149 +44,19 @@ namespace ICSharpCode.WpfDesign.Designer.Services if (value == null) throw new ArgumentNullException("value"); if (_currentTool == value) return; - _currentTool.Deactivate(_designPanel); + if (_designPanel != null) { + _currentTool.Deactivate(_designPanel); + } _currentTool = value; - _currentTool.Activate(_designPanel); - } - } - } - - sealed class PointerTool : ITool - { - public Cursor Cursor { - get { return null; } - } - - public void Activate(IDesignPanel designPanel) - { - designPanel.MouseDown += OnMouseDown; - } - - public void Deactivate(IDesignPanel designPanel) - { - designPanel.MouseDown -= OnMouseDown; - } - - void OnMouseDown(object sender, MouseButtonEventArgs e) - { - if (e.ChangedButton == MouseButton.Left && MouseGestureBase.IsOnlyButtonPressed(e, MouseButton.Left)) { - e.Handled = true; - IDesignPanel designPanel = (IDesignPanel)sender; - DesignPanelHitTestResult result = designPanel.HitTest(e, false, true); - if (result.ModelHit != null) { - IHandlePointerToolMouseDown b = result.ModelHit.GetBehavior(); - if (b != null) { - b.HandleSelectionMouseDown(designPanel, e, result); - } else { - ISelectionService selectionService = designPanel.Context.Services.Selection; - selectionService.SetSelectedComponents(new DesignItem[] { result.ModelHit }, SelectionTypes.Auto); - if (selectionService.IsComponentSelected(result.ModelHit)) { - new DragMoveMouseGesture(result.ModelHit).Start(designPanel, e); - } - } + if (_designPanel != null) { + _currentTool.Activate(_designPanel); + } + if (CurrentToolChanged != null) { + CurrentToolChanged(this, EventArgs.Empty); } } } - } - - /// - /// Base class for classes handling mouse gestures on the design surface. - /// - abstract class MouseGestureBase - { - /// - /// Checks if is the only button that is currently pressed. - /// - internal static bool IsOnlyButtonPressed(MouseEventArgs e, MouseButton button) - { - return e.LeftButton == (button == MouseButton.Left ? MouseButtonState.Pressed : MouseButtonState.Released) - && e.MiddleButton == (button == MouseButton.Middle ? MouseButtonState.Pressed : MouseButtonState.Released) - && e.RightButton == (button == MouseButton.Right ? MouseButtonState.Pressed : MouseButtonState.Released) - && e.XButton1 == (button == MouseButton.XButton1 ? MouseButtonState.Pressed : MouseButtonState.Released) - && e.XButton2 == (button == MouseButton.XButton2 ? MouseButtonState.Pressed : MouseButtonState.Released); - } - - protected IDesignPanel designPanel; - protected ServiceContainer services; - protected bool canAbortWithEscape = true; - bool isStarted; - - public void Start(IDesignPanel designPanel, MouseButtonEventArgs e) - { - if (designPanel == null) - throw new ArgumentNullException("designPanel"); - if (e == null) - throw new ArgumentNullException("e"); - if (isStarted) - throw new InvalidOperationException("Gesture already was started"); - - isStarted = true; - this.designPanel = designPanel; - this.services = designPanel.Context.Services; - designPanel.IsAdornerLayerHitTestVisible = false; - if (designPanel.CaptureMouse()) { - RegisterEvents(); - OnStarted(e); - } else { - Stop(); - } - } - - void RegisterEvents() - { - designPanel.LostMouseCapture += OnLostMouseCapture; - designPanel.MouseDown += OnMouseDown; - designPanel.MouseMove += OnMouseMove; - designPanel.MouseUp += OnMouseUp; - designPanel.KeyDown += OnKeyDown; - } - - void UnRegisterEvents() - { - designPanel.LostMouseCapture -= OnLostMouseCapture; - designPanel.MouseDown -= OnMouseDown; - designPanel.MouseMove -= OnMouseMove; - designPanel.MouseUp -= OnMouseUp; - designPanel.KeyDown -= OnKeyDown; - } - - void OnKeyDown(object sender, KeyEventArgs e) - { - if (canAbortWithEscape && e.Key == Key.Escape) { - e.Handled = true; - Stop(); - } - } - - void OnLostMouseCapture(object sender, MouseEventArgs e) - { - Stop(); - } - - protected virtual void OnMouseDown(object sender, MouseButtonEventArgs e) - { - } - - protected virtual void OnMouseMove(object sender, MouseEventArgs e) - { - } - - protected virtual void OnMouseUp(object sender, MouseButtonEventArgs e) - { - Stop(); - } - - protected void Stop() - { - if (!isStarted) return; - isStarted = false; - designPanel.ReleaseMouseCapture(); - UnRegisterEvents(); - designPanel.IsAdornerLayerHitTestVisible = true; - OnStopped(); - } - protected virtual void OnStarted(MouseButtonEventArgs e) {} - protected virtual void OnStopped() {} + public event EventHandler CurrentToolChanged; } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj index 189f14a888..e4ba22dc43 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj @@ -83,9 +83,12 @@ + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlComponentService.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlComponentService.cs index 895301183d..82bb39d197 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlComponentService.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlComponentService.cs @@ -39,8 +39,10 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml } public event EventHandler ComponentRegistered; - public event EventHandler ComponentUnregistered; + // TODO: this must not be a dictionary because there's no way to unregister components + // however, this isn't critical because our design items will stay alive for the lifetime of the + // designer anyway if we don't limit the Undo stack. Dictionary _sites = new Dictionary(IdentityEqualityComparer.Instance); public DesignItem GetDesignItem(object component) @@ -62,23 +64,10 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml XamlDesignItem item = new XamlDesignItem(_context.Document.CreateObject(component), _context); _sites.Add(component, item); - return item; - } - - /// - /// currently for use by UnregisterAllComponents only because it doesn't update the XAML - /// - void UnregisterComponentFromDesigner(DesignItem site) - { - if (site == null) - throw new ArgumentNullException("site"); - - if (!_sites.Remove(site.Component)) - throw new ArgumentException("The site was not registered here!"); - - if (ComponentUnregistered != null) { - ComponentUnregistered(this, new DesignItemEventArgs(site)); + if (ComponentRegistered != null) { + ComponentRegistered(this, new DesignItemEventArgs(item)); } + return item; } /// @@ -102,14 +91,5 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml } return site; } - - /// - /// unregisters all components - /// - internal void UnregisterAllComponents() - { - Array.ForEach(Func.ToArray(_sites.Values), UnregisterComponentFromDesigner); - _sites.Clear(); - } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTestHelper.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTestHelper.cs index 15a6a3cc12..a0dd74e981 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTestHelper.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTestHelper.cs @@ -31,12 +31,12 @@ namespace ICSharpCode.WpfDesign.Tests.Designer { log = new StringBuilder(); XamlDesignContext context = new XamlDesignContext(new XmlTextReader(new StringReader(xaml))); - context.Services.Component.ComponentRegistered += delegate(object sender, DesignItemEventArgs e) { + /*context.Services.Component.ComponentRegistered += delegate(object sender, DesignItemEventArgs e) { log.AppendLine("Register " + ItemIdentity(e.Item)); }; context.Services.Component.ComponentUnregistered += delegate(object sender, DesignItemEventArgs e) { log.AppendLine("Unregister " + ItemIdentity(e.Item)); - }; + };*/ return context; } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs index c535a1b737..f8f3809117 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs @@ -111,6 +111,34 @@ namespace ICSharpCode.WpfDesign.Tests.Designer AssertLog(""); } + [Test] + public void AddTextBoxToCanvasEmptyImplicitPanelChildrenCollection() + { + DesignItem canvas = CreateCanvasContext(""); + DesignItem textBox = canvas.Services.Component.RegisterComponentForDesigner(new TextBox()); + canvas.Properties["Children"].CollectionElements.Add(textBox); + AssertCanvasDesignerOutput("\n" + + " \n" + + " \n" + + " \n" + + "", canvas.Context); + AssertLog(""); + } + + [Test] + public void AddTextBoxToCanvasEmptyImplicitPanelChildrenCollectionEmptyTag() + { + DesignItem canvas = CreateCanvasContext(""); + DesignItem textBox = canvas.Services.Component.RegisterComponentForDesigner(new TextBox()); + canvas.Properties["Children"].CollectionElements.Add(textBox); + AssertCanvasDesignerOutput("\n" + + " \n" + + " \n" + + " \n" + + "", canvas.Context); + AssertLog(""); + } + [Test] public void AddTextBoxToCanvasEmptyExplicitPanelChildrenCollection() { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs index bbe9ceb750..6334eeab25 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs @@ -187,7 +187,7 @@ namespace ICSharpCode.WpfDesign.XamlDom if (defaultProperty != null && defaultProperty.IsCollection && !element.IsEmpty) { defaultPropertyValue = defaultProperty.GetValue(instance); - obj.AddProperty(defaultCollectionProperty = new XamlProperty(obj, defaultProperty, null)); + obj.AddProperty(defaultCollectionProperty = new XamlProperty(obj, defaultProperty)); } foreach (XmlNode childNode in GetNormalizedChildNodes(element)) { @@ -202,6 +202,9 @@ namespace ICSharpCode.WpfDesign.XamlDom XmlElement childElement = childNode as XmlElement; if (childElement != null) { + if (childElement.NamespaceURI == XamlConstants.XamlNamespace) + continue; + if (ObjectChildElementIsPropertyElement(childElement)) { // I don't know why the official XamlReader runs the property getter // here, but let's try to imitate it as good as possible @@ -431,7 +434,7 @@ namespace ICSharpCode.WpfDesign.XamlDom collectionInstance = propertyInfo.GetValue(obj.Instance); } if (collectionProperty == null) { - obj.AddProperty(collectionProperty = new XamlProperty(obj, propertyInfo, null)); + obj.AddProperty(collectionProperty = new XamlProperty(obj, propertyInfo)); } collectionProperty.ParserSetPropertyElement(element); } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs index 05829073ec..30ac4279d3 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs @@ -30,18 +30,11 @@ namespace ICSharpCode.WpfDesign.XamlDom // for use by parser only internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo, XamlPropertyValue propertyValue) + : this(parentObject, propertyInfo) { - this.parentObject = parentObject; - this.propertyInfo = propertyInfo; - this.propertyValue = propertyValue; if (propertyValue != null) { propertyValue.ParentProperty = this; - } else { - if (propertyInfo.IsCollection) { - isCollection = true; - collectionElements = new CollectionElementsCollection(this); - } } } @@ -49,7 +42,11 @@ namespace ICSharpCode.WpfDesign.XamlDom { this.parentObject = parentObject; this.propertyInfo = propertyInfo; - isCollection = propertyInfo.IsCollection; + + if (propertyInfo.IsCollection) { + isCollection = true; + collectionElements = new CollectionElementsCollection(this); + } } /// diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs index 9c8a4df207..ffc3525807 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs @@ -135,6 +135,8 @@ namespace ICSharpCode.WpfDesign internal void ReapplyExtensionServer(ExtensionManager extensionManager, ExtensionServer server) { + Debug.Assert(_extensionServers != null); + for (int i = 0; i < _extensionServers.Length; i++) { if (_extensionServers[i] == server) { bool shouldApply = server.ShouldApplyExtensions(this); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementOperation.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementOperation.cs index b53e1fe78d..30d20be262 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementOperation.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementOperation.cs @@ -24,8 +24,6 @@ namespace ICSharpCode.WpfDesign readonly ChangeGroup changeGroup; readonly ReadOnlyCollection placedItems; readonly PlacementType type; - readonly DesignItem oldContainer; - readonly IPlacementBehavior oldContainerBehavior; DesignItem currentContainer; IPlacementBehavior currentContainerBehavior; bool isAborted, isCommitted; @@ -155,11 +153,9 @@ namespace ICSharpCode.WpfDesign this.placedItems = new ReadOnlyCollection(information); this.type = type; - this.oldContainer = items[0].Parent; - this.oldContainerBehavior = GetPlacementBehavior(items); + this.currentContainer = items[0].Parent; + this.currentContainerBehavior = GetPlacementBehavior(items); - this.currentContainer = oldContainer; - this.currentContainerBehavior = oldContainerBehavior; this.changeGroup = items[0].Context.OpenGroup(type.ToString(), items); } @@ -186,6 +182,53 @@ namespace ICSharpCode.WpfDesign } #endregion + #region StartInsertNewComponents + /// + /// Try to insert new components into the container. + /// + /// The container that should become the parent of the components. + /// The components to add to the container. + /// The rectangle specifying the position the element should get. + /// The type + /// The operation that inserts the new components, or null if inserting is not possible. + public static PlacementOperation TryStartInsertNewComponents(DesignItem container, IList placedItems, IList positions, PlacementType type) + { + if (container == null) + throw new ArgumentNullException("container"); + if (placedItems == null) + throw new ArgumentNullException("placedItems"); + if (positions == null) + throw new ArgumentNullException("positions"); + if (type == null) + throw new ArgumentNullException("type"); + if (placedItems.Count == 0) + throw new ArgumentException("placedItems.Count must be > 0"); + if (placedItems.Count != positions.Count) + throw new ArgumentException("positions.Count must be = placedItems.Count"); + + DesignItem[] items = Func.ToArray(placedItems); + + PlacementOperation op = new PlacementOperation(items, type); + try { + for (int i = 0; i < items.Length; i++) { + op.placedItems[i].OriginalBounds = op.placedItems[i].Bounds = positions[i]; + } + op.currentContainer = container; + op.currentContainerBehavior = container.GetBehavior(); + if (op.currentContainerBehavior == null || !op.currentContainerBehavior.CanEnterContainer(op)) { + op.changeGroup.Abort(); + return null; + } + op.currentContainerBehavior.EnterContainer(op); + } catch (Exception ex) { + Debug.WriteLine(ex.ToString()); + op.changeGroup.Abort(); + throw; + } + return op; + } + #endregion + #region ChangeGroup handling /// /// Gets/Sets the description of the underlying change group. diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementType.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementType.cs index d25907e10d..5c4703aa21 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementType.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementType.cs @@ -26,6 +26,12 @@ namespace ICSharpCode.WpfDesign [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly PlacementType Move = Register("Move"); + /// + /// Not a "real" placement, but deleting the element. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] + public static readonly PlacementType Delete = Register("Delete"); + readonly string name; private PlacementType(string name) @@ -36,6 +42,8 @@ namespace ICSharpCode.WpfDesign /// /// Creates a new unique PlacementKind. /// + /// The name to return from a ToString() call. + /// Note that two PlacementTypes with the same name are NOT equal! public static PlacementType Register(string name) { return new PlacementType(name); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/DesignItemDataProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/DesignItemDataProperty.cs index 1e7edbabc1..d3cf33f7e4 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/DesignItemDataProperty.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/DesignItemDataProperty.cs @@ -40,8 +40,13 @@ namespace ICSharpCode.WpfDesign.PropertyEditor get { return property.Name; } } - public string Description { - get { return "Description for " + property.Name; } + public object GetDescription() + { + IPropertyDescriptionService p = ownerDataSource.DesignItem.Services.GetService(); + if (p != null) + return p.GetDescription(property); + else + return null; } public System.ComponentModel.TypeConverter TypeConverter { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/IPropertyEditorDataSource.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/IPropertyEditorDataSource.cs index 4ed5d12779..6c47bfa0ea 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/IPropertyEditorDataSource.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/IPropertyEditorDataSource.cs @@ -90,9 +90,10 @@ namespace ICSharpCode.WpfDesign.PropertyEditor TypeConverter TypeConverter { get; } /// - /// Gets the description of the property. + /// Gets the description of the property. The returned object should be something that + /// can be used as Content for a WPF tooltip. /// - string Description { get; } + object GetDescription(); /// /// Gets/Sets if the property has been assigned a local value. diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/MultiSelectionDataProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/MultiSelectionDataProperty.cs index 910318ac3e..bd2a6b6765 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/MultiSelectionDataProperty.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/MultiSelectionDataProperty.cs @@ -195,8 +195,9 @@ namespace ICSharpCode.WpfDesign.PropertyEditor get { return data[0].TypeConverter; } } - public string Description { - get { return data[0].Description; } + public object GetDescription() + { + return data[0].GetDescription(); } public bool CanUseCustomExpression { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/ServiceContainer.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/ServiceContainer.cs index fea166c141..875902aeac 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/ServiceContainer.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/ServiceContainer.cs @@ -20,6 +20,15 @@ namespace ICSharpCode.WpfDesign readonly Dictionary _services = new Dictionary(); readonly Dictionary _waitingSubscribers = new Dictionary(); + /// + /// Gets a collection of all registered services. + /// + public IEnumerable AllServices { + get { + return _services.Values; + } + } + /// /// Adds a new service to the container. /// diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Services.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Services.cs index 9a7a530f11..571cc1732e 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Services.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Services.cs @@ -42,11 +42,11 @@ namespace ICSharpCode.WpfDesign /// /// Remove from the selection. /// - Remove = 0x1, + Remove = 0x10, /// /// Replace the selection. /// - Replace = 0x2 + Replace = 0x20 } /// @@ -112,13 +112,8 @@ namespace ICSharpCode.WpfDesign /// Registers a component for usage in the designer. DesignItem RegisterComponentForDesigner(object component); - // /// Unregisters a component from usage in the designer. - // void UnregisterComponentFromDesigner(DesignSite site); - /// Event raised whenever a component is registered event EventHandler ComponentRegistered; - /// Event raised whenever a component is unregistered - event EventHandler ComponentUnregistered; } #endregion @@ -147,6 +142,19 @@ namespace ICSharpCode.WpfDesign } #endregion + #region IPropertyDescriptionService + /// + /// Used to get a description for properties. + /// + public interface IPropertyDescriptionService + { + /// + /// Gets a WPF object representing a graphical description of the property. + /// + object GetDescription(DesignItemProperty property); + } + #endregion + #region IErrorService /// /// Service for showing error UI. diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs index c37fcabd8f..e091c13708 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs @@ -52,6 +52,11 @@ namespace ICSharpCode.WpfDesign /// Gets/Sets the currently selected tool. /// ITool CurrentTool { get; set; } + + /// + /// Is raised when the current tool changes. + /// + event EventHandler CurrentToolChanged; } /// @@ -103,5 +108,25 @@ namespace ICSharpCode.WpfDesign /// Occurs when a mouse button is released. /// event MouseButtonEventHandler MouseUp; + + /// + /// Occurs when a drag operation enters the design panel. + /// + event DragEventHandler DragEnter; + + /// + /// Occurs when a drag operation is over the design panel. + /// + event DragEventHandler DragOver; + + /// + /// Occurs when a drag operation leaves the design panel. + /// + event DragEventHandler DragLeave; + + /// + /// Occurs when an element is dropped on the design panel. + /// + event DragEventHandler Drop; } }