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

Commit ed0a566

Browse files
committed
Skew Thumb Extension
1 parent 8c15e94 commit ed0a566

3 files changed

Lines changed: 237 additions & 0 deletions

File tree

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
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.Diagnostics;
21+
using System.Windows;
22+
using System.Windows.Controls.Primitives;
23+
using System.Windows.Input;
24+
using System.Windows.Media;
25+
using System.Windows.Shapes;
26+
using ICSharpCode.WpfDesign.Adorners;
27+
using ICSharpCode.WpfDesign.Designer.Controls;
28+
using ICSharpCode.WpfDesign.Extensions;
29+
using System.Collections.Generic;
30+
31+
namespace ICSharpCode.WpfDesign.Designer.Extensions
32+
{
33+
[ExtensionServer(typeof(OnlyOneItemSelectedExtensionServer))]
34+
[ExtensionFor(typeof(FrameworkElement))]
35+
public sealed class SkewThumbExtension : SelectionAdornerProvider
36+
{
37+
readonly AdornerPanel adornerPanel;
38+
readonly DesignItem[] extendedItemArray = new DesignItem[1];
39+
40+
private AdornerLayer _adornerLayer;
41+
42+
public SkewThumbExtension()
43+
{
44+
adornerPanel = new AdornerPanel();
45+
adornerPanel.Order = AdornerOrder.BeforeForeground;
46+
this.Adorners.Add(adornerPanel);
47+
}
48+
49+
#region Skew
50+
51+
private Point startPoint;
52+
private UIElement parent;
53+
private SkewTransform skewTransform;
54+
private double skewX;
55+
private double skewY;
56+
private DesignItem rtTransform;
57+
private Thumb thumb1;
58+
private Thumb thumb2;
59+
60+
private void dragX_Started(DragListener drag)
61+
{
62+
_adornerLayer = this.adornerPanel.TryFindParent<AdornerLayer>();
63+
64+
var designerItem = this.ExtendedItem.Component as FrameworkElement;
65+
this.parent = VisualTreeHelper.GetParent(designerItem) as UIElement;
66+
67+
startPoint = Mouse.GetPosition(this.parent);
68+
69+
if (this.skewTransform == null)
70+
{
71+
this.skewX = 0;
72+
this.skewY = 0;
73+
}
74+
else
75+
{
76+
this.skewX = this.skewTransform.AngleX;
77+
this.skewY = this.skewTransform.AngleY;
78+
}
79+
80+
rtTransform = this.ExtendedItem.Properties[FrameworkElement.RenderTransformProperty].Value;
81+
}
82+
83+
private void dragX_Changed(DragListener drag)
84+
{
85+
Point currentPoint = Mouse.GetPosition(this.parent);
86+
Vector deltaVector = Point.Subtract(currentPoint, this.startPoint);
87+
88+
var destAngle = (-0.5*deltaVector.X) + skewX;
89+
90+
if (destAngle == 0 && skewY == 0)
91+
{
92+
this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformProperty).Reset();
93+
rtTransform = null;
94+
skewTransform = null;
95+
}
96+
else
97+
{
98+
if (rtTransform == null)
99+
{
100+
if (!this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformOriginProperty).IsSet) {
101+
this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformOriginProperty).SetValue(new Point(0.5,0.5));
102+
}
103+
104+
if (this.skewTransform == null)
105+
this.skewTransform = new SkewTransform(0, 0);
106+
this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformProperty).SetValue(skewTransform);
107+
rtTransform = this.ExtendedItem.Properties[FrameworkElement.RenderTransformProperty].Value;
108+
}
109+
rtTransform.Properties["AngleX"].SetValue(destAngle);
110+
}
111+
112+
_adornerLayer.UpdateAdornersForElement(this.ExtendedItem.View, true);
113+
}
114+
115+
private void dragY_Started(DragListener drag)
116+
{
117+
_adornerLayer = this.adornerPanel.TryFindParent<AdornerLayer>();
118+
119+
var designerItem = this.ExtendedItem.Component as FrameworkElement;
120+
this.parent = VisualTreeHelper.GetParent(designerItem) as UIElement;
121+
122+
startPoint = Mouse.GetPosition(this.parent);
123+
124+
if (this.skewTransform == null)
125+
{
126+
this.skewX = 0;
127+
this.skewY = 0;
128+
}
129+
else
130+
{
131+
this.skewX = this.skewTransform.AngleX;
132+
this.skewY = this.skewTransform.AngleY;
133+
}
134+
135+
rtTransform = this.ExtendedItem.Properties[FrameworkElement.RenderTransformProperty].Value;
136+
}
137+
138+
private void dragY_Changed(DragListener drag)
139+
{
140+
Point currentPoint = Mouse.GetPosition(this.parent);
141+
Vector deltaVector = Point.Subtract(currentPoint, this.startPoint);
142+
143+
var destAngle = (-0.5*deltaVector.Y) + skewY;
144+
145+
if (destAngle == 0 && skewX == 0)
146+
{
147+
this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformProperty).Reset();
148+
rtTransform = null;
149+
skewTransform = null;
150+
}
151+
else
152+
{
153+
if (rtTransform == null)
154+
{
155+
if (!this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformOriginProperty).IsSet)
156+
{
157+
this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformOriginProperty).SetValue(new Point(0.5, 0.5));
158+
}
159+
160+
if (this.skewTransform == null)
161+
this.skewTransform = new SkewTransform(0, 0);
162+
this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformProperty).SetValue(skewTransform);
163+
rtTransform = this.ExtendedItem.Properties[FrameworkElement.RenderTransformProperty].Value;
164+
}
165+
rtTransform.Properties["AngleY"].SetValue(destAngle);
166+
}
167+
168+
_adornerLayer.UpdateAdornersForElement(this.ExtendedItem.View, true);
169+
}
170+
171+
#endregion
172+
173+
protected override void OnInitialized()
174+
{
175+
176+
if (this.ExtendedItem.Component is WindowClone)
177+
return;
178+
base.OnInitialized();
179+
180+
extendedItemArray[0] = this.ExtendedItem;
181+
this.ExtendedItem.PropertyChanged += OnPropertyChanged;
182+
183+
var designerItem = this.ExtendedItem.Component as FrameworkElement;
184+
this.skewTransform = designerItem.RenderTransform as SkewTransform;
185+
186+
if (skewTransform != null)
187+
{
188+
skewX = skewTransform.AngleX;
189+
skewY = skewTransform.AngleY;
190+
}
191+
192+
thumb1 = new Thumb() { Cursor = Cursors.ScrollWE, Height = 14, Width = 4, Opacity = 1 };
193+
thumb2 = new Thumb() { Cursor = Cursors.ScrollNS, Width = 14, Height = 4, Opacity = 1 };
194+
195+
OnPropertyChanged(null, null);
196+
197+
adornerPanel.Children.Add(thumb1);
198+
adornerPanel.Children.Add(thumb2);
199+
200+
DragListener drag1 = new DragListener(thumb1);
201+
drag1.Started += dragX_Started;
202+
drag1.Changed += dragX_Changed;
203+
DragListener drag2 = new DragListener(thumb2);
204+
drag2.Started += dragY_Started;
205+
drag2.Changed += dragY_Changed;
206+
}
207+
208+
void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
209+
{
210+
if (sender == null || e.PropertyName == "Width" || e.PropertyName == "Height") {
211+
AdornerPanel.SetPlacement(thumb1,
212+
new RelativePlacement(HorizontalAlignment.Center, VerticalAlignment.Top) {
213+
YOffset = 0,
214+
XOffset = -1 * ((FrameworkElement)ExtendedItem.View).ActualWidth / 4
215+
});
216+
217+
AdornerPanel.SetPlacement(thumb2,
218+
new RelativePlacement(HorizontalAlignment.Left, VerticalAlignment.Center) {
219+
YOffset = -1 * ((FrameworkElement)ExtendedItem.View).ActualHeight / 4,
220+
XOffset = 0
221+
});
222+
}
223+
}
224+
225+
protected override void OnRemove()
226+
{
227+
this.ExtendedItem.PropertyChanged -= OnPropertyChanged;
228+
base.OnRemove();
229+
}
230+
}
231+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
</Compile>
8888
<Compile Include="Extensions\RenderTransformOriginExtension.cs" />
8989
<Compile Include="Extensions\RightClickContextMenuExtension.cs" />
90+
<Compile Include="Extensions\SkewThumbExtension.cs" />
9091
<Compile Include="PropertyGrid\Editors\FlatCollectionEditor.xaml.cs">
9192
<DependentUpon>FlatCollectionEditor.xaml</DependentUpon>
9293
<SubType>Code</SubType>

src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Adorners/AdornerPanel.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,11 @@ public struct AdornerOrder : IComparable<AdornerOrder>, IEquatable<AdornerOrder>
179179
/// </summary>
180180
public static readonly AdornerOrder Foreground = new AdornerOrder(300);
181181

182+
/// <summary>
183+
/// The adorner is in the before foreground layer.
184+
/// </summary>
185+
public static readonly AdornerOrder BeforeForeground = new AdornerOrder(400);
186+
182187
int i;
183188

184189
internal AdornerOrder(int i)

0 commit comments

Comments
 (0)