using System;
using log4net;
using Steema.TeeChart;
using Steema.TeeChart.Drawing;
using Steema.TeeChart.Tools;
#if WPF
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;
#else
using System.Drawing;
using System.Windows.Forms;
#endif
namespace DelftTools.Controls.Swf.Charting.Tools
{
internal class RectangleTool : Annotation, IRectangleTool
{
private static readonly ILog log = LogManager.GetLogger(typeof(RectangleTool));
private int iEdge;
private bool iDrag;
private Point P;
public event RectangleToolDraggingEventHandler Dragging;
public event RectangleToolResizingEventHandler Resizing;
public event RectangleToolResizedEventHandler Resized;
public event RectangleToolDraggedEventHandler Dragged;
private bool allowResizeWidth = false;
public bool AllowResizeHeight { get; set; }
public bool AllowResizeWidth
{
get
{
return allowResizeWidth;
}
set
{
allowResizeWidth = value;
}
}
public RectangleTool() : this((Steema.TeeChart.Chart) null) {}
public RectangleTool(Steema.TeeChart.Chart c)
: base(c)
{
AllowResizeHeight = false;
AutoSize = false;
AllowDrag = true;
AllowResize = true;
iEdge = -1;
Shape.CustomPosition = true;
Shape.Shadow.Visible = false;
Shape.Transparency = 50;
Shape.Left = 10;
Shape.Top = 10;
Shape.Width = 50;
Shape.Height = 50;
Shape.Bevel.Inner = BevelStyles.None;
Shape.Bevel.Outer = BevelStyles.None;
PositionUnits = PositionUnits.Pixels;
#if ! POCKET
Cursor = Cursors.Hand;
#endif
P = new Point(0, 0);
Shape.Pen.Width = 3;
Shape.Pen.Color = Color.FromArgb(200, 150, 0, 0);
Shape.Brush.Transparency = 50;
allowResizeWidth = true;
}
protected override void ChartEvent(EventArgs e)
{
if (e is BeforeDrawEventArgs)
{
if (Shape.Left < Chart.ChartRect.Left)
{
Shape.Left = Chart.ChartRect.Left;
}
if (Shape.Left + Shape.Width > Chart.ChartRect.Right)
{
Shape.Left = Chart.ChartRect.Right - Shape.Width;
}
// Shape.Left = chart.ChartRect.Left;
// Shape.Width = chart.ChartRect.Width;
if (!AllowResizeHeight)
{
Shape.Top = Chart.ChartRect.Top;
Shape.Height = Chart.ChartRect.Height;
}
}
base.ChartEvent(e);
}
///
/// Gets descriptive text.
///
#if DESIGNATTRIBUTES
[Description("Gets descriptive text.")]
#endif
public override string Description
{
get
{
return Texts.RectangleTool;
}
}
#region public properties
#if DESIGNATTRIBUTES
[DefaultValue(true)]
#endif
public bool AllowResize { get; set; }
#if DESIGNATTRIBUTES
[DefaultValue(true)]
#endif
public bool AllowDrag { get; set; }
#endregion
protected virtual void OnDragging(EventArgs e)
{
if (Dragging != null)
{
Dragging(this, e);
}
}
protected virtual void OnResizing(EventArgs e)
{
if (Resizing != null)
{
Resizing(this, e);
}
}
protected virtual void OnResized(EventArgs e)
{
if (Resized != null)
{
Resized(this, e);
}
}
protected virtual void OnDragged(EventArgs e)
{
if (Dragged != null)
{
Dragged(this, e);
}
}
#if WPF
private void StartResizing(double X, double Y)
#else
private void StartResizing(int X, int Y)
#endif
{
if (iEdge == 2 || iEdge == 6 || iEdge == 7)
{
P.X = X - Shape.ShapeBounds.Right;
}
else
{
P.X = X - Shape.Left;
}
if (iEdge == 3 || iEdge == 5 || iEdge == 7)
{
P.Y = Y - Shape.ShapeBounds.Bottom;
}
else
{
P.Y = Y - Shape.Top;
}
Chart.CancelMouse = true;
}
#if WPF
private void StartDragging(double X, double Y)
#else
private void StartDragging(int X, int Y)
#endif
{
P.X = X - Shape.Left;
P.Y = Y - Shape.Top;
iDrag = true;
Chart.CancelMouse = true;
}
private void StopDrag()
{
OnDragged(EventArgs.Empty);
iDrag = false;
}
private void StopResize()
{
OnResized(EventArgs.Empty);
iEdge = -1;
}
#if WPF
private void TryDrag(double X, double Y)
#else
private void TryDrag(int X, int Y)
#endif
{
#if WPF
double tmpW, tmpH;
#else
int tmpW, tmpH;
#endif
if (X != P.X || Y != P.Y)
{
Shape.Left = X - P.X;
Shape.Top = Y - P.Y;
if (Shape.Left < Chart.ChartRect.Left)
{
Shape.Left = Chart.ChartRect.Left;
}
if (Shape.Left > Chart.ChartRect.Right - Shape.Width)
{
Shape.Left = Chart.ChartRect.Right - Shape.Width;
}
OnDragging(EventArgs.Empty);
}
}
#if WPF
private void ChangeLeft(ref double Left, double X)
#else
private void ChangeLeft(ref int Left, int X)
#endif
{
if (allowResizeWidth)
{
Left = Math.Min(Shape.Right - 3, X - P.X);
}
}
#if WPF
private void ChangeTop(ref double Top, double Y)
#else
private void ChangeTop(ref int Top, int Y)
#endif
{
if (AllowResizeHeight)
{
Top = Math.Min(Shape.Bottom - 3, Y - P.Y);
}
}
#if WPF
private void ChangeRight(ref double Right, double X)
#else
private void ChangeRight(ref int Right, int X)
#endif
{
if (allowResizeWidth)
{
Right = Math.Max(Shape.Left + 3, X - P.X);
}
}
#if WPF
private void ChangeBottom(ref double Bottom, double Y)
#else
private void ChangeBottom(ref int Bottom, int Y)
#endif
{
if (AllowResizeHeight)
{
Bottom = Math.Max(Shape.Top + 3, Y - P.Y);
}
}
#if WPF
private void DoResize(double X, double Y)
#else
private void DoResize(int X, int Y)
#endif
{
#if WPF
double left, right, top, bottom;
Rect tmpR = Rect.Empty;
#else
int left, right, top, bottom;
Rectangle tmpR = Rectangle.Empty;
#endif
left = Shape.Left;
right = Shape.Right;
top = Shape.Top;
bottom = Shape.Bottom;
switch (iEdge)
{
case 0:
ChangeLeft(ref left, X);
if (left < Chart.ChartRect.Left)
{
left = Chart.ChartRect.Left;
}
break;
case 1:
ChangeTop(ref top, Y);
break;
case 2:
ChangeRight(ref right, X);
if (right > Chart.ChartRect.Right)
{
right = Chart.ChartRect.Right;
}
break;
case 3:
ChangeBottom(ref bottom, Y);
break;
case 4:
ChangeLeft(ref left, X);
ChangeTop(ref top, Y);
break;
case 5:
ChangeLeft(ref left, X);
ChangeBottom(ref bottom, Y);
break;
case 6:
ChangeRight(ref right, X);
ChangeTop(ref top, Y);
break;
case 7:
ChangeRight(ref right, X);
ChangeBottom(ref bottom, Y);
break;
}
tmpR = Steema.TeeChart.Utils.FromLTRB(left, top, right, bottom);
Shape.ShapeBounds = tmpR;
Shape.Invalidate();
OnResizing(EventArgs.Empty);
}
protected override void MouseEvent(MouseEventKinds kind, MouseEventArgs e, ref Cursor c)
{
if (Active)
{
#if WPF
Point tmP = e.GetPosition(Chart.Parent.GetControl());
#else
Point tmP = new Point(e.X, e.Y);
#endif
switch (kind)
{
case MouseEventKinds.Down:
#if WPF
if (Utils.GetMouseButton(e) == MouseButton.Left)
#else
if (Steema.TeeChart.Utils.GetMouseButton(e) == MouseButtons.Left)
#endif
{
if (AllowResize)
{
iEdge = ClickedEdge(tmP.X, tmP.Y);
}
if (iEdge != -1)
{
StartResizing(tmP.X, tmP.Y);
}
else if (NearRectangle(tmP) && AllowDrag)
{
StartDragging(tmP.X, tmP.Y);
}
}
#if POCKET || WPF
OnClick(e);
#else
if (e.Clicks == 2)
{
OnDoubleClick(e);
}
else
{
OnClick(e);
}
#endif
break;
case MouseEventKinds.Move:
if (iDrag)
{
TryDrag(tmP.X, tmP.Y);
}
else
{
if (iEdge != -1)
{
DoResize(tmP.X, tmP.Y);
}
else
{
bool canGuessCursor = GuessEdgeCursor(tmP.X, tmP.Y); //also resets cursor
Chart.CancelMouse = canGuessCursor;
if (!canGuessCursor)
{
if (NearRectangle(tmP))
{
Chart.Parent.SetCursor(Cursors.Hand);
}
}
}
}
tmpX = tmP.X;
tmpY = tmP.Y;
break;
case MouseEventKinds.Up:
if (iDrag)
{
StopDrag();
}
else if (iEdge != -1)
{
StopResize();
}
break;
}
}
}
private bool NearRectangle(Point p)
{
Rectangle rect = Rectangle.FromLTRB(Left, Top, Left + Width, Top + Height);
rect.Inflate(10, 0);
return rect.Contains(p);
}
private bool TrySet(Cursor aCursor)
{
if (AllowResize)
{
Chart.Parent.SetCursor(aCursor);
return true;
}
else
{
return false;
}
}
#if WPF
private bool GuessEdgeCursor(double x, double y)
#else
private bool GuessEdgeCursor(int x, int y)
#endif
{
bool result = false;
#if WPF
Chart.parent.SetCursor(Cursors.Arrow);
#else
Chart.Parent.SetCursor(Cursors.Default);
#endif
switch (ClickedEdge(x, y))
{
#if ! POCKET
case 0:
if (allowResizeWidth)
{
result = TrySet(Cursors.SizeWE);
}
break;
case 1:
if (AllowResizeHeight)
{
result = TrySet(Cursors.SizeNS);
}
break;
case 2:
if (allowResizeWidth)
{
result = TrySet(Cursors.SizeWE);
}
break;
case 3:
if (AllowResizeHeight)
{
result = TrySet(Cursors.SizeNS);
}
break;
case 4:
result = TrySet(Cursors.SizeNWSE);
break;
case 5:
result = TrySet(Cursors.SizeNESW);
break;
case 6:
result = TrySet(Cursors.SizeNESW);
break;
case 7:
result = TrySet(Cursors.SizeNWSE);
break;
#endif
default:
#if WPF
if (Clicked(x, y) && Cursor != Cursors.Arrow)
#else
if (Clicked(x, y) && Cursor != Cursors.Default)
#endif
{
result = TrySet(Cursor);
}
break;
}
return result;
}
#if WPF
private int ClickedEdge(double x, double y)
#else
private int ClickedEdge(int x, int y)
#endif
{
const int Tolerance = 4;
#if WPF
Rect R;
#else
Rectangle R;
#endif
int result = -1;
if (Clicked(x, y))
{
R = Shape.ShapeBounds;
if (Math.Abs(x - R.Left) < Tolerance)
{
if (Math.Abs(y - R.Top) < Tolerance)
{
result = -1; // disable corner dragging
// result = 4;
}
else if (Math.Abs(y - R.Bottom) < Tolerance)
{
result = -1; // disable corner dragging
// result = 5;
}
else
{
result = 0;
}
}
else if (Math.Abs(y - R.Top) < Tolerance)
{
if (Math.Abs(x - R.Right) < Tolerance)
{
result = -1; // disable corner dragging
//result = 6;
}
else
{
result = 1;
}
}
else if (Math.Abs(x - R.Right) < Tolerance)
{
if (Math.Abs(y - R.Bottom) < Tolerance)
{
result = -1; // disable corner dragging
// result = 7;
}
else
{
result = 2;
}
}
else if (Math.Abs(y - R.Bottom) < Tolerance)
{
result = 3;
}
}
return result;
}
public void FireResisedEvent()
{
OnResized(EventArgs.Empty);
}
public void FireDraggedEvent()
{
OnDragged(EventArgs.Empty);
}
#region IChartViewTool Members
public IChartView ChartView { get; set; }
#endregion
public bool Enabled { get; set; }
public new bool Active
{
get
{
return base.Active;
}
set
{
base.Active = value;
if (ActiveChanged != null)
{
ActiveChanged(this, null);
}
}
}
public event EventHandler ActiveChanged;
}
public delegate void RectangleToolDraggingEventHandler(object sender, EventArgs e);
public delegate void RectangleToolResizingEventHandler(object sender, EventArgs e);
public delegate void RectangleToolResizedEventHandler(object sender, EventArgs e);
public delegate void RectangleToolDraggedEventHandler(object sender, EventArgs e);
}