From 63e41d9b9339dba5760c25b29366202c0be6f08b Mon Sep 17 00:00:00 2001 From: koldo Date: Thu, 6 Oct 2011 19:34:52 +0000 Subject: [PATCH] Scatter: Added context menu git-svn-id: svn://ultimatepp.org/upp/trunk@3956 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- bazaar/Scatter/Chart.iml | 78 +- bazaar/Scatter/Scatter.cpp | 3821 +++++++++++----------- bazaar/Scatter/Scatter.h | 12 +- bazaar/Scatter/Scatter.t | 61 +- bazaar/Scatter/Scatter.upp | 3 +- bazaar/Scatter/init | 1 + bazaar/Scatter/src.tpp/Scatter$en-us.tpp | 87 +- 7 files changed, 2162 insertions(+), 1901 deletions(-) diff --git a/bazaar/Scatter/Chart.iml b/bazaar/Scatter/Chart.iml index 94edf9411..d2af877d3 100644 --- a/bazaar/Scatter/Chart.iml +++ b/bazaar/Scatter/Chart.iml @@ -1,7 +1,79 @@ PREMULTIPLIED IMAGE_ID(cursor1) +IMAGE_ID(ZoomMinus) +IMAGE_ID(ZoomPlus) +IMAGE_ID(ShapeHandles) +IMAGE_ID(Copy) +IMAGE_ID(RightArrow) +IMAGE_ID(LeftArrow) +IMAGE_ID(Save) +IMAGE_ID(DownArrow) +IMAGE_ID(UpArrow) IMAGE_BEGIN_DATA -IMAGE_DATA(120,156,99,144,96,144,96,224,6,194,193,6,254,131,209,168,249,163,230,143,154,63,152,204,7,233,163,54,166,167,251,71) -IMAGE_DATA(205,31,53,127,212,252,129,55,127,48,2,0,68,40,81,245,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) -IMAGE_END_DATA(64, 1) +IMAGE_DATA(120,156,237,152,105,80,84,87,22,199,65,203,15,58,85,153,153,170,169,154,76,149,21,199,169,73,149,83,154,137,32,90) +IMAGE_DATA(137,226,135,153,170,201,135,36,53,101,88,148,48,33,70,54,25,150,132,61,2,134,96,16,4,23,68,16,162,128,128,128) +IMAGE_DATA(236,8,130,128,2,162,194,19,69,209,184,97,177,67,55,251,46,107,3,13,252,231,220,215,116,79,55,208,208,77,71,101) +IMAGE_DATA(38,156,230,95,77,223,62,191,115,206,189,239,222,251,238,107,173,183,181,222,214,250,21,189,126,105,6,254,111,37,254,74) +IMAGE_DATA(252,149,248,75,97,127,78,189,238,250,87,226,175,196,95,137,255,102,227,47,75,251,13,189,230,177,245,164,50,45,201,128) +IMAGE_DATA(72,85,54,211,190,152,25,51,255,176,176,176,66,249,198,153,207,44,142,209,2,236,250,249,216,121,98,40,171,163,76,25) +IMAGE_DATA(59,43,70,153,146,175,37,19,192,40,21,74,37,239,167,140,215,242,129,114,169,192,27,83,30,101,90,152,87,181,255,119) +IMAGE_DATA(148,124,173,233,248,51,51,154,47,134,148,61,190,113,35,78,235,232,64,123,225,24,243,205,63,86,243,122,31,250,159,241) +IMAGE_DATA(42,196,152,215,180,255,79,99,56,111,222,44,84,151,151,198,176,212,210,18,218,188,245,150,112,121,111,6,252,226,243,145) +IMAGE_DATA(45,2,181,55,131,89,188,92,12,213,55,3,198,191,169,205,64,62,255,82,54,3,229,253,87,109,51,80,127,252,121,74) +IMAGE_DATA(107,101,51,120,237,49,94,229,102,176,100,243,240,240,16,6,4,4,192,201,201,233,197,98,190,123,246,236,185,105,109,109) +IMAGE_DATA(13,3,3,3,153,111,96,96,32,158,61,123,134,163,71,143,226,100,78,27,142,103,183,34,144,228,159,73,186,220,10,191) +IMAGE_DATA(244,102,248,166,53,195,39,165,25,230,230,230,224,56,14,38,38,38,178,201,110,103,103,247,208,215,215,23,199,78,133,227) +IMAGE_DATA(18,215,141,132,146,110,196,147,226,110,117,33,246,102,23,98,138,187,16,93,212,129,168,194,14,216,58,123,195,208,208,16) +IMAGE_DATA(250,250,250,156,124,93,44,223,165,82,41,215,141,139,196,197,50,238,70,39,46,16,23,89,208,129,243,215,218,241,99,94) +IMAGE_DATA(27,220,46,52,204,89,152,172,214,184,219,51,57,165,92,209,127,185,115,196,133,231,182,225,108,78,43,28,35,234,230,240) +IMAGE_DATA(172,143,210,90,25,23,69,92,196,245,14,156,203,39,142,216,179,87,91,17,154,211,130,51,87,90,96,31,94,51,135,63) +IMAGE_DATA(146,218,76,125,236,228,251,200,56,105,173,97,87,89,206,22,132,16,23,156,217,140,211,151,155,97,27,82,61,135,255,62) +IMAGE_DATA(81,160,208,71,105,173,140,59,147,217,194,115,167,50,154,113,34,77,8,235,160,170,57,188,87,156,64,82,107,174,164,214) +IMAGE_DATA(144,108,73,173,167,51,37,220,201,116,33,142,167,10,16,152,34,128,249,201,23,115,248,111,99,26,168,86,73,31,165,181) +IMAGE_DATA(6,177,156,196,157,152,225,142,37,53,193,63,177,17,251,3,43,231,240,46,145,245,138,181,166,179,90,37,92,64,178,0) +IMAGE_DATA(254,196,250,93,106,196,209,248,70,152,249,63,87,224,119,238,220,41,220,189,123,55,62,250,196,80,214,71,86,43,227,142) +IMAGE_DATA(73,185,132,70,248,198,55,96,243,182,191,99,221,186,117,88,179,102,205,11,57,30,249,249,249,216,186,85,7,214,193,85) +IMAGE_DATA(176,164,241,97,125,60,64,117,178,90,205,252,43,241,47,191,231,48,37,173,93,187,22,137,137,137,88,189,122,181,172,134) +IMAGE_DATA(77,155,54,61,220,178,101,203,244,134,13,27,238,206,238,215,108,91,181,106,85,161,182,182,54,99,185,197,124,85,50,249) +IMAGE_DATA(205,224,15,127,222,97,96,243,67,124,145,217,247,41,156,153,119,18,103,118,56,145,51,245,136,231,76,14,93,228,246,185) +IMAGE_DATA(199,112,123,221,162,57,99,151,40,206,208,41,130,51,117,10,46,98,254,242,177,172,124,147,75,28,131,178,57,85,101,228) +IMAGE_DATA(16,90,34,207,127,233,147,194,169,163,127,218,134,42,12,130,153,119,50,167,142,125,122,240,140,34,255,93,34,223,94,124) +IMAGE_DATA(251,54,23,28,157,87,31,148,85,59,233,153,88,7,207,132,26,120,196,85,193,45,250,57,92,46,60,133,115,196,79,112) +IMAGE_DATA(60,255,8,223,132,63,128,253,217,114,184,134,22,14,111,124,255,35,59,54,94,204,110,17,239,159,65,19,146,22,162,170) +IMAGE_DATA(250,58,232,230,148,169,87,60,207,223,46,41,225,188,146,234,160,142,172,79,220,130,201,161,88,9,95,90,202,121,38,212) +IMAGE_DATA(66,29,179,56,118,3,198,174,81,60,95,66,242,136,175,230,219,199,196,147,16,141,139,49,44,18,227,229,200,56,122,135) +IMAGE_DATA(68,232,234,31,69,123,247,8,90,186,134,208,208,62,200,251,125,229,87,0,67,199,243,178,177,101,227,197,108,98,114,18) +IMAGE_DATA(227,20,99,116,66,18,99,96,84,140,190,225,49,116,15,82,156,151,34,116,244,140,242,126,95,30,201,199,95,62,220,251) +IMAGE_DATA(195,30,135,112,238,83,155,16,206,61,182,146,111,23,79,77,97,130,52,78,113,70,88,29,99,98,12,81,156,193,17,49) +IMAGE_DATA(250,135,38,208,51,56,198,251,125,225,157,171,176,168,93,162,158,240,237,147,211,211,188,164,113,198,88,44,177,24,34,170) +IMAGE_DATA(135,175,137,226,49,51,241,204,82,224,191,249,177,130,111,159,146,139,49,49,19,67,42,17,213,52,42,150,240,70,110,233) +IMAGE_DATA(10,188,125,200,61,181,198,255,51,231,20,5,126,251,39,142,41,54,65,165,176,12,40,198,1,191,66,236,247,189,14,211) +IMAGE_DATA(195,217,48,241,186,130,125,30,151,177,215,61,131,114,166,193,208,37,5,159,57,165,128,249,171,177,236,231,183,95,211,235) +IMAGE_DATA(53,152,38,63,198,72,143,137,75,98,125,124,124,150,202,35,190,72,188,24,15,101,98,236,34,188,204,103,33,41,225,85) +IMAGE_DATA(98,149,240,26,229,213,160,191,202,108,169,28,207,106,114,125,151,200,73,217,87,99,203,124,65,46,121,176,53,185,192,108) +IMAGE_DATA(130,168,201,202,56,57,86,153,148,114,11,105,22,171,50,167,164,47,75,205,171,105,127,231,240,11,248,44,100,154,44,68) +IMAGE_DATA(173,69,106,83,149,127,53,38,127,92,254,253,251,6,78,239,232,219,6,111,54,14,175,208,181,200,236,211,179,185,54,177) +IMAGE_DATA(221,182,96,122,135,93,33,118,216,74,244,161,125,17,118,125,125,3,59,29,10,161,103,153,217,175,243,121,216,131,223,254) +IMAGE_DATA(105,23,255,227,216,31,255,230,28,249,164,105,20,79,154,68,116,204,154,134,136,52,58,62,69,199,172,73,58,26,77,160) +IMAGE_DATA(119,80,204,127,22,77,76,161,123,64,140,134,14,209,116,65,69,135,120,159,119,65,207,239,54,253,195,226,61,211,152,170) +IMAGE_DATA(39,141,163,240,73,237,164,163,12,177,228,103,121,242,30,250,134,196,232,34,255,193,209,73,62,238,0,189,11,123,198,81) +IMAGE_DATA(219,62,134,130,199,125,184,241,184,7,250,246,185,99,186,150,89,47,31,19,239,157,220,193,251,48,49,190,115,96,130,142) +IMAGE_DATA(104,98,62,47,203,223,65,181,212,119,140,161,182,77,4,207,120,1,74,43,251,161,103,147,55,205,250,91,81,63,66,124) +IMAGE_DATA(59,239,195,100,125,170,28,157,244,62,52,70,71,45,170,169,127,120,18,141,157,44,183,8,213,173,34,28,138,107,66,74) +IMAGE_DATA(73,59,182,219,228,129,141,85,121,221,48,190,75,106,135,128,234,99,106,238,29,167,220,147,124,238,33,209,20,90,123,39) +IMAGE_DATA(100,108,85,235,40,190,141,109,64,66,113,11,244,14,94,5,27,231,187,213,196,39,182,241,117,91,81,238,131,65,229,176) +IMAGE_DATA(15,121,0,7,210,191,131,239,195,138,218,45,229,228,26,85,131,152,2,1,244,172,115,248,235,115,167,106,16,94,9,205) +IMAGE_DATA(212,47,18,189,123,37,8,225,21,207,36,160,35,191,128,242,53,194,157,158,77,93,163,235,225,28,85,11,215,11,117,136) +IMAGE_DATA(200,173,135,158,213,21,158,47,169,28,148,176,36,9,39,228,99,48,246,208,197,38,190,94,183,232,6,158,115,137,172,33) +IMAGE_DATA(85,35,44,171,6,219,44,51,121,190,248,233,75,98,133,51,18,200,114,243,44,229,117,143,169,231,89,103,226,156,206,87) +IMAGE_DATA(209,99,199,11,4,165,85,98,155,69,6,241,5,40,124,220,15,207,56,33,127,157,85,145,67,248,51,28,79,122,10,93) +IMAGE_DATA(243,52,124,64,227,119,237,81,63,95,171,136,174,85,192,45,243,5,197,230,130,109,232,79,244,12,253,8,186,7,82,241) +IMAGE_DATA(129,125,33,242,42,250,40,191,132,47,169,187,185,160,24,111,19,252,16,71,162,43,136,79,166,250,175,79,231,220,239,37) +IMAGE_DATA(190,73,229,252,86,167,238,227,112,100,57,182,238,79,156,254,235,23,113,13,25,101,221,200,184,211,165,114,255,15,71,220) +IMAGE_DATA(131,199,185,187,120,239,243,200,222,119,118,217,156,126,247,99,223,92,29,243,180,190,237,54,249,52,39,115,249,121,165,103) +IMAGE_DATA(157,141,109,86,89,116,141,46,67,215,34,157,198,42,149,234,77,129,206,87,201,146,188,166,81,3,239,126,124,132,123,213) +IMAGE_DATA(119,103,85,119,235,121,89,21,238,18,191,84,86,233,113,117,129,187,165,2,191,216,221,121,177,199,4,101,188,138,119,205) +IMAGE_DATA(57,188,154,119,91,25,255,6,142,217,90,26,112,139,219,114,63,46,107,122,236,93,234,133,214,116,130,105,58,177,213,125) +IMAGE_DATA(142,84,115,65,42,196,250,31,216,128,150,13,59,143,126,86,251,15,116,241,146,1,0,0,0,0,0,0,0,0,0,0) +IMAGE_END_DATA(2080, 10) diff --git a/bazaar/Scatter/Scatter.cpp b/bazaar/Scatter/Scatter.cpp index 222663dd6..38cb6a471 100644 --- a/bazaar/Scatter/Scatter.cpp +++ b/bazaar/Scatter/Scatter.cpp @@ -1,1885 +1,1936 @@ -#include "Scatter.h" - -#define IMAGECLASS ChartImg -#define IMAGEFILE -#include - -Scatter::MouseBehaviour defaultMouse[] = { - {false, false, false, true , false, 0, false, Scatter::SHOW_INFO}, - {false, false, false, false, true , 0, false, Scatter::SCROLL}, - {false, false, false, false, false, 1, false, Scatter::ZOOM_H_RED}, - {false, false, false, false, false, 1, false, Scatter::ZOOM_V_RED}, - {false, false, false, false, false,-1, false, Scatter::ZOOM_H_ENL}, - {false, false, false, false, false,-1, false, Scatter::ZOOM_V_ENL}, - {false, false, false, false, false, 0, false, Scatter::NO_ACTION}}; - - -Scatter& Scatter::SetColor(const class::Color& _color) -{ - graphColor=_color; - return *this; -} - -Scatter& Scatter::SetTitle(const String& _title) -{ - title=_title; - return *this; -} -Scatter& Scatter::SetTitleFont(const Font& fontTitle) -{ - titleFont=fontTitle; - return *this; -} -Scatter& Scatter::SetTitleColor(const class::Color& colorTitle) -{ - titleColor=colorTitle; - return *this; -} -void Scatter::SetLabels(const WString& _xLabel, const WString& _yLabel, const WString& _yLabel2) -{ - xLabel=_xLabel; - yLabel=_yLabel; - yLabel2=_yLabel2; -} -Scatter& Scatter::SetLabelX(const WString& _xLabel) -{ - xLabel=_xLabel; - return *this; -} -Scatter& Scatter::SetLabelY(const WString& _yLabel) -{ - yLabel=_yLabel; - return *this; -} -Scatter& Scatter::SetLabelY2(const WString& _yLabel) -{ - yLabel2=_yLabel; - return *this; -} -Scatter& Scatter::SetLabelsFont(const Font& fontLabels) -{ - labelsFont=fontLabels; - return *this; -} -Scatter& Scatter::SetLabelsColor(const class::Color& colorLabels) -{ - labelsColor=colorLabels; - return *this; -} -Scatter& Scatter::SetPlotAreaPoz(const int& poz_x, const int& poz_y) -{ - px=poz_x; - py=poz_y; - return *this; -} -Scatter& Scatter::H_Border(const int& poz_x) -{ - if(poz_x>=0) - px=poz_x; - return *this; -} -Scatter& Scatter::V_Border(const int& poz_y) -{ - if(poz_y>=0) - py=poz_y; - return *this; -} - -Scatter& Scatter::SetPlotAreaColor(const class::Color& p_a_color) -{ - plotAreaColor=p_a_color; - return *this; -} -Scatter& Scatter::SetAxisColor(const class::Color& axis_color) -{ - axisColor=axis_color; - return *this; -} -Scatter& Scatter::SetAxisWidth(const int& axis_width) -{ - axisWidth=axis_width; - return *this; -} -Scatter& Scatter::SetGridColor(const class::Color& grid_color) -{ - gridColor=grid_color; - return *this; -} -Scatter& Scatter::SetGridWidth(const int& grid_width) -{ - gridWidth=grid_width; - return *this; -} -Scatter& Scatter::ShowHGrid(const bool& show) -{ - drawHGrid=show; - return *this; -} -Scatter& Scatter::ShowVGrid(const bool& show) -{ - drawVGrid=show; - return *this; -} -Scatter& Scatter::ShowLegend(const bool& show) -{ - showLegend=show; - return *this; -} -Scatter& Scatter::SetLegendWeight(const int& weight) -{ - legendWeight=weight; - return *this; -} -Scatter& Scatter::SetAntialiasing(const bool& aa) -{ - antialiasing=aa; - return *this; -} -Scatter &Scatter::SetDrawXReticle(bool set) -{ - drawXReticle = set; - return *this; -} -Scatter &Scatter::SetDrawYReticle(bool set) -{ - drawYReticle = set; - return *this; -} -Scatter &Scatter::SetDrawY2Reticle(bool set) -{ - drawY2Reticle = set; - return *this; -} -void Scatter::DrawLegend(Draw& w,const int& scale) const -{ - Vector L; - L.Append(vLegend); - L.Append(vFLegend); - Vector Thick; - Thick.Append(vPThickness); - Thick.Append(vFThickness); - Vector LC; - LC.Append(vPColors); - LC.Append(vFColors); - Vector LW; - LW.Append(vPWidth); - VectorVJ; - VJ.Append(vJoin); - Vector MS; - MS.Append(vMarkStyles); - Vector MC; - MC.Append(vMarkColors); - Vector Patt; - Patt.Append(vPPattern); - Patt.Append(vFPattern); - - int NMR=fround((GetSize().cx-2*px)/legendWeight);//max number of labels per row - if (NMR>0) - { - int N=L.GetCount();//number of labels - int Nc;//number of complete rows - int LCR;//number of labels on complete row - int R;//number of remaining labels on incomplete row - if(NMR>N) - {Nc=0; LCR=0; R=N;} - else if (NMR==N) - {Nc=1; LCR=N; R=0;} - else - {Nc=N/NMR; LCR=NMR; R=N%NMR;} - for(int j=0;j<=Nc;j++) - { - int start=N-(j+1)*LCR; - int end=N-j*LCR; - if (j==Nc) - {start=0; end=R;} - for(int i=start;i vp; - vp << Point(scale*(i-start)*legendWeight, scale*(4-12*(j+1))) << - Point(scale*(i-start)*legendWeight+scale*23, scale*(4-12*(j+1))); - if (VJ.At(i)) - DrawPolylineX(w, vp, scale*Thick.At(i)/6, LC.At(i), Patt.At(i), scale); - Point p(scale*((i-start)*legendWeight+7),scale*(4-12*(j+1))/*+scale*Thick.At(i)/12*/); - if (LW.At(i,0) > 1) - DrawMark(MS.At(i),w,scale,p,LW.At(i,0),MC.At(i)); - Font scaledFont; - scaledFont.Height(scale*StdFont().GetHeight()); - w.DrawText(scale*(i-start)*legendWeight+scale*25, - scale*(-2-12*(j+1)), - L.At(i), - scaledFont,LC.At(i)); - } - } - } -} - -void Scatter::AdjustMinUnitX() -{ - if (xMajorUnit > 0) { - while (xMinUnit < 0) - xMinUnit += xMajorUnit; - while (xMinUnit > xMajorUnit) - xMinUnit -= xMajorUnit; - } -} -void Scatter::AdjustMinUnitY() -{ - if (yMajorUnit > 0) { - while (yMinUnit < 0) - yMinUnit += yMajorUnit; - while (yMinUnit > yMajorUnit) - yMinUnit -= yMajorUnit; - } -} -void Scatter::AdjustMinUnitY2() -{ - if (yMajorUnit2 > 0) { - while (yMinUnit2 < 0) - yMinUnit2 += yMajorUnit2; - while (yMinUnit2 > yMajorUnit2) - yMinUnit2 -= yMajorUnit2; - } -} -Scatter &Scatter::SetRange(double rx, double ry, double ry2) -{ - if (rx <= 0 || ry <= 0 || ry2 <= 0) - throw (Exc(t_("Invalid graph range"))); - xRange=rx; - yRange=ry; - yRange2=ry2; - xMajorUnit=xRange/10; - AdjustMinUnitX(); - yMajorUnit=yRange/10; - AdjustMinUnitY(); - yMajorUnit2=yRange2/10; - AdjustMinUnitY2(); - WhenSetRange(); - return *this; -} -Scatter &Scatter::SetMajorUnits(double ux, double uy) -{ - //if (ux > xRange) throw (Exc(t_("Invalid X major units!"))); - //if (uy > yRange) throw (Exc(t_("Invalid Y major units!"))); - xMajorUnit=ux; - yMajorUnit=uy; - yMajorUnit2=yRange2*yMajorUnit/yRange; - AdjustMinUnitX(); - AdjustMinUnitY(); - AdjustMinUnitY2(); - return *this; -} -Scatter &Scatter::SetMinUnits(double ux, double uy) -{ - xMinUnit=ux; - yMinUnit=uy; - yMinUnit2=yRange2*yMinUnit/yRange; - AdjustMinUnitX(); - AdjustMinUnitY(); - AdjustMinUnitY2(); - return *this; -} -Scatter &Scatter::SetXYMin(double xmin, double ymin, double ymin2) -{ - xMin=xmin; - yMin=ymin; - yMin2=ymin2; - WhenSetXYMin(); - return *this; -} - -void Scatter::FitToData(bool Y) { - double minx, maxx, miny, miny2, maxy, maxy2; - minx = miny = miny2 = -DOUBLE_NULL; - maxx = maxy = maxy2 = DOUBLE_NULL; - - for (int j=0; j maxx) - maxx = vPointsData[j][i].x; - } - } - for (int j=0; j maxy) - maxy = vPointsData[j][i].y; - } else { - if (vPointsData[j][i].y < miny2) - miny2 = vPointsData[j][i].y; - if (vPointsData[j][i].y > maxy2) - maxy2 = vPointsData[j][i].y; - } - } - } - for (int j=0; j & points,const String& legend,const bool& join, const class::Color& pcolor, const int& width, const int& thickness) -{ - vPointsData.AddPick(points); - vJoin.Add(join); - vSmooth.Add(false); - vPColors.Add(pcolor); - vPWidth.Add(width); - vPThickness.Add(thickness); - vLegend.Add(legend); - vMarkColors.Add(pcolor); - if (width <= 1) - vShowMark.Add(false); - else - vShowMark.Add(true); - vMarkStyles.Add(CIRCLE); - vPPrimaryY.Add(true); - vPSequential.Add(sequentialXAll); - vPPattern.Add(LINE_SOLID); - - Refresh(); - return *this; -} - -Color GetNewColor(int id) -{ - switch(id) { - case 0: return LtBlue(); - case 1: return LtRed(); - case 2: return LtGreen(); - case 3: return Black(); - case 4: return LtGray(); - case 5: return Yellow(); - case 6: return Brown(); - case 7: return Blue(); - case 8: return Red(); - case 9: return Green(); - case 10:return Gray(); - } - return Color(Random(), Random(), Random()); -} - -Scatter &Scatter::Stroke(int width, class::Color pcolor, const String pattern) -{ - int id = vPointsData.GetCount() - 1; - - vJoin[id] = width > 0; - if (IsNull(pcolor)) - pcolor = GetNewColor(id); - vPColors[id] = pcolor; - vPWidth[id] = width; - - Refresh(); - return *this; -} - -Scatter &Scatter::Mark(int thickness, class::Color pcolor, MarkStyle style) -{ - int id = vPointsData.GetCount() - 1; - - vPThickness[id] = thickness; - if (IsNull(pcolor)) - pcolor = GetNewColor(id); - vMarkColors[id] = pcolor; - vShowMark[id] = thickness > 0; - vMarkStyles[id] = style; - - Refresh(); - return *this; -} - -Scatter &Scatter::SetPattern(const String pattern) -{ - vPPattern[vPPattern.GetCount()-1] = pattern; - return *this; -} - -void Scatter::AddPoint(const int& j, const XY & point, const bool& refresh) -{ - if(IsValid(j)) - { - vPointsData[j].Add(point); - if(refresh) Refresh(); - } -} -void Scatter::InsertPoint(const int& j, const int& i, const XY & point) -{ - if(IsValid(j)) - { - if(i>=0 && vPointsData[j].GetCount()>=i) - { - vPointsData[j].Insert(i,point); - Refresh(); - } - } -} -void Scatter::RemovePoint(const int& j, const int& i) -{ - if(IsValid(j)) - { - if(i>=0 && vPointsData[j].GetCount()>i) - { - vPointsData[j].Remove(i); - Refresh(); - } - } -} -void Scatter::SetData(const int& j, const int& i, const XY & point) -{ - if(IsValid(j)) - { - if(i>=0 && vPointsData[j].GetCount()>i) - { - vPointsData[j][i]=point; - Refresh(); - } - } -} - -void Scatter::SetData(const int& j, Vector & points) -{ - if(IsValid(j)) - { - vPointsData[j]<<=points; - Refresh(); - } -} -void Scatter::SetDataColor(const int& j, const class::Color& pcolor) -{ - if(IsValid(j)) - { - vPColors[j]=pcolor; - Refresh(); - } -} -void Scatter::SetFunctColor(const int& j, const class::Color& fcolor) -{ - if(IsValid(j)) - { - vFColors[j]=fcolor; - Refresh(); - } -} -Color Scatter::GetDataColor(const int& j) const -{ - if(IsValid(j)) - { - return vPColors[j]; - } - throw (Exc(t_("Invalid series index!"))); -} - -Color Scatter::GetFunctColor(const int& j) const -{ - if(IsValid(j)) - { - return vFColors[j]; - } - throw (Exc(t_("Invalid function index!"))); -} - -void Scatter::SetDataThickness(const int& j, const int& thick_dots) -{ - if(IsValid(j)) - { - vPThickness[j]=thick_dots; - Refresh(); - } -} - -void Scatter::SetFunctThickness(const int& j, const int& thick_dots) -{ - if(IsValid(j)) - { - vFThickness[j]=thick_dots; - Refresh(); - } -} -int Scatter::GetDataThickness(const int& j) const -{ - if(IsValid(j)) - { - return vPThickness[j]; - } - throw (Exc(t_("Invalid series index!"))); -} - -int Scatter::GetFunctThickness(const int& j) const -{ - if(IsValid(j)) - { - return vFThickness[j]; - } - throw (Exc(t_("Invalid series index!"))); -} - -void Scatter::SetMarkWidth(const int& j, const int& width_dots) -{ - if(IsValid(j)) - { - vPWidth[j]=width_dots; - Refresh(); - } -} - -int Scatter::GetMarkWidth(const int& j) const -{ - if(IsValid(j)) - { - return vPWidth[j]; - } - throw (Exc(t_("Invalid series index!"))); -} - -void Scatter::SetMarkStyle(const int& j, MarkStyle noStyle) -{ - if(IsValid(j)) - { - vMarkStyles[j]=noStyle; - Refresh(); - } -} - -int Scatter::GetMarkStyle(const int& j) const -{ - if(IsValid(j)) - { - return vMarkStyles[j]; - } - throw (Exc(t_("Invalid series index!"))); -} - -void Scatter::SetMarkColor(const int& j, const ::Color& mcolor) -{ - if(IsValid(j)) - { - vMarkColors[j]=mcolor; - Refresh(); - } -} - -Color Scatter::GetMarkColor(const int& j) const -{ - if(IsValid(j)) - { - return vMarkColors[j]; - } - throw (Exc(t_("Invalid series index!"))); -} - -void Scatter::SetShowMark(const int& j, const bool& show) -{ - if(IsValid(j)) - { - vShowMark[j]=show; - Refresh(); - } -} - -bool Scatter::IsMarkShow(const int& j) const throw (Exc) -{ - if(!IsValid(j)) - throw (Exc(t_("Invalid series index!"))); - return vShowMark[j]; -} - -void Scatter::SetJoin(const int& j, const bool& join) -{ - if(IsValid(j)) - { - vJoin[j]=join; - Refresh(); - } -} - -bool Scatter::IsJoined(const int& j) const throw (Exc) -{ - if(!IsValid(j)) - throw (Exc(t_("Invalid series index!"))); - - return vJoin[j]; -} - -void Scatter::SetSmooth(const int& j, const bool& smooth) -{ - if(IsValid(j)) - { - vSmooth[j]=smooth; - Refresh(); - } -} - -bool Scatter::IsSmooth(const int& j) const throw (Exc) -{ - if(!IsValid(j)) - throw (Exc(t_("Invalid series index!"))); - - return vSmooth[j]; -} - -void Scatter::SetDataPrimaryY(const int& j, const bool& primary) -{ - if(IsValid(j)) - { - vPPrimaryY[j]=primary; - Refresh(); - } -} - -Scatter &Scatter::SetDataPrimaryY(const bool& primary) -{ - SetDataPrimaryY(vPPrimaryY.GetCount()-1, primary); - return *this; -} - -bool Scatter::IsDataPrimaryY(const int& j) const throw (Exc) -{ - if(!IsValid(j)) - throw (Exc(t_("Invalid series index!"))); - return vPPrimaryY[j]; -} - -void Scatter::SetSequentialX(const int& j, const bool& sequential) -{ - if(IsValid(j)) - { - vPSequential[j]=sequential; - Refresh(); - } -} - -Scatter &Scatter::SetSequentialX(const bool& sequential) -{ - SetSequentialX(vPSequential.GetCount()-1, sequential); - return *this; -} - -Scatter &Scatter::SetSequentialXAll(const bool& sequential) -{ - for (int i = 0; i < vPSequential.GetCount(); ++i) - SetSequentialX(i, sequential); - sequentialXAll = sequential; - return *this; -} - -void Scatter::SetFunctPrimaryY(const int& j, const bool& primary) -{ - if(IsValid(j)) - { - vFPrimaryY[j]=primary; - Refresh(); - } -} - -Scatter &Scatter::SetFunctPrimaryY(const bool& primary) -{ - SetFunctPrimaryY(vFPrimaryY.GetCount()-1, primary); - return *this; -} - -bool Scatter::IsFunctPrimaryY(const int& j) const throw (Exc) -{ - if(!IsValid(j)) - throw (Exc(t_("Invalid series index!"))); - return vFPrimaryY[j]; -} - -void Scatter::RemoveSeries(const int& j) -{ - if (IsValid(j)) - { - vPointsData.Remove(j); - vJoin.Remove(j); - vSmooth.Remove(j); - vPColors.Remove(j); - vPWidth.Remove(j); - vPThickness.Remove(j); - vLegend.Remove(j); - vMarkColors.Remove(j); - vShowMark.Remove(j); - vMarkStyles.Remove(j); - vPPrimaryY.Remove(j); - vPPattern.Remove(j); - vPSequential.Remove(j); - - Refresh(); - } -} - -void Scatter::RemoveAllSeries() -{ - vPointsData.Clear(); - vJoin.Clear(); - vSmooth.Clear(); - vPColors.Clear(); - vPWidth.Clear(); - vPThickness.Clear(); - vLegend.Clear(); - vMarkColors.Clear(); - vShowMark.Clear(); - vMarkStyles.Clear(); - vPPrimaryY.Clear(); - vPSequential.Clear(); - vPPattern.Clear(); - - Refresh(); -} - - -void Scatter::PlotFunction(PlotFunc f, const String& legend, const class::Color& fcolor, const int& weight) -{ - Vector series; - vFunctionData.AddPick(series); - - vAdress.Add(f); - - vFColors.Add(fcolor); - vFThickness.Add(weight); - vFLegend.Add(legend); - vFPrimaryY.Add(true); - vFPattern.Add(LINE_SOLID); - Refresh(); -} -void Scatter::PlotParaFunction(PlotParamFunc f, const String& legend, const class::Color& fcolor, const int& weight,const int& Np) -{ - double t;//t must be choosed between [0,1] - Vector series; - for (int i=0; i<=Np;i++) - { - t=(double)i/Np; - //series<j) - { - if(vFunctionData[j].IsEmpty()) - { - int nf=-1; - for(int i=0; i<=j; i++) - { - if (vFunctionData[i].IsEmpty()) - nf++; - } - vAdress.Remove(nf); - } - - vFunctionData.Remove(j); - vFColors.Remove(j); - vFThickness.Remove(j); - vFLegend.Remove(j); - vFPrimaryY.Remove(j); - vFPattern.Remove(j); - - Refresh(); - } -} - -void Scatter::RemoveAllFSeries() -{ - vAdress.Clear(); - vFunctionData.Clear(); - vFColors.Clear(); - vFThickness.Clear(); - vFLegend.Clear(); - vFPrimaryY.Clear(); - vFPattern.Clear(); - - Refresh(); -} - -Drawing Scatter::GetDrawing() const -{ - DrawingDraw ddw(6*GetSize()); - SetDrawing (ddw, 6); - return ddw; -} - -Image Scatter::GetImage(const int& scale) -{ - bool aa=antialiasing; - antialiasing=false; - ImageDraw idraw(scale*GetSize()); - SetDrawing (idraw,scale); - antialiasing=aa; - return idraw; -} - -#ifdef PLATFORM_WIN32 - -void Scatter::SaveAsMetafile(const char* file) const -{ - WinMetaFileDraw wmfd; - wmfd.Create(6*GetSize().cx,6*GetSize().cy,"Scatter","chart",file); - SetDrawing (wmfd, 6); - wmfd.Close(); -} - -void Scatter::SaveToClipboard(bool saveAsMetafile) -{ - if (saveAsMetafile) { - WinMetaFileDraw wmfd; - wmfd.Create(6*GetSize().cx,6*GetSize().cy,"Scatter","chart"); - SetDrawing (wmfd, 6); - WinMetaFile wmf = wmfd.Close(); - wmf.WriteClipboard(); - } else { - Image img = GetImage(3); - WriteClipboardImage(img); - } -} -#else - -void Scatter::SaveToClipboard(bool) -{ - Image img = GetImage(3); - WriteClipboardImage(img); -} - -#endif - -double Scatter::GetXByPoint(const int x) -{ - return (x-GetH_Border())*GetXRange()/(GetSize().cx-2*GetH_Border()-1)+GetXMin(); -} - -double Scatter::GetYByPoint(const int y) -{ - return (GetSize().cy-GetV_Border()-y-1)*GetYRange()/(GetSize().cy-2*GetV_Border()-GetTitleFont().GetHeight()-1)+GetYMin(); -} - -double Scatter::GetY2ByPoint(const int y) -{ - return (GetSize().cy-GetV_Border()-y-1)*GetY2Range()/(GetSize().cy-2*GetV_Border()-GetTitleFont().GetHeight()-1)+GetYMin2(); -} - -double Scatter::GetXPointByValue(const double x) -{ - return (x-GetXMin())/GetXRange()*(GetSize().cx-2*GetH_Border()-1)+GetH_Border(); -} - -double Scatter::GetYPointByValue(const double y) -{ - return (GetSize().cy-GetV_Border()-1)-(y-GetYMin())/GetYRange()*(GetSize().cy-2*GetV_Border()-GetTitleFont().GetHeight()-1); -} - -void Scatter::Paint(Draw& w) -{ - SetDrawing(w,1); -} - -void Scatter::ShowInfo(bool show) -{ - paintInfo=show; -} - -void Scatter::ProcessPopUp(const Point & pt) -{ - double _x= (popLT.x-px)*xRange/(GetSize().cx-2*px-1)+xMin; - double _y= (GetSize().cy-py-popLT.y-1)*yRange/(GetSize().cy-2*py-titleFont.GetHeight()-1)+yMin; - double _y2=(GetSize().cy-py-popLT.y-1)*yRange2/(GetSize().cy-2*py-titleFont.GetHeight()-1)+yMin2; - double x= (pt.x-px)*xRange/(GetSize().cx-2*px-1)+xMin; - double y= (GetSize().cy-py-pt.y-1)*yRange/(GetSize().cy-2*py-titleFont.GetHeight()-1)+yMin; - double y2=(GetSize().cy-py-pt.y-1)*yRange2/(GetSize().cy-2*py-titleFont.GetHeight()-1)+yMin2; - - double dx = x - _x; - double dy = y - _y; - double dy2 = y2 - _y2; - if(logX) { - x = pow(10.0, x); - _x = pow(10.0, _x); - dx = pow(10.0, dx); - } - if(logY) { - y = pow(10.0, y); - _y = pow(10.0, _y); - dy = pow(10.0, dy); - } - if(logY2) { - y2 = pow(10.0, y2); - _y2 = pow(10.0, _y2); - dy2 = pow(10.0, dy2); - } - String strx, _strx, dstrx, stry, _stry, dstry; - if (cbModifFormatX) { - cbModifFormatX(strx, 0, x); strx.Replace("\n", " "); - cbModifFormatX(_strx, 0, _x); _strx.Replace("\n", " "); - } else { - strx = VariableFormatX(x); - _strx = VariableFormatX(_x); - } - if (cbModifFormatDeltaX) { - cbModifFormatDeltaX(dstrx, 0, dx); dstrx.Replace("\n", " "); - } else { - dstrx = VariableFormatX(dx); - } - if (cbModifFormatY) { - cbModifFormatY(stry, 0, y); stry.Replace("\n", " "); - cbModifFormatY(_stry, 0, _y); _stry.Replace("\n", " "); - } else { - stry = VariableFormatY(y); - _stry = VariableFormatY(_y); - } - if (cbModifFormatDeltaY) { - cbModifFormatDeltaY(dstry, 0, dy); dstry.Replace("\n", " "); - } else { - dstry = VariableFormatY(dy); - } - String str= popTextX + ": " + _strx; - if (strx != _strx) - str << "; " + popTextX + "': " + strx + "; Δ" + popTextX + ": " + dstrx; - str << "\n" + popTextY + ": " + _stry; - if (stry != _stry) - str << "; " + popTextY + "': " + stry + "; Δ" + popTextY + ": " + dstry; - if (drawY2Reticle) { - String stry2, _stry2, dstry2; - if (cbModifFormatY2) { - cbModifFormatY2(stry2, 0, y2); stry2.Replace("\n", " "); - cbModifFormatY2(_stry2, 0, _y2); _stry2.Replace("\n", " "); - } else { - stry2 = VariableFormatY2(y2); - _stry2 = VariableFormatY2(_y2); - } - if (cbModifFormatDeltaY2) { - cbModifFormatDeltaY2(dstry2, 0, dy2); dstry2.Replace("\n", " "); - } else { - dstry2 = VariableFormatY(dy2); - } - str << "\n" + popTextY2 + ": " + _stry2; - if (stry2 != _stry2) - str << "; " + popTextY2 + ": " + stry2 + "; Δ" + popTextY2 + ": " + dstry2; - } - const Point p2 = pt+offset; - popText.SetText(str).Move(this,p2.x,p2.y); -} - -void Scatter::DoMouseAction(bool down, Point pt, MouseAction action, int value) -{ - switch (action) { - case SCROLL: Scrolling(down, pt); - break; - case ZOOM_H_ENL: - case ZOOM_H_RED: MouseZoom(value, true, false); - break; - case ZOOM_V_ENL: - case ZOOM_V_RED: MouseZoom(value, false, true); - break; - case SHOW_INFO: LabelPopUp(down, pt); - break; - } -} - -bool Scatter::SetMouseBehavior(MouseBehaviour *_mouseBehavior) -{ - if (!_mouseBehavior) - return false; - int i; - for (i = 0; _mouseBehavior[i].action != NO_ACTION && i < MAX_MOUSEBEHAVIOR; ++i) ; - if (i == MAX_MOUSEBEHAVIOR) - return false; - mouseBehavior = _mouseBehavior; - return true; -} - -void Scatter::ProcessMouse(bool down, Point &pt, bool ctrl, bool alt, bool shift, bool left, bool middle, int middleWheel, bool right) -{ - int i; - for (i = 0; mouseBehavior[i].action != NO_ACTION && i < MAX_MOUSEBEHAVIOR; ++i) { - if (mouseBehavior[i].ctrl == ctrl && mouseBehavior[i].alt == alt && - mouseBehavior[i].shift == shift && mouseBehavior[i].left == left && - mouseBehavior[i].middle == middle && mouseBehavior[i].right == right && - ((mouseBehavior[i].middleWheel == 0) || mouseBehavior[i].middleWheel == ((middleWheel > 0) - (middleWheel < 0)))) - DoMouseAction(down, pt, mouseBehavior[i].action, middleWheel); - } -} - -void Scatter::LabelPopUp(bool down, Point &pt) -{ - if (down) { - if(paintInfo && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) - { - popText.AppearOnly(this); - - isLabelPopUp = true; - if (IsNull(popLT)) - popLT = pt; - popRB = pt; - ProcessPopUp(pt); - } - } else { - if(paintInfo && isLabelPopUp) - { - popText.Close(); - isLabelPopUp = false; - popLT = popRB = Null; - Refresh(); - } - } -} - -#ifdef PLATFORM_LINUX - #include -#endif - -void Scatter::Scrolling(bool down, Point &pt, bool isOut) -{ - static Image mouseImg; - if (down) { - if((mouseHandlingX || mouseHandlingY) && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) - { - butDownX = pt.x; - butDownY = pt.y; - isScrolling = true; - INTERLOCKED { -#ifdef PLATFORM_WIN32 - static Image img = Win32Cursor(IDC_SIZEALL); -#else - static Image img = X11Cursor(XC_fleur); -#endif - mouseImg = Ctrl::OverrideCursor(img); - } - } - } else { - if (isScrolling) { - if (!isOut) - MouseMove(pt, 0); - isScrolling = false; - Ctrl::OverrideCursor(mouseImg); - } - } -} - -void Scatter::LeftDown(Point pt, dword keyFlags) -{ - ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, true, false, 0, false); -} - -void Scatter::LeftUp(Point pt, dword keyFlags) -{ - ProcessMouse(false, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, true, false, 0, false); -} - -void Scatter::MiddleDown(Point pt, dword keyFlags) -{ - ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, true, 0, false); -} - -void Scatter::MiddleUp(Point pt, dword keyFlags) -{ - ProcessMouse(false, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, true, 0, false); -} - -void Scatter::RightDown(Point pt, dword keyFlags) -{ - ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, false, 0, true); -} - -void Scatter::RightUp(Point pt, dword keyFlags) -{ - ProcessMouse(false, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, false, 0, true); -} - -void Scatter::MouseWheel(Point pt, int zdelta, dword keyFlags) -{ - if (zdelta == 0) - return; - ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, false, zdelta, false); -} - -void Scatter::MouseMove(Point pt, dword) -{ - if (isScrolling) - { - int shiftX = pt.x - butDownX; - if (mouseHandlingX && shiftX != 0) { - double deltaX = shiftX*xRange/(GetSize().cx - 2*px - 1); - xMin -= deltaX; - xMinUnit += deltaX; - AdjustMinUnitX(); - butDownX = pt.x; - } - int shiftY = pt.y - butDownY; - if (mouseHandlingY && shiftY != 0) { - double deltaY = -shiftY*yRange/(GetSize().cy - 2*py - 1); - yMin -= deltaY; - yMinUnit += deltaY; - AdjustMinUnitY(); - if (drawY2Reticle) { - double deltaY2 = -shiftY*yRange2/(GetSize().cy - 2*py - 1); - yMin2 -= deltaY2; - yMinUnit2 += deltaY2; - AdjustMinUnitY2(); - } - butDownY = pt.y; - } - if ((mouseHandlingX && shiftX != 0) || (mouseHandlingY && shiftY != 0)) { - WhenSetXYMin(); - Refresh(); - WhenZoomScroll(); - } - } - if(isLabelPopUp) { - if (paintInfo && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) - { - if (IsNull(popLT)) - popLT = pt; - popRB = pt; - popText.AppearOnlyOpen(this); - - ProcessPopUp(pt); - Refresh(); - } - } -} - -void Scatter::MouseLeave() -{ - Point p = Null; - Scrolling(false, p, true); -} - -void Scatter::MouseZoom(int zdelta, bool hor, bool ver) -{ - double scale = zdelta > 0 ? zdelta/100. : -100./zdelta; - Zoom(scale); -} - -void Scatter::Zoom(double scale, bool hor, bool ver) -{ - bool mouseX = mouseHandlingX && hor; - mouseX = mouseX && ((minXZoom > 0 && xRange*scale > minXZoom) || (minXZoom < 0)); - mouseX = mouseX && ((maxXZoom > 0 && xRange*scale < maxXZoom) || (maxXZoom < 0)); - bool mouseY = mouseHandlingY && ver; - mouseY = mouseY && ((minYZoom > 0 && yRange*scale > minYZoom) || (minYZoom < 0)); - mouseY = mouseY && ((maxYZoom > 0 && yRange*scale < maxYZoom) || (maxYZoom < 0)); - mouseX = mouseX && (!mouseHandlingY || mouseY); - mouseY = mouseY && (!mouseHandlingX || mouseX); - if (mouseX) - { - double oldXMin = xMin; - xMin += xRange*(1-scale)/2.; - xMinUnit = oldXMin + xMinUnit - xMin; - AdjustMinUnitX(); - xRange *= scale; - } - - if (mouseY) - { - yRange *= scale; - yRange2 *= scale; - } - if (mouseX || mouseY) { - WhenSetRange(); - Refresh(); - WhenZoomScroll(); - } -} - -void Scatter::Scroll(double factorX, double factorY) -{ - if (factorX != 0) { - double deltaX = factorX*xRange; - xMin -= deltaX; - xMinUnit += deltaX; - AdjustMinUnitX(); - } - if (factorY != 0) { - double deltaY = -factorY*yRange; - yMin -= deltaY; - yMinUnit += deltaY; - AdjustMinUnitY(); - if (drawY2Reticle) { - double deltaY2 = -factorY*yRange2; - yMin2 -= deltaY2; - yMinUnit2 += deltaY2; - AdjustMinUnitY2(); - } - } - if (factorX != 0 || factorY != 0) { - Refresh(); - WhenZoomScroll(); - } -} - -Image Scatter::CursorImage(Point p, dword keyflags) -{ - return ChartImg::cursor1(); -} - -void Scatter::Circle(Draw& w, const int& scale, const Point& cp, const int& size, const class::Color& markColor)const -{ - int radius = fround(scale*size/6); int radius2 = radius/2; - w.DrawEllipse(cp.x-radius2, cp.y-radius2, radius, radius, markColor, 1, markColor); -} - -void Scatter::Square(Draw& w, const int& scale, const Point& cp, const int& size, const class::Color& markColor)const -{ - Vector p; - p< p; - p< p; - p< GetLinePattern(String pattern) -{ - Vector ret; - - ret.Add(); - int retPos = 0; - ret[0] = 2; - for (int i = 1; i < pattern.GetCount(); ++i) { - if (pattern[i] != pattern[i-1]) { - ret.Add(); - retPos++; - ret[retPos] = 0; - } - ret[retPos] += 2; - } - return ret; -} - -Vector &GetPatternArray(String pattern) -{ - static VectorMap > pats; - - int pos = pats.Find(pattern); - if (pos < 0) { - pats.Add(pattern, GetLinePattern(pattern)); - pos = pats.GetCount()-1; - } - return pats.GetValues()[pos]; -} - -void Scatter::DrawLineX(Draw& w, const int x0, const int y0, const int x1, const int y1, int thick, const class::Color &color, String pattern, const int &scale) -{ - Vector p; - p.SetCount(2); - p[0].x = x0; - p[0].y = y0; - p[1].x = x1; - p[1].y = y1; - DrawPolylineX(w, p, thick, color, pattern, scale); -} - -void Scatter::DrawPolylineX(Draw& w, const Vector &p, int thick, const class::Color &color, String pattern, const int &scale) -{ - if (pattern == LINE_SOLID) - w.DrawPolyline(p, thick, color); - else { - Vector &pat = GetPatternArray(pattern); - int iPat = 0; - - double len = pat[0]*scale; // Pixels por barra - Pointf begin, end; - begin = p[0]; - for (int i = 1; i < p.GetCount();) { - double d = Dist(begin, p[i]); - if (d >= len) - end = PointAtLen(begin, p[i], len); - else { - end = p[i]; - len -= d; - ++i; - } - if (Even(iPat)) - w.DrawLine(begin, end, thick, color); - if (d >= len) { - iPat++; - if (iPat == pat.GetCount()) - iPat = 0; - len = pat[iPat]*scale; - } - begin = end; - } - } -} - -void Scatter::Plot(Draw& w, const int& scale,const int& l,const int& h)const -{ - double d1=xRange/xMajorUnit; - double d2=yRange/yMajorUnit; - - w.DrawRect(1,1,l-2,h-1,plotAreaColor); //grosimea liniei nu este scalata - int gW=fround(gridWidth*scale/6); - if(gridWidth<0) - gW=gridWidth; - Vector p; - p.SetCount(2); - if (drawVGrid) - for(int i=0; xMinUnit+i*xMajorUnit < xRange;i++) { - p[0].x = fround(l*xMinUnit/xRange+i*l/d1); p[0].y = 0; - p[1].x = fround(l*xMinUnit/xRange+i*l/d1); p[1].y = h; - DrawPolylineX(w, p, gW, gridColor, "oo..", scale); - } - - if (drawHGrid) - for(int i=0; yMinUnit+i*yMajorUnit < yRange;i++) { - p[0].x = 0; p[0].y = fround(-h*yMinUnit/yRange + h-i*h/d2); - p[1].x = l; p[1].y = fround(-h*yMinUnit/yRange + h-i*h/d2); - DrawPolylineX(w, p, gW, gridColor, "oo..", scale); - } - w.DrawLine(0, h, l, h, scale, Black); - w.DrawLine(0, 0, l, 0, scale, Black); - w.DrawLine(0, 0, 0, h, scale, Black); - w.DrawLine(l, 0, l, h+1, scale, Black); - w.Clip(Rect(0,0,l,h)); - int ix;//int x points coordinates - int iy;//int y points coordinates - if (!vPointsData.IsEmpty()){ - for (int j=0; j p1; - int imin, imax; - if (vPSequential[j]) { - imin = imax = Null; - for (int i = 1; i= xMin) - imin = i-1; - } else if (IsNull(imax)) { - if (vPointsData[j][i].x >= xMin+xRange) - imax = i+1; - } - } - if (IsNull(imin)) - imin = 0; - if (IsNull(imax)) - imax = vPointsData[j].GetCount(); - } else { - imin = 0; - imax = vPointsData[j].GetCount(); - } - int numV; - if (fastViewX) - numV = 1+(imax-imin)/l; - else - numV = 1; - for (int i=imin; i 1) { - yy = 0; - int ii; - for (ii = 0; ii < numV && i+ii < imax; ++ii) - yy += vPointsData[j][i+ii].y; - yy /= double(ii); - xx = (vPointsData[j][i].x + vPointsData[j][i+ii-1].x)/2; - } else { - xx = vPointsData[j][i].x; - yy = vPointsData[j][i].y; - } - ix=fround(l*(xx-xMin)/xRange); - if (vPPrimaryY[j]) - iy=fround(h*(yy-yMin)/yRange); - else - iy=fround(h*(yy-yMin2)/yRange2); - p1<2) - { - Vector p2; - Vector v(Cubic(vPointsData[j])); - for (int i=0; i= 1) { - for (int i=0; i<(imax-imin)/numV; i++) - DrawMark(vMarkStyles[j],w,scale,p1[i],vPWidth[j],vMarkColors[j]); - } - } - } - - int nf=0; //number of functions to draw - - for (int j=0; j p1; - for (int i=0; i p1; - for(int i=0; i Scatter::Cubic(const Vector& DataSet, const int& fineness,double tension) const -{ - Vector OutSet; - if(DataSet.GetCount()>2) { - OutSet<(OutSet); -} - -void ParseTextMultiline(const String &text, Font fnt, Array &texts, Array &sizes) { - Size ret(0, 0); - int npos = 0; - for (int pos = 0; npos != -1; pos = npos+1) { - npos = text.Find('\n', pos); - String &t = texts.Add(); - if (npos != -1) - t = text.Mid(pos, npos-pos); - else - t = text.Mid(pos); - Size &s = sizes.Add(); - s.cx = GetTextSize(t, fnt).cx; - s.cy = GetTextSize(t, fnt).cy; - } -} - -Size GetTextSizeMultiline(Array &sizes) { - Size ret(0, 0); - for (int i = 0; i < sizes.GetCount(); ++i) { - if (sizes[i].cx > ret.cx) - ret.cx = sizes[i].cx; - ret.cy += sizes[i].cy; - } - return ret; -} - -void Scatter::SetDrawing(Draw& w, const int& scale) const -{ - w.DrawRect(scale*GetSize(),graphColor); - Size sz; - sz.cx=0; - sz.cy=0; - if(!title.IsEmpty()) - { - Font FontTitle6; - FontTitle6=titleFont; - FontTitle6.Height(scale*titleFont.GetHeight()); - FontTitle6.Width(scale*titleFont.GetWidth()); - sz= GetTextSize(title, FontTitle6); - w.DrawText((scale*GetSize().cx-sz.cx)/2,scale*2,title,FontTitle6,titleColor); - } - - w.Offset(Point(scale*px,scale*py+scale*titleFont.GetHeight())); - if(showLegend) - DrawLegend(w,scale); - int l=scale*GetSize().cx-2*scale*px; - int h=scale*GetSize().cy-2*scale*py-scale*titleFont.GetHeight(); - - Font FontLabel6; - FontLabel6=labelsFont; - FontLabel6.Height(scale*labelsFont.GetHeight()); - - Size lx=GetTextSize(xLabel,FontLabel6); - Size ly=GetTextSize(yLabel,FontLabel6); - Size ly2=GetTextSize(yLabel2,FontLabel6); - w.DrawText(fround((l-lx.cx)/2),h+scale*py-lx.cy-scale*2,xLabel,FontLabel6,labelsColor); - w.DrawText(scale*2-scale*px,fround((h+ly.cx)/2),900,yLabel,FontLabel6,labelsColor); - w.DrawText(fround(l+scale*px-ly2.cy-2*scale),fround((h+ly2.cx)/2),900,yLabel2,FontLabel6,labelsColor); - - if (drawXReticle) - for(int i=0; xMinUnit+i*xMajorUnit<=xRange;i++){ - w.DrawLine(fround(l*xMinUnit/xRange+i*l/(xRange/xMajorUnit)), - h, - fround(l*xMinUnit/xRange+i*l/(xRange/xMajorUnit)), - h+scale*4, - fround(scale/2), - axisColor); - Font Standard6; - Standard6.Height(scale*StdFont().GetHeight()); - double gridX=xMinUnit+i*xMajorUnit+xMin; - String gridLabelX; - if (cbModifFormatX) - cbModifFormatX(gridLabelX, i, gridX); - else - gridLabelX = VariableFormatX(gridX); - - Array texts; - Array sizes; - ParseTextMultiline(gridLabelX, StdFont(), texts, sizes); - for (int ii = 0; ii < texts.GetCount(); ++ii) { - int cy = ii == 0 ? 0 : sizes[ii-1].cy; - w.DrawText(fround(l*xMinUnit/xRange+i*l/(xRange/xMajorUnit) - scale*sizes[ii].cx/2), h+scale*(4+ii*cy), texts[ii], Standard6, axisColor); - } - } - if (drawYReticle) - for(int i=0; yMinUnit+i*yMajorUnit<=yRange;i++){ - w.DrawLine(-(scale*4), - fround(-h*yMinUnit/yRange+h-i*h/(yRange/yMajorUnit)), - 0, - fround(-h*yMinUnit/yRange+h-i*h/(yRange/yMajorUnit)), - fround(scale/2), - axisColor); - double gridY=yMinUnit+i*yMajorUnit+yMin; - String gridLabelY; - if (cbModifFormatY) - cbModifFormatY(gridLabelY, i, gridY); - else - gridLabelY = VariableFormatY(gridY); - int dx=scale*GetTextSize(gridLabelY,StdFont()).cx; - Font Standard6; - Standard6.Height(scale*StdFont().GetHeight()); - w.DrawText(-dx-scale*6, fround(-h*yMinUnit/yRange+h-i*h/(yRange/yMajorUnit))-scale*8, gridLabelY, Standard6, axisColor); - } - if (drawY2Reticle) - for(int i=0; yMinUnit+i*yMajorUnit<=yRange;i++){ - w.DrawLine(l+(scale*4), - fround(-h*yMinUnit2/yRange2+h-i*h/(yRange/yMajorUnit)), - l, - fround(-h*yMinUnit2/yRange2+h-i*h/(yRange/yMajorUnit)), - fround(scale/2), - axisColor); - double gridY2=yMinUnit2+i*yMajorUnit2+yMin2; - String gridLabelY2; - if (cbModifFormatY2) - cbModifFormatY2(gridLabelY2, i, gridY2); - else - gridLabelY2 = VariableFormatY2(gridY2); - Font Standard6; - Standard6.Height(scale*StdFont().GetHeight()); - w.DrawText(l+scale*10,fround(-h*yMinUnit2/yRange2+h-i*h/(yRange/yMajorUnit))-scale*8,gridLabelY2,Standard6,axisColor); - } - - if(antialiasing) // && w.IsGui()) IsGui() is always false in Linux - { - ImageDraw imdraw(3*l,3*h); - Plot (imdraw,3,3*l,3*h); - w.DrawImage(0,0,l,h,imdraw); - } else - Plot(w,scale,l,h); - - w.End(); -} - -Scatter::Scatter(): - title (""), - titleColor(Black), - graphColor(White), - titleFont(Roman(20)), - xLabel(""),yLabel(""), - labelsFont(StdFont()), - labelsColor(Black), - plotAreaColor(::Color(245,245,248)), - axisColor(Black), - axisWidth(6), - px(30), - py(30), - xRange(100.0), - yRange(100.0), - yRange2(100.0), - xMajorUnit(xRange/10), - yMajorUnit(yRange/5), - xMin(0.0), yMin(0.0), yMin2(0.0), - xMinUnit(0.0), yMinUnit(0.0), yMinUnit2(0.0), - logX(false), logY(false), logY2(false), - cbModifFormatX(NULL),cbModifFormatY(NULL),cbModifFormatY2(NULL), - cbModifFormatDeltaX(NULL),cbModifFormatDeltaY(NULL),cbModifFormatDeltaY2(NULL), - gridColor(::Color(102,102,102)), - gridWidth(4), - paintInfo(false), - mouseHandlingX(false), mouseHandlingY(false), isScrolling(false), isLabelPopUp(false), - drawXReticle(true), drawYReticle(true), drawY2Reticle(false), - drawVGrid(true), drawHGrid(true), - showLegend(true),legendWeight(80), - antialiasing(false), - offset(10,12), - minXZoom(-1), maxXZoom(-1), minYZoom(-1), maxYZoom(-1), fastViewX(false), - sequentialXAll(false), popTextX("x"), popTextY("y1"), popTextY2("y2"), - popLT(Null), popRB(Null) -{ - Color(graphColor); - BackPaint(); - popText.SetColor(::Color(200,220,255)); - SetMouseBehavior(defaultMouse); -} - +#include "Scatter.h" + +#define IMAGECLASS ChartImg +#define IMAGEFILE +#include + +Scatter::MouseBehaviour defaultMouse[] = { + {false, false, false, true , false, 0, false, Scatter::SHOW_INFO}, + {false, false, false, false, false, 0, true , Scatter::CONTEXT_MENU}, + {false, false, false, false, true , 0, false, Scatter::SCROLL}, + {false, false, false, false, false, 1, false, Scatter::ZOOM_H_RED}, + {false, false, false, false, false, 1, false, Scatter::ZOOM_V_RED}, + {false, false, false, false, false,-1, false, Scatter::ZOOM_H_ENL}, + {false, false, false, false, false,-1, false, Scatter::ZOOM_V_ENL}, + {false, false, false, false, false, 0, false, Scatter::NO_ACTION}}; + + +Scatter& Scatter::SetColor(const class::Color& _color) +{ + graphColor=_color; + return *this; +} + +Scatter& Scatter::SetTitle(const String& _title) +{ + title=_title; + return *this; +} +Scatter& Scatter::SetTitleFont(const Font& fontTitle) +{ + titleFont=fontTitle; + return *this; +} +Scatter& Scatter::SetTitleColor(const class::Color& colorTitle) +{ + titleColor=colorTitle; + return *this; +} +void Scatter::SetLabels(const WString& _xLabel, const WString& _yLabel, const WString& _yLabel2) +{ + xLabel=_xLabel; + yLabel=_yLabel; + yLabel2=_yLabel2; +} +Scatter& Scatter::SetLabelX(const WString& _xLabel) +{ + xLabel=_xLabel; + return *this; +} +Scatter& Scatter::SetLabelY(const WString& _yLabel) +{ + yLabel=_yLabel; + return *this; +} +Scatter& Scatter::SetLabelY2(const WString& _yLabel) +{ + yLabel2=_yLabel; + return *this; +} +Scatter& Scatter::SetLabelsFont(const Font& fontLabels) +{ + labelsFont=fontLabels; + return *this; +} +Scatter& Scatter::SetLabelsColor(const class::Color& colorLabels) +{ + labelsColor=colorLabels; + return *this; +} +Scatter& Scatter::SetPlotAreaPoz(const int& poz_x, const int& poz_y) +{ + px=poz_x; + py=poz_y; + return *this; +} +Scatter& Scatter::H_Border(const int& poz_x) +{ + if(poz_x>=0) + px=poz_x; + return *this; +} +Scatter& Scatter::V_Border(const int& poz_y) +{ + if(poz_y>=0) + py=poz_y; + return *this; +} + +Scatter& Scatter::SetPlotAreaColor(const class::Color& p_a_color) +{ + plotAreaColor=p_a_color; + return *this; +} +Scatter& Scatter::SetAxisColor(const class::Color& axis_color) +{ + axisColor=axis_color; + return *this; +} +Scatter& Scatter::SetAxisWidth(const int& axis_width) +{ + axisWidth=axis_width; + return *this; +} +Scatter& Scatter::SetGridColor(const class::Color& grid_color) +{ + gridColor=grid_color; + return *this; +} +Scatter& Scatter::SetGridWidth(const int& grid_width) +{ + gridWidth=grid_width; + return *this; +} +Scatter& Scatter::ShowHGrid(const bool& show) +{ + drawHGrid=show; + return *this; +} +Scatter& Scatter::ShowVGrid(const bool& show) +{ + drawVGrid=show; + return *this; +} +Scatter& Scatter::ShowLegend(const bool& show) +{ + showLegend=show; + return *this; +} +Scatter& Scatter::SetLegendWeight(const int& weight) +{ + legendWeight=weight; + return *this; +} +Scatter& Scatter::SetAntialiasing(const bool& aa) +{ + antialiasing=aa; + return *this; +} +Scatter &Scatter::SetDrawXReticle(bool set) +{ + drawXReticle = set; + return *this; +} +Scatter &Scatter::SetDrawYReticle(bool set) +{ + drawYReticle = set; + return *this; +} +Scatter &Scatter::SetDrawY2Reticle(bool set) +{ + drawY2Reticle = set; + return *this; +} +void Scatter::DrawLegend(Draw& w,const int& scale) const +{ + Vector L; + L.Append(vLegend); + L.Append(vFLegend); + Vector Thick; + Thick.Append(vPThickness); + Thick.Append(vFThickness); + Vector LC; + LC.Append(vPColors); + LC.Append(vFColors); + Vector LW; + LW.Append(vPWidth); + VectorVJ; + VJ.Append(vJoin); + Vector MS; + MS.Append(vMarkStyles); + Vector MC; + MC.Append(vMarkColors); + Vector Patt; + Patt.Append(vPPattern); + Patt.Append(vFPattern); + + int NMR=fround((GetSize().cx-2*px)/legendWeight);//max number of labels per row + if (NMR>0) + { + int N=L.GetCount();//number of labels + int Nc;//number of complete rows + int LCR;//number of labels on complete row + int R;//number of remaining labels on incomplete row + if(NMR>N) + {Nc=0; LCR=0; R=N;} + else if (NMR==N) + {Nc=1; LCR=N; R=0;} + else + {Nc=N/NMR; LCR=NMR; R=N%NMR;} + for(int j=0;j<=Nc;j++) + { + int start=N-(j+1)*LCR; + int end=N-j*LCR; + if (j==Nc) + {start=0; end=R;} + for(int i=start;i vp; + vp << Point(scale*(i-start)*legendWeight, scale*(4-12*(j+1))) << + Point(scale*(i-start)*legendWeight+scale*23, scale*(4-12*(j+1))); + if (VJ.At(i)) + DrawPolylineX(w, vp, scale*Thick.At(i)/6, LC.At(i), Patt.At(i), scale); + Point p(scale*((i-start)*legendWeight+7),scale*(4-12*(j+1))/*+scale*Thick.At(i)/12*/); + if (LW.At(i,0) > 1) + DrawMark(MS.At(i),w,scale,p,LW.At(i,0),MC.At(i)); + Font scaledFont; + scaledFont.Height(scale*StdFont().GetHeight()); + w.DrawText(scale*(i-start)*legendWeight+scale*25, + scale*(-2-12*(j+1)), + L.At(i), + scaledFont,LC.At(i)); + } + } + } +} + +void Scatter::AdjustMinUnitX() +{ + if (xMajorUnit > 0) { + while (xMinUnit < 0) + xMinUnit += xMajorUnit; + while (xMinUnit > xMajorUnit) + xMinUnit -= xMajorUnit; + } +} +void Scatter::AdjustMinUnitY() +{ + if (yMajorUnit > 0) { + while (yMinUnit < 0) + yMinUnit += yMajorUnit; + while (yMinUnit > yMajorUnit) + yMinUnit -= yMajorUnit; + } +} +void Scatter::AdjustMinUnitY2() +{ + if (yMajorUnit2 > 0) { + while (yMinUnit2 < 0) + yMinUnit2 += yMajorUnit2; + while (yMinUnit2 > yMajorUnit2) + yMinUnit2 -= yMajorUnit2; + } +} +Scatter &Scatter::SetRange(double rx, double ry, double ry2) +{ + if (rx <= 0 || ry <= 0 || ry2 <= 0) + throw (Exc(t_("Invalid graph range"))); + xRange=rx; + yRange=ry; + yRange2=ry2; + xMajorUnit=xRange/10; + AdjustMinUnitX(); + yMajorUnit=yRange/10; + AdjustMinUnitY(); + yMajorUnit2=yRange2/10; + AdjustMinUnitY2(); + WhenSetRange(); + return *this; +} +Scatter &Scatter::SetMajorUnits(double ux, double uy) +{ + //if (ux > xRange) throw (Exc(t_("Invalid X major units!"))); + //if (uy > yRange) throw (Exc(t_("Invalid Y major units!"))); + xMajorUnit=ux; + yMajorUnit=uy; + yMajorUnit2=yRange2*yMajorUnit/yRange; + AdjustMinUnitX(); + AdjustMinUnitY(); + AdjustMinUnitY2(); + return *this; +} +Scatter &Scatter::SetMinUnits(double ux, double uy) +{ + xMinUnit=ux; + yMinUnit=uy; + yMinUnit2=yRange2*yMinUnit/yRange; + AdjustMinUnitX(); + AdjustMinUnitY(); + AdjustMinUnitY2(); + return *this; +} +Scatter &Scatter::SetXYMin(double xmin, double ymin, double ymin2) +{ + xMin=xmin; + yMin=ymin; + yMin2=ymin2; + WhenSetXYMin(); + return *this; +} + +void Scatter::FitToData(bool Y) { + double minx, maxx, miny, miny2, maxy, maxy2; + minx = miny = miny2 = -DOUBLE_NULL; + maxx = maxy = maxy2 = DOUBLE_NULL; + + for (int j=0; j maxx) + maxx = vPointsData[j][i].x; + } + } + for (int j=0; j maxy) + maxy = vPointsData[j][i].y; + } else { + if (vPointsData[j][i].y < miny2) + miny2 = vPointsData[j][i].y; + if (vPointsData[j][i].y > maxy2) + maxy2 = vPointsData[j][i].y; + } + } + } + for (int j=0; j & points,const String& legend,const bool& join, const class::Color& pcolor, const int& width, const int& thickness) +{ + vPointsData.AddPick(points); + vJoin.Add(join); + vSmooth.Add(false); + vPColors.Add(pcolor); + vPWidth.Add(width); + vPThickness.Add(thickness); + vLegend.Add(legend); + vMarkColors.Add(pcolor); + if (width <= 1) + vShowMark.Add(false); + else + vShowMark.Add(true); + vMarkStyles.Add(CIRCLE); + vPPrimaryY.Add(true); + vPSequential.Add(sequentialXAll); + vPPattern.Add(LINE_SOLID); + + Refresh(); + return *this; +} + +Color GetNewColor(int id) +{ + switch(id) { + case 0: return LtBlue(); + case 1: return LtRed(); + case 2: return LtGreen(); + case 3: return Black(); + case 4: return LtGray(); + case 5: return Yellow(); + case 6: return Brown(); + case 7: return Blue(); + case 8: return Red(); + case 9: return Green(); + case 10:return Gray(); + } + return Color(Random(), Random(), Random()); +} + +Scatter &Scatter::Stroke(int width, class::Color pcolor, const String pattern) +{ + int id = vPointsData.GetCount() - 1; + + vJoin[id] = width > 0; + if (IsNull(pcolor)) + pcolor = GetNewColor(id); + vPColors[id] = pcolor; + vPWidth[id] = width; + + Refresh(); + return *this; +} + +Scatter &Scatter::Mark(int thickness, class::Color pcolor, MarkStyle style) +{ + int id = vPointsData.GetCount() - 1; + + vPThickness[id] = thickness; + if (IsNull(pcolor)) + pcolor = GetNewColor(id); + vMarkColors[id] = pcolor; + vShowMark[id] = thickness > 0; + vMarkStyles[id] = style; + + Refresh(); + return *this; +} + +Scatter &Scatter::SetPattern(const String pattern) +{ + vPPattern[vPPattern.GetCount()-1] = pattern; + return *this; +} + +void Scatter::AddPoint(const int& j, const XY & point, const bool& refresh) +{ + if(IsValid(j)) + { + vPointsData[j].Add(point); + if(refresh) Refresh(); + } +} +void Scatter::InsertPoint(const int& j, const int& i, const XY & point) +{ + if(IsValid(j)) + { + if(i>=0 && vPointsData[j].GetCount()>=i) + { + vPointsData[j].Insert(i,point); + Refresh(); + } + } +} +void Scatter::RemovePoint(const int& j, const int& i) +{ + if(IsValid(j)) + { + if(i>=0 && vPointsData[j].GetCount()>i) + { + vPointsData[j].Remove(i); + Refresh(); + } + } +} +void Scatter::SetData(const int& j, const int& i, const XY & point) +{ + if(IsValid(j)) + { + if(i>=0 && vPointsData[j].GetCount()>i) + { + vPointsData[j][i]=point; + Refresh(); + } + } +} + +void Scatter::SetData(const int& j, Vector & points) +{ + if(IsValid(j)) + { + vPointsData[j]<<=points; + Refresh(); + } +} +void Scatter::SetDataColor(const int& j, const class::Color& pcolor) +{ + if(IsValid(j)) + { + vPColors[j]=pcolor; + Refresh(); + } +} +void Scatter::SetFunctColor(const int& j, const class::Color& fcolor) +{ + if(IsValid(j)) + { + vFColors[j]=fcolor; + Refresh(); + } +} +Color Scatter::GetDataColor(const int& j) const +{ + if(IsValid(j)) + { + return vPColors[j]; + } + throw (Exc(t_("Invalid series index!"))); +} + +Color Scatter::GetFunctColor(const int& j) const +{ + if(IsValid(j)) + { + return vFColors[j]; + } + throw (Exc(t_("Invalid function index!"))); +} + +void Scatter::SetDataThickness(const int& j, const int& thick_dots) +{ + if(IsValid(j)) + { + vPThickness[j]=thick_dots; + Refresh(); + } +} + +void Scatter::SetFunctThickness(const int& j, const int& thick_dots) +{ + if(IsValid(j)) + { + vFThickness[j]=thick_dots; + Refresh(); + } +} +int Scatter::GetDataThickness(const int& j) const +{ + if(IsValid(j)) + { + return vPThickness[j]; + } + throw (Exc(t_("Invalid series index!"))); +} + +int Scatter::GetFunctThickness(const int& j) const +{ + if(IsValid(j)) + { + return vFThickness[j]; + } + throw (Exc(t_("Invalid series index!"))); +} + +void Scatter::SetMarkWidth(const int& j, const int& width_dots) +{ + if(IsValid(j)) + { + vPWidth[j]=width_dots; + Refresh(); + } +} + +int Scatter::GetMarkWidth(const int& j) const +{ + if(IsValid(j)) + { + return vPWidth[j]; + } + throw (Exc(t_("Invalid series index!"))); +} + +void Scatter::SetMarkStyle(const int& j, MarkStyle noStyle) +{ + if(IsValid(j)) + { + vMarkStyles[j]=noStyle; + Refresh(); + } +} + +int Scatter::GetMarkStyle(const int& j) const +{ + if(IsValid(j)) + { + return vMarkStyles[j]; + } + throw (Exc(t_("Invalid series index!"))); +} + +void Scatter::SetMarkColor(const int& j, const ::Color& mcolor) +{ + if(IsValid(j)) + { + vMarkColors[j]=mcolor; + Refresh(); + } +} + +Color Scatter::GetMarkColor(const int& j) const +{ + if(IsValid(j)) + { + return vMarkColors[j]; + } + throw (Exc(t_("Invalid series index!"))); +} + +void Scatter::SetShowMark(const int& j, const bool& show) +{ + if(IsValid(j)) + { + vShowMark[j]=show; + Refresh(); + } +} + +bool Scatter::IsMarkShow(const int& j) const throw (Exc) +{ + if(!IsValid(j)) + throw (Exc(t_("Invalid series index!"))); + return vShowMark[j]; +} + +void Scatter::SetJoin(const int& j, const bool& join) +{ + if(IsValid(j)) + { + vJoin[j]=join; + Refresh(); + } +} + +bool Scatter::IsJoined(const int& j) const throw (Exc) +{ + if(!IsValid(j)) + throw (Exc(t_("Invalid series index!"))); + + return vJoin[j]; +} + +void Scatter::SetSmooth(const int& j, const bool& smooth) +{ + if(IsValid(j)) + { + vSmooth[j]=smooth; + Refresh(); + } +} + +bool Scatter::IsSmooth(const int& j) const throw (Exc) +{ + if(!IsValid(j)) + throw (Exc(t_("Invalid series index!"))); + + return vSmooth[j]; +} + +void Scatter::SetDataPrimaryY(const int& j, const bool& primary) +{ + if(IsValid(j)) + { + vPPrimaryY[j]=primary; + Refresh(); + } +} + +Scatter &Scatter::SetDataPrimaryY(const bool& primary) +{ + SetDataPrimaryY(vPPrimaryY.GetCount()-1, primary); + return *this; +} + +bool Scatter::IsDataPrimaryY(const int& j) const throw (Exc) +{ + if(!IsValid(j)) + throw (Exc(t_("Invalid series index!"))); + return vPPrimaryY[j]; +} + +void Scatter::SetSequentialX(const int& j, const bool& sequential) +{ + if(IsValid(j)) + { + vPSequential[j]=sequential; + Refresh(); + } +} + +Scatter &Scatter::SetSequentialX(const bool& sequential) +{ + SetSequentialX(vPSequential.GetCount()-1, sequential); + return *this; +} + +Scatter &Scatter::SetSequentialXAll(const bool& sequential) +{ + for (int i = 0; i < vPSequential.GetCount(); ++i) + SetSequentialX(i, sequential); + sequentialXAll = sequential; + return *this; +} + +void Scatter::SetFunctPrimaryY(const int& j, const bool& primary) +{ + if(IsValid(j)) + { + vFPrimaryY[j]=primary; + Refresh(); + } +} + +Scatter &Scatter::SetFunctPrimaryY(const bool& primary) +{ + SetFunctPrimaryY(vFPrimaryY.GetCount()-1, primary); + return *this; +} + +bool Scatter::IsFunctPrimaryY(const int& j) const throw (Exc) +{ + if(!IsValid(j)) + throw (Exc(t_("Invalid series index!"))); + return vFPrimaryY[j]; +} + +void Scatter::RemoveSeries(const int& j) +{ + if (IsValid(j)) + { + vPointsData.Remove(j); + vJoin.Remove(j); + vSmooth.Remove(j); + vPColors.Remove(j); + vPWidth.Remove(j); + vPThickness.Remove(j); + vLegend.Remove(j); + vMarkColors.Remove(j); + vShowMark.Remove(j); + vMarkStyles.Remove(j); + vPPrimaryY.Remove(j); + vPPattern.Remove(j); + vPSequential.Remove(j); + + Refresh(); + } +} + +void Scatter::RemoveAllSeries() +{ + vPointsData.Clear(); + vJoin.Clear(); + vSmooth.Clear(); + vPColors.Clear(); + vPWidth.Clear(); + vPThickness.Clear(); + vLegend.Clear(); + vMarkColors.Clear(); + vShowMark.Clear(); + vMarkStyles.Clear(); + vPPrimaryY.Clear(); + vPSequential.Clear(); + vPPattern.Clear(); + + Refresh(); +} + + +void Scatter::PlotFunction(PlotFunc f, const String& legend, const class::Color& fcolor, const int& weight) +{ + Vector series; + vFunctionData.AddPick(series); + + vAdress.Add(f); + + vFColors.Add(fcolor); + vFThickness.Add(weight); + vFLegend.Add(legend); + vFPrimaryY.Add(true); + vFPattern.Add(LINE_SOLID); + Refresh(); +} +void Scatter::PlotParaFunction(PlotParamFunc f, const String& legend, const class::Color& fcolor, const int& weight,const int& Np) +{ + double t;//t must be choosed between [0,1] + Vector series; + for (int i=0; i<=Np;i++) + { + t=(double)i/Np; + //series<j) + { + if(vFunctionData[j].IsEmpty()) + { + int nf=-1; + for(int i=0; i<=j; i++) + { + if (vFunctionData[i].IsEmpty()) + nf++; + } + vAdress.Remove(nf); + } + + vFunctionData.Remove(j); + vFColors.Remove(j); + vFThickness.Remove(j); + vFLegend.Remove(j); + vFPrimaryY.Remove(j); + vFPattern.Remove(j); + + Refresh(); + } +} + +void Scatter::RemoveAllFSeries() +{ + vAdress.Clear(); + vFunctionData.Clear(); + vFColors.Clear(); + vFThickness.Clear(); + vFLegend.Clear(); + vFPrimaryY.Clear(); + vFPattern.Clear(); + + Refresh(); +} + +Drawing Scatter::GetDrawing() const +{ + DrawingDraw ddw(6*GetSize()); + SetDrawing (ddw, 6); + return ddw; +} + +Image Scatter::GetImage(const int& scale) +{ + bool aa=antialiasing; + antialiasing=false; + ImageDraw idraw(scale*GetSize()); + SetDrawing (idraw,scale); + antialiasing=aa; + return idraw; +} + +#ifdef PLATFORM_WIN32 + +void Scatter::SaveAsMetafile(const char* file) const +{ + GuiLock __; + WinMetaFileDraw wmfd; + wmfd.Create(6*GetSize().cx,6*GetSize().cy,"Scatter","chart",file); + SetDrawing (wmfd, 6); + wmfd.Close(); +} + +void Scatter::SaveToClipboard(bool saveAsMetafile) +{ + GuiLock __; + if (saveAsMetafile) { + WinMetaFileDraw wmfd; + wmfd.Create(6*GetSize().cx,6*GetSize().cy,"Scatter","chart"); + SetDrawing (wmfd, 6); + WinMetaFile wmf = wmfd.Close(); + wmf.WriteClipboard(); + } else { + Image img = GetImage(3); + WriteClipboardImage(img); + } +} +#else + +void Scatter::SaveToClipboard(bool) +{ + GuiLock __; + Image img = GetImage(3); + WriteClipboardImage(img); +} + +#endif + +double Scatter::GetXByPoint(const int x) +{ + return (x-GetH_Border())*GetXRange()/(GetSize().cx-2*GetH_Border()-1)+GetXMin(); +} + +double Scatter::GetYByPoint(const int y) +{ + return (GetSize().cy-GetV_Border()-y-1)*GetYRange()/(GetSize().cy-2*GetV_Border()-GetTitleFont().GetHeight()-1)+GetYMin(); +} + +double Scatter::GetY2ByPoint(const int y) +{ + return (GetSize().cy-GetV_Border()-y-1)*GetY2Range()/(GetSize().cy-2*GetV_Border()-GetTitleFont().GetHeight()-1)+GetYMin2(); +} + +double Scatter::GetXPointByValue(const double x) +{ + return (x-GetXMin())/GetXRange()*(GetSize().cx-2*GetH_Border()-1)+GetH_Border(); +} + +double Scatter::GetYPointByValue(const double y) +{ + return (GetSize().cy-GetV_Border()-1)-(y-GetYMin())/GetYRange()*(GetSize().cy-2*GetV_Border()-GetTitleFont().GetHeight()-1); +} + +void Scatter::Paint(Draw& w) +{ + SetDrawing(w,1); +} + +Scatter &Scatter::ShowInfo(bool show) +{ + paintInfo=show; + return *this; +} + +void Scatter::ProcessPopUp(const Point & pt) +{ + double _x= (popLT.x-px)*xRange/(GetSize().cx-2*px-1)+xMin; + double _y= (GetSize().cy-py-popLT.y-1)*yRange/(GetSize().cy-2*py-titleFont.GetHeight()-1)+yMin; + double _y2=(GetSize().cy-py-popLT.y-1)*yRange2/(GetSize().cy-2*py-titleFont.GetHeight()-1)+yMin2; + double x= (pt.x-px)*xRange/(GetSize().cx-2*px-1)+xMin; + double y= (GetSize().cy-py-pt.y-1)*yRange/(GetSize().cy-2*py-titleFont.GetHeight()-1)+yMin; + double y2=(GetSize().cy-py-pt.y-1)*yRange2/(GetSize().cy-2*py-titleFont.GetHeight()-1)+yMin2; + + double dx = x - _x; + double dy = y - _y; + double dy2 = y2 - _y2; + if(logX) { + x = pow(10.0, x); + _x = pow(10.0, _x); + dx = pow(10.0, dx); + } + if(logY) { + y = pow(10.0, y); + _y = pow(10.0, _y); + dy = pow(10.0, dy); + } + if(logY2) { + y2 = pow(10.0, y2); + _y2 = pow(10.0, _y2); + dy2 = pow(10.0, dy2); + } + String strx, _strx, dstrx, stry, _stry, dstry; + if (cbModifFormatX) { + cbModifFormatX(strx, 0, x); strx.Replace("\n", " "); + cbModifFormatX(_strx, 0, _x); _strx.Replace("\n", " "); + } else { + strx = VariableFormatX(x); + _strx = VariableFormatX(_x); + } + if (cbModifFormatDeltaX) { + cbModifFormatDeltaX(dstrx, 0, dx); dstrx.Replace("\n", " "); + } else { + dstrx = VariableFormatX(dx); + } + if (cbModifFormatY) { + cbModifFormatY(stry, 0, y); stry.Replace("\n", " "); + cbModifFormatY(_stry, 0, _y); _stry.Replace("\n", " "); + } else { + stry = VariableFormatY(y); + _stry = VariableFormatY(_y); + } + if (cbModifFormatDeltaY) { + cbModifFormatDeltaY(dstry, 0, dy); dstry.Replace("\n", " "); + } else { + dstry = VariableFormatY(dy); + } + String str= popTextX + ": " + _strx; + if (strx != _strx) + str << "; " + popTextX + "': " + strx + "; Δ" + popTextX + ": " + dstrx; + str << "\n" + popTextY + ": " + _stry; + if (stry != _stry) + str << "; " + popTextY + "': " + stry + "; Δ" + popTextY + ": " + dstry; + if (drawY2Reticle) { + String stry2, _stry2, dstry2; + if (cbModifFormatY2) { + cbModifFormatY2(stry2, 0, y2); stry2.Replace("\n", " "); + cbModifFormatY2(_stry2, 0, _y2); _stry2.Replace("\n", " "); + } else { + stry2 = VariableFormatY2(y2); + _stry2 = VariableFormatY2(_y2); + } + if (cbModifFormatDeltaY2) { + cbModifFormatDeltaY2(dstry2, 0, dy2); dstry2.Replace("\n", " "); + } else { + dstry2 = VariableFormatY(dy2); + } + str << "\n" + popTextY2 + ": " + _stry2; + if (stry2 != _stry2) + str << "; " + popTextY2 + ": " + stry2 + "; Δ" + popTextY2 + ": " + dstry2; + } + const Point p2 = pt+offset; + popText.SetText(str).Move(this,p2.x,p2.y); +} + +void Scatter::DoMouseAction(bool down, Point pt, MouseAction action, int value) +{ + switch (action) { + case SCROLL: Scrolling(down, pt); + break; + case ZOOM_H_ENL: + case ZOOM_H_RED: MouseZoom(value, true, false); + break; + case ZOOM_V_ENL: + case ZOOM_V_RED: MouseZoom(value, false, true); + break; + case SHOW_INFO: LabelPopUp(down, pt); + break; + case CONTEXT_MENU: if(showContextMenu) + MenuBar::Execute(THISBACK(ContextMenu)); + break; + } +} + +bool Scatter::SetMouseBehavior(MouseBehaviour *_mouseBehavior) +{ + if (!_mouseBehavior) + return false; + int i; + for (i = 0; _mouseBehavior[i].action != NO_ACTION && i < MAX_MOUSEBEHAVIOR; ++i) ; + if (i == MAX_MOUSEBEHAVIOR) + return false; + mouseBehavior = _mouseBehavior; + return true; +} + +void Scatter::ProcessMouse(bool down, Point &pt, bool ctrl, bool alt, bool shift, bool left, bool middle, int middleWheel, bool right) +{ + for (int i = 0; mouseBehavior[i].action != NO_ACTION && i < MAX_MOUSEBEHAVIOR; ++i) { + if (mouseBehavior[i].ctrl == ctrl && mouseBehavior[i].alt == alt && + mouseBehavior[i].shift == shift && mouseBehavior[i].left == left && + mouseBehavior[i].middle == middle && mouseBehavior[i].right == right && + ((mouseBehavior[i].middleWheel == 0) || mouseBehavior[i].middleWheel == ((middleWheel > 0) - (middleWheel < 0)))) + DoMouseAction(down, pt, mouseBehavior[i].action, middleWheel); + } +} + +void Scatter::LabelPopUp(bool down, Point &pt) +{ + if (down) { + if(paintInfo && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) + { + popText.AppearOnly(this); + + isLabelPopUp = true; + if (IsNull(popLT)) + popLT = pt; + popRB = pt; + ProcessPopUp(pt); + } + } else { + if(paintInfo && isLabelPopUp) + { + popText.Close(); + isLabelPopUp = false; + popLT = popRB = Null; + Refresh(); + } + } +} + +#ifdef PLATFORM_LINUX + #include +#endif + +void Scatter::Scrolling(bool down, Point &pt, bool isOut) +{ + static Image mouseImg; + if (down) { + if((mouseHandlingX || mouseHandlingY) && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) + { + butDownX = pt.x; + butDownY = pt.y; + isScrolling = true; + INTERLOCKED { +#ifdef PLATFORM_WIN32 + static Image img = Win32Cursor(IDC_SIZEALL); +#else + static Image img = X11Cursor(XC_fleur); +#endif + mouseImg = Ctrl::OverrideCursor(img); + } + } + } else { + if (isScrolling) { + if (!isOut) + MouseMove(pt, 0); + isScrolling = false; + Ctrl::OverrideCursor(mouseImg); + } + } +} + +void Scatter::LeftDown(Point pt, dword keyFlags) +{ + ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, true, false, 0, false); +} + +void Scatter::LeftUp(Point pt, dword keyFlags) +{ + ProcessMouse(false, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, true, false, 0, false); +} + +void Scatter::MiddleDown(Point pt, dword keyFlags) +{ + ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, true, 0, false); +} + +void Scatter::MiddleUp(Point pt, dword keyFlags) +{ + ProcessMouse(false, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, true, 0, false); +} + +void Scatter::RightDown(Point pt, dword keyFlags) +{ + ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, false, 0, true); +} + +void Scatter::RightUp(Point pt, dword keyFlags) +{ + ProcessMouse(false, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, false, 0, true); +} + +void Scatter::MouseWheel(Point pt, int zdelta, dword keyFlags) +{ + if (zdelta == 0) + return; + ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, false, zdelta, false); +} + +void Scatter::MouseMove(Point pt, dword) +{ + if (isScrolling) + { + int shiftX = pt.x - butDownX; + if (mouseHandlingX && shiftX != 0) { + double deltaX = shiftX*xRange/(GetSize().cx - 2*px - 1); + xMin -= deltaX; + xMinUnit += deltaX; + AdjustMinUnitX(); + butDownX = pt.x; + } + int shiftY = pt.y - butDownY; + if (mouseHandlingY && shiftY != 0) { + double deltaY = -shiftY*yRange/(GetSize().cy - 2*py - 1); + yMin -= deltaY; + yMinUnit += deltaY; + AdjustMinUnitY(); + if (drawY2Reticle) { + double deltaY2 = -shiftY*yRange2/(GetSize().cy - 2*py - 1); + yMin2 -= deltaY2; + yMinUnit2 += deltaY2; + AdjustMinUnitY2(); + } + butDownY = pt.y; + } + if ((mouseHandlingX && shiftX != 0) || (mouseHandlingY && shiftY != 0)) { + WhenSetXYMin(); + Refresh(); + WhenZoomScroll(); + } + } + if(isLabelPopUp) { + if (paintInfo && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) + { + if (IsNull(popLT)) + popLT = pt; + popRB = pt; + popText.AppearOnlyOpen(this); + + ProcessPopUp(pt); + Refresh(); + } + } +} + +void Scatter::MouseLeave() +{ + Point p = Null; + Scrolling(false, p, true); +} + +void Scatter::MouseZoom(int zdelta, bool hor, bool ver) +{ + double scale = zdelta > 0 ? zdelta/100. : -100./zdelta; + Zoom(scale, mouseHandlingX, mouseHandlingY); +} + +void Scatter::Zoom(double scale, bool mouseX, bool mouseY) +{ + mouseX = mouseX && ((minXZoom > 0 && xRange*scale > minXZoom) || (minXZoom < 0)); + mouseX = mouseX && ((maxXZoom > 0 && xRange*scale < maxXZoom) || (maxXZoom < 0)); + mouseY = mouseY && ((minYZoom > 0 && yRange*scale > minYZoom) || (minYZoom < 0)); + mouseY = mouseY && ((maxYZoom > 0 && yRange*scale < maxYZoom) || (maxYZoom < 0)); + //mouseX = mouseX && (!mouseHandlingY || mouseY); + //mouseY = mouseY && (!mouseHandlingX || mouseX); + if (mouseX) + { + double oldXMin = xMin; + xMin += xRange*(1-scale)/2.; + xMinUnit = oldXMin + xMinUnit - xMin; + AdjustMinUnitX(); + xRange *= scale; + } + if (mouseY) + { + yRange *= scale; + yRange2 *= scale; + } + if (mouseX || mouseY) { + WhenSetRange(); + Refresh(); + WhenZoomScroll(); + } +} + +void Scatter::Scroll(double factorX, double factorY) +{ + if (factorX != 0) { + double deltaX = factorX*xRange; + xMin -= deltaX; + xMinUnit += deltaX; + AdjustMinUnitX(); + } + if (factorY != 0) { + double deltaY = -factorY*yRange; + yMin -= deltaY; + yMinUnit += deltaY; + AdjustMinUnitY(); + if (drawY2Reticle) { + double deltaY2 = -factorY*yRange2; + yMin2 -= deltaY2; + yMinUnit2 += deltaY2; + AdjustMinUnitY2(); + } + } + if (factorX != 0 || factorY != 0) { + Refresh(); + WhenZoomScroll(); + } +} + +Image Scatter::CursorImage(Point p, dword keyflags) +{ + return ChartImg::cursor1(); +} + +void Scatter::Circle(Draw& w, const int& scale, const Point& cp, const int& size, const class::Color& markColor)const +{ + int radius = fround(scale*size/6); int radius2 = radius/2; + w.DrawEllipse(cp.x-radius2, cp.y-radius2, radius, radius, markColor, 1, markColor); +} + +void Scatter::Square(Draw& w, const int& scale, const Point& cp, const int& size, const class::Color& markColor)const +{ + Vector p; + p< p; + p< p; + p< GetLinePattern(String pattern) +{ + Vector ret; + + ret.Add(); + int retPos = 0; + ret[0] = 2; + for (int i = 1; i < pattern.GetCount(); ++i) { + if (pattern[i] != pattern[i-1]) { + ret.Add(); + retPos++; + ret[retPos] = 0; + } + ret[retPos] += 2; + } + return ret; +} + +Vector &GetPatternArray(String pattern) +{ + static VectorMap > pats; + + int pos = pats.Find(pattern); + if (pos < 0) { + pats.Add(pattern, GetLinePattern(pattern)); + pos = pats.GetCount()-1; + } + return pats.GetValues()[pos]; +} + +void Scatter::DrawLineX(Draw& w, const int x0, const int y0, const int x1, const int y1, int thick, const class::Color &color, String pattern, const int &scale) +{ + Vector p; + p.SetCount(2); + p[0].x = x0; + p[0].y = y0; + p[1].x = x1; + p[1].y = y1; + DrawPolylineX(w, p, thick, color, pattern, scale); +} + +void Scatter::DrawPolylineX(Draw& w, const Vector &p, int thick, const class::Color &color, String pattern, const int &scale) +{ + if (pattern == LINE_SOLID) + w.DrawPolyline(p, thick, color); + else { + Vector &pat = GetPatternArray(pattern); + int iPat = 0; + + double len = pat[0]*scale; // Pixels por barra + Pointf begin, end; + begin = p[0]; + for (int i = 1; i < p.GetCount();) { + double d = Dist(begin, p[i]); + if (d >= len) + end = PointAtLen(begin, p[i], len); + else { + end = p[i]; + len -= d; + ++i; + } + if (Even(iPat)) + w.DrawLine(begin, end, thick, color); + if (d >= len) { + iPat++; + if (iPat == pat.GetCount()) + iPat = 0; + len = pat[iPat]*scale; + } + begin = end; + } + } +} + +void Scatter::Plot(Draw& w, const int& scale,const int& l,const int& h)const +{ + double d1=xRange/xMajorUnit; + double d2=yRange/yMajorUnit; + + w.DrawRect(1,1,l-2,h-1,plotAreaColor); //grosimea liniei nu este scalata + int gW=fround(gridWidth*scale/6); + if(gridWidth<0) + gW=gridWidth; + Vector p; + p.SetCount(2); + if (drawVGrid) + for(int i=0; xMinUnit+i*xMajorUnit < xRange;i++) { + p[0].x = fround(l*xMinUnit/xRange+i*l/d1); p[0].y = 0; + p[1].x = fround(l*xMinUnit/xRange+i*l/d1); p[1].y = h; + DrawPolylineX(w, p, gW, gridColor, "oo..", scale); + } + + if (drawHGrid) + for(int i=0; yMinUnit+i*yMajorUnit < yRange;i++) { + p[0].x = 0; p[0].y = fround(-h*yMinUnit/yRange + h-i*h/d2); + p[1].x = l; p[1].y = fround(-h*yMinUnit/yRange + h-i*h/d2); + DrawPolylineX(w, p, gW, gridColor, "oo..", scale); + } + w.DrawLine(0, h, l, h, scale, Black); + w.DrawLine(0, 0, l, 0, scale, Black); + w.DrawLine(0, 0, 0, h, scale, Black); + w.DrawLine(l, 0, l, h+1, scale, Black); + w.Clip(Rect(0,0,l,h)); + int ix;//int x points coordinates + int iy;//int y points coordinates + if (!vPointsData.IsEmpty()){ + for (int j=0; j p1; + int imin, imax; + if (vPSequential[j]) { + imin = imax = Null; + for (int i = 1; i= xMin) + imin = i-1; + } else if (IsNull(imax)) { + if (vPointsData[j][i].x >= xMin+xRange) + imax = i+1; + } + } + if (IsNull(imin)) + imin = 0; + if (IsNull(imax)) + imax = vPointsData[j].GetCount(); + } else { + imin = 0; + imax = vPointsData[j].GetCount(); + } + int numV; + if (fastViewX) + numV = 1+(imax-imin)/l; + else + numV = 1; + for (int i=imin; i 1) { + yy = 0; + int ii; + for (ii = 0; ii < numV && i+ii < imax; ++ii) + yy += vPointsData[j][i+ii].y; + yy /= double(ii); + xx = (vPointsData[j][i].x + vPointsData[j][i+ii-1].x)/2; + } else { + xx = vPointsData[j][i].x; + yy = vPointsData[j][i].y; + } + ix=fround(l*(xx-xMin)/xRange); + if (vPPrimaryY[j]) + iy=fround(h*(yy-yMin)/yRange); + else + iy=fround(h*(yy-yMin2)/yRange2); + p1<2) + { + Vector p2; + Vector v(Cubic(vPointsData[j])); + for (int i=0; i= 1) { + for (int i=0; i<(imax-imin)/numV; i++) + DrawMark(vMarkStyles[j],w,scale,p1[i],vPWidth[j],vMarkColors[j]); + } + } + } + + int nf=0; //number of functions to draw + + for (int j=0; j p1; + for (int i=0; i p1; + for(int i=0; i Scatter::Cubic(const Vector& DataSet, const int& fineness,double tension) const +{ + Vector OutSet; + if(DataSet.GetCount()>2) { + OutSet<(OutSet); +} + +void ParseTextMultiline(const String &text, Font fnt, Array &texts, Array &sizes) { + Size ret(0, 0); + int npos = 0; + for (int pos = 0; npos != -1; pos = npos+1) { + npos = text.Find('\n', pos); + String &t = texts.Add(); + if (npos != -1) + t = text.Mid(pos, npos-pos); + else + t = text.Mid(pos); + Size &s = sizes.Add(); + s.cx = GetTextSize(t, fnt).cx; + s.cy = GetTextSize(t, fnt).cy; + } +} + +Size GetTextSizeMultiline(Array &sizes) { + Size ret(0, 0); + for (int i = 0; i < sizes.GetCount(); ++i) { + if (sizes[i].cx > ret.cx) + ret.cx = sizes[i].cx; + ret.cy += sizes[i].cy; + } + return ret; +} + +void Scatter::SetDrawing(Draw& w, const int& scale) const +{ + GuiLock __; + w.DrawRect(scale*GetSize(),graphColor); + Size sz; + sz.cx=0; + sz.cy=0; + if(!title.IsEmpty()) + { + Font FontTitle6; + FontTitle6=titleFont; + FontTitle6.Height(scale*titleFont.GetHeight()); + FontTitle6.Width(scale*titleFont.GetWidth()); + sz= GetTextSize(title, FontTitle6); + w.DrawText((scale*GetSize().cx-sz.cx)/2,scale*2,title,FontTitle6,titleColor); + } + + w.Offset(Point(scale*px,scale*py+scale*titleFont.GetHeight())); + if(showLegend) + DrawLegend(w,scale); + int l=scale*GetSize().cx-2*scale*px; + int h=scale*GetSize().cy-2*scale*py-scale*titleFont.GetHeight(); + + Font FontLabel6; + FontLabel6=labelsFont; + FontLabel6.Height(scale*labelsFont.GetHeight()); + + Size lx=GetTextSize(xLabel,FontLabel6); + Size ly=GetTextSize(yLabel,FontLabel6); + Size ly2=GetTextSize(yLabel2,FontLabel6); + w.DrawText(fround((l-lx.cx)/2),h+scale*py-lx.cy-scale*2,xLabel,FontLabel6,labelsColor); + w.DrawText(scale*2-scale*px,fround((h+ly.cx)/2),900,yLabel,FontLabel6,labelsColor); + w.DrawText(fround(l+scale*px-ly2.cy-2*scale),fround((h+ly2.cx)/2),900,yLabel2,FontLabel6,labelsColor); + + if (drawXReticle) + for(int i=0; xMinUnit+i*xMajorUnit<=xRange;i++){ + w.DrawLine(fround(l*xMinUnit/xRange+i*l/(xRange/xMajorUnit)), + h, + fround(l*xMinUnit/xRange+i*l/(xRange/xMajorUnit)), + h+scale*4, + fround(scale/2), + axisColor); + Font Standard6; + Standard6.Height(scale*StdFont().GetHeight()); + double gridX=xMinUnit+i*xMajorUnit+xMin; + String gridLabelX; + if (cbModifFormatX) + cbModifFormatX(gridLabelX, i, gridX); + else + gridLabelX = VariableFormatX(gridX); + + Array texts; + Array sizes; + ParseTextMultiline(gridLabelX, StdFont(), texts, sizes); + for (int ii = 0; ii < texts.GetCount(); ++ii) { + int cy = ii == 0 ? 0 : sizes[ii-1].cy; + w.DrawText(fround(l*xMinUnit/xRange+i*l/(xRange/xMajorUnit) - scale*sizes[ii].cx/2), h+scale*(4+ii*cy), texts[ii], Standard6, axisColor); + } + } + if (drawYReticle) + for(int i=0; yMinUnit+i*yMajorUnit<=yRange;i++){ + w.DrawLine(-(scale*4), + fround(-h*yMinUnit/yRange+h-i*h/(yRange/yMajorUnit)), + 0, + fround(-h*yMinUnit/yRange+h-i*h/(yRange/yMajorUnit)), + fround(scale/2), + axisColor); + double gridY=yMinUnit+i*yMajorUnit+yMin; + String gridLabelY; + if (cbModifFormatY) + cbModifFormatY(gridLabelY, i, gridY); + else + gridLabelY = VariableFormatY(gridY); + int dx=scale*GetTextSize(gridLabelY,StdFont()).cx; + Font Standard6; + Standard6.Height(scale*StdFont().GetHeight()); + w.DrawText(-dx-scale*6, fround(-h*yMinUnit/yRange+h-i*h/(yRange/yMajorUnit))-scale*8, gridLabelY, Standard6, axisColor); + } + if (drawY2Reticle) + for(int i=0; yMinUnit+i*yMajorUnit<=yRange;i++){ + w.DrawLine(l+(scale*4), + fround(-h*yMinUnit2/yRange2+h-i*h/(yRange/yMajorUnit)), + l, + fround(-h*yMinUnit2/yRange2+h-i*h/(yRange/yMajorUnit)), + fround(scale/2), + axisColor); + double gridY2=yMinUnit2+i*yMajorUnit2+yMin2; + String gridLabelY2; + if (cbModifFormatY2) + cbModifFormatY2(gridLabelY2, i, gridY2); + else + gridLabelY2 = VariableFormatY2(gridY2); + Font Standard6; + Standard6.Height(scale*StdFont().GetHeight()); + w.DrawText(l+scale*10,fround(-h*yMinUnit2/yRange2+h-i*h/(yRange/yMajorUnit))-scale*8,gridLabelY2,Standard6,axisColor); + } + + if(antialiasing) // && w.IsGui()) IsGui() is always false in Linux + { + ImageDraw imdraw(3*l,3*h); + Plot (imdraw,3,3*l,3*h); + w.DrawImage(0,0,l,h,imdraw); + } else + Plot(w,scale,l,h); + + w.End(); +} + +Scatter::Scatter(): + title (""), + titleColor(SColorText), + graphColor(White), + titleFont(Roman(20)), + xLabel(""),yLabel(""), + labelsFont(StdFont()), + labelsColor(SColorText), + plotAreaColor(SColorLtFace), + axisColor(SColorText), + axisWidth(6), + px(30), + py(30), + xRange(100.0), + yRange(100.0), + yRange2(100.0), + xMajorUnit(xRange/10), + yMajorUnit(yRange/5), + xMin(0.0), yMin(0.0), yMin2(0.0), + xMinUnit(0.0), yMinUnit(0.0), yMinUnit2(0.0), + logX(false), logY(false), logY2(false), + cbModifFormatX(NULL),cbModifFormatY(NULL),cbModifFormatY2(NULL), + cbModifFormatDeltaX(NULL),cbModifFormatDeltaY(NULL),cbModifFormatDeltaY2(NULL), + gridColor(SColorDkShadow), + gridWidth(4), + paintInfo(false), + mouseHandlingX(false), mouseHandlingY(false), isScrolling(false), isLabelPopUp(false), + drawXReticle(true), drawYReticle(true), drawY2Reticle(false), + drawVGrid(true), drawHGrid(true), + showLegend(true),legendWeight(80), + antialiasing(false), + offset(10,12), + minXZoom(-1), maxXZoom(-1), minYZoom(-1), maxYZoom(-1), fastViewX(false), + sequentialXAll(false), popTextX("x"), popTextY("y1"), popTextY2("y2"), + popLT(Null), popRB(Null), showContextMenu(false) +{ + Color(graphColor); + BackPaint(); + popText.SetColor(SColorFace); + SetMouseBehavior(defaultMouse); +} + diff --git a/bazaar/Scatter/Scatter.h b/bazaar/Scatter/Scatter.h index 2fe0e0434..43cfcfeb8 100644 --- a/bazaar/Scatter/Scatter.h +++ b/bazaar/Scatter/Scatter.h @@ -7,6 +7,7 @@ Copyright (C) 2006-2007, Andrei-Catalin #define _Scatter_Scatter_h #include "PopUpText.h" +#include using namespace Upp; @@ -58,7 +59,7 @@ public: Callback WhenSetRange; Callback WhenSetXYMin; - enum MouseAction {NO_ACTION = 1111110, SCROLL, ZOOM_H_ENL, ZOOM_H_RED, ZOOM_V_ENL, ZOOM_V_RED, SHOW_INFO}; + enum MouseAction {NO_ACTION = 0, SCROLL, ZOOM_H_ENL, ZOOM_H_RED, ZOOM_V_ENL, ZOOM_V_RED, SHOW_INFO, CONTEXT_MENU}; struct MouseBehaviour { bool ctrl; @@ -104,6 +105,8 @@ public: Scatter& ShowLegend(const bool& show=true); Scatter& SetLegendWeight(const int& weight); + Scatter& ShowContextMenu(const bool& show=true) {showContextMenu = show; return *this;} + Scatter& SetAntialiasing(const bool& aa=true); void FitToData(bool Y = false); @@ -219,7 +222,7 @@ public: void RemoveFSeries(const int& j); void RemoveAllFSeries(); - void ShowInfo(bool show=true); + Scatter &ShowInfo(bool show=true); void ProcessPopUp(const Point & pt); Drawing GetDrawing()const; @@ -230,6 +233,7 @@ public: #endif void SaveToClipboard(bool saveAsMetafile = false); + void SaveToImage(String fileName = Null); Scatter& LogX(const bool& logx=true) {logX=logx; return *this;} Scatter& LogY(const bool& logy=true) {logY=logy; return *this;} @@ -312,7 +316,7 @@ private: int legendWeight; bool antialiasing; bool mouseHandlingX, mouseHandlingY; - + bool showContextMenu; Vector Cubic (const Vector& DataSet, const int& fineness=10, double tension=0.4)const; void DrawLegend(Draw& w,const int& scale) const; @@ -342,6 +346,8 @@ private: void AdjustMinUnitY(); void AdjustMinUnitY2(); + void ContextMenu(Bar& bar); + virtual Image CursorImage(Point p, dword keyflags); void ExpFormat(String& s, int i, double d) diff --git a/bazaar/Scatter/Scatter.t b/bazaar/Scatter/Scatter.t index e36e8a24e..77e779880 100644 --- a/bazaar/Scatter/Scatter.t +++ b/bazaar/Scatter/Scatter.t @@ -3,10 +3,63 @@ #endif // Scatter.cpp +T_("Invalid graph range") +caES("") +esES("Rango del gr\303\241fico incorrecto") + T_("Invalid series index!") -caES("¡Sèrie amb índex incorrecte!") -esES("¡Serie con índice incorrecto!") +caES("\302\241S\303\250rie amb \303\255ndex incorrecte!") +esES("\302\241Serie con \303\255ndice incorrecto!") T_("Invalid function index!") -caES("¡Funció amb índex incorrecte!") -esES("¡Función con índice incorrecto!") +caES("\302\241Funci\303\263 amb \303\255ndex incorrecte!") +esES("\302\241Funci\303\263n con \303\255ndice incorrecto!") + +T_("Fit to data") +caES("Ajust a les dades") +esES("Ajustar a los datos") + +T_("Zoom +") +caES("") +esES("") + +T_("Zoom -") +caES("") +esES("") + +T_("Scroll Left") +caES("Moure a l'esquerra") +esES("Mover a la izquierda") + +T_("Scroll Right") +caES("More a la dreta") +esES("Mover a la derecha") + +T_("Scroll Up") +caES("Moure amunt") +esES("Mover arriba") + +T_("Scroll Down") +caES("Moure baix") +esES("Mover abajo ") + +T_("Copy") +caES("Copiar") +esES("Copiar") + +T_("Save to file") +caES("Guardar a fitxer") +esES("Guardar en fichero") + +T_("Saving plot to PNG or JPEG file") +caES("Guardant gr\303\240fic en fitxer PNG o JPEG") +esES("Guardando gr\303\241fico en fichero PNG o JPEG") + +T_("Plot has not been saved") +caES("El gr\303\240fic no s'ha desat") +esES("El gr\303\241fico no ha sido guardado") + +T_("File format %s not found") +caES("Format %s no trobat") +esES("Formato %s no encontrado") + diff --git a/bazaar/Scatter/Scatter.upp b/bazaar/Scatter/Scatter.upp index 5d88f600e..64d9d320a 100644 --- a/bazaar/Scatter/Scatter.upp +++ b/bazaar/Scatter/Scatter.upp @@ -1,7 +1,8 @@ description "Bazaar: Scatter & Pie ctrls, by Andrei-Catalin\377"; uses - CtrlLib; + CtrlLib, + plugin\jpg; file Scatter.cpp, diff --git a/bazaar/Scatter/init b/bazaar/Scatter/init index 6d8132a60..62142e738 100644 --- a/bazaar/Scatter/init +++ b/bazaar/Scatter/init @@ -1,4 +1,5 @@ #ifndef _Scatter_icpp_init_stub #define _Scatter_icpp_init_stub #include "CtrlLib/init" +#include "plugin\jpg/init" #endif diff --git a/bazaar/Scatter/src.tpp/Scatter$en-us.tpp b/bazaar/Scatter/src.tpp/Scatter$en-us.tpp index 794d92a08..a3c0e942b 100644 --- a/bazaar/Scatter/src.tpp/Scatter$en-us.tpp +++ b/bazaar/Scatter/src.tpp/Scatter$en-us.tpp @@ -27,11 +27,31 @@ changed to fit the data.&] [s4; &] [s5;:Scatter`:`:SaveToClipboard`(bool`): [@(0.0.255) void]_[* SaveToClipboard]([@(0.0.255) b ool]_[*@3 saveAsMetafile]_`=_[@(0.0.255) false])&] -[s2;%% Saves Scatter to clipboard as a bitmap.&] +[s2;%% Saves graph to clipboard as a bitmap.&] [s2;%% In windows if [%-*@3 saveAsMetafile ]is true, a metafile is sent to clipboard.&] [s3;%% &] [s4; &] +[s5;:Scatter`:`:SaveToImage`(String`): [@(0.0.255) void]_[* SaveToImage]([_^String^ String]_ +[*@3 fileName]_`=_Null)&] +[s2;%% Saves graph to file [%-*@3 fileName.] Supported formats are +.PNG and .JPG.&] +[s2;%% If [%-*@3 fileName] is null, a window is opened asking the user +to enter a file name.&] +[s3;%% &] +[s4; &] +[s5;:Scatter`:`:SetFastViewX`(bool`): [_^Scatter^ Scatter][@(0.0.255) `&]_[* SetFastViewX]( +[@(0.0.255) bool]_[*@3 set]_`=_[@(0.0.255) true])&] +[s2;%% If [%-*@3 set ]is true, it will be viewed a point per horizontal +pixel. This point will be the average of all data that is in +that pixel.&] +[s2;%% This speeds up the graph painting.&] +[s3;%% &] +[s4; &] +[s5;:Scatter`:`:GetTitleFont`(`): [_^Font^ Font][@(0.0.255) `&]_[* GetTitleFont]()&] +[s2;%% Returns title font.&] +[s3; &] +[s4; &] [s5;:Scatter`:`:GetXByPoint`(const int`): [@(0.0.255) double]_[* GetXByPoint]([@(0.0.255) c onst]_[@(0.0.255) int]_[*@3 x])&] [s2;%% Gets the X coordinate in data units from value [%-*@3 x ]in @@ -62,13 +82,40 @@ value [%-*@3 x ]in data units.&] [%-*@3 y ]in data units.&] [s3;%% &] [s4; &] -[s5;:Scatter`:`:ShowInfo`(bool`): [@(0.0.255) void]_[* ShowInfo]([@(0.0.255) bool]_[*@3 show][@(0.0.255) `= -true])&] +[s5;:Scatter`:`:ShowInfo`(bool`): [_^Scatter^ Scatter][@(0.0.255) `&]_[* ShowInfo]([@(0.0.255) b +ool]_[*@3 show][@(0.0.255) `=true])&] [s2;%% Defines to show or not with [%-*@3 show ]the pop`-up window that indicates in data units the cursor location and, if dragged, the size of the window.&] [s3;%% &] [s4; &] +[s5;:Scatter`:`:ShowContextMenu`(const bool`&`): [_^Scatter^ Scatter][@(0.0.255) `&]_[* Sho +wContextMenu]([@(0.0.255) const]_[@(0.0.255) bool`&]_[*@3 show][@(0.0.255) `=true])&] +[s2;%% Defines to show or not with [%-*@3 show ]the context menu with +options to move and zoom the plot (if SetMouseHandling(true)) +and to save it to file or clipboard.&] +[s3;%% &] +[s4; &] +[s5;:Scatter`:`:FitToData`(bool`): [@(0.0.255) void]_[* FitToData]([@(0.0.255) bool]_[*@3 Y]_ +`=_[@(0.0.255) false])&] +[s2;%% Scales and scrolls the plots so that all data is included +in X axis. If [%-*@3 Y] is true, Y axis is also fitted so that +all plot points are visible.&] +[s3;%% &] +[s4; &] +[s5;:Scatter`:`:Zoom`(double`,bool`,bool`): [@(0.0.255) void]_[* Zoom]([@(0.0.255) double]_ +[*@3 scale], [@(0.0.255) bool]_[*@3 hor]_`=_[@(0.0.255) true], [@(0.0.255) bool]_[*@3 ver]_`= +_[@(0.0.255) true])&] +[s2;%% Zooms graph by [%-*@3 scale] factor. The axis scaled are X if +[%-*@3 hor] is true and Y if [%-*@3 ver ]is true.&] +[s3;%% &] +[s4; &] +[s5;:Scatter`:`:Scroll`(double`,double`): [@(0.0.255) void]_[* Scroll]([@(0.0.255) double]_ +[*@3 factorX], [@(0.0.255) double]_[*@3 factorY])&] +[s2;%% Scrolls graph by [%-*@3 factorX] in X axis and [%-*@3 factorY +]in Y axis.&] +[s3;%% &] +[s4; &] [s5;:Scatter`:`:SetRange`(double`,double`,double`): [_^Scatter^ Scatter][@(0.0.255) `&]_[* S etRange]([@(0.0.255) double]_[*@3 rx], [@(0.0.255) double]_[*@3 ry], [@(0.0.255) double]_[*@3 ry2]_`=_`-[@3 1])&] @@ -183,6 +230,37 @@ TRIANGLE, CROSS, X, RHOMB.&] [s2;%% Hides the of the latest added series.marks.&] [s3; &] [s4; &] +[s5;:Scatter`:`:SetSequentialX`(const int`&`,const bool`&`): [@(0.0.255) void]_[* SetSequ +entialX]([@(0.0.255) const]_[@(0.0.255) int`&]_[*@3 j], [@(0.0.255) const]_[@(0.0.255) bool +`&]_[*@3 sequential]_`=_[@(0.0.255) true])&] +[s2;%% If [%-*@3 sequential] is true, it Indicates that the [%-*@3 j] +graph data has been sequentially inserted following X axis.&] +[s2;%% This speeds up the graph painting.&] +[s3;%% &] +[s4; &] +[s5;:Scatter`:`:SetSequentialX`(const bool`&`): [_^Scatter^ Scatter]_`&[* SetSequentialX]( +[@(0.0.255) const]_[@(0.0.255) bool`&]_[*@3 sequential]_`=_[@(0.0.255) true])&] +[s2;%% If [%-*@3 sequential] is true, it Indicates that the last inserted +graph data has been sequentially inserted following X axis.&] +[s2;%% This speeds up the graph painting.&] +[s3;%% &] +[s4; &] +[s5;:Scatter`:`:SetSequentialXAll`(const bool`&`): [_^Scatter^ Scatter]_`&[* SetSequentia +lXAll]([@(0.0.255) const]_[@(0.0.255) bool`&]_[*@3 sequential]_`=_[@(0.0.255) true])&] +[s2;%% If [%-*@3 sequential] is true, it Indicates that all graph data +has been sequentially inserted following X axis.&] +[s2;%% This speeds up the graph painting.&] +[s3;%% &] +[s4; &] +[s5;:Scatter`:`:RemoveSeries`(const int`&`): [@(0.0.255) void]_[* RemoveSeries]([@(0.0.255) c +onst]_[@(0.0.255) int`&]_[*@3 j])&] +[s2;%% Remove [%-*@3 j] data series.&] +[s3;%% &] +[s4; &] +[s5;:Scatter`:`:RemoveAllSeries`(`): [@(0.0.255) void]_[* RemoveAllSeries]()&] +[s2;%% Remove all data series, cleaning the graph.&] +[s3; &] +[s4; &] [s5;:Scatter`:`:SetMouseBehavior`(Scatter`:`:MouseBehaviour`*`): [@(0.0.255) bool]_[* Set MouseBehavior]([_^Scatter`:`:MouseBehaviour^ MouseBehaviour]_`*[*@3 mouseBehavior])&] [s2;%% Sets with [%-*@3 mouseBehavior] the array of MouseBehavior conditions @@ -206,8 +284,7 @@ used.&] [s3;%% &] [s0; &] [ {{10000F(128)G(128)@1 [s0;%% [* Public Member List]]}}&] -[s3;%% &] -[s4; &] +[s4;%% &] [s5;:Scatter`:`:MouseBehaviour`:`:ctrl: [@(0.0.255) bool]_[* ctrl]&] [s2;%% Set to true if Ctrl has to be pressed.&] [s3; &]