diff --git a/samples/XamlDesigner/Document.cs b/samples/XamlDesigner/Document.cs index bc7bc8b98f..4998e87618 100644 --- a/samples/XamlDesigner/Document.cs +++ b/samples/XamlDesigner/Document.cs @@ -146,7 +146,10 @@ namespace ICSharpCode.XamlDesigner public XamlErrorService XamlErrorService { get { - return DesignContext.Services.GetService(); + if (DesignContext != null) { + return DesignContext.Services.GetService(); + } + return null; } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs index dc44bc90d1..cea1bc97f9 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs @@ -152,16 +152,9 @@ namespace ICSharpCode.WpfDesign.AddIn propertyContainer.PropertyGridReplacementControl = propertyEditorHost; } - ICollection oldItems = new DesignItem[0]; - void OnSelectionChanged(object sender, DesignItemCollectionEventArgs e) { - ISelectionService selectionService = designer.DesignContext.Services.Selection; - ICollection items = selectionService.SelectedItems; - if (!IsCollectionWithSameElements(items, oldItems)) { - propertyGridView.PropertyGrid.SelectedItems = items; - oldItems = items; - } + propertyGridView.PropertyGrid.SelectedItems = DesignContext.Services.Selection.SelectedItems; } static bool IsCollectionWithSameElements(ICollection a, ICollection b) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/CreateComponentTool.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/CreateComponentTool.cs index 60924d6afb..7d8695dbf0 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/CreateComponentTool.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/CreateComponentTool.cs @@ -20,6 +20,9 @@ namespace ICSharpCode.WpfDesign.Designer.Services public class CreateComponentTool : ITool { readonly Type componentType; + MoveLogic moveLogic; + ChangeGroup changeGroup; + Point createPoint; /// /// Creates a new CreateComponentTool instance. @@ -45,16 +48,89 @@ namespace ICSharpCode.WpfDesign.Designer.Services public void Activate(IDesignPanel designPanel) { designPanel.MouseDown += OnMouseDown; - designPanel.DragOver += OnDragOver; - designPanel.Drop += OnDrop; + //designPanel.DragEnter += designPanel_DragOver; + designPanel.DragOver += designPanel_DragOver; + designPanel.Drop += designPanel_Drop; + designPanel.DragLeave += designPanel_DragLeave; } public void Deactivate(IDesignPanel designPanel) { designPanel.MouseDown -= OnMouseDown; - designPanel.DragOver -= OnDragOver; - designPanel.Drop -= OnDrop; + //designPanel.DragEnter -= designPanel_DragOver; + designPanel.DragOver -= designPanel_DragOver; + designPanel.Drop -= designPanel_Drop; + designPanel.DragLeave -= designPanel_DragLeave; } + + void designPanel_DragOver(object sender, DragEventArgs e) + { + try { + IDesignPanel designPanel = (IDesignPanel)sender; + e.Effects = DragDropEffects.Copy; + e.Handled = true; + Point p = e.GetPosition(designPanel); + + if (moveLogic == null) { + if (e.Data.GetData(typeof(CreateComponentTool)) != this) return; + // TODO: dropLayer in designPanel + designPanel.IsAdornerLayerHitTestVisible = false; + DesignPanelHitTestResult result = designPanel.HitTest(p, false, true); + + if (result.ModelHit != null) { + designPanel.Focus(); + DesignItem createdItem = CreateItem(designPanel.Context); + if (AddItemWithDefaultSize(result.ModelHit, createdItem, e.GetPosition(result.ModelHit.View))) { + moveLogic = new MoveLogic(createdItem); + createPoint = p; + } else { + changeGroup.Abort(); + } + } + } else if ((moveLogic.ClickedOn.View as FrameworkElement).IsLoaded) { + if (moveLogic.Operation == null) { + moveLogic.Start(createPoint); + } else { + moveLogic.Move(p); + } + } + } catch (Exception x) { + DragDropExceptionHandler.HandleException(x); + } + } + + void designPanel_Drop(object sender, DragEventArgs e) + { + try { + if (moveLogic != null) { + moveLogic.Stop(); + if (moveLogic.ClickedOn.Services.Tool.CurrentTool is CreateComponentTool) { + moveLogic.ClickedOn.Services.Tool.CurrentTool = moveLogic.ClickedOn.Services.Tool.PointerTool; + } + moveLogic.DesignPanel.IsAdornerLayerHitTestVisible = true; + moveLogic = null; + changeGroup.Commit(); + } + } catch (Exception x) { + DragDropExceptionHandler.HandleException(x); + } + } + + void designPanel_DragLeave(object sender, DragEventArgs e) + { + try { + if (moveLogic != null) { + moveLogic.Cancel(); + moveLogic.ClickedOn.Services.Selection.SetSelectedComponents(null); + moveLogic.DesignPanel.IsAdornerLayerHitTestVisible = true; + moveLogic = null; + changeGroup.Abort(); + + } + } catch (Exception x) { + DragDropExceptionHandler.HandleException(x); + } + } /// /// Is called to create the item used by the CreateComponentTool. @@ -63,54 +139,18 @@ namespace ICSharpCode.WpfDesign.Designer.Services { object newInstance = context.Services.ExtensionManager.CreateInstanceWithCustomInstanceFactory(componentType, null); DesignItem item = context.Services.Component.RegisterComponentForDesigner(newInstance); + changeGroup = item.OpenGroup("Drop Control"); context.Services.ExtensionManager.ApplyDefaultInitializers(item); return item; } - void OnDragOver(object sender, DragEventArgs e) - { - try { - if (e.Data.GetData(typeof(CreateComponentTool)) == this) { - e.Effects = DragDropEffects.Copy; - e.Handled = true; - } else { - e.Effects = DragDropEffects.None; - } - } catch (Exception ex) { - DragDropExceptionHandler.HandleException(ex); - } - } - - void OnDrop(object sender, DragEventArgs e) - { - try { - if (e.Data.GetData(typeof(CreateComponentTool)) != this) - return; - e.Handled = true; - - IDesignPanel designPanel = (IDesignPanel)sender; - DesignPanelHitTestResult result = designPanel.HitTest(e.GetPosition(designPanel), false, true); - if (result.ModelHit != null) { - designPanel.Focus(); - - DesignItem createdItem = CreateItem(designPanel.Context); - AddItemWithDefaultSize(result.ModelHit, createdItem, e.GetPosition(result.ModelHit.View)); - } - - if (designPanel.Context.Services.Tool.CurrentTool is CreateComponentTool) { - designPanel.Context.Services.Tool.CurrentTool = designPanel.Context.Services.Tool.PointerTool; - } - } catch (Exception ex) { - DragDropExceptionHandler.HandleException(ex); - } - } - internal static bool AddItemWithDefaultSize(DesignItem container, DesignItem createdItem, Point position) { + var size = ModelTools.GetDefaultSize(createdItem); PlacementOperation operation = PlacementOperation.TryStartInsertNewComponents( container, new DesignItem[] { createdItem }, - new Rect[] { new Rect(position, ModelTools.GetDefaultSize(createdItem)) }, + new Rect[] { new Rect(position, size) }, PlacementType.AddItem ); if (operation != null) { 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 6ecbb3a207..df58dbdf1b 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/DragMoveMouseGesture.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/DragMoveMouseGesture.cs @@ -19,137 +19,48 @@ namespace ICSharpCode.WpfDesign.Designer.Services /// sealed class DragMoveMouseGesture : ClickOrDragMouseGesture { - readonly DesignItem clickedOn; - PlacementOperation operation; - ICollection selectedItems; bool isDoubleClick; + MoveLogic moveLogic; internal DragMoveMouseGesture(DesignItem clickedOn, bool isDoubleClick) { Debug.Assert(clickedOn != null); - this.clickedOn = clickedOn; this.isDoubleClick = isDoubleClick; if (clickedOn.Parent != null) this.positionRelativeTo = clickedOn.Parent.View; else this.positionRelativeTo = clickedOn.View; - - selectedItems = clickedOn.Services.Selection.SelectedItems; - if (!selectedItems.Contains(clickedOn)) - selectedItems = SharedInstances.EmptyDesignItemArray; + + moveLogic = new MoveLogic(clickedOn); } protected override void OnDragStarted(MouseEventArgs e) { - IPlacementBehavior b = PlacementOperation.GetPlacementBehavior(selectedItems); - if (b != null && b.CanPlace(selectedItems, PlacementType.Move, PlacementAlignment.TopLeft)) { - List sortedSelectedItems = new List(selectedItems); - sortedSelectedItems.Sort(ModelTools.ComparePositionInModelFile); - selectedItems = sortedSelectedItems; - operation = PlacementOperation.Start(selectedItems, PlacementType.Move); - } + moveLogic.Start(startPoint); } protected override void OnMouseMove(object sender, MouseEventArgs e) { base.OnMouseMove(sender, e); // call OnDragStarted if min. drag distace is reached - if (operation != null) { - UIElement currentContainer = operation.CurrentContainer.View; - Point p = e.GetPosition(currentContainer); - - // try to switch the container - if (operation.CurrentContainerBehavior.CanLeaveContainer(operation)) { - ChangeContainerIfPossible(e); - } - - Vector v = e.GetPosition(positionRelativeTo) - startPoint; - foreach (PlacementInformation info in operation.PlacedItems) { - info.Bounds = new Rect(info.OriginalBounds.Left + v.X, - info.OriginalBounds.Top + v.Y, - info.OriginalBounds.Width, - info.OriginalBounds.Height); - } - operation.CurrentContainerBehavior.BeforeSetPosition(operation); - foreach (PlacementInformation info in operation.PlacedItems) { - operation.CurrentContainerBehavior.SetPosition(info); - } - } - } - - // Perform hit testing on the design panel and return the first model that is not selected - DesignPanelHitTestResult HitTestUnselectedModel(MouseEventArgs e) - { - DesignPanelHitTestResult result = DesignPanelHitTestResult.NoHit; - ISelectionService selection = services.Selection; - designPanel.HitTest( - e.GetPosition(designPanel), false, true, - delegate(DesignPanelHitTestResult r) { - if (r.ModelHit == null) - return true; // continue hit testing - if (selection.IsComponentSelected(r.ModelHit)) - return true; // continue hit testing - result = r; - return false; // finish hit testing - }); - return result; - } - - bool ChangeContainerIfPossible(MouseEventArgs e) - { - DesignPanelHitTestResult result = HitTestUnselectedModel(e); - if (result.ModelHit == null) return false; - if (result.ModelHit == operation.CurrentContainer) return false; - - // check that we don't move an item into itself: - DesignItem tmp = result.ModelHit; - while (tmp != null) { - if (tmp == clickedOn) return false; - tmp = tmp.Parent; - } - - IPlacementBehavior b = result.ModelHit.GetBehavior(); - if (b != null && b.CanEnterContainer(operation)) { - operation.ChangeContainer(result.ModelHit); - return true; - } - return false; + moveLogic.Move(e.GetPosition(positionRelativeTo)); } protected override void OnMouseUp(object sender, MouseButtonEventArgs e) { if (!hasDragStarted && isDoubleClick) { // user made a double-click - Debug.Assert(operation == null); - HandleDoubleClick(); - } - if (operation != null) { - operation.Commit(); - operation = null; + Debug.Assert(moveLogic.Operation == null); + moveLogic.HandleDoubleClick(); } + moveLogic.Stop(); Stop(); } protected override void OnStopped() { - if (operation != null) { - operation.Abort(); - operation = null; - } - } - - void HandleDoubleClick() - { - if (selectedItems.Count == 1) { - IEventHandlerService ehs = services.GetService(); - if (ehs != null) { - DesignItemProperty defaultEvent = ehs.GetDefaultEvent(clickedOn); - if (defaultEvent != null) { - ehs.CreateEventHandler(defaultEvent); - } - } - } + moveLogic.Cancel(); } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/MoveLogic.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/MoveLogic.cs new file mode 100644 index 0000000000..fc82bfbe34 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/MoveLogic.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; + +namespace ICSharpCode.WpfDesign.Designer.Services +{ + class MoveLogic + { + public MoveLogic(DesignItem clickedOn) + { + this.clickedOn = clickedOn; + + selectedItems = clickedOn.Services.Selection.SelectedItems; + if (!selectedItems.Contains(clickedOn)) + selectedItems = SharedInstances.EmptyDesignItemArray; + } + + DesignItem clickedOn; + PlacementOperation operation; + ICollection selectedItems; + Point startPoint; + + public DesignItem ClickedOn { + get { return clickedOn; } + } + + public PlacementOperation Operation { + get { return operation; } + } + + public IDesignPanel DesignPanel { + get { return clickedOn.Services.DesignPanel; } + } + + public void Start(Point p) + { + startPoint = p; + IPlacementBehavior b = PlacementOperation.GetPlacementBehavior(selectedItems); + if (b != null && b.CanPlace(selectedItems, PlacementType.Move, PlacementAlignment.TopLeft)) { + List sortedSelectedItems = new List(selectedItems); + sortedSelectedItems.Sort(ModelTools.ComparePositionInModelFile); + selectedItems = sortedSelectedItems; + operation = PlacementOperation.Start(selectedItems, PlacementType.Move); + } + } + + public void Move(Point p) + { + if (operation != null) { + + // try to switch the container + if (operation.CurrentContainerBehavior.CanLeaveContainer(operation)) { + ChangeContainerIfPossible(p); + } + + Vector v = p - startPoint; + foreach (PlacementInformation info in operation.PlacedItems) { + info.Bounds = new Rect(info.OriginalBounds.Left + v.X, + info.OriginalBounds.Top + v.Y, + info.OriginalBounds.Width, + info.OriginalBounds.Height); + } + operation.CurrentContainerBehavior.BeforeSetPosition(operation); + foreach (PlacementInformation info in operation.PlacedItems) { + operation.CurrentContainerBehavior.SetPosition(info); + } + } + } + + public void Stop() + { + if (operation != null) { + operation.Commit(); + operation = null; + } + } + + public void Cancel() + { + if (operation != null) { + operation.Abort(); + operation = null; + } + } + + // Perform hit testing on the design panel and return the first model that is not selected + DesignPanelHitTestResult HitTestUnselectedModel(Point p) + { + DesignPanelHitTestResult result = DesignPanelHitTestResult.NoHit; + ISelectionService selection = clickedOn.Services.Selection; + + DesignPanel.HitTest(p, false, true, delegate(DesignPanelHitTestResult r) { + if (r.ModelHit == null) + return true; // continue hit testing + if (selection.IsComponentSelected(r.ModelHit)) + return true; // continue hit testing + result = r; + return false; // finish hit testing + }); + + return result; + } + + bool ChangeContainerIfPossible(Point p) + { + DesignPanelHitTestResult result = HitTestUnselectedModel(p); + if (result.ModelHit == null) return false; + if (result.ModelHit == operation.CurrentContainer) return false; + + // check that we don't move an item into itself: + DesignItem tmp = result.ModelHit; + while (tmp != null) { + if (tmp == clickedOn) return false; + tmp = tmp.Parent; + } + + IPlacementBehavior b = result.ModelHit.GetBehavior(); + if (b != null && b.CanEnterContainer(operation)) { + operation.ChangeContainer(result.ModelHit); + return true; + } + return false; + } + + public void HandleDoubleClick() + { + if (selectedItems.Count == 1) { + IEventHandlerService ehs = clickedOn.Services.GetService(); + if (ehs != null) { + DesignItemProperty defaultEvent = ehs.GetDefaultEvent(clickedOn); + if (defaultEvent != null) { + ehs.CreateEventHandler(defaultEvent); + } + } + } + } + } +} 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 86dd820650..678fcfb295 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj @@ -180,6 +180,7 @@ + Code