Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

Commit 28af1f0

Browse files
committed
Select Items below the current by Pressing Alt Key when Clicking on Control!
1 parent 632aa87 commit 28af1f0

8 files changed

Lines changed: 102 additions & 30 deletions

File tree

src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ namespace ICSharpCode.WpfDesign.Designer
3535
public sealed class DesignPanel : Decorator, IDesignPanel, INotifyPropertyChanged
3636
{
3737
#region Hit Testing
38+
39+
private List<DependencyObject> hitTestElements = new List<DependencyObject>();
40+
private DependencyObject lastElement;
41+
3842
/// <summary>
3943
/// this element is always hit (unless HitTestVisible is set to false)
4044
/// </summary>
@@ -54,7 +58,7 @@ protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParam
5458
void RunHitTest(Visual reference, Point point, HitTestFilterCallback filterCallback, HitTestResultCallback resultCallback)
5559
{
5660
VisualTreeHelper.HitTest(reference, filterCallback, resultCallback,
57-
new PointHitTestParameters(point));
61+
new PointHitTestParameters(point));
5862
}
5963

6064
HitTestFilterBehavior FilterHitTestInvisibleElements(DependencyObject potentialHitTestTarget)
@@ -70,32 +74,36 @@ HitTestFilterBehavior FilterHitTestInvisibleElements(DependencyObject potentialH
7074

7175
if (designItem != null && designItem.IsDesignTimeLocked) {
7276
return HitTestFilterBehavior.ContinueSkipSelfAndChildren;
77+
}
7378
}
7479

75-
}
80+
hitTestElements.Add(element);
7681

7782
return HitTestFilterBehavior.Continue;
7883
}
7984

8085
/// <summary>
8186
/// Performs a custom hit testing lookup for the specified mouse event args.
8287
/// </summary>
83-
public DesignPanelHitTestResult HitTest(Point mousePosition, bool testAdorners, bool testDesignSurface)
88+
public DesignPanelHitTestResult HitTest(Point mousePosition, bool testAdorners, bool testDesignSurface, HitTestType hitTestType)
8489
{
90+
hitTestElements.Clear();
91+
8592
DesignPanelHitTestResult result = DesignPanelHitTestResult.NoHit;
8693
HitTest(mousePosition, testAdorners, testDesignSurface,
87-
delegate(DesignPanelHitTestResult r) {
88-
result = r;
89-
return false;
90-
});
94+
delegate(DesignPanelHitTestResult r) {
95+
result = r;
96+
return false;
97+
}, hitTestType);
98+
9199
return result;
92100
}
93101

94102
/// <summary>
95103
/// Performs a hit test on the design surface, raising <paramref name="callback"/> for each match.
96104
/// Hit testing continues while the callback returns true.
97105
/// </summary>
98-
public void HitTest(Point mousePosition, bool testAdorners, bool testDesignSurface, Predicate<DesignPanelHitTestResult> callback)
106+
public void HitTest(Point mousePosition, bool testAdorners, bool testDesignSurface, Predicate<DesignPanelHitTestResult> callback, HitTestType hitTestType)
99107
{
100108
if (mousePosition.X < 0 || mousePosition.Y < 0 || mousePosition.X > this.RenderSize.Width || mousePosition.Y > this.RenderSize.Height) {
101109
return;
@@ -104,6 +112,8 @@ public void HitTest(Point mousePosition, bool testAdorners, bool testDesignSurfa
104112

105113
bool continueHitTest = true;
106114

115+
hitTestElements.Clear();
116+
107117
if (testAdorners) {
108118
RunHitTest(
109119
_adornerLayer, mousePosition, FilterHitTestInvisibleElements,
@@ -135,6 +145,19 @@ public void HitTest(Point mousePosition, bool testAdorners, bool testDesignSurfa
135145

136146
ViewService viewService = _context.Services.View;
137147
DependencyObject obj = result.VisualHit;
148+
149+
if (hitTestType == HitTestType.ElementSelection)
150+
{
151+
if (Keyboard.IsKeyDown(Key.LeftAlt))
152+
if (lastElement != null && lastElement != _context.RootItem.Component &&
153+
hitTestElements.Contains(lastElement))
154+
{
155+
var idx = hitTestElements.IndexOf(lastElement) - 1;
156+
if (idx >= 0)
157+
obj = hitTestElements[idx];
158+
}
159+
}
160+
138161
while (obj != null) {
139162
if ((customResult.ModelHit = viewService.GetModel(obj)) != null)
140163
break;
@@ -143,6 +166,13 @@ public void HitTest(Point mousePosition, bool testAdorners, bool testDesignSurfa
143166
if (customResult.ModelHit == null) {
144167
customResult.ModelHit = _context.RootItem;
145168
}
169+
170+
if (hitTestType == HitTestType.ElementSelection)
171+
{
172+
lastElement = obj;
173+
}
174+
175+
146176
continueHitTest = callback(customResult);
147177
return continueHitTest ? HitTestResultBehavior.Continue : HitTestResultBehavior.Stop;
148178
} else {
@@ -223,7 +253,7 @@ public bool UseSnaplinePlacement {
223253
}
224254
}
225255
}
226-
256+
227257
/// <summary>
228258
/// Enables / Disables the Raster Placement
229259
/// </summary>
@@ -341,14 +371,14 @@ void DesignPanel_KeyDown(object sender, KeyEventArgs e)
341371
if (e.Key == Key.Left || e.Key == Key.Right || e.Key == Key.Up || e.Key == Key.Down)
342372
{
343373
e.Handled = true;
344-
374+
345375
if (placementOp == null) {
346376
dx = 0;
347377
dy = 0;
348378
placementOp = PlacementOperation.Start(Context.Services.Selection.SelectedItems, PlacementType.Move);
349379
}
350-
351-
380+
381+
352382
dx += (e.Key == Key.Left) ? Keyboard.IsKeyDown(Key.LeftShift) ? -10 : -1 : 0;
353383
dy += (e.Key == Key.Up) ? Keyboard.IsKeyDown(Key.LeftShift) ? -10 : -1 : 0;
354384
dx += (e.Key == Key.Right) ? Keyboard.IsKeyDown(Key.LeftShift) ? 10 : 1 : 0;
@@ -358,18 +388,18 @@ void DesignPanel_KeyDown(object sender, KeyEventArgs e)
358388
if (!Keyboard.IsKeyDown(Key.LeftCtrl))
359389
{
360390
info.Bounds = new Rect(info.OriginalBounds.Left + dx,
361-
info.OriginalBounds.Top + dy,
362-
info.OriginalBounds.Width,
363-
info.OriginalBounds.Height);
391+
info.OriginalBounds.Top + dy,
392+
info.OriginalBounds.Width,
393+
info.OriginalBounds.Height);
364394
}
365395
else
366396
{
367397
info.Bounds = new Rect(info.OriginalBounds.Left,
368-
info.OriginalBounds.Top,
369-
info.OriginalBounds.Width + dx,
370-
info.OriginalBounds.Height + dy);
398+
info.OriginalBounds.Top,
399+
info.OriginalBounds.Width + dx,
400+
info.OriginalBounds.Height + dy);
371401
}
372-
402+
373403
placementOp.CurrentContainerBehavior.SetPosition(info);
374404
}
375405
}

src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/InPlaceEditorExtension.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ public void StartEdit()
159159

160160
void MouseDown(object sender,MouseEventArgs e)
161161
{
162-
result = designPanel.HitTest(e.GetPosition(designPanel), false, true);
162+
result = designPanel.HitTest(e.GetPosition(designPanel), false, true, HitTestType.Default);
163163
if(result.ModelHit==ExtendedItem && result.VisualHit is TextBlock) {
164164
Start = Mouse.GetPosition(null);
165165
Current = Start;
@@ -171,7 +171,7 @@ void MouseDown(object sender,MouseEventArgs e)
171171
void MouseMove(object sender, MouseEventArgs e)
172172
{
173173
Current += e.GetPosition(null) - Start;
174-
result = designPanel.HitTest(e.GetPosition(designPanel), false, true);
174+
result = designPanel.HitTest(e.GetPosition(designPanel), false, true, HitTestType.Default);
175175
if (result.ModelHit == ExtendedItem && result.VisualHit is TextBlock) {
176176
if (numClicks > 0) {
177177
if (isMouseDown &&
@@ -190,7 +190,7 @@ void MouseMove(object sender, MouseEventArgs e)
190190

191191
void MouseUp(object sender,MouseEventArgs e)
192192
{
193-
result = designPanel.HitTest(e.GetPosition(designPanel), false, true);
193+
result = designPanel.HitTest(e.GetPosition(designPanel), false, true, HitTestType.Default);
194194
if (result.ModelHit == ExtendedItem && result.VisualHit is TextBlock && numClicks>0){
195195
if (!isGettingDragged) {
196196
PlaceEditor(result.VisualHit, e);

src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/CreateComponentTool.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ void designPanel_DragOver(object sender, DragEventArgs e)
8686
if (e.Data.GetData(typeof(CreateComponentTool)) != this) return;
8787
// TODO: dropLayer in designPanel
8888
designPanel.IsAdornerLayerHitTestVisible = false;
89-
DesignPanelHitTestResult result = designPanel.HitTest(p, false, true);
89+
DesignPanelHitTestResult result = designPanel.HitTest(p, false, true, HitTestType.Default);
9090

9191
if (result.ModelHit != null) {
9292
designPanel.Focus();
@@ -180,7 +180,7 @@ void OnMouseDown(object sender, MouseButtonEventArgs e)
180180
if (e.ChangedButton == MouseButton.Left && MouseGestureBase.IsOnlyButtonPressed(e, MouseButton.Left)) {
181181
e.Handled = true;
182182
IDesignPanel designPanel = (IDesignPanel)sender;
183-
DesignPanelHitTestResult result = designPanel.HitTest(e.GetPosition(designPanel), false, true);
183+
DesignPanelHitTestResult result = designPanel.HitTest(e.GetPosition(designPanel), false, true, HitTestType.Default);
184184
if (result.ModelHit != null) {
185185
IPlacementBehavior behavior = result.ModelHit.GetBehavior<IPlacementBehavior>();
186186
if (behavior != null) {

src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/MoveLogic.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ DesignPanelHitTestResult HitTestUnselectedModel(Point p)
124124
return true; // continue hit testing
125125
result = r;
126126
return false; // finish hit testing
127-
});
127+
}, HitTestType.Default);
128128

129129
return result;
130130
}

src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/PointerTool.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public void Deactivate(IDesignPanel designPanel)
4242
void OnMouseDown(object sender, MouseButtonEventArgs e)
4343
{
4444
IDesignPanel designPanel = (IDesignPanel)sender;
45-
DesignPanelHitTestResult result = designPanel.HitTest(e.GetPosition(designPanel), false, true);
45+
DesignPanelHitTestResult result = designPanel.HitTest(e.GetPosition(designPanel), false, true, HitTestType.ElementSelection);
4646
if (result.ModelHit != null) {
4747
IHandlePointerToolMouseDown b = result.ModelHit.GetBehavior<IHandlePointerToolMouseDown>();
4848
if (b != null) {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4+
// software and associated documentation files (the "Software"), to deal in the Software
5+
// without restriction, including without limitation the rights to use, copy, modify, merge,
6+
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7+
// to whom the Software is furnished to do so, subject to the following conditions:
8+
//
9+
// The above copyright notice and this permission notice shall be included in all copies or
10+
// substantial portions of the Software.
11+
//
12+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13+
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14+
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15+
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17+
// DEALINGS IN THE SOFTWARE.
18+
19+
using System;
20+
using System.Collections.Generic;
21+
using System.Linq;
22+
using System.Text;
23+
24+
namespace ICSharpCode.WpfDesign
25+
{
26+
/// <summary>
27+
///
28+
/// </summary>
29+
public enum HitTestType
30+
{
31+
/// <summary>
32+
///
33+
/// </summary>
34+
Default,
35+
36+
/// <summary>
37+
///
38+
/// </summary>
39+
ElementSelection,
40+
}
41+
}

src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,14 @@ public interface IDesignPanel : IInputElement
9999
/// <summary>
100100
/// Performs a hit test on the design surface.
101101
/// </summary>
102-
DesignPanelHitTestResult HitTest(Point mousePosition, bool testAdorners, bool testDesignSurface);
103-
102+
DesignPanelHitTestResult HitTest(Point mousePosition, bool testAdorners, bool testDesignSurface, HitTestType hitTestType);
103+
104104
/// <summary>
105105
/// Performs a hit test on the design surface, raising <paramref name="callback"/> for each match.
106106
/// Hit testing continues while the callback returns true.
107107
/// </summary>
108-
void HitTest(Point mousePosition, bool testAdorners, bool testDesignSurface, Predicate<DesignPanelHitTestResult> callback);
109-
108+
void HitTest(Point mousePosition, bool testAdorners, bool testDesignSurface, Predicate<DesignPanelHitTestResult> callback, HitTestType hitTestType);
109+
110110
// The following members were missing in <see cref="IInputElement"/>, but
111111
// are supported on the DesignPanel:
112112

src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
<Compile Include="Adorners\AdornerProviderClasses.cs" />
7575
<Compile Include="Adorners\RelativePlacement.cs" />
7676
<Compile Include="ExtensionMethods.cs" />
77+
<Compile Include="HitTestType.cs" />
7778
<Compile Include="Metadata.cs" />
7879
<Compile Include="PlacementInformation.cs" />
7980
<Compile Include="PlacementBehavior.cs" />

0 commit comments

Comments
 (0)