using Northwoods.GoXam;
using Northwoods.GoXam.Model;
using Northwoods.GoXam.Tool;
using System;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
namespace WpfWindow1
{
/// <summary>
/// Interaction logic for Flip.xaml
/// </summary>
public partial class Flip : UserControl
{
public Flip()
{
InitializeComponent();
// model is a GraphLinksModel using instances of MyNodeData as the node data
// and MyLinkData as the link data
var model = new GraphLinksModel<MyNodeData, String, String, MyLinkData>();
// Flip: 0 normal, 1 flipped horizontally, 2 flipped vertically, 3 flipped both ways
model.NodesSource = new ObservableCollection<MyNodeData>() {
new MyNodeData() { Key="Alpha", Location=new Point(0, 0) },
new MyNodeData() { Key="Beta", Location=new Point(150, 50), Flip=1 },
new MyNodeData() { Key="Gamma", Location=new Point(-80, 120), Flip=2 },
new MyNodeData() { Key="Delta", Location=new Point(100, 200), Flip=3 }
};
model.LinksSource = new ObservableCollection<MyLinkData>() {
new MyLinkData() { From="Alpha", FromPort="TR", To="Beta", ToPort="TR" },
new MyLinkData() { From="Alpha", FromPort="BL", To="Gamma", ToPort="TR" },
new MyLinkData() { From="Gamma", FromPort="R", To="Delta", ToPort="R" },
new MyLinkData() { From="Beta", FromPort="BL", To="Delta", ToPort="TL" }
};
model.Modifiable = true;
model.HasUndoManager = true;
myDiagram.Model = model;
}
private void FlipH_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("FlipH_Click.01");
var elt = sender as FrameworkElement;
if (elt != null && elt.DataContext != null)
{
Console.WriteLine("FlipH_Click.02");
//MessageBox.Show("dataType:" + ((PartManager.PartBinding)elt.DataContext).Data.GetType().ToString());
var data = ((PartManager.PartBinding)elt.DataContext).Data as MyNodeData;
if (data != null)
{
Console.WriteLine("FlipH_Click.03");
myDiagram.StartTransaction("FlippedH");
data.Flip ^= 1;
myDiagram.CommitTransaction("FlippedH");
}
Console.WriteLine("FlipH_Click.04");
}
}
private void FlipV_Click(object sender, RoutedEventArgs e)
{
var elt = sender as FrameworkElement;
if (elt != null && elt.DataContext != null)
{
var data = ((PartManager.PartBinding)elt.DataContext).Data as MyNodeData;
if (data != null)
{
myDiagram.StartTransaction("FlippedV");
data.Flip ^= 2;
myDiagram.CommitTransaction("FlippedV");
}
}
}
private void Rotate90_click(object sender, RoutedEventArgs e)
{
var elt = sender as FrameworkElement;
if (elt != null && elt.DataContext != null)
{
var data = ((PartManager.PartBinding)elt.DataContext).Data as MyNodeData;
if (data != null)
{
myDiagram.StartTransaction("rot90");
((PartManager.PartBinding)elt.DataContext).Node.RotationAngle += 90;
myDiagram.CommitTransaction("rot90");
}
}
}
}
// Define custom node data; the node key is of type String.
// Add a property named Color that might change.
[Serializable] // serializable in WPF to support the clipboard
public class MyNodeData : GraphLinksModelNodeData<String>
{
public String Color
{
get { return _Color; }
set
{
if (_Color != value)
{
String old = _Color;
_Color = value;
RaisePropertyChanged("Color", old, value);
}
}
}
private String _Color = "White";
public int Flip
{
get { return _Flip; }
set
{
if (_Flip != value)
{
int old = _Flip;
_Flip = value;
RaisePropertyChanged("Flip", old, value);
}
}
}
private int _Flip = 0;
}
// Define custom link data; the node key is of type String,
// the port key should be of type String but is unused in this app.
[Serializable] // serializable in WPF to support the clipboard
public class MyLinkData : GraphLinksModelLinkData<String, String>
{
// nothing to add
}
// Flip: 0 normal, 1 flipped horizontally, 2 flipped vertically, 3 flipped both ways
public class FlipToTransformConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
switch (value)
{
case 1: return new ScaleTransform(-1, 1);
case 2: return new ScaleTransform(1, -1);
case 3: return new ScaleTransform(-1, -1);
default: return new ScaleTransform(1, 1);
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class FlipToSpotConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var name = parameter == null ? "R" : parameter.ToString();
if (name.Length == 0) name = "R";
switch (name[0])
{
case 'T': // top
switch (value)
{
case 1: return new Spot(0.5, 0); // flipped horizontally
case 2: return new Spot(0.5, 1, 0, -8); // flipped vertically
case 3: return new Spot(0.5, 1, 0, -8); // flipped both
default: return new Spot(0.5, 0); // normal
}
case 'L': // left
switch (value)
{
case 1: return new Spot(1, 0.5, -8, 0); // flipped horizontally
case 2: return new Spot(0, 0.5); // flipped vertically
case 3: return new Spot(1, 0.5, -8, 0); // flipped both
default: return new Spot(0, 0.5); // normal
}
case 'R': // right
switch (value)
{
case 1: return new Spot(0, 0.5, 8, 0); // flipped horizontally
case 2: return new Spot(1, 0.5); // flipped vertically
case 3: return new Spot(0, 0.5, 8, 0); // flipped both
default: return new Spot(1, 0.5); // normal
}
default: // bottom
switch (value)
{
case 1: return new Spot(0.5, 1); // flipped horizontally
case 2: return new Spot(0.5, 0, 0, 8); // flipped vertically
case 3: return new Spot(0.5, 0, 0, 8); // flipped both
default: return new Spot(0.5, 1); // normal
}
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class CustomResizingTool : ResizingTool
{
public override void UpdateAdornments(Part part)
{
if (part == null || part is Link) return; // can't resize links
var ToolCategory = "Resize";
Adornment adornment = null;
if (part.IsSelected)
{
FrameworkElement selelt = null;
//String eltname = part.ResizeElementName;
//if (eltname != null) selelt = part.FindNamedDescendant(eltname);
if (selelt == null) selelt = part.SelectionElement;
if (selelt != null && part.CanResize() && Part.IsVisibleElement(selelt))
{
adornment = part.GetAdornment(ToolCategory);
if (adornment == null)
{
DataTemplate template = part.ResizeAdornmentTemplate;
if (template == null) template = Diagram.FindDefault<DataTemplate>("DefaultResizeAdornmentTemplate");
adornment = part.MakeAdornment(selelt, template);
if (adornment != null)
{
adornment.Category = ToolCategory;
adornment.LocationSpot = Spot.TopLeft;
}
}
if (adornment != null)
{
Node node = (Node)part;
Point loc = part.GetElementPoint(selelt, Spot.TopLeft);
var shape = selelt as Shape;
if (shape != null) loc.Offset(3, 3);
// use the node's angle, not part.GetAngle(selelt)
//?? this can be wrong if there are additional rotational transforms in the tree
double angle = node.RotationAngle;
UpdateResizeHandles(adornment.VisualElement, angle);
adornment.Location = loc;
adornment.RotationAngle = angle;
adornment.Remeasure();
}
}
}
part.SetAdornment(ToolCategory, adornment);
}
// copied from ResizingTool.cs
private void UpdateResizeHandles(FrameworkElement elt, double angle)
{
if (elt == null) return;
if (NodePanel.GetFigure(elt) != NodeFigure.None)
{
SetResizeCursor(elt, angle);
}
else
{
int count = VisualTreeHelper.GetChildrenCount(elt);
for (int i = 0; i < count; i++)
{
UpdateResizeHandles(VisualTreeHelper.GetChild(elt, i) as FrameworkElement, angle);
}
}
}
private void SetResizeCursor(FrameworkElement h, double angle)
{
Spot spot = SpotPanel.GetSpot(h);
if (spot.IsNoSpot) spot = Spot.Center;
double a = angle;
if (spot.X <= 0)
{ // left
if (spot.Y <= 0)
{ // top-left
a += 225;
}
else if (spot.Y >= 1)
{ // bottom-left
a += 135;
}
else
{ // middle-left
a += 180;
}
}
else if (spot.X >= 1)
{ // right
if (spot.Y <= 0)
{ // top-right
a += 315;
}
else if (spot.Y >= 1)
{ // bottom-right
a += 45;
}
else
{ // middle-right
// a += 0;
}
}
else
{ // middle-X
if (spot.Y <= 0)
{ // top-middle
a += 270;
}
else if (spot.Y >= 1)
{ // bottom-middle
a += 90;
}
else
{
// handle is in the middle-middle -- don't do anything
return;
}
}
if (a < 0) a += 360;
else if (a >= 360) a -= 360;
if (a < 22.5)
h.Cursor = Cursors.SizeWE;
else if (a < 67.5)
h.Cursor = Cursors.SizeNWSE;
else if (a < 112.5)
h.Cursor = Cursors.SizeNS;
else if (a < 157.5)
h.Cursor = Cursors.SizeNESW;
else if (a < 202.5)
h.Cursor = Cursors.SizeWE;
else if (a < 247.5)
h.Cursor = Cursors.SizeNWSE;
else if (a < 292.5)
h.Cursor = Cursors.SizeNS;
else if (a < 337.5)
h.Cursor = Cursors.SizeNESW;
else
h.Cursor = Cursors.SizeWE;
}
private Spot ComputeResizeSpot(FrameworkElement h)
{
int flip = 0;
var data = this.AdornedNode.Data as MyNodeData;
if (data != null) flip = data.Flip;
Spot spot = SpotPanel.GetSpot(h);
if (spot.IsNoSpot) spot = Spot.Center;
double a = 0;
if (spot.X <= 0)
{ // left
if (spot.Y <= 0)
{ // top-left
a += 225;
}
else if (spot.Y >= 1)
{ // bottom-left
a += 135;
}
else
{ // middle-left
a += 180;
}
}
else if (spot.X >= 1)
{ // right
if (spot.Y <= 0)
{ // top-right
a += 315;
}
else if (spot.Y >= 1)
{ // bottom-right
a += 45;
}
else
{ // middle-right
// a += 0;
}
}
else
{ // middle-X
if (spot.Y <= 0)
{ // top-middle
a += 270;
}
else if (spot.Y >= 1)
{ // bottom-middle
a += 90;
}
else
{
// handle is in the middle-middle -- don't do anything
return spot;
}
}
if (a < 0) a += 360;
else if (a >= 360) a -= 360;
var angle = a;
if (flip == 1)
{ // flip horizontally
a = 180 - a;
}
else if (flip == 2)
{ // flip vertically
a = -a;
}
else if (flip == 3)
{ // flipping both is same as rotating 180
a += 180;
}
if (a < 0) a += 360;
else if (a >= 360) a -= 360;
Spot newspot = spot;
if (a < 22.5)
newspot = Spot.MiddleRight;
else if (a < 67.5)
newspot = Spot.BottomRight;
else if (a < 112.5)
newspot = Spot.BottomCenter;
else if (a < 157.5)
newspot = Spot.BottomLeft;
else if (a < 202.5)
newspot = Spot.MiddleLeft;
else if (a < 247.5)
newspot = Spot.TopLeft;
else if (a < 292.5)
newspot = Spot.TopCenter;
else if (a < 337.5)
newspot = Spot.TopRight;
else
newspot = Spot.MiddleRight;
return newspot;
}
public override void DoActivate()
{
base.DoActivate();
//var spot = SpotPanel.GetSpot(this.Handle);
var spot = ComputeResizeSpot(this.Handle);
var pt = this.AdornedNode.GetElementPoint(this.AdornedElement, spot.Opposite);
int flip = 0;
var data = this.AdornedNode.Data as MyNodeData;
if (data != null) flip = data.Flip;
switch (flip)
{
case 1:
if (spot.X == 1) pt.X += this.OriginalBounds.Width;
else if (spot.X == 0) pt.X -= this.OriginalBounds.Width;
break;
case 2:
if (spot.Y == 1) pt.Y += this.OriginalBounds.Height;
else if (spot.Y == 0) pt.Y -= this.OriginalBounds.Height;
break;
case 3:
if (spot.X == 1) pt.X += this.OriginalBounds.Width;
else if (spot.X == 0) pt.X -= this.OriginalBounds.Width;
if (spot.Y == 1) pt.Y += this.OriginalBounds.Height;
else if (spot.Y == 0) pt.Y -= this.OriginalBounds.Height;
break;
default: break;
}
this.OriginalPoint = pt;
}
private Point OriginalPoint;
protected override void DoResize(Rect newr)
{
Node node = this.AdornedNode;
FrameworkElement elt = node.FindNamedDescendant("SHAPE");
//var spot = SpotPanel.GetSpot(this.Handle);
var spot = ComputeResizeSpot(this.Handle);
elt.Width = newr.Width;
elt.Height = newr.Height;
node.Remeasure();
var pt = node.GetElementPoint(elt, spot.Opposite);
var newloc = node.Location;
newloc.X = newloc.X - pt.X + this.OriginalPoint.X;
newloc.Y = newloc.Y - pt.Y + this.OriginalPoint.Y;
node.Location = newloc;
}
}
}