1 #include "ScatterDraw.h"
2
3 namespace Upp {
4
ScatterDraw()5 ScatterDraw::ScatterDraw() {
6 lastxRange = xRange;
7 lastyRange = yRange;
8 }
9
debug_h()10 void debug_h() {
11 ; // It does nothing. It just serves to set a breakpoint in templated functions
12 }
13
SetColor(const Color & _color)14 ScatterDraw& ScatterDraw::SetColor(const Color& _color) {
15 graphColor = _color;
16 return *this;
17 }
18
SetTitle(const String & _title)19 ScatterDraw& ScatterDraw::SetTitle(const String& _title) {
20 title = _title;
21 return *this;
22 }
23
GetTitle()24 const String& ScatterDraw::GetTitle() {
25 return title;
26 }
27
SetTitleFont(const Font & fontTitle)28 ScatterDraw& ScatterDraw::SetTitleFont(const Font& fontTitle) {
29 titleFont = fontTitle;
30 return *this;
31 }
32
SetTitleColor(const Color & colorTitle)33 ScatterDraw& ScatterDraw::SetTitleColor(const Color& colorTitle) {
34 titleColor = colorTitle;
35 return *this;
36 }
37
SetLabels(const String & _xLabel,const String & _yLabel,const String & _yLabel2)38 ScatterDraw& ScatterDraw::SetLabels(const String& _xLabel, const String& _yLabel, const String& _yLabel2) {
39 xLabel_base = _xLabel;
40 yLabel_base = _yLabel;
41 yLabel2_base = _yLabel2;
42 labelsChanged = true;
43 return *this;
44 }
45
SetLabelX(const String & _xLabel)46 ScatterDraw& ScatterDraw::SetLabelX(const String& _xLabel) {
47 xLabel_base = _xLabel;
48 labelsChanged = true;
49 return *this;
50 }
51
SetLabelY(const String & _yLabel)52 ScatterDraw& ScatterDraw::SetLabelY(const String& _yLabel) {
53 yLabel_base = _yLabel;
54 labelsChanged = true;
55 return *this;
56 }
57
SetLabelY2(const String & _yLabel)58 ScatterDraw& ScatterDraw::SetLabelY2(const String& _yLabel) {
59 yLabel2_base = _yLabel;
60 labelsChanged = true;
61 return *this;
62 }
63
SetLabelsFont(const Font & fontLabels)64 ScatterDraw& ScatterDraw::SetLabelsFont(const Font& fontLabels) {
65 labelsFont = fontLabels;
66 return *this;
67 }
68
SetLabelsColor(const Color & colorLabels)69 ScatterDraw& ScatterDraw::SetLabelsColor(const Color& colorLabels) {
70 labelsColor = colorLabels;
71 return *this;
72 }
73
SetPlotAreaMargin(int hLeft,int hRight,int vTop,int vBottom)74 ScatterDraw& ScatterDraw::SetPlotAreaMargin(int hLeft, int hRight, int vTop, int vBottom) {
75 hPlotLeft = hLeft;
76 hPlotRight = hRight;
77 vPlotTop = vTop;
78 vPlotBottom = vBottom;
79 return *this;
80 }
81
SetPlotAreaLeftMargin(int margin)82 ScatterDraw& ScatterDraw::SetPlotAreaLeftMargin(int margin) {
83 hPlotLeft = margin;
84 return *this;
85 }
86
SetPlotAreaRightMargin(int margin)87 ScatterDraw& ScatterDraw::SetPlotAreaRightMargin(int margin) {
88 hPlotRight = margin;
89 return *this;
90 }
91
SetPlotAreaTopMargin(int margin)92 ScatterDraw& ScatterDraw::SetPlotAreaTopMargin(int margin) {
93 vPlotTop = margin;
94 return *this;
95 }
96
SetPlotAreaBottomMargin(int margin)97 ScatterDraw& ScatterDraw::SetPlotAreaBottomMargin(int margin) {
98 vPlotBottom = margin;
99 return *this;
100 }
101
SetPlotAreaColor(const Color & p_a_color)102 ScatterDraw& ScatterDraw::SetPlotAreaColor(const Color& p_a_color) {
103 plotAreaColor = p_a_color;
104 return *this;
105 }
106
SetAxisColor(const Color & axis_color)107 ScatterDraw& ScatterDraw::SetAxisColor(const Color& axis_color) {
108 axisColor = axis_color;
109 return *this;
110 }
111
SetAxisWidth(double axis_width)112 ScatterDraw& ScatterDraw::SetAxisWidth(double axis_width) {
113 axisWidth = axis_width;
114 return *this;
115 }
116
ShowHGrid(bool show)117 ScatterDraw& ScatterDraw::ShowHGrid(bool show) {
118 drawHGrid = show;
119 return *this;
120 }
121
122 /*ScatterDraw& ScatterDraw::ShowHGrid2(bool show) {
123 drawHGrid2 = show;
124 return *this;
125 }*/
126
ShowVGrid(bool show)127 ScatterDraw& ScatterDraw::ShowVGrid(bool show) {
128 drawVGrid = show;
129 return *this;
130 }
131
132 /*ScatterDraw& ScatterDraw::ShowVGrid2(bool show) {
133 drawVGrid2 = show;
134 return *this;
135 }
136
137 ScatterDraw& ScatterDraw::FreqGrid2(double freq) {
138 freqGrid2 = freq;
139 return *this;
140 }*/
141
PointInPlot(Point & pt)142 bool ScatterDraw::PointInPlot(Point &pt)
143 {
144 return hPlotLeft*plotScaleX <= pt.x && pt.x <= (GetSize().cx - hPlotRight*plotScaleX) &&
145 (vPlotTop*plotScaleY + titleHeight) <= pt.y && pt.y <= (GetSize().cy - vPlotBottom*plotScaleY);
146 }
147
PointInBorder(Point & pt)148 bool ScatterDraw::PointInBorder(Point &pt)
149 {
150 return !PointInPlot(pt);
151 }
152
PointInLegend(Point &)153 bool ScatterDraw::PointInLegend(Point &)
154 {
155 return false;
156 }
157
AdjustMinUnitX()158 void ScatterDraw::AdjustMinUnitX() {
159 if (SetGridLinesX)
160 return;
161 xMinUnit = xMinUnit0;
162 if (xMajorUnit > 0) {
163 if (xMinUnit < 0)
164 xMinUnit += (fabs(floor(xMinUnit/xMajorUnit)))*xMajorUnit;
165 else if (xMinUnit >= xMajorUnit)
166 xMinUnit -= (fabs(floor(xMinUnit/xMajorUnit)))*xMajorUnit;
167 }
168 }
169
AdjustMinUnitY()170 void ScatterDraw::AdjustMinUnitY() {
171 if (SetGridLinesY)
172 return;
173 yMinUnit = yMinUnit0;
174 if (yMajorUnit > 0) {
175 if (yMinUnit < 0)
176 yMinUnit += (fabs(ceil(yMinUnit/yMajorUnit)) + 1)*yMajorUnit;
177 else if (yMinUnit >= yMajorUnit)
178 yMinUnit -= (fabs(floor(yMinUnit/yMajorUnit)))*yMajorUnit;
179 }
180 }
181
AdjustMinUnitY2()182 void ScatterDraw::AdjustMinUnitY2() {
183 if (SetGridLinesY)
184 return;
185 yMinUnit2 = yMinUnit20;
186 if (yMajorUnit2 > 0) {
187 if (yMinUnit2 < 0)
188 yMinUnit2 += (fabs(ceil(yMinUnit2/yMajorUnit2)) + 1)*yMajorUnit2;
189 else if (yMinUnit2 >= yMajorUnit2)
190 yMinUnit2 -= (fabs(floor(yMinUnit2/yMajorUnit2)))*yMajorUnit2;
191 }
192 }
193
AdjustMajorUnitX()194 void ScatterDraw::AdjustMajorUnitX() {
195 if (xMajorUnit == 0 || IsNull(xMajorUnit))
196 return;
197 while (xRange/xMajorUnit > 1.2*xMajorUnitNum)
198 xMajorUnit *= 2;
199 while (xRange/xMajorUnit < xMajorUnitNum/1.5)
200 xMajorUnit /= 2;
201 }
202
AdjustMajorUnitY()203 void ScatterDraw::AdjustMajorUnitY() {
204 if (yMajorUnit == 0 || IsNull(yMajorUnit))
205 return;
206 while (yRange/yMajorUnit > 1.2*yMajorUnitNum)
207 yMajorUnit *= 2;
208 while (yRange/yMajorUnit < yMajorUnitNum/1.5)
209 yMajorUnit /= 2;
210 }
211
AdjustMajorUnitY2()212 void ScatterDraw::AdjustMajorUnitY2() {
213 if (yMajorUnit2 == 0 || IsNull(yMajorUnit2))
214 return;
215 while (yRange2/yMajorUnit2 > 1.2*yMajorUnitNum)
216 yMajorUnit2 *= 2;
217 while (yRange2/yMajorUnit2 < yMajorUnitNum/1.5)
218 yMajorUnit2 /= 2;
219 }
220
SetRange(double rx,double ry,double ry2)221 ScatterDraw &ScatterDraw::SetRange(double rx, double ry, double ry2) {
222 ASSERT(IsNull(rx) || rx > 0);
223 ASSERT(IsNull(ry) || ry > 0);
224 ASSERT(IsNull(ry2)|| ry2 > 0);
225
226 if (!IsNull(rx)) {
227 xRange = rx;
228 AdjustMajorUnitX();
229 AdjustMinUnitX();
230 }
231 if (!IsNull(ry)) {
232 yRange = ry;
233 AdjustMajorUnitY();
234 AdjustMinUnitY();
235 }
236 if (!IsNull(ry2)) {
237 yRange2 = ry2;
238 AdjustMajorUnitY2();
239 AdjustMinUnitY2();
240 }
241 WhenSetRange();
242 return *this;
243 }
244
SetMajorUnits(double ux,double uy)245 ScatterDraw &ScatterDraw::SetMajorUnits(double ux, double uy) {
246 if (!IsNull(ux)) {
247 xMajorUnit = ux;
248 xMajorUnitNum = int(xRange/ux);
249 AdjustMinUnitX();
250 }
251 if (!IsNull(uy)) {
252 yMajorUnit = uy;
253 yMajorUnit2 = yMajorUnit*yRange2/yRange;
254 yMajorUnitNum = int(yRange/uy);
255 AdjustMinUnitY();
256 AdjustMinUnitY2();
257 }
258 return *this;
259 }
260
SetMajorUnitsNum(int nx,int ny)261 ScatterDraw &ScatterDraw::SetMajorUnitsNum(int nx, int ny) {
262 if (!IsNull(nx)) {
263 xMajorUnitNum = nx;
264 xMajorUnit = xRange/nx;
265 AdjustMinUnitX();
266 }
267 if (!IsNull(ny)) {
268 yMajorUnitNum = ny;
269 yMajorUnit = yRange/ny;
270 yMajorUnit2 = yMajorUnit*yRange2/yRange;
271 AdjustMinUnitY();
272 AdjustMinUnitY2();
273 }
274 return *this;
275 }
276
SetMinUnits(double ux,double uy)277 ScatterDraw &ScatterDraw::SetMinUnits(double ux, double uy) {
278 if (!IsNull(ux))
279 xMinUnit = xMinUnit0 = ux;
280 if (!IsNull(uy)) {
281 yMinUnit = yMinUnit0 = uy;
282 yMinUnit2 = yMinUnit20 = yRange2*yMinUnit/yRange;
283 }
284 if (!IsNull(ux))
285 AdjustMinUnitX();
286 if (!IsNull(uy)) {
287 AdjustMinUnitY();
288 AdjustMinUnitY2();
289 }
290 return *this;
291 }
292
SetXYMin(double xmin,double ymin,double ymin2)293 ScatterDraw &ScatterDraw::SetXYMin(double xmin, double ymin, double ymin2) {
294 if (!IsNull(xmin))
295 xMin = xmin;
296 if (!IsNull(ymin))
297 yMin = ymin;
298 if (!IsNull(ymin2))
299 yMin2 = ymin2;
300 WhenSetXYMin();
301 return *this;
302 }
303
ZoomToFit(bool horizontal,bool vertical,double factor)304 ScatterDraw &ScatterDraw::ZoomToFit(bool horizontal, bool vertical, double factor) {
305 if (linkedMaster) {
306 linkedMaster->ZoomToFit(horizontal, vertical, factor);
307 return *this;
308 }
309 DoFitToData(horizontal, vertical, factor);
310 if (!linkedCtrls.IsEmpty()) {
311 for (int i = 0; i < linkedCtrls.GetCount(); ++i)
312 linkedCtrls[i]->DoFitToData(horizontal, vertical, factor);
313 }
314 WhenZoomToFit();
315 return *this;
316 }
317
DoFitToData(bool horizontal,bool vertical,double factor)318 ScatterDraw &ScatterDraw::DoFitToData(bool horizontal, bool vertical, double factor) {
319 double minx, maxx, miny, miny2, maxy, maxy2;
320 minx = miny = miny2 = -DOUBLE_NULL;
321 maxx = maxy = maxy2 = DOUBLE_NULL;
322
323 try {
324 if (horizontal) {
325 for (int j = 0; j < series.GetCount(); j++) {
326 ScatterSeries &serie = series[j];
327 if (serie.IsDeleted() || serie.opacity == 0 || serie.Data().IsExplicit())
328 continue;
329 double mn = serie.Data().MinX();
330 if (!IsNull(mn))
331 minx = min(minx, mn);
332 double mx = serie.Data().MaxX();
333 if (!IsNull(mx))
334 maxx = max(maxx, mx);
335 }
336 if (minx != -DOUBLE_NULL) {
337 double deltaX = (maxx - minx)*factor;
338 minx -= deltaX;
339 maxx += deltaX;
340 }
341 if (surf) {
342 minx = min(minx, surf->MinX());
343 maxx = max(maxx, surf->MaxX());
344 }
345 }
346 if (vertical) {
347 for (int j = 0; j < series.GetCount(); j++) {
348 ScatterSeries &serie = series[j];
349 if (serie.IsDeleted() || serie.opacity == 0 || serie.Data().IsExplicit())
350 continue;
351 for (int64 i = 0; i < serie.Data().GetCount(); i++) {
352 double py = serie.Data().y(i);
353 if (IsNull(py))
354 continue;
355 if (serie.primaryY) {
356 if (py < miny)
357 miny = py;
358 if (py > maxy)
359 maxy = py;
360 } else {
361 if (py < miny2)
362 miny2 = py;
363 if (py > maxy2)
364 maxy2 = py;
365 }
366 }
367 }
368 if (miny != -DOUBLE_NULL) {
369 double deltaY = (maxy - miny)*factor;
370 miny -= deltaY;
371 maxy += deltaY;
372 }
373 if (miny2 != -DOUBLE_NULL) {
374 double deltaY2 = (maxy2 - miny2)*factor;
375 miny2 -= deltaY2;
376 maxy2 += deltaY2;
377 }
378 if (surf) {
379 miny = min(miny, surf->MinY());
380 maxy = max(maxy, surf->MaxY());
381 }
382 }
383 if (horizontal) {
384 if (minx != -DOUBLE_NULL) {
385 if (maxx == minx) {
386 if (maxx == 0) {
387 xRange = 2;
388 xMin = -1;
389 } else
390 xRange = 2*maxx;
391 } else
392 xRange = maxx - minx;
393 double deltaX = xMin - minx;
394 xMin -= deltaX;
395
396 AdjustMinUnitX();
397 AdjustMajorUnitX();
398 }
399 }
400 if (vertical) {
401 if (miny != -DOUBLE_NULL) {
402 if (maxy == miny)
403 yRange = maxy > 0 ? 2*maxy : 1;
404 else
405 yRange = maxy - miny;
406 double deltaY = yMin - miny;
407 yMin -= deltaY;
408
409 AdjustMajorUnitY();
410 AdjustMinUnitY();
411 }
412 if (miny2 != -DOUBLE_NULL) {
413 if (maxy2 == miny2)
414 yRange2 = maxy2 > 0 ? 2*maxy2 : 1;
415 else
416 yRange2 = maxy2 - miny2;
417 double deltaY2 = yMin2 - miny2;
418 yMin2 -= deltaY2;
419
420 AdjustMajorUnitY2();
421 AdjustMinUnitY2();
422 }
423 }
424 } catch (ValueTypeError err) {
425 ASSERT_(true, err);
426 return *this;
427 }
428 WhenSetRange();
429 WhenSetXYMin();
430 Refresh();
431 return *this;
432 }
433
Graduation_FormatX(Formats fi)434 ScatterDraw &ScatterDraw::Graduation_FormatX(Formats fi) {
435 switch (fi) {
436 case EXP: cbModifFormatX = cbModifFormatXGridUnits = ExpFormat; break;
437 case MON: cbModifFormatX = cbModifFormatXGridUnits = MonFormat; break;
438 case DY: cbModifFormatX = cbModifFormatXGridUnits = DyFormat; break;
439 default: break;
440 }
441 return *this;
442 }
443
Graduation_FormatY(Formats fi)444 ScatterDraw &ScatterDraw::Graduation_FormatY(Formats fi) {
445 switch (fi) {
446 case EXP: cbModifFormatY = cbModifFormatYGridUnits = ExpFormat; break;
447 case MON: cbModifFormatY = cbModifFormatYGridUnits = MonFormat; break;
448 case DY: cbModifFormatY = cbModifFormatYGridUnits = DyFormat; break;
449 default: break;
450 }
451 return *this;
452 }
453
Graduation_FormatY2(Formats fi)454 ScatterDraw &ScatterDraw::Graduation_FormatY2(Formats fi) {
455 switch (fi) {
456 case EXP: cbModifFormatY2 = cbModifFormatY2GridUnits = ExpFormat; break;
457 case MON: cbModifFormatY2 = cbModifFormatY2GridUnits = MonFormat; break;
458 case DY: cbModifFormatY2 = cbModifFormatY2GridUnits = DyFormat; break;
459 default: break;
460 }
461 return *this;
462 }
463
VariableFormat(double range,double d)464 String ScatterDraw::VariableFormat(double range, double d) {
465 if (fabs(d) <= 1e-15)
466 d = 0;
467 if (0.001 <= range && range < 0.01) return FormatDouble(d, 5);
468 else if (0.01 <= range && range < 0.1) return FormatDouble(d, 4);
469 else if (0.1 <= range && range < 1) return FormatDouble(d, 3);
470 else if (1 <= range && range < 10) return FormatDouble(d, 2);
471 else if (10 <= range && range < 100) return FormatDouble(d, 1);
472 else if (100 <= range && range < 10000000)return FormatDouble(d, 0);
473 else return FormatDoubleExp(d, 2);
474 }
475
GetNewColor(int index,int version)476 Color ScatterDraw::GetNewColor(int index, int version) {
477 Color old[20] = {LtBlue(), LtRed(), LtGreen(), Black(), LtGray(), Brown(), Blue(), Red(), Green(), Gray(),
478 LtBlue(), LtRed(), LtGreen(), Black(), LtGray(), Brown(), Blue(), Red(), Green(), Gray()};
479 // Colours from http://tools.medialab.sciences-po.fr/iwanthue/
480 Color nwc[20] = {Color(197,127,117), Color(115,214,74), Color(205,80,212), Color(124,193,215), Color(85,82,139),
481 Color(109,212,161), Color(207,72,48), Color(209,206,59), Color(194,134,55), Color(63,72,41),
482 Color(201,63,109), Color(193,192,158), Color(91,134,56), Color(105,48,38), Color(201,170,200),
483 Color(86,117,119), Color(188,91,165), Color(124,120,216), Color(195,208,119), Color(79,46,75)};
484 if (index < 20) {
485 if (version == 0)
486 return old[index];
487 else
488 return nwc[index];
489 } else
490 return Color(Random(), Random(), Random());
491 }
492
GetNewDash(int index)493 String ScatterDraw::GetNewDash(int index) {
494 switch(index) {
495 case 0: return LINE_SOLID;
496 case 1: return LINE_DOTTED;
497 case 2: return LINE_DASHED;
498 case 3: return LINE_DASH_DOT;
499 case 4: return LINE_SOLID;
500 case 5: return LINE_DOTTED;
501 case 6: return LINE_DASHED;
502 case 7: return LINE_DASH_DOT;
503 case 8: return LINE_SOLID;
504 case 9: return LINE_DOTTED;
505 case 10: return LINE_DASHED;
506 case 11: return LINE_DASH_DOT;
507 }
508 dword r = Random();
509 if (r < 8000)
510 r += 2000;
511 String ret = FormatInt(r).Right(4);
512 String space = " ";
513 return ret.Mid(0, 1) + space + ret.Mid(1, 1) + space + ret.Mid(2, 1) + space + ret.Mid(3, 1);
514 }
515
GetNewMarkPlot(int index)516 MarkPlot *ScatterDraw::GetNewMarkPlot(int index) {
517 switch(index) {
518 case 0: return new CircleMarkPlot();
519 case 1: return new SquareMarkPlot();
520 case 2: return new TriangleMarkPlot();
521 case 3: return new CrossMarkPlot();
522 case 4: return new XMarkPlot();
523 case 5: return new RhombMarkPlot();
524 }
525 return new CircleMarkPlot();
526 }
527
GetOpaqueColor(const Color & color,const Color & background,double opacity)528 Color GetOpaqueColor(const Color &color, const Color &background, double opacity) {
529 if (opacity == 1)
530 return color;
531 if (opacity == 0)
532 return background;
533 return Color(int(opacity*(color.GetR() - background.GetR()) + background.GetR()),
534 int(opacity*(color.GetG() - background.GetG()) + background.GetG()),
535 int(opacity*(color.GetB() - background.GetB()) + background.GetB()));
536 }
537
ScatterBasicSeries()538 ScatterDraw::ScatterBasicSeries::ScatterBasicSeries() {
539 color = Null;
540 thickness = 3;
541 legend = "";
542 unitsX = "";
543 unitsY = "";
544 opacity = 1;
545 primaryY = true;
546 sequential = false;
547 dash = LINE_SOLID;
548 seriesPlot = new LineSeriesPlot();
549 markPlot = new CircleMarkPlot();
550 markWidth = 8;
551 markColor = Null;
552 markBorderWidth = 1;
553 markBorderColor = Null;
554 fillColor = Null;
555 labels = 0;
556 isClosed = false;
557 barWidth = 10;
558 labelsFont = StdFont();
559 labelsColor = Null;
560 labelsDx = labelsDy = 0;
561 labelsAlign = ALIGN_CENTER;
562 showLegend = true;
563 legendLine = false;
564 }
565
Init(int index)566 void ScatterDraw::ScatterBasicSeries::Init(int index) {
567 color = GetNewColor(index);
568 markColor = Color(max(color.GetR()-30, 0), max(color.GetG()-30, 0), max(color.GetB()-30, 0));
569
570 dash = GetNewDash(int(index/6));
571 markPlot = GetNewMarkPlot(index);
572 }
573
AddSeries(DataSource & data)574 ScatterDraw &ScatterDraw::AddSeries(DataSource &data) {
575 ScatterSeries &s = series.Add();
576 s.Init(series.GetCount()-1);
577 s.SetDataSource(&data, false);
578 if (sequentialXAll)
579 s.sequential = true;
580 Refresh();
581 return *this;
582 }
583
_AddSeries(DataSource * data)584 ScatterDraw &ScatterDraw::_AddSeries(DataSource *data) {
585 ScatterSeries &s = series.Add();
586 s.Init(series.GetCount()-1);
587 s.SetDataSource(data);
588 Refresh();
589 return *this;
590 }
591
InsertSeries(int index,double * yData,int numData,double x0,double deltaX)592 ScatterDraw &ScatterDraw::InsertSeries(int index, double *yData, int numData, double x0, double deltaX) {
593 return InsertSeries<CArray>(index, yData, numData, x0, deltaX);
594 }
595
InsertSeries(int index,double * xData,double * yData,int numData)596 ScatterDraw &ScatterDraw::InsertSeries(int index, double *xData, double *yData, int numData) {
597 return InsertSeries<CArray>(index, xData, yData, numData);
598 }
599
InsertSeries(int index,Vector<double> & xData,Vector<double> & yData)600 ScatterDraw &ScatterDraw::InsertSeries(int index, Vector<double> &xData, Vector<double> &yData) {
601 return InsertSeries<VectorXY>(index, xData, yData);
602 }
603
InsertSeries(int index,Upp::Array<double> & xData,Upp::Array<double> & yData)604 ScatterDraw &ScatterDraw::InsertSeries(int index, Upp::Array<double> &xData, Upp::Array<double> &yData) {
605 return InsertSeries<ArrayXY>(index, xData, yData);
606 }
607
InsertSeries(int index,Vector<Pointf> & points)608 ScatterDraw &ScatterDraw::InsertSeries(int index, Vector<Pointf> &points) {
609 return InsertSeries<VectorPointf>(index, points);
610 }
611
InsertSeries(int index,Upp::Array<Pointf> & points)612 ScatterDraw &ScatterDraw::InsertSeries(int index, Upp::Array<Pointf> &points) {
613 return InsertSeries<ArrayPointf>(index, points);
614 }
615
InsertSeries(int index,double (* function)(double))616 ScatterDraw &ScatterDraw::InsertSeries(int index, double (*function)(double)) {
617 return InsertSeries<FuncSource>(index, function);
618 }
619
InsertSeries(int index,Pointf (* function)(double),int np,double from,double to)620 ScatterDraw &ScatterDraw::InsertSeries(int index, Pointf (*function)(double), int np, double from, double to) {
621 return InsertSeries<FuncSourcePara>(index, function, np, from, to);
622 }
623
InsertSeries(int index,PlotExplicFunc & function)624 ScatterDraw &ScatterDraw::InsertSeries(int index, PlotExplicFunc &function) {
625 return InsertSeries<PlotExplicFuncSource>(index, function);
626 }
627
InsertSeries(int index,PlotParamFunc function,int np,double from,double to)628 ScatterDraw &ScatterDraw::InsertSeries(int index, PlotParamFunc function, int np, double from, double to) {
629 return InsertSeries<PlotParamFuncSource>(index, function, np, from, to);
630 }
631
_InsertSeries(int index,DataSource * data)632 ScatterDraw &ScatterDraw::_InsertSeries(int index, DataSource *data) {
633 ASSERT(IsValid(index));
634
635 ScatterSeries &s = series.Insert(index);
636 s.Init(index);
637 s.SetDataSource(data);
638 Refresh();
639 return *this;
640 }
641
GetCount(int index)642 int64 ScatterDraw::GetCount(int index) {
643 ASSERT(IsValid(index));
644 ASSERT(!series[index].IsDeleted());
645
646 return series[index].Data().GetCount();
647 }
648
GetValues(int index,int64 idata,double & x,double & y)649 void ScatterDraw::GetValues(int index, int64 idata, double &x, double &y) {
650 ASSERT(IsValid(index) && !IsNull(GetCount(index)));
651 ASSERT(!series[index].IsDeleted());
652 ASSERT(idata >= 0 && idata < series[index].Data().GetCount());
653
654 try {
655 x = series[index].Data().x(idata);
656 y = series[index].Data().y(idata);
657 } catch(ValueTypeError error) {
658 ASSERT_(true, error);
659 x = y = Null;
660 }
661 }
662
GetValueX(int index,int64 idata)663 double ScatterDraw::GetValueX(int index, int64 idata) {
664 ASSERT(IsValid(index) && !IsNull(GetCount(index)));
665 ASSERT(!series[index].IsDeleted());
666 ASSERT(idata >= 0 && idata < series[index].Data().GetCount());
667
668 try {
669 return series[index].Data().x(idata);
670 } catch(ValueTypeError error) {
671 ASSERT_(true, error);
672 return Null;
673 }
674 }
675
GetStringX(int index,int64 idata)676 Value ScatterDraw::GetStringX(int index, int64 idata) {
677 double ret = GetValueX(index, idata);
678 if (IsNull(ret))
679 return Null;
680 if (cbModifFormatX) {
681 String sret;
682 cbModifFormatX(sret, int(idata), ret);
683 return sret;
684 } else
685 return ret;
686 }
687
688
GetValueY(int index,int64 idata)689 double ScatterDraw::GetValueY(int index, int64 idata) {
690 ASSERT(IsValid(index) && !IsNull(GetCount(index)));
691 ASSERT(!series[index].IsDeleted());
692 ASSERT(idata >= 0 && idata < series[index].Data().GetCount());
693
694 try {
695 return series[index].Data().y(idata);
696 } catch(ValueTypeError error) {
697 ASSERT_(true, error);
698 return Null;
699 }
700 }
701
GetStringY(int index,int64 idata)702 Value ScatterDraw::GetStringY(int index, int64 idata) {
703 double ret = GetValueY(index, idata);
704 if (IsNull(ret))
705 return Null;
706 if (cbModifFormatY) {
707 String sret;
708 cbModifFormatY(sret, int(idata), ret);
709 return sret;
710 } else
711 return ret;
712 }
713
SetNoPlot(int index)714 ScatterDraw &ScatterDraw::SetNoPlot(int index) {
715 ASSERT(IsValid(index));
716 ASSERT(!series[index].IsDeleted());
717
718 series[index].seriesPlot = NULL;
719 return *this;
720 }
721
PlotStyle(int index,SeriesPlot * data)722 ScatterDraw &ScatterDraw::PlotStyle(int index, SeriesPlot *data) {
723 ASSERT(IsValid(index));
724 ASSERT(!series[index].IsDeleted());
725
726 series[index].seriesPlot = data;
727 return *this;
728 }
729
MarkStyle(int index,MarkPlot * data)730 ScatterDraw &ScatterDraw::MarkStyle(int index, MarkPlot *data) {
731 ASSERT(IsValid(index));
732 ASSERT(!series[index].IsDeleted());
733
734 series[index].markPlot = data;
735 return *this;
736 }
737
MarkStyle(int index,const String name)738 ScatterDraw &ScatterDraw::MarkStyle(int index, const String name) {
739 ASSERT(IsValid(index));
740 ASSERT(!series[index].IsDeleted());
741
742 int typeidx = MarkPlot::TypeIndex(name);
743
744 if (typeidx >= 0)
745 series[index].markPlot = MarkPlot::Create(typeidx);
746 else
747 series[index].markPlot = 0;
748 return *this;
749 }
750
GetMarkStyleName(int index)751 const String ScatterDraw::GetMarkStyleName(int index) {
752 ASSERT(IsValid(index));
753 ASSERT(!series[index].IsDeleted());
754
755 if (series[index].markPlot)
756 return MarkPlot::TypeName(series[index].markPlot->GetType());
757 else
758 return t_("No mark");
759 }
760
GetMarkStyleType(int index)761 int ScatterDraw::GetMarkStyleType(int index) {
762 ASSERT(IsValid(index));
763 ASSERT(!series[index].IsDeleted());
764
765 if (series[index].markPlot)
766 return series[index].markPlot->GetTypeType();
767 else
768 return -1;
769 }
770
SetMarkStyleType(int index,int type)771 ScatterDraw &ScatterDraw::SetMarkStyleType(int index, int type) {
772 ASSERT(IsValid(index));
773 ASSERT(!series[index].IsDeleted());
774
775 if (series[index].markPlot)
776 series[index].markPlot->SetTypeType(type);
777
778 return *this;
779 }
780
Stroke(int index,double thickness,Color color)781 ScatterDraw &ScatterDraw::Stroke(int index, double thickness, Color color) {
782 ASSERT(IsValid(index));
783 ASSERT(!series[index].IsDeleted());
784
785 if (IsNull(color))
786 color = GetNewColor(index);
787 series[index].color = color;
788 series[index].thickness = thickness;
789 //series[index].dash = GetNewDash(index);
790
791 Refresh();
792 return *this;
793 }
794
GetStroke(int index,double & thickness,Color & color)795 void ScatterDraw::GetStroke(int index, double &thickness, Color &color) {
796 ASSERT(IsValid(index));
797 ASSERT(!series[index].IsDeleted());
798
799 color = series[index].color;
800 thickness = series[index].thickness;
801 }
802
Fill(Color color)803 ScatterDraw &ScatterDraw::Fill(Color color) {
804 int index = series.GetCount() - 1;
805
806 if (IsNull(color)) {
807 color = GetNewColor(index);
808 color = Color(min(color.GetR()+30, 255), min(color.GetG()+30, 255), min(color.GetB()+30, 255));
809 }
810 series[index].fillColor = color;
811
812 Refresh();
813 return *this;
814 }
815
MarkColor(Color color)816 ScatterDraw &ScatterDraw::MarkColor(Color color) {
817 int index = series.GetCount() - 1;
818
819 if (IsNull(color)) {
820 color = GetNewColor(index);
821 color = Color(max(color.GetR()-30, 0), max(color.GetG()-30, 0), max(color.GetB()-30, 0));
822 }
823 series[index].markColor = color;
824
825 Refresh();
826 return *this;
827 }
828
MarkBorderColor(Color color)829 ScatterDraw &ScatterDraw::MarkBorderColor(Color color) {
830 int index = series.GetCount() - 1;
831
832 if (IsNull(color)) {
833 color = GetNewColor(index + 1);
834 color = Color(max(color.GetR()-30, 0), max(color.GetG()-30, 0), max(color.GetB()-30, 0));
835 }
836 series[index].markBorderColor = color;
837
838 Refresh();
839 return *this;
840 }
841
MarkWidth(double markWidth)842 ScatterDraw &ScatterDraw::MarkWidth(double markWidth) {
843 int index = series.GetCount() - 1;
844
845 series[index].markWidth = markWidth;
846
847 Refresh();
848 return *this;
849 }
850
MarkBorderWidth(double markWidth)851 ScatterDraw &ScatterDraw::MarkBorderWidth(double markWidth) {
852 int index = series.GetCount() - 1;
853
854 series[index].markBorderWidth = markWidth;
855
856 Refresh();
857 return *this;
858 }
859
ShowSeriesLegend(int index,bool show)860 ScatterDraw &ScatterDraw::ShowSeriesLegend(int index, bool show) {
861 ASSERT(IsValid(index));
862 ASSERT(!series[index].IsDeleted());
863
864 series[index].showLegend = show;
865
866 Refresh();
867 return *this;
868 }
869
Closed(int index,bool closed)870 ScatterDraw &ScatterDraw::Closed(int index, bool closed) {
871 ASSERT(IsValid(index));
872 ASSERT(!series[index].IsDeleted());
873
874 series[index].isClosed = closed;
875 Refresh();
876 return *this;
877 }
878
IsClosed(int index)879 bool ScatterDraw::IsClosed(int index) {
880 ASSERT(IsValid(index));
881 ASSERT(!series[index].IsDeleted());
882
883 return series[index].isClosed;
884 }
885
BarWidth(int index,double width)886 ScatterDraw &ScatterDraw::BarWidth(int index, double width) {
887 ASSERT(IsValid(index));
888 ASSERT(!series[index].IsDeleted());
889
890 series[index].barWidth = width;
891 Refresh();
892 return *this;
893 }
894
Dash(const char * dash)895 ScatterDraw &ScatterDraw::Dash(const char *dash) {
896 int index = series.GetCount() - 1;
897
898 return Dash(index, dash);
899 }
900
Dash(int index,const char * dash)901 ScatterDraw &ScatterDraw::Dash(int index, const char *dash) {
902 ASSERT(IsValid(index));
903 ASSERT(!series[index].IsDeleted());
904
905 series[index].dash = dash;
906 Refresh();
907 return *this;
908 }
909
NoDash()910 ScatterDraw &ScatterDraw::NoDash() {
911 int index = series.GetCount() - 1;
912
913 return NoDash(index);
914 }
915
NoDash(int index)916 ScatterDraw &ScatterDraw::NoDash(int index) {
917 ASSERT(IsValid(index));
918 ASSERT(!series[index].IsDeleted());
919
920 series[index].dash = LINE_SOLID;
921 Refresh();
922 return *this;
923 }
924
GetDash(int index)925 const String ScatterDraw::GetDash(int index) {
926 ASSERT(IsValid(index));
927 ASSERT(!series[index].IsDeleted());
928
929 return series[index].dash;
930 }
931
Legend(const String legend)932 ScatterDraw &ScatterDraw::Legend(const String legend) {
933 int index = series.GetCount() - 1;
934
935 return Legend(index, legend);
936 }
937
Legend(int index,const String legend)938 ScatterDraw& ScatterDraw::Legend(int index, const String legend) {
939 ASSERT(IsValid(index));
940 ASSERT(!series[index].IsDeleted());
941
942 series[index].legend = legend;
943 return *this;
944 }
945
GetLegend(int index)946 const String& ScatterDraw::GetLegend(int index) {
947 ASSERT(IsValid(index));
948 ASSERT(!series[index].IsDeleted());
949
950 return series[index].legend;
951 }
952
Units(const String unitsY,const String unitsX)953 ScatterDraw &ScatterDraw::Units(const String unitsY, const String unitsX) {
954 int index = series.GetCount() - 1;
955
956 return Units(index, unitsY, unitsX);
957 }
958
Units(int index,const String unitsY,const String unitsX)959 ScatterDraw& ScatterDraw::Units(int index, const String unitsY, const String unitsX) {
960 ASSERT(IsValid(index));
961 ASSERT(!series[index].IsDeleted());
962
963 series[index].unitsX = unitsX;
964 series[index].unitsY = unitsY;
965 labelsChanged = true;
966
967 return *this;
968 }
969
GetUnitsX(int index)970 const String ScatterDraw::GetUnitsX(int index) {
971 ASSERT(IsValid(index));
972 ASSERT(!series[index].IsDeleted());
973
974 return series[index].unitsX;
975 }
976
GetUnitsY(int index)977 const String ScatterDraw::GetUnitsY(int index) {
978 ASSERT(IsValid(index));
979 ASSERT(!series[index].IsDeleted());
980
981 return series[index].unitsY;
982 }
983
SetFillColor(int index,const Color & color)984 ScatterDraw& ScatterDraw::SetFillColor(int index, const Color& color) {
985 ASSERT(IsValid(index));
986 ASSERT(!series[index].IsDeleted());
987
988 series[index].fillColor = color;
989 Refresh();
990 return *this;
991 }
992
GetFillColor(int index) const993 Color ScatterDraw::GetFillColor(int index) const {
994 ASSERT(IsValid(index));
995 ASSERT(!series[index].IsDeleted());
996
997 return series[index].fillColor;
998 }
999
SetMarkBorderWidth(int index,double width)1000 ScatterDraw &ScatterDraw::SetMarkBorderWidth(int index, double width) {
1001 ASSERT(IsValid(index));
1002 ASSERT(!series[index].IsDeleted());
1003
1004 series[index].markBorderWidth = width;
1005 Refresh();
1006 return *this;
1007 }
1008
GetMarkBorderWidth(int index)1009 double ScatterDraw::GetMarkBorderWidth(int index) {
1010 ASSERT(IsValid(index));
1011 ASSERT(!series[index].IsDeleted());
1012
1013 return series[index].markBorderWidth;
1014 }
1015
SetMarkWidth(int index,double markWidth)1016 ScatterDraw &ScatterDraw::SetMarkWidth(int index, double markWidth) {
1017 ASSERT(IsValid(index));
1018 ASSERT(!series[index].IsDeleted());
1019
1020 series[index].markWidth = markWidth;
1021 Refresh();
1022 return *this;
1023 }
1024
GetMarkWidth(int index)1025 double ScatterDraw::GetMarkWidth(int index) {
1026 ASSERT(IsValid(index));
1027 ASSERT(!series[index].IsDeleted());
1028
1029 return series[index].markWidth;
1030 }
1031
SetMarkColor(int index,const Color & color)1032 ScatterDraw &ScatterDraw::SetMarkColor(int index, const Color& color) {
1033 ASSERT(IsValid(index));
1034 ASSERT(!series[index].IsDeleted());
1035
1036 series[index].markColor = color;
1037 Refresh();
1038 return *this;
1039 }
1040
GetMarkColor(int index) const1041 Color ScatterDraw::GetMarkColor(int index) const {
1042 ASSERT(IsValid(index));
1043 ASSERT(!series[index].IsDeleted());
1044
1045 return series[index].markColor;
1046 }
1047
SetMarkBorderColor(int index,const Color & color)1048 ScatterDraw &ScatterDraw::SetMarkBorderColor(int index, const Color& color) {
1049 ASSERT(IsValid(index));
1050 ASSERT(!series[index].IsDeleted());
1051
1052 series[index].markBorderColor = color;
1053 Refresh();
1054 return *this;
1055 }
1056
GetMarkBorderColor(int index) const1057 Color ScatterDraw::GetMarkBorderColor(int index) const {
1058 ASSERT(IsValid(index));
1059 ASSERT(!series[index].IsDeleted());
1060
1061 return series[index].markBorderColor;
1062 }
1063
NoMark(int index)1064 void ScatterDraw::NoMark(int index) {
1065 ASSERT(IsValid(index));
1066 ASSERT(!series[index].IsDeleted());
1067
1068 series[index].markWidth = 0;
1069 }
1070
SetDataPrimaryY(int index,bool primary)1071 void ScatterDraw::SetDataPrimaryY(int index, bool primary) {
1072 ASSERT(IsValid(index));
1073 ASSERT(!series[index].IsDeleted());
1074
1075 series[index].primaryY = primary;
1076 if (!primary)
1077 SetDrawY2Reticle(true);
1078 Refresh();
1079 }
1080
SetDataPrimaryY(bool primary)1081 ScatterDraw &ScatterDraw::SetDataPrimaryY(bool primary) {
1082 SetDataPrimaryY(series.GetCount()-1, primary);
1083 return *this;
1084 }
1085
SetDataSecondaryY(int index,bool secondary)1086 void ScatterDraw::SetDataSecondaryY(int index, bool secondary) {
1087 ASSERT(IsValid(index));
1088 ASSERT(!series[index].IsDeleted());
1089
1090 series[index].primaryY = !secondary;
1091 if (secondary)
1092 SetDrawY2Reticle().SetDrawY2ReticleNumbers();
1093 Refresh();
1094 }
1095
SetDataSecondaryY(bool secondary)1096 ScatterDraw &ScatterDraw::SetDataSecondaryY(bool secondary) {
1097 SetDataSecondaryY(series.GetCount()-1, secondary);
1098 return *this;
1099 }
1100
IsDataPrimaryY(int index)1101 bool ScatterDraw::IsDataPrimaryY(int index) {
1102 ASSERT(IsValid(index));
1103 ASSERT(!series[index].IsDeleted());
1104
1105 return series[index].primaryY;
1106 }
1107 /*
1108 void ScatterDraw::SetDataSourceInternal() {
1109 for (int i = 0; i < series.GetCount(); ++i)
1110 series[i].SetDataSource_Internal(true);
1111 }*/
1112
ThereAreSecondaryY()1113 bool ScatterDraw::ThereAreSecondaryY() {
1114 for (int i = 0; i < series.GetCount(); ++i)
1115 if (!series[i].primaryY)
1116 return true;
1117 return false;
1118 }
1119
SetSequentialX(int index,bool sequential)1120 void ScatterDraw::SetSequentialX(int index, bool sequential) {
1121 ASSERT(IsValid(index));
1122 ASSERT(!series[index].IsDeleted());
1123
1124 series[index].sequential = sequential;
1125 Refresh();
1126 }
1127
SetSequentialX(bool sequential)1128 ScatterDraw &ScatterDraw::SetSequentialX(bool sequential) {
1129 SetSequentialX(series.GetCount()-1, sequential);
1130 return *this;
1131 }
1132
GetSequentialX(int index)1133 bool ScatterDraw::GetSequentialX(int index) {
1134 ASSERT(IsValid(index));
1135 ASSERT(!series[index].IsDeleted());
1136
1137 return series[index].sequential;
1138 }
1139
GetSequentialX()1140 bool ScatterDraw::GetSequentialX() {
1141 return GetSequentialX(series.GetCount()-1);
1142 }
1143
SetSequentialXAll(bool sequential)1144 ScatterDraw &ScatterDraw::SetSequentialXAll(bool sequential) {
1145 for (int i = 0; i < series.GetCount(); ++i) {
1146 const ScatterSeries &serie = series[i];
1147 if (serie.IsDeleted())
1148 continue;
1149 SetSequentialX(i, sequential);
1150 }
1151 sequentialXAll = sequential;
1152 return *this;
1153 }
1154
Show(int index,bool show)1155 void ScatterDraw::Show(int index, bool show) {
1156 ASSERT(IsValid(index));
1157 ASSERT(!series[index].IsDeleted());
1158
1159 series[index].opacity = show ? 1 : 0;
1160 labelsChanged = true;
1161 Refresh();
1162 }
1163
IsVisible(int index)1164 bool ScatterDraw::IsVisible(int index) {
1165 ASSERT(IsValid(index));
1166 ASSERT(!series[index].IsDeleted());
1167
1168 return series[index].opacity > 0;
1169 }
1170
ShowAll(bool)1171 ScatterDraw &ScatterDraw::ShowAll(bool ) {
1172 for (int i = 0; i < series.GetCount(); ++i) {
1173 ScatterSeries &serie = series[i];
1174 if (serie.IsDeleted())
1175 continue;
1176 serie.opacity = 1;
1177 }
1178 return *this;
1179 }
1180
Id(int id)1181 ScatterDraw& ScatterDraw::Id(int id) {
1182 return Id(series.GetCount()-1, id);
1183 }
1184
Id(int index,int id)1185 ScatterDraw& ScatterDraw::Id(int index, int id) {
1186 ASSERT(IsValid(index));
1187 ASSERT(!series[index].IsDeleted());
1188
1189 series[index].id = id;
1190 return *this;
1191 }
1192
GetId(int index)1193 int ScatterDraw::GetId(int index) {
1194 ASSERT(IsValid(index));
1195 ASSERT(!series[index].IsDeleted());
1196
1197 return series[index].id;
1198 }
1199
RemoveSeries(int index)1200 bool ScatterDraw::RemoveSeries(int index) {
1201 ASSERT(IsValid(index));
1202 ASSERT(!series[index].IsDeleted());
1203
1204 if (WhenRemoveSeries)
1205 if (!WhenRemoveSeries(index))
1206 return false;
1207 series.Remove(index);
1208 Refresh();
1209 return true;
1210 }
1211
RemoveAllSeries()1212 void ScatterDraw::RemoveAllSeries() {
1213 series.Clear();
1214 Refresh();
1215 }
1216
SwapSeries(int i1,int i2)1217 bool ScatterDraw::SwapSeries(int i1, int i2) {
1218 ASSERT(IsValid(i1));
1219 ASSERT(!series[i1].IsDeleted());
1220 ASSERT(IsValid(i2));
1221 ASSERT(!series[i2].IsDeleted());
1222
1223 if (WhenSwapSeries)
1224 if (!WhenSwapSeries(i1, i2))
1225 return false;
1226 series.Swap(i1, i2);
1227 Refresh();
1228 return true;
1229 }
1230
GetDrawing()1231 Drawing ScatterDraw::GetDrawing() {
1232 DrawingDraw ddw(size);
1233
1234 SetDrawing<DrawingDraw>(ddw, true);
1235 PlotTexts(ddw);
1236
1237 return ddw;
1238 }
1239
GetImage()1240 Image ScatterDraw::GetImage() {
1241 #ifndef flagGUI
1242 ASSERT(mode != MD_DRAW);
1243 #endif
1244 ImageBuffer ib(size);
1245 BufferPainter bp(ib, mode);
1246
1247 bp.LineCap(LINECAP_SQUARE);
1248 bp.LineJoin(LINEJOIN_MITER);
1249 SetDrawing(bp, false);
1250
1251 return ib;
1252 }
1253
1254
GetXByPoint(double x)1255 double ScatterDraw::GetXByPoint(double x) {
1256 return (x - hPlotLeft)*GetXRange()/(GetSize().cx - (hPlotLeft + hPlotRight) - 1) + GetXMin();
1257 }
1258
GetYByPoint(double y)1259 double ScatterDraw::GetYByPoint(double y) {
1260 return (GetSize().cy - vPlotTop - y - 1)*GetYRange()/(GetSize().cy - (vPlotTop + vPlotBottom) - GetTitleFont().GetHeight() - GetTitleFont().GetDescent() - 1) + GetYMin();
1261 }
1262
GetY2ByPoint(double y)1263 double ScatterDraw::GetY2ByPoint(double y) {
1264 return (GetSize().cy - vPlotTop - y - 1)*GetY2Range()/(GetSize().cy - (vPlotTop + vPlotBottom) - GetTitleFont().GetHeight() - GetTitleFont().GetDescent() - 1) + GetYMin2();
1265 }
1266
GetXPointByValue(double x)1267 double ScatterDraw::GetXPointByValue(double x) {
1268 return (x - GetXMin())/GetXRange()*(GetSize().cx - (hPlotLeft + hPlotRight) - 1) + hPlotLeft;
1269 }
1270
GetYPointByValue(double y)1271 double ScatterDraw::GetYPointByValue(double y) {
1272 return (GetSize().cy - vPlotTop - 1) - (y - GetYMin())/GetYRange()*(GetSize().cy - (vPlotTop + vPlotBottom) - GetTitleFont().GetHeight() - GetTitleFont().GetDescent() - 1);
1273 }
1274
SetRangeLinked(double rx,double ry,double ry2)1275 ScatterDraw &ScatterDraw::SetRangeLinked(double rx, double ry, double ry2) {
1276 if (linkedMaster) {
1277 linkedMaster->SetRangeLinked(rx, ry, ry2);
1278 linkedMaster->Refresh();
1279 return *this;
1280 }
1281 SetRange(rx, ry, ry2);
1282 if (!linkedCtrls.IsEmpty()) {
1283 for (int i = 0; i < linkedCtrls.GetCount(); ++i) {
1284 linkedCtrls[i]->SetRange(rx, ry, ry2);
1285 linkedCtrls[i]->Refresh();
1286 }
1287 }
1288 return *this;
1289 }
1290
SetXYMinLinked(double xmin,double ymin,double ymin2)1291 ScatterDraw &ScatterDraw::SetXYMinLinked(double xmin, double ymin, double ymin2) {
1292 if (linkedMaster) {
1293 linkedMaster->SetXYMinLinked(xmin, ymin, ymin2);
1294 linkedMaster->Refresh();
1295 return *this;
1296 }
1297 SetXYMin(xmin, ymin, ymin2);
1298 if (!linkedCtrls.IsEmpty()) {
1299 for (int i = 0; i < linkedCtrls.GetCount(); ++i) {
1300 linkedCtrls[i]->SetXYMin(xmin, ymin, ymin2);
1301 linkedCtrls[i]->Refresh();
1302 }
1303 }
1304 return *this;
1305 }
1306
Zoom(double scale,bool mouseX,bool mouseY)1307 void ScatterDraw::Zoom(double scale, bool mouseX, bool mouseY) {
1308 if (linkedMaster) {
1309 linkedMaster->Zoom(scale, mouseX, mouseY);
1310 return;
1311 }
1312 DoZoom(scale, mouseX, mouseY);
1313 if (!linkedCtrls.IsEmpty()) {
1314 for (int i = 0; i < linkedCtrls.GetCount(); ++i)
1315 linkedCtrls[i]->DoZoom(scale, mouseX, mouseY);
1316 }
1317 }
1318
DoZoom(double scale,bool mouseX,bool mouseY)1319 void ScatterDraw::DoZoom(double scale, bool mouseX, bool mouseY) {
1320 if (scale == 1)
1321 return;
1322 lastRefresh_sign = (scale >= 0) ? 1 : -1;
1323
1324 if (scale > 1) {
1325 if (maxXRange > 0) {
1326 if (xRange*scale > maxXRange) {
1327 highlight_0 = GetTickCount();
1328 if (xRange == maxXRange) {
1329 Refresh();
1330 return;
1331 } else
1332 scale = maxXRange/xRange;
1333 }
1334 }
1335 if (maxYRange > 0) {
1336 if (yRange*scale > maxYRange) {
1337 highlight_0 = GetTickCount();
1338 if (yRange == maxYRange) {
1339 Refresh();
1340 return;
1341 } else
1342 scale = maxYRange/xRange;
1343 }
1344 }
1345 } else {
1346 if (maxXRange > 0) {
1347 if (xRange*scale < minXRange) {
1348 highlight_0 = GetTickCount();
1349 if (xRange == minXRange) {
1350 Refresh();
1351 return;
1352 } else
1353 scale = minXRange/xRange;
1354 }
1355 }
1356 if (maxYRange > 0) {
1357 if (yRange*scale < minYRange) {
1358 highlight_0 = GetTickCount();
1359 if (yRange == minYRange) {
1360 Refresh();
1361 return;
1362 } else
1363 scale = minYRange/xRange;
1364 }
1365 }
1366 }
1367
1368 if (mouseX) {
1369 if (zoomStyleX == TO_CENTER) {
1370 if (!IsNull(minXmin) && xMin + xRange*(1-scale)/2. <= minXmin) {
1371 highlight_0 = GetTickCount();
1372 Refresh();
1373 return;
1374 }
1375 if (!IsNull(maxXmax) && xMin + xRange*scale + xRange*(1-scale)/2. >= maxXmax) {
1376 highlight_0 = GetTickCount();
1377 Refresh();
1378 return;
1379 }
1380 double oldXMin = xMin;
1381 xMin += xRange*(1-scale)/2.;
1382 xMinUnit = oldXMin + xMinUnit - xMin;
1383 AdjustMinUnitX();
1384 }
1385 xRange *= scale;
1386
1387 AdjustMajorUnitX();
1388 AdjustMinUnitX();
1389 lastxRange = xRange;
1390 }
1391 if (mouseY) {
1392 if (zoomStyleY == TO_CENTER) {
1393 if (!IsNull(minYmin) && yMin + yRange*(1-scale)/2. <= minYmin) {
1394 highlight_0 = GetTickCount();
1395 Refresh();
1396 return;
1397 }
1398 if (!IsNull(maxYmax) && yMin + yRange*scale + yRange*(1-scale)/2. >= maxYmax) {
1399 highlight_0 = GetTickCount();
1400 Refresh();
1401 return;
1402 }
1403 double oldYMin = yMin;
1404 yMin += yRange*(1 - scale)/2.;
1405 yMinUnit = oldYMin + yMinUnit - yMin;
1406 AdjustMinUnitY();
1407 double oldYMin2 = yMin2;
1408 yMin2 += yRange2*(1-scale)/2.;
1409 yMinUnit2 = oldYMin2 + yMinUnit2 - yMin2;
1410 AdjustMinUnitY2();
1411 }
1412 yRange *= scale;
1413 yRange2 *= scale;
1414
1415 AdjustMajorUnitY();
1416 AdjustMinUnitY();
1417 lastyRange = yRange;
1418 }
1419 if (mouseX || mouseY) {
1420 WhenSetRange();
1421 if (zoomStyleX == TO_CENTER || zoomStyleY == TO_CENTER)
1422 WhenSetXYMin();
1423 Refresh();
1424 WhenZoomScroll();
1425 }
1426 }
1427
Scroll(double factorX,double factorY)1428 void ScatterDraw::Scroll(double factorX, double factorY) {
1429 if (linkedMaster) {
1430 linkedMaster->Scroll(factorX, factorY);
1431 return;
1432 }
1433 DoScroll(factorX, factorY);
1434 if (!linkedCtrls.IsEmpty()) {
1435 for (int i = 0; i < linkedCtrls.GetCount(); ++i)
1436 linkedCtrls[i]->DoScroll(factorX, factorY);
1437 }
1438 }
1439
DoScroll(double factorX,double factorY)1440 void ScatterDraw::DoScroll(double factorX, double factorY) {
1441 if (factorX != 0) {
1442 double deltaX = factorX*xRange;
1443 if (!IsNull(minXmin) && factorX > 0) {
1444 if (xMin > minXmin) {
1445 if (xMin - deltaX < minXmin) {
1446 highlight_0 = GetTickCount();
1447 deltaX = xMin - minXmin;
1448 }
1449 } else {
1450 factorX = Null;
1451 highlight_0 = GetTickCount();
1452 }
1453 }
1454 if (!IsNull(maxXmax) && factorX < 0) {
1455 if (xMin + xRange < maxXmax) {
1456 if (xMin + xRange - deltaX > maxXmax) {
1457 highlight_0 = GetTickCount();
1458 deltaX = xMin + xRange - maxXmax;
1459 }
1460 } else {
1461 factorX = Null;
1462 highlight_0 = GetTickCount();
1463 }
1464 }
1465 if (factorX != 0 && !IsNull(factorX)) {
1466 xMin -= deltaX;
1467 xMinUnit += deltaX;
1468 AdjustMinUnitX();
1469 }
1470 }
1471 if (factorY != 0) {
1472 double deltaY = factorY*yRange;
1473 if (!IsNull(minYmin) && factorY > 0) {
1474 if (yMin > minYmin) {
1475 if (yMin - deltaY < minYmin) {
1476 highlight_0 = GetTickCount();
1477 deltaY = yMin - minYmin;
1478 }
1479 } else {
1480 factorY = Null;
1481 highlight_0 = GetTickCount();
1482 }
1483 }
1484 if (!IsNull(maxYmax) && factorY < 0) {
1485 if (yMin + yRange < maxYmax) {
1486 if (yMin + yRange - deltaY > maxYmax) {
1487 highlight_0 = GetTickCount();
1488 deltaY = yMin + yRange - maxYmax;
1489 }
1490 } else {
1491 factorY = Null;
1492 highlight_0 = GetTickCount();
1493 }
1494 }
1495 if (factorY != 0 && !IsNull(factorY)) {
1496 yMin -= deltaY;
1497 yMinUnit += deltaY;
1498 AdjustMinUnitY();
1499 if (drawY2Reticle) {
1500 double deltaY2 = factorY*yRange2;
1501 yMin2 -= deltaY2;
1502 yMinUnit2 += deltaY2;
1503 AdjustMinUnitY2();
1504 }
1505 }
1506 }
1507 if (IsNull(factorX) || IsNull(factorY))
1508 Refresh();
1509 else if (factorX != 0 || factorY != 0) {
1510 WhenSetXYMin();
1511 Refresh();
1512 WhenZoomScroll();
1513 }
1514 }
1515
LinkedWith(ScatterDraw & ctrl)1516 ScatterDraw &ScatterDraw::LinkedWith(ScatterDraw &ctrl) {
1517 Unlinked();
1518
1519 if (ctrl.linkedMaster)
1520 linkedMaster = ctrl.linkedMaster;
1521 else
1522 linkedMaster = &ctrl;
1523
1524 linkedMaster->linkedCtrls.FindAdd(this);
1525
1526 return *this;
1527 }
1528
Unlinked()1529 void ScatterDraw::Unlinked() {
1530 if (!linkedMaster) {
1531 for (int i = 0; i < linkedCtrls.GetCount(); ++i)
1532 linkedCtrls[i]->linkedMaster = 0;
1533 linkedCtrls.Clear();
1534 } else {
1535 linkedMaster->linkedCtrls.RemoveKey(this);
1536 linkedMaster = 0;
1537 }
1538 }
1539
SetMouseHandling(bool valx,bool valy)1540 ScatterDraw& ScatterDraw::SetMouseHandling(bool valx, bool valy) {
1541 mouseHandlingX = valx;
1542 mouseHandlingY = valy;
1543 return *this;
1544 }
1545
SetMouseHandlingLinked(bool valx,bool valy)1546 ScatterDraw& ScatterDraw::SetMouseHandlingLinked(bool valx, bool valy) {
1547 if (linkedMaster)
1548 return linkedMaster->SetMouseHandlingLinked(valx, valy);
1549
1550 SetMouseHandling(valx, valy);
1551 if (!linkedCtrls.IsEmpty()) {
1552 for (int i = 0; i < linkedCtrls.GetCount(); ++i)
1553 linkedCtrls[i]->SetMouseHandling(valx, valy);
1554 }
1555 return *this;
1556 }
1557
1558
1559 INITBLOCK {
1560 SeriesPlot::Register<LineSeriesPlot>("Line");
1561 SeriesPlot::Register<StaggeredSeriesPlot>("Staggered");
1562 SeriesPlot::Register<BarSeriesPlot>("Bar");
1563
1564 MarkPlot::Register<CircleMarkPlot>("Circle");
1565 MarkPlot::Register<SquareMarkPlot>("Square");
1566 MarkPlot::Register<TriangleMarkPlot>("Triangle");
1567 MarkPlot::Register<CrossMarkPlot>("Cross");
1568 MarkPlot::Register<XMarkPlot>("X");
1569 MarkPlot::Register<RhombMarkPlot>("Rhomb");
1570 MarkPlot::Register<RangePlot>("Range");
1571 MarkPlot::Register<BubblePlot>("Bubble");
1572
1573 DashStyle::Register("LINE_SOLID", LINE_SOLID);
1574 DashStyle::Register("LINE_DOTTED_FINER", LINE_DOTTED_FINER);
1575 DashStyle::Register("LINE_DOTTED_FINE", LINE_DOTTED_FINE);
1576 DashStyle::Register("LINE_DOTTED", LINE_DOTTED);
1577 DashStyle::Register("LINE_DOTTED_SEP", LINE_DOTTED_SEP);
1578 DashStyle::Register("LINE_DASHED", LINE_DASHED);
1579 DashStyle::Register("LINE_DASH_DOT", LINE_DASH_DOT);
1580 DashStyle::Register("- -", LINE_BEGIN_END);
1581 }
1582
1583 }