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

Commit 3dd4916

Browse files
committed
Snapline for middle of Object (like in VisualStudio)
1 parent 9bb17ef commit 3dd4916

1 file changed

Lines changed: 47 additions & 41 deletions

File tree

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

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -41,51 +41,51 @@ public class SnaplinePlacementBehavior : RasterPlacementBehavior
4141
List<Snapline> horizontalMap;
4242
List<Snapline> verticalMap;
4343
double? baseline;
44-
44+
4545
public const double Accuracy = 5;
4646
public const double Margin = 8;
47-
47+
4848
public override void BeginPlacement(PlacementOperation operation)
4949
{
5050
base.BeginPlacement(operation);
5151
CreateSurface(operation);
5252
}
53-
53+
5454
public override void EndPlacement(PlacementOperation operation)
5555
{
5656
base.EndPlacement(operation);
5757
DeleteSurface();
5858
}
59-
59+
6060
public override void EnterContainer(PlacementOperation operation)
6161
{
6262
base.EnterContainer(operation);
6363
CreateSurface(operation);
6464
}
65-
65+
6666
public override void LeaveContainer(PlacementOperation operation)
6767
{
6868
base.LeaveContainer(operation);
6969
DeleteSurface();
7070
}
71-
71+
7272
public override void BeforeSetPosition(PlacementOperation operation)
7373
{
7474
base.BeforeSetPosition(operation);
7575
if (surface == null) return;
76-
76+
7777
DesignPanel designPanel = ExtendedItem.Services.DesignPanel as DesignPanel;
7878
if (designPanel == null || !designPanel.UseSnaplinePlacement)
7979
return;
8080

8181
surface.Children.Clear();
8282
if (Keyboard.IsKeyDown(Key.LeftCtrl)) return;
83-
83+
8484
Rect bounds = Rect.Empty;
8585
foreach (var item in operation.PlacedItems) {
8686
bounds.Union(item.Bounds);
8787
}
88-
88+
8989
var horizontalInput = new List<Snapline>();
9090
var verticalInput = new List<Snapline>();
9191
var info = operation.PlacedItems[0];
@@ -99,7 +99,7 @@ public override void BeforeSetPosition(PlacementOperation operation)
9999
horizontalInput.Add(new Snapline() { Group = 1, Offset = textOffset, Start = bounds.Left, End = bounds.Right });
100100
}
101101
}
102-
102+
103103
// debug
104104
//foreach (var t in horizontalMap.Concat(horizontalInput)) {
105105
// surface.Children.Add(new Line() { X1 = t.Start, X2 = t.End, Y1 = t.Offset, Y2 = t.Offset, Stroke = Brushes.Black });
@@ -108,12 +108,12 @@ public override void BeforeSetPosition(PlacementOperation operation)
108108
// surface.Children.Add(new Line() { X1 = t.Offset, X2 = t.Offset, Y1 = t.Start , Y2 = t.End, Stroke = Brushes.Black });
109109
//}
110110
//return;
111-
111+
112112
List<Snapline> drawLines;
113113
double delta;
114-
114+
115115
if (Snap(horizontalInput, horizontalMap, Accuracy, out drawLines, out delta)) {
116-
116+
117117
if (operation.Type == PlacementType.Resize) {
118118
if (info.ResizeThumbAlignment.Vertical == VerticalAlignment.Top) {
119119
bounds.Y += delta;
@@ -129,14 +129,14 @@ public override void BeforeSetPosition(PlacementOperation operation)
129129
item.Bounds = r;
130130
}
131131
}
132-
132+
133133
foreach (var d in drawLines) {
134134
DrawLine(d.Start, d.Offset, d.End, d.Offset);
135135
}
136136
}
137-
137+
138138
if (Snap(verticalInput, verticalMap, Accuracy, out drawLines, out delta)) {
139-
139+
140140
if (operation.Type == PlacementType.Resize) {
141141
if (info.ResizeThumbAlignment.Horizontal == HorizontalAlignment.Left) {
142142
bounds.X += delta;
@@ -158,52 +158,52 @@ public override void BeforeSetPosition(PlacementOperation operation)
158158
}
159159
}
160160
}
161-
161+
162162
void CreateSurface(PlacementOperation operation)
163163
{
164164
if (ExtendedItem.Services.GetService<IDesignPanel>() != null) {
165-
165+
166166
surface = new Canvas();
167167
adornerPanel = new AdornerPanel();
168168
adornerPanel.SetAdornedElement(ExtendedItem.View, ExtendedItem);
169169
AdornerPanel.SetPlacement(surface, AdornerPlacement.FillContent);
170170
adornerPanel.Children.Add(surface);
171171
ExtendedItem.Services.DesignPanel.Adorners.Add(adornerPanel);
172-
172+
173173
BuildMaps(operation);
174-
174+
175175
if (operation.Type != PlacementType.Resize && operation.PlacedItems.Count == 1) {
176176
baseline = GetBaseline(operation.PlacedItems[0].Item.View);
177177
}
178178
}
179179
}
180-
180+
181181
void BuildMaps(PlacementOperation operation)
182182
{
183183
horizontalMap = new List<Snapline>();
184184
verticalMap = new List<Snapline>();
185-
185+
186186
var containerRect = new Rect(0, 0, ModelTools.GetWidth(ExtendedItem.View), ModelTools.GetHeight(ExtendedItem.View));
187187
AddLines(containerRect, -Margin, false);
188-
188+
189189
AddLines(containerRect, 0, false);
190190

191191
foreach (var item in ExtendedItem.ContentProperty.CollectionElements
192-
.Except(operation.PlacedItems.Select(f => f.Item)))
192+
.Except(operation.PlacedItems.Select(f => f.Item)))
193193
{
194194
var bounds = GetPosition(operation, item);
195-
195+
196196
AddLines(bounds, 0, false);
197197
AddLines(bounds, Margin, true);
198198
AddBaseline(item, bounds, horizontalMap);
199199
}
200200
}
201-
201+
202202
void AddLines(Rect r, double inflate, bool requireOverlap)
203203
{
204204
AddLines(r, inflate, requireOverlap, horizontalMap, verticalMap, null);
205205
}
206-
206+
207207
void AddLines(Rect r, double inflate, bool requireOverlap, List<Snapline> h, List<Snapline> v, PlacementAlignment? filter)
208208
{
209209
Rect r2 = r;
@@ -217,8 +217,14 @@ void AddLines(Rect r, double inflate, bool requireOverlap, List<Snapline> h, Lis
217217
v.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Left - 1, Start = r.Top, End = r.Bottom });
218218
if (filter == null || filter.Value.Horizontal == HorizontalAlignment.Right)
219219
v.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Right - 1, Start = r.Top, End = r.Bottom });
220+
221+
if (filter == null)
222+
{
223+
h.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Top + Math.Abs((r2.Top - r2.Bottom) / 2), Start = r.Left, End = r.Right });
224+
v.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Left + Math.Abs((r2.Left - r2.Right) / 2), Start = r.Top, End = r.Bottom });
225+
}
220226
}
221-
227+
222228
void AddBaseline(DesignItem item, Rect bounds, List<Snapline> list)
223229
{
224230
var baseline = GetBaseline(item.View);
@@ -227,7 +233,7 @@ void AddBaseline(DesignItem item, Rect bounds, List<Snapline> list)
227233
list.Add(new Snapline() { Group = 1, Offset = textOffset, Start = bounds.Left, End = bounds.Right });
228234
}
229235
}
230-
236+
231237
void DeleteSurface()
232238
{
233239
if (surface != null) {
@@ -238,7 +244,7 @@ void DeleteSurface()
238244
verticalMap = null;
239245
}
240246
}
241-
247+
242248
void DrawLine(double x1, double y1, double x2, double y2)
243249
{
244250
var line1 = new Line() {
@@ -250,7 +256,7 @@ void DrawLine(double x1, double y1, double x2, double y2)
250256
Stroke = Brushes.White
251257
};
252258
surface.Children.Add(line1);
253-
259+
254260
var line2 = new Line() {
255261
X1 = x1,
256262
Y1 = y1,
@@ -263,7 +269,7 @@ void DrawLine(double x1, double y1, double x2, double y2)
263269
};
264270
surface.Children.Add(line2);
265271
}
266-
272+
267273
//TODO: GlyphRun must be used
268274
static double? GetBaseline(UIElement element) {
269275
var textBox = element as TextBox;
@@ -274,32 +280,32 @@ void DrawLine(double x1, double y1, double x2, double y2)
274280
var textBlock = element as TextBlock;
275281
if (textBlock != null)
276282
return textBlock.TranslatePoint(new Point(0, textBlock.ActualHeight), element).Y;
277-
283+
278284
return null;
279285
}
280-
286+
281287
static bool Snap(List<Snapline> input, List<Snapline> map, double accuracy,
282-
out List<Snapline> drawLines, out double delta)
288+
out List<Snapline> drawLines, out double delta)
283289
{
284290
delta = double.MaxValue;
285291
drawLines = null;
286-
292+
287293
foreach (var inputLine in input) {
288294
foreach (var mapLine in map) {
289295
if (Math.Abs(mapLine.Offset - inputLine.Offset) <= accuracy) {
290296
if (!inputLine.RequireOverlap && !mapLine.RequireOverlap ||
291-
Math.Max(inputLine.Start, mapLine.Start) < Math.Min(inputLine.End, mapLine.End))
297+
Math.Max(inputLine.Start, mapLine.Start) < Math.Min(inputLine.End, mapLine.End))
292298
{
293299
if (mapLine.Group == inputLine.Group)
294300
delta = mapLine.Offset - inputLine.Offset;
295301
}
296302
}
297303
}
298304
}
299-
305+
300306
if (delta == double.MaxValue) return false;
301307
var offsetDict = new Dictionary<double, Snapline>();
302-
308+
303309
foreach (var inputLine in input) {
304310
inputLine.Offset += delta;
305311
foreach (var mapLine in map) {
@@ -318,11 +324,11 @@ static bool Snap(List<Snapline> input, List<Snapline> map, double accuracy,
318324
}
319325
}
320326
}
321-
327+
322328
drawLines = offsetDict.Values.ToList();
323329
return true;
324330
}
325-
331+
326332
[DebuggerDisplay("Snapline: {Offset}")]
327333
class Snapline
328334
{

0 commit comments

Comments
 (0)