Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLluis Sanchez <lluis@novell.com>2010-03-17 15:35:28 +0300
committerLluis Sanchez <lluis@novell.com>2010-03-17 15:35:28 +0300
commit8fa37870e9cc22ffccdd494fa951b2c3807d7978 (patch)
treebda14806802947c51676c183b08f166878964c40 /main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart
parentf1a8582658af8aeb0f6fa459965a2e4d0684c347 (diff)
parent585086f0ea0a49166046bb8f48d2def87907d0e0 (diff)
Merged MD.Projects into MD.Core, and MD.Projects.Gui, MD.Core.Gui and MD.Components into MD.Ide.
svn path=/trunk/monodevelop/; revision=153730
Diffstat (limited to 'main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart')
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/Axis.cs95
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/AxisDimension.cs35
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/AxisPosition.cs40
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/BasicChart.cs928
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/ChartCursor.cs89
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/DateTimeAxis.cs143
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/IntegerAxis.cs96
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/Serie.cs198
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/TickEnumerator.cs46
9 files changed, 1670 insertions, 0 deletions
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/Axis.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/Axis.cs
new file mode 100644
index 0000000000..d0e5f2d008
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/Axis.cs
@@ -0,0 +1,95 @@
+//
+// Axis.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+
+namespace MonoDevelop.Components.Chart
+{
+ public abstract class Axis
+ {
+ int tickSize = 6;
+ internal BasicChart Owner;
+ AxisPosition position;
+ AxisDimension dim;
+ bool showLabels = true;
+
+ public Axis ()
+ {
+ }
+
+ public Axis (bool showLabels)
+ {
+ this.showLabels = showLabels;
+ }
+
+ public int TickSize {
+ get { return tickSize; }
+ set {
+ tickSize = value;
+ if (Owner != null) Owner.QueueDraw ();
+ }
+ }
+
+ public bool ShowLabels {
+ get { return showLabels; }
+ set {
+ showLabels = value;
+ if (Owner != null) Owner.OnLayoutChanged ();
+ }
+ }
+
+ internal AxisPosition Position {
+ get { return position; }
+ set {
+ position = value;
+ if (position == AxisPosition.Top || position == AxisPosition.Bottom)
+ dim = AxisDimension.X;
+ else
+ dim = AxisDimension.Y;
+ }
+ }
+
+ internal AxisDimension Dimension {
+ get { return dim; }
+ }
+
+ public TickEnumerator GetTickEnumerator (double minTickStep)
+ {
+ TickEnumerator e = CreateTickEnumerator (minTickStep);
+ e.axis = this;
+ return e;
+ }
+
+ protected abstract TickEnumerator CreateTickEnumerator (double minTickStep);
+
+ public virtual string GetValueLabel (double value)
+ {
+ return value.ToString ();
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/AxisDimension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/AxisDimension.cs
new file mode 100644
index 0000000000..ebf0833059
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/AxisDimension.cs
@@ -0,0 +1,35 @@
+//
+// AxisDimension.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MonoDevelop.Components.Chart
+{
+ public enum AxisDimension
+ {
+ X, Y
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/AxisPosition.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/AxisPosition.cs
new file mode 100644
index 0000000000..42b81826ec
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/AxisPosition.cs
@@ -0,0 +1,40 @@
+//
+// AxisPosition.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+
+namespace MonoDevelop.Components.Chart
+{
+ public enum AxisPosition
+ {
+ Left,
+ Top,
+ Right,
+ Bottom
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/BasicChart.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/BasicChart.cs
new file mode 100644
index 0000000000..52304a20f2
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/BasicChart.cs
@@ -0,0 +1,928 @@
+//
+// BasicChart.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Gtk;
+using Gdk;
+
+namespace MonoDevelop.Components.Chart
+{
+ public class BasicChart: DrawingArea
+ {
+ double startX, endX;
+ double startY, endY;
+ int left, top, width, height;
+ int minTickStep = 5;
+ bool xrangeChanged = true;
+ bool yrangeChanged = true;
+
+ bool autoStartX, autoStartY;
+ bool autoEndX, autoEndY;
+
+ double originX;
+ double originY;
+ bool reverseXAxis;
+ bool reverseYAxis;
+
+ int AreaBorderWidth = 1;
+ int AutoScaleMargin = 3;
+ int MinLabelGapX = 3;
+ int MinLabelGapY = 1;
+ BackgroundDisplay backgroundDisplay = BackgroundDisplay.Gradient;
+ Cairo.Color backroundColor = new Cairo.Color (0.9, 0.9, 1);
+
+ ArrayList series = new ArrayList ();
+ ArrayList axis = new ArrayList ();
+ ArrayList cursors = new ArrayList ();
+
+ bool enableSelection;
+ bool draggingCursor;
+ ChartCursor activeCursor;
+
+ ChartCursor selectionStart;
+ ChartCursor selectionEnd;
+
+ public BasicChart ()
+ {
+ this.Events = EventMask.ButtonPressMask | EventMask.ButtonReleaseMask | EventMask.PointerMotionMask;
+ selectionStart = new ChartCursor ();
+ selectionStart.Visible = false;
+ selectionEnd = new ChartCursor ();
+ selectionEnd.Visible = false;
+ AddCursor (selectionStart, AxisDimension.X);
+ AddCursor (selectionEnd, AxisDimension.X);
+ selectionStart.ValueChanged += new EventHandler (OnSelectionCursorChanged);
+ selectionEnd.ValueChanged += new EventHandler (OnSelectionCursorChanged);
+ }
+
+ public event EventHandler SelectionChanged;
+
+ public bool AllowSelection {
+ get {
+ return enableSelection;
+ }
+ set {
+ enableSelection = value;
+ if (!enableSelection) {
+ selectionStart.Visible = false;
+ selectionEnd.Visible = false;
+ }
+ }
+ }
+
+ public ChartCursor SelectionStart {
+ get { return selectionStart; }
+ }
+
+ public ChartCursor SelectionEnd {
+ get { return selectionEnd; }
+ }
+
+ public ChartCursor ActiveCursor {
+ get { return activeCursor; }
+ }
+
+ public bool ReverseXAxis {
+ get { return reverseXAxis; }
+ set { reverseXAxis = value; QueueDraw (); }
+ }
+
+ public bool ReverseYAxis {
+ get { return reverseYAxis; }
+ set { reverseYAxis = value; QueueDraw (); }
+ }
+
+ public double OriginX {
+ get { return originX; }
+ set {
+ xrangeChanged = true;
+ originX = value;
+ OnSerieChanged ();
+ }
+ }
+
+ public double OriginY {
+ get { return originY; }
+ set {
+ yrangeChanged = true;
+ originY = value;
+ OnSerieChanged ();
+ }
+ }
+
+ public double StartX {
+ get { return startX; }
+ set {
+ xrangeChanged = true;
+ startX = value;
+ if (startX > endX)
+ endX = startX;
+ OriginX = value;
+ UpdateCursors ();
+ OnSerieChanged ();
+ }
+ }
+
+ public double EndX {
+ get { return endX; }
+ set {
+ xrangeChanged = true;
+ endX = value;
+ if (endX < startX)
+ startX = endX;
+ UpdateCursors ();
+ OnSerieChanged ();
+ }
+ }
+
+ public double StartY {
+ get { return startY; }
+ set {
+ yrangeChanged = true;
+ startY = value;
+ if (startY > endY)
+ endY = startY;
+ OriginY = value;
+ UpdateCursors ();
+ OnSerieChanged ();
+ }
+ }
+
+ public double EndY {
+ get { return endY; }
+ set {
+ yrangeChanged = true;
+ endY = value;
+ if (endY < startY)
+ startY = endY;
+ UpdateCursors ();
+ OnSerieChanged ();
+ }
+ }
+
+ void FixOrigins ()
+ {
+ if (originX < startX)
+ originX = startX;
+ else if (originX > endX)
+ originX = endX;
+ if (originY < startY)
+ originY = startY;
+ else if (originY > endY)
+ originY = endY;
+ }
+
+ public void Reset ()
+ {
+ ArrayList list = (ArrayList) series.Clone ();
+ foreach (Serie s in list)
+ RemoveSerie (s);
+
+ axis.Clear ();
+ }
+
+ public void AddAxis (Axis ax, AxisPosition position)
+ {
+ ax.Owner = this;
+ ax.Position = position;
+ axis.Add (ax);
+ QueueDraw ();
+ }
+
+ public void AddSerie (Serie serie)
+ {
+ serie.Owner = this;
+ series.Add (serie);
+ OnSerieChanged ();
+ }
+
+ public void RemoveSerie (Serie serie)
+ {
+ series.Remove (serie);
+ serie.Owner = null;
+ OnSerieChanged ();
+ }
+
+ public void AddCursor (ChartCursor cursor, AxisDimension dimension)
+ {
+ cursor.Dimension = dimension;
+ cursor.ValueChanged += new EventHandler (OnCursorChanged);
+ cursor.LayoutChanged += new EventHandler (OnCursorChanged);
+ cursors.Add (cursor);
+ xrangeChanged = yrangeChanged = true;
+ QueueDraw ();
+ }
+
+ public void RemoveCursor (ChartCursor cursor)
+ {
+ cursor.ValueChanged -= new EventHandler (OnCursorChanged);
+ cursor.LayoutChanged -= new EventHandler (OnCursorChanged);
+ cursors.Remove (cursor);
+ QueueDraw ();
+ }
+
+ public void SetAutoScale (AxisDimension ad, bool autoStart, bool autoEnd)
+ {
+ if (ad == AxisDimension.X) {
+ autoStartX = autoStart;
+ autoEndX = autoEnd;
+ } else {
+ autoStartY = autoStart;
+ autoEndY = autoEnd;
+ }
+ }
+
+ void UpdateCursors ()
+ {
+ foreach (ChartCursor c in cursors) {
+ if (c.Value < GetStart (c.Dimension)) c.Value = GetStart (c.Dimension);
+ else if (c.Value > GetEnd (c.Dimension)) c.Value = GetEnd (c.Dimension);
+ }
+ }
+
+ void OnCursorChanged (object sender, EventArgs args)
+ {
+ ChartCursor c = (ChartCursor) sender;
+ if (c.Value < GetStart (c.Dimension)) c.Value = GetStart (c.Dimension);
+ else if (c.Value > GetEnd (c.Dimension)) c.Value = GetEnd (c.Dimension);
+ QueueDraw ();
+ }
+
+ internal void OnSerieChanged ()
+ {
+ xrangeChanged = true;
+ yrangeChanged = true;
+ QueueDraw ();
+ }
+
+ public void Clear ()
+ {
+ foreach (Serie s in series)
+ s.Clear ();
+ OnSerieChanged ();
+ }
+
+ double GetOrigin (AxisDimension ad)
+ {
+ if (ad == AxisDimension.X)
+ return OriginX;
+ else
+ return OriginY;
+ }
+
+ double GetStart (AxisDimension ad)
+ {
+ if (ad == AxisDimension.X)
+ return startX;
+ else
+ return startY;
+ }
+
+ double GetEnd (AxisDimension ad)
+ {
+ if (ad == AxisDimension.X)
+ return endX;
+ else
+ return endY;
+ }
+
+ int GetAreaSize (AxisDimension ad)
+ {
+ if (ad == AxisDimension.X)
+ return width;
+ else
+ return height;
+ }
+
+ double GetMinTickStep (AxisDimension ad)
+ {
+ return (((double) minTickStep) * (GetEnd (ad) - GetStart (ad))) / (double) GetAreaSize (ad);
+ }
+
+ protected override bool OnExposeEvent (Gdk.EventExpose args)
+ {
+ Gdk.Window win = GdkWindow;
+ int rwidth, rheight;
+
+ Cairo.Context ctx = CairoHelper.Create (win);
+
+ win.GetSize (out rwidth, out rheight);
+
+ if (autoStartY || autoEndY) {
+ double nstartY = double.MaxValue;
+ double nendY = double.MinValue;
+ GetValueRange (AxisDimension.Y, out nstartY, out nendY);
+
+ if (!autoStartY) nstartY = startY;
+ if (!autoEndY) nendY = endY;
+ if (nendY < nstartY) nendY = nstartY;
+
+ if (nstartY != startY || nendY != endY) {
+ yrangeChanged = true;
+ startY = nstartY;
+ endY = nendY;
+ }
+ }
+
+ if (autoStartX || autoEndX) {
+ double nstartX = double.MaxValue;
+ double nendX = double.MinValue;
+ GetValueRange (AxisDimension.X, out nstartX, out nendX);
+
+ if (!autoStartX) nstartX = startX;
+ if (!autoEndX) nendX = endX;
+ if (nendX < nstartX) nendX = nstartX;
+
+ if (nstartX != startX || nendX != endX) {
+ xrangeChanged = true;
+ startX = nstartX;
+ endX = nendX;
+ }
+ }
+
+ if (yrangeChanged) {
+ FixOrigins ();
+ int right = rwidth - 2 - AreaBorderWidth;
+ left = AreaBorderWidth;
+ left += MeasureAxisSize (AxisPosition.Left) + 1;
+ right -= MeasureAxisSize (AxisPosition.Right) + 1;
+ yrangeChanged = false;
+ width = right - left + 1;
+ if (width <= 0) width = 1;
+ }
+
+ if (xrangeChanged) {
+ FixOrigins ();
+ int bottom = rheight - 2 - AreaBorderWidth;
+ top = AreaBorderWidth;
+ bottom -= MeasureAxisSize (AxisPosition.Bottom);
+ top += MeasureAxisSize (AxisPosition.Top);
+
+ // Make room for cursor handles
+ foreach (ChartCursor cursor in cursors) {
+ if (cursor.Dimension == AxisDimension.X && top - AreaBorderWidth < cursor.HandleSize)
+ top = cursor.HandleSize + AreaBorderWidth;
+ }
+
+ xrangeChanged = false;
+ height = bottom - top + 1;
+ if (height <= 0) height = 1;
+ }
+
+ if (AutoScaleMargin != 0 && height > 0) {
+ double margin = (double)AutoScaleMargin * (endY - startY) / (double) height;
+ if (autoStartY) startY -= margin;
+ if (autoEndY) endY += margin;
+ }
+
+// Console.WriteLine ("L:" + left + " T:" + top + " W:" + width + " H:" + height);
+
+ // Draw the background
+
+ if (backgroundDisplay == BackgroundDisplay.Gradient) {
+ ctx.Rectangle (left - 1, top - 1, width + 2, height + 2);
+ Cairo.Gradient pat = new Cairo.LinearGradient (left - 1, top - 1, left - 1, height + 2);
+ pat.AddColorStop (0, backroundColor);
+ Cairo.Color endc = new Cairo.Color (1,1,1);
+ pat.AddColorStop (1, endc);
+ ctx.Pattern = pat;
+ ctx.Fill ();
+ } else {
+ ctx.Rectangle (left - 1, top - 1, width + 2, height + 2);
+ ctx.Color = backroundColor;
+ ctx.Fill ();
+ }
+// win.DrawRectangle (Style.WhiteGC, true, left - 1, top - 1, width + 2, height + 2);
+ win.DrawRectangle (Style.BlackGC, false, left - AreaBorderWidth, top - AreaBorderWidth, width + AreaBorderWidth*2, height + AreaBorderWidth*2);
+
+ // Draw selected area
+
+ if (enableSelection) {
+ int sx, sy, ex, ey;
+ GetPoint (selectionStart.Value, selectionStart.Value, out sx, out sy);
+ GetPoint (selectionEnd.Value, selectionEnd.Value, out ex, out ey);
+ if (sx > ex) {
+ int tmp = sx; sx = ex; ex = tmp;
+ }
+ Gdk.GC sgc = new Gdk.GC (GdkWindow);
+ sgc.RgbFgColor = new Color (225, 225, 225);
+ win.DrawRectangle (sgc, true, sx, top, ex - sx, height + 1);
+ }
+
+ // Draw axes
+
+ Gdk.GC gc = Style.BlackGC;
+
+ foreach (Axis ax in axis)
+ DrawAxis (win, gc, ax);
+
+ // Draw values
+ foreach (Serie serie in series)
+ if (serie.Visible)
+ DrawSerie (ctx, serie);
+
+ // Draw cursors
+ foreach (ChartCursor cursor in cursors)
+ DrawCursor (cursor);
+
+ // Draw cursor labels
+ foreach (ChartCursor cursor in cursors)
+ if (cursor.ShowValueLabel)
+ DrawCursorLabel (cursor);
+
+ ((IDisposable)ctx).Dispose ();
+ return true;
+ }
+
+ void GetValueRange (AxisDimension ad, out double min, out double max)
+ {
+ min = double.MaxValue;
+ max = double.MinValue;
+
+ foreach (Serie serie in series) {
+ if (!serie.HasData || !serie.Visible)
+ continue;
+
+ double lmin, lmax;
+ serie.GetRange (ad, out lmin, out lmax);
+ if (lmin < min) min = lmin;
+ if (lmax > max) max = lmax;
+ }
+ }
+
+ void DrawAxis (Gdk.Window win, Gdk.GC gc, Axis ax)
+ {
+ double minStep = GetMinTickStep (ax.Dimension);
+
+ TickEnumerator enumSmall = ax.GetTickEnumerator (minStep);
+ if (enumSmall == null)
+ return;
+
+ TickEnumerator enumBig = ax.GetTickEnumerator (minStep * 2);
+
+ if (enumBig == null) {
+ DrawTicks (win, gc, enumSmall, ax.Position, ax.Dimension, ax.TickSize, ax.ShowLabels);
+ } else {
+ DrawTicks (win, gc, enumSmall, ax.Position, ax.Dimension, ax.TickSize / 2, false);
+ DrawTicks (win, gc, enumBig, ax.Position, ax.Dimension, ax.TickSize, ax.ShowLabels);
+ }
+ }
+
+ void DrawTicks (Gdk.Window win, Gdk.GC gc, TickEnumerator e, AxisPosition pos, AxisDimension ad, int tickSize, bool showLabels)
+ {
+ int rwidth, rheight;
+ win.GetSize (out rwidth, out rheight);
+
+ Pango.Layout layout = null;
+
+ if (showLabels) {
+ layout = new Pango.Layout (this.PangoContext);
+ layout.FontDescription = Pango.FontDescription.FromString ("Tahoma 8");
+ }
+
+ bool isX = pos == AxisPosition.Top || pos == AxisPosition.Bottom;
+ bool isTop = pos == AxisPosition.Top || pos == AxisPosition.Right;
+
+ double start = GetStart (ad);
+ double end = GetEnd (ad);
+
+ e.Init (GetOrigin (ad));
+
+ while (e.CurrentValue > start)
+ e.MovePrevious ();
+
+ int lastPosLabel;
+ int lastPos;
+ int lastTw = 0;
+
+ if (isX) {
+ lastPosLabel = reverseXAxis ? left + width + MinLabelGapX : left - MinLabelGapX;
+ lastPos = left - minTickStep*2;
+ }
+ else {
+ lastPosLabel = reverseYAxis ? top - MinLabelGapY : rheight + MinLabelGapY;
+ lastPos = top + height + minTickStep*2;
+ }
+
+ for ( ; e.CurrentValue <= end; e.MoveNext ())
+ {
+ int px, py;
+ int tw = 0, th = 0;
+ int tick = tickSize;
+
+ GetPoint (e.CurrentValue, e.CurrentValue, out px, out py);
+
+ if (showLabels) {
+ layout.SetMarkup (e.CurrentLabel);
+ layout.GetPixelSize (out tw, out th);
+ }
+
+ if (isX) {
+ if (Math.Abs ((long)px - (long)lastPos) < minTickStep || px < left || px > left + width)
+ continue;
+ lastPos = px;
+
+ bool labelFits = false;
+ if ((Math.Abs (px - lastPosLabel) - (tw/2) - (lastTw/2)) >= MinLabelGapX) {
+ lastPosLabel = px;
+ lastTw = tw;
+ labelFits = true;
+ }
+
+ if (isTop) {
+ if (showLabels) {
+ if (labelFits)
+ win.DrawLayout (gc, px - (tw/2), top - AreaBorderWidth - th, layout);
+ else
+ tick = tick / 2;
+ }
+ win.DrawLine (gc, px, top, px, top + tick);
+ }
+ else {
+ if (showLabels) {
+ if (labelFits)
+ win.DrawLayout (gc, px - (tw/2), top + height + AreaBorderWidth, layout);
+ else
+ tick = tick / 2;
+ }
+ win.DrawLine (gc, px, top + height, px, top + height - tick);
+ }
+ }
+ else {
+ if (Math.Abs ((long)lastPos - (long)py) < minTickStep || py < top || py > top + height)
+ continue;
+ lastPos = py;
+
+ bool labelFits = false;
+ if ((Math.Abs (py - lastPosLabel) - (th/2) - (lastTw/2)) >= MinLabelGapY) {
+ lastPosLabel = py;
+ lastTw = th;
+ labelFits = true;
+ }
+
+ if (isTop) {
+ if (showLabels) {
+ if (labelFits)
+ win.DrawLayout (gc, left + width + AreaBorderWidth + 1, py - (th/2), layout);
+ else
+ tick = tick / 2;
+ }
+ win.DrawLine (gc, left + width, py, left + width - tick, py);
+ }
+ else {
+ if (showLabels) {
+ if (labelFits)
+ win.DrawLayout (gc, left - AreaBorderWidth - tw - 1, py - (th/2), layout);
+ else
+ tick = tick / 2;
+ }
+ win.DrawLine (gc, left, py, left + tick, py);
+ }
+ }
+ }
+ }
+
+ int MeasureAxisSize (AxisPosition pos)
+ {
+ int max = 0;
+ foreach (Axis ax in axis)
+ if (ax.Position == pos && ax.ShowLabels) {
+ int nmax = MeasureAxisSize (ax);
+ if (nmax > max) max = nmax;
+ }
+ return max;
+ }
+
+ int MeasureAxisSize (Axis ax)
+ {
+ double minStep = GetMinTickStep (ax.Dimension);
+
+ TickEnumerator enumSmall = ax.GetTickEnumerator (minStep);
+ if (enumSmall == null)
+ return 0;
+
+ TickEnumerator enumBig = ax.GetTickEnumerator (minStep * 2);
+
+ if (enumBig == null)
+ return MeasureTicksSize (enumSmall, ax.Dimension);
+ else
+ return MeasureTicksSize (enumBig, ax.Dimension);
+ }
+
+ int MeasureTicksSize (TickEnumerator e, AxisDimension ad)
+ {
+ int max = 0;
+ Pango.Layout layout = new Pango.Layout (this.PangoContext);
+ layout.FontDescription = Pango.FontDescription.FromString ("Tahoma 8");
+
+ double start = GetStart (ad);
+ double end = GetEnd (ad);
+
+ e.Init (GetOrigin (ad));
+
+ while (e.CurrentValue > start)
+ e.MovePrevious ();
+
+ for ( ; e.CurrentValue <= end; e.MoveNext ())
+ {
+ int tw = 0, th = 0;
+
+ layout.SetMarkup (e.CurrentLabel);
+ layout.GetPixelSize (out tw, out th);
+
+ if (ad == AxisDimension.X) {
+ if (th > max)
+ max = th;
+ } else {
+ if (tw > max)
+ max = tw;
+ }
+ }
+ return max;
+ }
+
+ void DrawSerie (Cairo.Context ctx, Serie serie)
+ {
+ ctx.NewPath ();
+ ctx.Rectangle (left, top, width + 1, height + 1);
+ ctx.Clip ();
+
+ ctx.NewPath ();
+ ctx.Color = serie.Color;
+ ctx.LineWidth = serie.LineWidth;
+
+ bool first = true;
+ bool blockMode = serie.DisplayMode == DisplayMode.BlockLine;
+
+ double lastY = 0;
+
+ foreach (Data d in serie.GetData (startX, endX)) {
+ double x, y;
+ GetPoint (d.X, d.Y, out x, out y);
+ if (first) {
+ ctx.MoveTo (x, y);
+ lastY = y;
+ first = false;
+ } else {
+ if (blockMode) {
+ if (lastY != y)
+ ctx.LineTo (x, lastY);
+ ctx.LineTo (x, y);
+ } else
+ ctx.LineTo (x, y);
+ }
+ lastY = y;
+ }
+
+ ctx.Stroke ();
+ }
+
+ void DrawCursor (ChartCursor cursor)
+ {
+ Gdk.GC gc = new Gdk.GC (GdkWindow);
+ gc.RgbFgColor = cursor.Color;
+
+ int x, y;
+ GetPoint (cursor.Value, cursor.Value, out x, out y);
+
+ if (cursor.Dimension == AxisDimension.X) {
+ int cy = top - AreaBorderWidth - 1;
+ Point[] ps = new Point [4];
+ ps [0] = new Point (x, cy);
+ ps [1] = new Point (x + (cursor.HandleSize/2), cy - cursor.HandleSize + 1);
+ ps [2] = new Point (x - (cursor.HandleSize/2), cy - cursor.HandleSize + 1);
+ ps [3] = ps [0];
+ GdkWindow.DrawPolygon (gc, false, ps);
+ if (activeCursor == cursor)
+ GdkWindow.DrawPolygon (gc, true, ps);
+ GdkWindow.DrawLine (gc, x, top, x, top + height);
+ } else {
+ throw new NotSupportedException ();
+ }
+ }
+
+ void DrawCursorLabel (ChartCursor cursor)
+ {
+ Gdk.GC gc = new Gdk.GC (GdkWindow);
+ gc.RgbFgColor = cursor.Color;
+
+ int x, y;
+ GetPoint (cursor.Value, cursor.Value, out x, out y);
+
+ if (cursor.Dimension == AxisDimension.X) {
+
+ string text;
+
+ if (cursor.LabelAxis != null) {
+ double minStep = GetMinTickStep (cursor.Dimension);
+ TickEnumerator tenum = cursor.LabelAxis.GetTickEnumerator (minStep);
+ tenum.Init (cursor.Value);
+ text = tenum.CurrentLabel;
+ } else {
+ text = GetValueLabel (cursor.Dimension, cursor.Value);
+ }
+
+ if (text != null && text.Length > 0) {
+ Pango.Layout layout = new Pango.Layout (this.PangoContext);
+ layout.FontDescription = Pango.FontDescription.FromString ("Tahoma 8");
+ layout.SetMarkup (text);
+
+ int tw, th;
+ layout.GetPixelSize (out tw, out th);
+ int tl = x - tw/2;
+ int tt = top + 4;
+ if (tl + tw + 2 >= left + width) tl = left + width - tw - 1;
+ if (tl < left + 1) tl = left + 1;
+ GdkWindow.DrawRectangle (Style.WhiteGC, true, tl - 1, tt - 1, tw + 2, th + 2);
+ GdkWindow.DrawRectangle (Style.BlackGC, false, tl - 2, tt - 2, tw + 3, th + 3);
+ GdkWindow.DrawLayout (gc, tl, tt, layout);
+ }
+ } else {
+ throw new NotSupportedException ();
+ }
+ }
+
+ void GetPoint (double wx, double wy, out int x, out int y)
+ {
+ double dx, dy;
+ GetPoint (wx, wy, out dx, out dy);
+ x = (int) dx;
+ y = (int) dy;
+ }
+
+ void GetPoint (double wx, double wy, out double x, out double y)
+ {
+ unchecked {
+ if (reverseXAxis)
+ x = left + width - (((wx - startX) * ((double) width)) / (endX - startX));
+ else
+ x = left + (((wx - startX) * ((double) width)) / (endX - startX));
+
+ if (reverseYAxis)
+ y = top + ((wy - startY) * ((double) height) / (endY - startY));
+ else
+ y = top + height - ((wy - startY) * ((double) height) / (endY - startY));
+ }
+ }
+
+ void GetValue (int x, int y, out double wx, out double wy)
+ {
+ unchecked {
+ if (reverseXAxis)
+ wx = startX + ((double) (left + width - 1 - x)) * (endX - startX) / (double) width;
+ else
+ wx = startX + ((double) (x - left)) * (endX - startX) / (double) width;
+
+ if (reverseYAxis)
+ wy = startY + ((double) (top + y)) * (endY - startY) / (double) height;
+ else
+ wy = startY + ((double) (top + height - y - 1)) * (endY - startY) / (double) height;
+ }
+ }
+
+ string GetValueLabel (AxisDimension ad, double value)
+ {
+ foreach (Axis ax in axis)
+ if (ax.Dimension == ad)
+ return ax.GetValueLabel (value);
+ return null;
+ }
+
+ internal void OnLayoutChanged ()
+ {
+ xrangeChanged = true;
+ yrangeChanged = true;
+ QueueDraw ();
+ }
+
+ void OnSelectionCursorChanged (object sender, EventArgs args)
+ {
+ if (enableSelection) {
+ if (selectionStart.Value > selectionEnd.Value) {
+ ChartCursor tmp = selectionStart;
+ selectionStart = selectionEnd;
+ selectionEnd = tmp;
+ }
+ OnSelectionChanged ();
+ }
+ }
+
+ protected override bool OnButtonPressEvent (Gdk.EventButton ev)
+ {
+ if (ev.Button == 1) {
+ foreach (ChartCursor cursor in cursors) {
+ int cx, cy;
+ GetPoint (cursor.Value, cursor.Value, out cx, out cy);
+ if (cursor.Dimension == AxisDimension.X) {
+ if (Math.Abs (ev.X - cx) <= 2 || (ev.Y < top && (Math.Abs (ev.X - cx) <= cursor.HandleSize/2))) {
+ activeCursor = cursor;
+ draggingCursor = true;
+ activeCursor.ShowValueLabel = true;
+ QueueDraw ();
+ break;
+ }
+ } else {
+ // Implement
+ }
+ }
+
+ if (enableSelection && !draggingCursor) {
+ selectionStart.Visible = true;
+ selectionEnd.Visible = true;
+
+ double x, y;
+ GetValue ((int)ev.X, (int)ev.Y, out x, out y);
+ // avoid cursor swaping
+ ChartCursor c1 = selectionStart;
+ ChartCursor c2 = selectionEnd;
+ c1.Value = x;
+ c2.Value = x;
+ activeCursor = selectionEnd;
+ activeCursor.ShowValueLabel = true;
+ draggingCursor = true;
+ QueueDraw ();
+ }
+
+ if (draggingCursor)
+ return true;
+ }
+ return base.OnButtonPressEvent (ev);
+ }
+
+ protected override bool OnButtonReleaseEvent (EventButton e)
+ {
+ if (draggingCursor) {
+ draggingCursor = false;
+ activeCursor.ShowValueLabel = false;
+ }
+ return base.OnButtonReleaseEvent (e);
+ }
+
+ protected override bool OnMotionNotifyEvent (EventMotion e)
+ {
+ if (draggingCursor) {
+ double x, y;
+ GetValue ((int)e.X, (int)e.Y, out x, out y);
+
+ if (activeCursor.Dimension == AxisDimension.X) {
+ if (x < startX) x = startX;
+ else if (x > endX) x = endX;
+ activeCursor.Value = x;
+ }
+ else {
+ if (y < startY) y = startY;
+ else if (y > endY) y = endY;
+ activeCursor.Value = y;
+ }
+ return true;
+ }
+ return base.OnMotionNotifyEvent (e);
+ }
+
+ protected override void OnSizeAllocated (Gdk.Rectangle rect)
+ {
+ xrangeChanged = true;
+ yrangeChanged = true;
+ base.OnSizeAllocated (rect);
+ }
+
+ protected virtual void OnSelectionChanged ()
+ {
+ if (SelectionChanged != null)
+ SelectionChanged (this, EventArgs.Empty);
+ }
+ }
+
+ public enum BackgroundDisplay
+ {
+ Solid,
+ Gradient
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/ChartCursor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/ChartCursor.cs
new file mode 100644
index 0000000000..11c0af94e8
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/ChartCursor.cs
@@ -0,0 +1,89 @@
+//
+// ChartCursor.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using Gdk;
+
+namespace MonoDevelop.Components.Chart
+{
+ public class ChartCursor
+ {
+ double val;
+ internal AxisDimension Dimension;
+ Gdk.Color color;
+ int handleSize = 6;
+ bool visible = true;
+ bool showValueLabel;
+ Axis labelAxis;
+
+ public double Value {
+ get { return val; }
+ set { val = value; OnValueChanged (); }
+ }
+
+ public bool Visible {
+ get { return visible; }
+ set { visible = value; OnLayoutChanged (); }
+ }
+
+ public Gdk.Color Color {
+ get { return color; }
+ set { color = value; OnLayoutChanged (); }
+ }
+
+ public int HandleSize {
+ get { return handleSize; }
+ set { handleSize = value; OnLayoutChanged (); }
+ }
+
+ public bool ShowValueLabel {
+ get { return showValueLabel; }
+ set { showValueLabel = value; OnLayoutChanged (); }
+ }
+
+ public Axis LabelAxis {
+ get { return labelAxis; }
+ set { labelAxis = value; OnLayoutChanged (); }
+ }
+
+ public virtual void OnValueChanged ()
+ {
+ if (ValueChanged != null)
+ ValueChanged (this, EventArgs.Empty);
+ }
+
+ public virtual void OnLayoutChanged ()
+ {
+ if (LayoutChanged != null)
+ LayoutChanged (this, EventArgs.Empty);
+ }
+
+ public EventHandler ValueChanged;
+ public EventHandler LayoutChanged;
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/DateTimeAxis.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/DateTimeAxis.cs
new file mode 100644
index 0000000000..e1bc83998e
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/DateTimeAxis.cs
@@ -0,0 +1,143 @@
+//
+// DateTimeAxis.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+
+namespace MonoDevelop.Components.Chart
+{
+ public class DateTimeAxis: Axis
+ {
+ public DateTimeAxis ()
+ {
+ }
+
+ public DateTimeAxis (bool showLabels): base (showLabels)
+ {
+ }
+
+ protected override TickEnumerator CreateTickEnumerator (double minTickStep)
+ {
+ long val = (long) minTickStep;
+ int scale;
+
+ if (val > TimeSpan.TicksPerDay * 30 * 365)
+ return null;
+ else if (val > TimeSpan.TicksPerDay * 30)
+ scale = 7;
+ else if (val > TimeSpan.TicksPerDay)
+ scale = 6;
+ else if (val > TimeSpan.TicksPerHour)
+ scale = 5;
+ else if (val > TimeSpan.TicksPerMinute * 15)
+ scale = 4;
+ else if (val > TimeSpan.TicksPerMinute)
+ scale = 3;
+ else if (val > TimeSpan.TicksPerSecond * 15)
+ scale = 2;
+ else if (val > TimeSpan.TicksPerSecond)
+ scale = 1;
+ else
+ scale = 0;
+
+ return new DateTimeTickEnumerator (scale);
+ }
+ }
+
+ internal class DateTimeTickEnumerator: TickEnumerator
+ {
+ int scale;
+ DateTime current;
+
+ public DateTimeTickEnumerator (int scale)
+ {
+ this.scale = scale;
+ }
+
+ public override void Init (double startValue)
+ {
+ DateTime t = new DateTime ((long)startValue);
+ DateTime nt;
+ switch (scale) {
+ case 0: nt = new DateTime (t.Year, t.Month, t.Day, t.Hour, t.Minute, t.Second); break;
+ case 1: nt = new DateTime (t.Year, t.Month, t.Day, t.Hour, t.Minute, (t.Second / 15) * 15); break;
+ case 2: nt = new DateTime (t.Year, t.Month, t.Day, t.Hour, t.Minute, 0); break;
+ case 3: nt = new DateTime (t.Year, t.Month, t.Day, t.Hour, (t.Minute / 15) * 15, 0); break;
+ case 4: nt = new DateTime (t.Year, t.Month, t.Day, t.Hour, 0, 0); break;
+ case 5: nt = new DateTime (t.Year, t.Month, t.Day); break;
+ case 6: nt = new DateTime (t.Year, t.Month, 1); break;
+ default: nt = new DateTime (t.Year, 1, 1); break;
+ }
+ current = nt;
+ }
+
+ public override void MoveNext ()
+ {
+ switch (scale) {
+ case 0: current = current.AddSeconds (1); break;
+ case 1: current = current.AddSeconds (15); break;
+ case 2: current = current.AddMinutes (1); break;
+ case 3: current = current.AddMinutes (15); break;
+ case 4: current = current.AddHours (1); break;
+ case 5: current = current.AddDays (1); break;
+ case 6: current = current.AddMonths (1); break;
+ case 7: current = current.AddYears (1); break;
+ }
+ }
+
+ public override void MovePrevious ()
+ {
+ switch (scale) {
+ case 0: current = current.AddSeconds (-1); break;
+ case 1: current = current.AddSeconds (-15); break;
+ case 2: current = current.AddMinutes (-1); break;
+ case 3: current = current.AddMinutes (-15); break;
+ case 4: current = current.AddHours (-1); break;
+ case 5: current = current.AddDays (-1); break;
+ case 6: current = current.AddMonths (-1); break;
+ case 7: current = current.AddYears (-1); break;
+ }
+ }
+
+ public override double CurrentValue {
+ get { return (double) current.Ticks; }
+ }
+
+ public override string CurrentLabel {
+ get {
+ switch (scale) {
+ case 0: case 1: return string.Format ("{0}:{1:00}:{2:00}", current.Hour, current.Minute, current.Second);
+ case 2: case 3: return string.Format ("{0}:{1:00}", current.Hour, current.Minute);
+ case 4: return string.Format ("{0}:00", current.Hour);
+ case 5: return current.ToShortDateString ();
+ case 6: return string.Format ("{0}/{1}", current.Month, current.Year);
+ default: return string.Format ("{0}", current.Year);
+ }
+ }
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/IntegerAxis.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/IntegerAxis.cs
new file mode 100644
index 0000000000..e0fe4b0c1f
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/IntegerAxis.cs
@@ -0,0 +1,96 @@
+//
+// IntegerAxis.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+
+namespace MonoDevelop.Components.Chart
+{
+ public class IntegerAxis: Axis
+ {
+ public IntegerAxis ()
+ {
+ }
+
+ public IntegerAxis (bool showLabels): base (showLabels)
+ {
+ }
+
+ protected override TickEnumerator CreateTickEnumerator (double minTickStep)
+ {
+ long val;
+ unchecked {
+ val = (long) minTickStep;
+ long red = 10;
+ while (val > red)
+ red = red * 10;
+
+ long scale;
+
+ if (val <= 1)
+ scale = 1;
+ else if (val > red / 2)
+ scale = red;
+ else if (val > red / 4)
+ scale = red / 2;
+ else
+ scale = red / 4;
+ return new IntegerTickEnumerator (scale);
+ }
+ }
+ }
+
+ internal class IntegerTickEnumerator: TickEnumerator
+ {
+ long scale;
+ long current;
+
+ public IntegerTickEnumerator (long scale)
+ {
+ this.scale = scale;
+ }
+
+ public override void Init (double startValue)
+ {
+ current = (((long)startValue) / scale) * scale;
+ }
+
+ public override void MoveNext ()
+ {
+ current += scale;
+ }
+
+ public override void MovePrevious ()
+ {
+ current -= scale;
+ }
+
+ public override double CurrentValue {
+ get { return (double) current; }
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/Serie.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/Serie.cs
new file mode 100644
index 0000000000..45475ee559
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/Serie.cs
@@ -0,0 +1,198 @@
+//
+// Serie.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+using Gdk;
+
+namespace MonoDevelop.Components.Chart
+{
+ public class Serie
+ {
+ string title;
+ List<Data> dataArray = new List<Data> ();
+ bool visible = true;
+ internal BasicChart Owner;
+ Cairo.Color color;
+ bool extendBoundingValues;
+ DisplayMode mode;
+ double initialValue;
+ bool averageData;
+ double averageSpan;
+ double averageOrigin;
+ int lineWidth = 2;
+
+ public Serie ()
+ {
+ }
+
+ public Serie (string title)
+ {
+ this.title = title;
+ }
+
+ public void AddData (double x, double y)
+ {
+ dataArray.Add (new Data (x, y));
+ OnSerieChanged ();
+ }
+
+ public void Clear ()
+ {
+ dataArray.Clear ();
+ OnSerieChanged ();
+ }
+
+ public string Title {
+ get { return title; }
+ set { title = value; OnSerieChanged (); }
+ }
+
+ public bool Visible {
+ get { return visible; }
+ set { visible = value; OnSerieChanged (); }
+ }
+
+ public bool ExtendBoundingValues {
+ get { return extendBoundingValues; }
+ set { extendBoundingValues = value; OnSerieChanged (); }
+ }
+
+ // Initial value to use when ExtendBoundingValues is set to true
+ public double InitialValue {
+ get { return initialValue; }
+ set { initialValue = value; OnSerieChanged (); }
+ }
+
+ public DisplayMode DisplayMode {
+ get { return mode; }
+ set { mode = value; OnSerieChanged (); }
+ }
+
+ public bool AverageData {
+ get { return this.averageData; }
+ set { this.averageData = value; OnSerieChanged ();}
+ }
+
+ public double AverageSpan {
+ get { return this.averageSpan; }
+ set { this.averageSpan = value; OnSerieChanged ();}
+ }
+
+ public double AverageOrigin {
+ get { return this.averageOrigin; }
+ set { this.averageOrigin = value; OnSerieChanged (); }
+ }
+
+ public int LineWidth {
+ get { return this.lineWidth; }
+ set { this.lineWidth = value; }
+ }
+
+ public bool HasData {
+ get { return dataArray.Count > 0; }
+ }
+
+ public virtual void OnSerieChanged ()
+ {
+ if (Owner != null)
+ Owner.OnSerieChanged ();
+ }
+
+ public Cairo.Color Color {
+ get { return color; }
+ set { color = value; OnSerieChanged (); }
+ }
+
+ public void GetRange (AxisDimension axis, out double min, out double max)
+ {
+ min = double.MaxValue;
+ max = double.MinValue;
+ foreach (Data d in dataArray) {
+ double v = d.GetValue (axis);
+ if (v > max) max = v;
+ if (v < min) min = v;
+ }
+ }
+
+ internal IEnumerable<Data> GetData (double startX, double endX)
+ {
+ if (dataArray.Count == 0)
+ yield break;
+
+ if (extendBoundingValues) {
+ Data dfirst = dataArray [0];
+ if (dfirst.X > startX)
+ yield return new Data (startX, initialValue);
+ }
+
+ foreach (Data d in dataArray)
+ yield return d;
+
+ if (extendBoundingValues) {
+ Data dlast = dataArray [dataArray.Count - 1];
+ if (dlast.X < endX)
+ yield return new Data (endX, dlast.Y);
+ }
+ }
+ }
+
+ public enum DisplayMode
+ {
+ Line,
+ BlockLine,
+ Bar
+ }
+
+ internal class Data
+ {
+ double x;
+ double y;
+
+ internal Data (double x, double y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ public double X {
+ get { return x; }
+ set { x = value; }
+ }
+
+ public double Y {
+ get { return y; }
+ set { y = value; }
+ }
+
+ public double GetValue (AxisDimension a) {
+ if (a == AxisDimension.X) return x;
+ else return y;
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/TickEnumerator.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/TickEnumerator.cs
new file mode 100644
index 0000000000..721d37910b
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Chart/TickEnumerator.cs
@@ -0,0 +1,46 @@
+//
+// TickEnumerator.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+
+namespace MonoDevelop.Components.Chart
+{
+ public abstract class TickEnumerator
+ {
+ internal Axis axis;
+
+ public abstract void Init (double startValue);
+ public abstract void MoveNext ();
+ public abstract void MovePrevious ();
+ public abstract double CurrentValue { get; }
+
+ public virtual string CurrentLabel {
+ get { return axis.GetValueLabel (CurrentValue); }
+ }
+ }
+}