diff options
| -rw-r--r-- | FL/Fl_Chart.H | 201 | ||||
| -rw-r--r-- | src/Fl_Chart.cxx | 552 |
2 files changed, 428 insertions, 325 deletions
diff --git a/FL/Fl_Chart.H b/FL/Fl_Chart.H index fc9c22f19..0a0f7ffc6 100644 --- a/FL/Fl_Chart.H +++ b/FL/Fl_Chart.H @@ -1,7 +1,7 @@ // -// Forms chart header file for the Fast Light Tool Kit (FLTK). +// Fl_Chart widget header file for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -14,8 +14,9 @@ // https://www.fltk.org/bugs.php // -/* \file - Fl_Chart widget . */ +/** \file FL/Fl_Chart.H + \brief Fl_Chart widget. +*/ #ifndef Fl_Chart_H #define Fl_Chart_H @@ -25,24 +26,24 @@ #endif // values for type() -#define FL_BAR_CHART 0 /**< type() for Bar Chart variant */ -#define FL_HORBAR_CHART 1 /**< type() for Horizontal Bar Chart variant */ -#define FL_LINE_CHART 2 /**< type() for Line Chart variant */ -#define FL_FILL_CHART 3 /**< type() for Fill Line Chart variant */ -#define FL_SPIKE_CHART 4 /**< type() for Spike Chart variant */ -#define FL_PIE_CHART 5 /**< type() for Pie Chart variant */ -#define FL_SPECIALPIE_CHART 6 /**< type() for Special Pie Chart variant */ +#define FL_BAR_CHART 0 ///< type() for Bar Chart variant +#define FL_HORBAR_CHART 1 ///< type() for Horizontal Bar Chart variant +#define FL_LINE_CHART 2 ///< type() for Line Chart variant +#define FL_FILL_CHART 3 ///< type() for Fill Line Chart variant +#define FL_SPIKE_CHART 4 ///< type() for Spike Chart variant +#define FL_PIE_CHART 5 ///< type() for Pie Chart variant +#define FL_SPECIALPIE_CHART 6 ///< type() for Special Pie Chart variant -#define FL_FILLED_CHART FL_FILL_CHART /**< for compatibility */ +#define FL_FILLED_CHART FL_FILL_CHART ///< for compatibility -#define FL_CHART_MAX 128 /**< max entries per chart */ -#define FL_CHART_LABEL_MAX 18 /**< max label length for entry */ +#define FL_CHART_MAX 128 ///< max entries per chart +#define FL_CHART_LABEL_MAX 18 ///< max label length for entry -/** For internal use only */ +/** For internal use only. */ struct FL_CHART_ENTRY { - float val; /**< For internal use only. */ - unsigned col; /**< For internal use only. */ - char str[FL_CHART_LABEL_MAX+1]; /**< For internal use only. */ + float val; ///< For internal use only. + unsigned col; ///< For internal use only. + char str[FL_CHART_LABEL_MAX + 1]; ///< For internal use only. }; /** @@ -52,94 +53,126 @@ struct FL_CHART_ENTRY { \image html charts.png \image latex charts.png "Fl_Chart" width=10cm + \todo Refactor Fl_Chart::type() information. The type of an Fl_Chart object can be set using type(uchar t) to: - \li \c FL_BAR_CHART: Each sample value is drawn as a vertical bar. - \li \c FL_FILLED_CHART: The chart is filled from the bottom of the graph - to the sample values. - \li \c FL_HORBAR_CHART: Each sample value is drawn as a horizontal bar. - \li \c FL_LINE_CHART: The chart is drawn as a polyline with vertices at - each sample value. - \li \c FL_PIE_CHART: A pie chart is drawn with each sample value being - drawn as a proportionate slice in the circle. - \li \c FL_SPECIALPIE_CHART: Like \c FL_PIE_CHART, but the first slice is - separated from the pie. - \li \c FL_SPIKE_CHART: Each sample value is drawn as a vertical line. - */ + + | Chart Type | Description | + |---------------------|-------------------------------------------------------------------------------------------------| + | FL_BAR_CHART | Each sample value is drawn as a vertical bar. | + | FL_FILLED_CHART | The chart is filled from the bottom of the graph to the sample values. | + | FL_HORBAR_CHART | Each sample value is drawn as a horizontal bar. | + | FL_LINE_CHART | The chart is drawn as a polyline with vertices at each sample value. | + | FL_PIE_CHART | A pie chart is drawn with each sample value being drawn as a proportionate slice in the circle. | + | FL_SPECIALPIE_CHART | Like \c FL_PIE_CHART, but the first slice is separated from the pie. | + | FL_SPIKE_CHART | Each sample value is drawn as a vertical line. | +*/ class FL_EXPORT Fl_Chart : public Fl_Widget { - int numb; - int maxnumb; - int sizenumb; - FL_CHART_ENTRY *entries; - double min,max; - uchar autosize_; - Fl_Font textfont_; - Fl_Fontsize textsize_; - Fl_Color textcolor_; + int numb; + int maxnumb; + int sizenumb; + FL_CHART_ENTRY *entries; + double min, max; + uchar autosize_; + Fl_Font textfont_; + Fl_Fontsize textsize_; + Fl_Color textcolor_; + protected: - void draw() FL_OVERRIDE; + void draw() FL_OVERRIDE; + + // (static) protected draw methods (STR 2022) + // these methods are documented in src/Fl_Chart.cxx + + static void draw_barchart(int x, int y, int w, int h, int numb, FL_CHART_ENTRY entries[], + double min, double max, int autosize, int maxnumb, Fl_Color textcolor); + + static void draw_horbarchart(int x, int y, int w, int h, int numb, FL_CHART_ENTRY entries[], + double min, double max, int autosize, int maxnumb, + Fl_Color textcolor); + + static void draw_linechart(int type, int x, int y, int w, int h, int numb, + FL_CHART_ENTRY entries[], double min, double max, int autosize, + int maxnumb, Fl_Color textcolor); + + static void draw_piechart(int x, int y, int w, int h, int numb, FL_CHART_ENTRY entries[], + int special, Fl_Color textcolor); + public: - Fl_Chart(int X, int Y, int W, int H, const char *L = 0); + Fl_Chart(int X, int Y, int W, int H, const char *L = 0); + + ~Fl_Chart(); + + void clear(); + + void add(double val, const char *str = 0, unsigned col = 0); + + void insert(int ind, double val, const char *str = 0, unsigned col = 0); + + void replace(int ind, double val, const char *str = 0, unsigned col = 0); - ~Fl_Chart(); + /** + Gets the lower and upper bounds of the chart values. + \param[out] a, b are set to lower, upper + */ + void bounds(double *a, double *b) const { + *a = min; + *b = max; + } - void clear(); + void bounds(double a, double b); - void add(double val, const char *str = 0, unsigned col = 0); + /** + Returns the number of data values in the chart. + */ + int size() const { return numb; } - void insert(int ind, double val, const char *str = 0, unsigned col = 0); + /** + Sets the widget size (width, height). - void replace(int ind, double val, const char *str = 0, unsigned col = 0); + This is the same as calling Fl_Widget::size(int W, int H); - /** - Gets the lower and upper bounds of the chart values. - \param[out] a, b are set to lower, upper - */ - void bounds(double *a,double *b) const {*a = min; *b = max;} + \param[in] W,H new width and height of the widget + */ + void size(int W, int H) { Fl_Widget::size(W, H); } - void bounds(double a,double b); + /** + Gets the maximum number of data values for a chart. + */ + int maxsize() const { return maxnumb; } - /** - Returns the number of data values in the chart. - */ - int size() const {return numb;} + void maxsize(int m); - void size(int W, int H) { Fl_Widget::size(W, H); } + /** Gets the chart's text font */ + Fl_Font textfont() const { return textfont_; } - /** - Gets the maximum number of data values for a chart. - */ - int maxsize() const {return maxnumb;} + /** Sets the chart's text font to \p s. */ + void textfont(Fl_Font s) { textfont_ = s; } - void maxsize(int m); + /** Gets the chart's text size */ + Fl_Fontsize textsize() const { return textsize_; } - /** Gets the chart's text font */ - Fl_Font textfont() const {return textfont_;} - /** Sets the chart's text font to \p s. */ - void textfont(Fl_Font s) {textfont_ = s;} + /** Sets the chart's text size to \p s. */ + void textsize(Fl_Fontsize s) { textsize_ = s; } - /** Gets the chart's text size */ - Fl_Fontsize textsize() const {return textsize_;} - /** gets the chart's text size to \p s. */ - void textsize(Fl_Fontsize s) {textsize_ = s;} + /** Gets the chart's text color */ + Fl_Color textcolor() const { return textcolor_; } - /** Gets the chart's text color */ - Fl_Color textcolor() const {return textcolor_;} - /** gets the chart's text color to \p n. */ - void textcolor(Fl_Color n) {textcolor_ = n;} + /** Sets the chart's text color to \p n. */ + void textcolor(Fl_Color n) { textcolor_ = n; } - /** - Get whether the chart will automatically adjust the bounds of the chart. - \returns non-zero if auto-sizing is enabled and zero if disabled. - */ - uchar autosize() const {return autosize_;} + /** + Gets whether the chart will automatically adjust the bounds of the chart. + \returns non-zero if auto-sizing is enabled and zero if disabled. + */ + uchar autosize() const { return autosize_; } - /** - Set whether the chart will automatically adjust the bounds of the chart. - \param[in] n non-zero to enable automatic resizing, zero to disable. - */ - void autosize(uchar n) {autosize_ = n;} + /** + Sets whether the chart will automatically adjust the bounds of the chart. + \param[in] n non-zero to enable automatic resizing, zero to disable. + */ + void autosize(uchar n) { autosize_ = n; } }; #endif diff --git a/src/Fl_Chart.cxx b/src/Fl_Chart.cxx index e7a30fc92..0b68a6582 100644 --- a/src/Fl_Chart.cxx +++ b/src/Fl_Chart.cxx @@ -1,7 +1,7 @@ // -// Forms-compatible chart widget for the Fast Light Tool Kit (FLTK). +// Chart widget for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -21,290 +21,347 @@ #include "flstring.h" #include <stdlib.h> -#define ARCINC (2.0*M_PI/360.0) - // this function is in fl_boxtype.cxx: -void fl_rectbound(int x,int y,int w,int h, Fl_Color color); +void fl_rectbound(int x, int y, int w, int h, Fl_Color color); + -/* Widget specific information */ +static const double ARCINC = (2.0 * M_PI / 360.0); -static void draw_barchart(int x,int y,int w,int h, - int numb, FL_CHART_ENTRY entries[], - double min, double max, int autosize, int maxnumb, - Fl_Color textcolor) -/* Draws a bar chart. x,y,w,h is the bounding box, entries the array of - numb entries and min and max the boundaries. */ + +/** + Draws a bar chart. + + \p x, \p y, \p w, \p h is the bounding box, + \p entries the array of \p numb entries, + and \p min and \p max the boundaries. + + \param[in] x, y, w, h Widget position and size + \param[in] numb Number of values + \param[in] entries Array of values + \param[in] min Lower boundary + \param[in] max Upper boundary + \param[in] autosize Whether the chart autosizes + \param[in] maxnumb Maximal number of entries + \param[in] textcolor Text color +*/ +void Fl_Chart::draw_barchart(int x, int y, int w, int h, int numb, FL_CHART_ENTRY entries[], + double min, double max, int autosize, int maxnumb, Fl_Color textcolor) { double incr; int zeroh; double lh = fl_height(); - if (max == min) incr = h; - else incr = h/(max-min); - if ( (-min*incr) < lh) { - incr = (h - lh + min*incr)/(max-min); - zeroh = int(y+h-lh); + if (max == min) + incr = h; + else + incr = h / (max - min); + if ((-min * incr) < lh) { + incr = (h - lh + min * incr) / (max - min); + zeroh = int(y + h - lh); } else { - zeroh = (int)rint(y+h+min * incr); + zeroh = (int)rint(y + h + min * incr); } - int bwidth = (int)rint(w/double(autosize?numb:maxnumb)); - /* Draw base line */ + int bwidth = (int)rint(w / double(autosize ? numb : maxnumb)); + // Draw base line fl_color(textcolor); - fl_line(x, zeroh, x+w, zeroh); - if (min == 0.0 && max == 0.0) return; /* Nothing else to draw */ + fl_line(x, zeroh, x + w, zeroh); + if (min == 0.0 && max == 0.0) + return; // Nothing else to draw int i; - /* Draw the bars */ - for (i=0; i<numb; i++) { - int hh = (int)rint(entries[i].val*incr); - if (hh < 0) - fl_rectbound(x+i*bwidth,zeroh,bwidth+1,-hh+1, (Fl_Color)entries[i].col); - else if (hh > 0) - fl_rectbound(x+i*bwidth,zeroh-hh,bwidth+1,hh+1,(Fl_Color)entries[i].col); + // Draw the bars + for (i = 0; i < numb; i++) { + int hh = (int)rint(entries[i].val * incr); + if (hh < 0) + fl_rectbound(x + i * bwidth, zeroh, bwidth + 1, -hh + 1, (Fl_Color)entries[i].col); + else if (hh > 0) + fl_rectbound(x + i * bwidth, zeroh - hh, bwidth + 1, hh + 1, (Fl_Color)entries[i].col); } - /* Draw the labels */ + // Draw the labels fl_color(textcolor); - for (i=0; i<numb; i++) - fl_draw(entries[i].str, - x+i*bwidth+bwidth/2,zeroh,0,0, - FL_ALIGN_TOP); + for (i = 0; i < numb; i++) + fl_draw(entries[i].str, x + i * bwidth + bwidth / 2, zeroh, 0, 0, FL_ALIGN_TOP); } -static void draw_horbarchart(int x,int y,int w,int h, - int numb, FL_CHART_ENTRY entries[], - double min, double max, int autosize, int maxnumb, - Fl_Color textcolor) -/* Draws a horizontal bar chart. x,y,w,h is the bounding box, entries the - array of numb entries and min and max the boundaries. */ + +/** + Draws a horizontal bar chart. + + \p x, \p y, \p w, \p h is the bounding box, + \p entries the array of \p numb entries, + and \p min and \p max the boundaries. + + \param[in] x, y, w, h Widget position and size + \param[in] numb Number of values + \param[in] entries Array of values + \param[in] min Lower boundary + \param[in] max Upper boundary + \param[in] autosize Whether the chart autosizes + \param[in] maxnumb Maximal number of entries + \param[in] textcolor Text color +*/ +void Fl_Chart::draw_horbarchart(int x, int y, int w, int h, int numb, FL_CHART_ENTRY entries[], + double min, double max, int autosize, int maxnumb, + Fl_Color textcolor) { int i; - double lw = 0.0; /* Maximal label width */ - /* Compute maximal label width */ - for (i=0; i<numb; i++) { - double w1 = fl_width(entries[i].str); - if (w1 > lw) lw = w1; + double lw = 0.0; // Maximal label width + // Compute maximal label width + for (i = 0; i < numb; i++) { + double w1 = fl_width(entries[i].str); + if (w1 > lw) + lw = w1; } - if (lw > 0.0) lw += 4.0; + if (lw > 0.0) + lw += 4.0; double incr; int zeroh; - if (max == min) incr = w; - else incr = w/(max-min); - if ( (-min*incr) < lw) { - incr = (w - lw + min*incr)/(max-min); - zeroh = x+(int)rint(lw); + if (max == min) + incr = w; + else + incr = w / (max - min); + if ((-min * incr) < lw) { + incr = (w - lw + min * incr) / (max - min); + zeroh = x + (int)rint(lw); } else { - zeroh = (int)rint(x-min * incr); + zeroh = (int)rint(x - min * incr); } - int bwidth = (int)rint(h/double(autosize?numb:maxnumb)); - /* Draw base line */ + int bwidth = (int)rint(h / double(autosize ? numb : maxnumb)); + // Draw base line fl_color(textcolor); - fl_line(zeroh, y, zeroh, y+h); - if (min == 0.0 && max == 0.0) return; /* Nothing else to draw */ - /* Draw the bars */ - for (i=0; i<numb; i++) { - int ww = (int)rint(entries[i].val*incr); - if (ww > 0) - fl_rectbound(zeroh,y+i*bwidth,ww+1,bwidth+1, (Fl_Color)entries[i].col); - else if (ww < 0) - fl_rectbound(zeroh+ww,y+i*bwidth,-ww+1,bwidth+1,(Fl_Color)entries[i].col); + fl_line(zeroh, y, zeroh, y + h); + if (min == 0.0 && max == 0.0) + return; // Nothing else to draw + // Draw the bars + for (i = 0; i < numb; i++) { + int ww = (int)rint(entries[i].val * incr); + if (ww > 0) + fl_rectbound(zeroh, y + i * bwidth, ww + 1, bwidth + 1, (Fl_Color)entries[i].col); + else if (ww < 0) + fl_rectbound(zeroh + ww, y + i * bwidth, -ww + 1, bwidth + 1, (Fl_Color)entries[i].col); } - /* Draw the labels */ + // Draw the labels fl_color(textcolor); - for (i=0; i<numb; i++) - fl_draw(entries[i].str, - zeroh-2,y+i*bwidth+bwidth/2,0,0, - FL_ALIGN_RIGHT); + for (i = 0; i < numb; i++) + fl_draw(entries[i].str, zeroh - 2, y + i * bwidth + bwidth / 2, 0, 0, FL_ALIGN_RIGHT); } -static void draw_linechart(int type, int x,int y,int w,int h, - int numb, FL_CHART_ENTRY entries[], - double min, double max, int autosize, int maxnumb, - Fl_Color textcolor) -/* Draws a line chart. x,y,w,h is the bounding box, entries the array of - numb entries and min and max the boundaries. */ + +/** + Draws a line chart. + + \p x, \p y, \p w, \p h is the bounding box, + \p entries the array of \p numb entries, + and \p min and \p max the boundaries. + + \param[in] x, y, w, h Widget position and size + \param[in] numb Number of values + \param[in] entries Array of values + \param[in] min Lower boundary + \param[in] max Upper boundary + \param[in] autosize Whether the chart autosizes + \param[in] maxnumb Maximal number of entries + \param[in] textcolor Text color +*/ +void Fl_Chart::draw_linechart(int type, int x, int y, int w, int h, int numb, + FL_CHART_ENTRY entries[], double min, double max, int autosize, + int maxnumb, Fl_Color textcolor) { int i; double lh = fl_height(); double incr; - if (max == min) incr = h-2.0*lh; - else incr = (h-2.0*lh)/ (max-min); - int zeroh = (int)rint(y+h-lh+min * incr); - double bwidth = w/double(autosize?numb:maxnumb); - /* Draw the values */ - for (i=0; i<numb; i++) { - int x0 = x + (int)rint((i-.5)*bwidth); - int x1 = x + (int)rint((i+.5)*bwidth); - int yy0 = i ? zeroh - (int)rint(entries[i-1].val*incr) : 0; - int yy1 = zeroh - (int)rint(entries[i].val*incr); - if (type == FL_SPIKE_CHART) { - fl_color((Fl_Color)entries[i].col); - fl_line(x1, zeroh, x1, yy1); - } else if (type == FL_LINE_CHART && i != 0) { - fl_color((Fl_Color)entries[i-1].col); - fl_line(x0,yy0,x1,yy1); - } else if (type == FL_FILLED_CHART && i != 0) { - fl_color((Fl_Color)entries[i-1].col); - if ((entries[i-1].val>0.0)!=(entries[i].val>0.0)) { - double ttt = entries[i-1].val/(entries[i-1].val-entries[i].val); - int xt = x + (int)rint((i-.5+ttt)*bwidth); - fl_polygon(x0,zeroh, x0,yy0, xt,zeroh); - fl_polygon(xt,zeroh, x1,yy1, x1,zeroh); - } else { - fl_polygon(x0,zeroh, x0,yy0, x1,yy1, x1,zeroh); - } - fl_color(textcolor); - fl_line(x0,yy0,x1,yy1); + if (max == min) + incr = h - 2.0 * lh; + else + incr = (h - 2.0 * lh) / (max - min); + int zeroh = (int)rint(y + h - lh + min * incr); + double bwidth = w / double(autosize ? numb : maxnumb); + // Draw the values + for (i = 0; i < numb; i++) { + int x0 = x + (int)rint((i - .5) * bwidth); + int x1 = x + (int)rint((i + .5) * bwidth); + int yy0 = i ? zeroh - (int)rint(entries[i - 1].val * incr) : 0; + int yy1 = zeroh - (int)rint(entries[i].val * incr); + if (type == FL_SPIKE_CHART) { + fl_color((Fl_Color)entries[i].col); + fl_line(x1, zeroh, x1, yy1); + } else if (type == FL_LINE_CHART && i != 0) { + fl_color((Fl_Color)entries[i - 1].col); + fl_line(x0, yy0, x1, yy1); + } else if (type == FL_FILLED_CHART && i != 0) { + fl_color((Fl_Color)entries[i - 1].col); + if ((entries[i - 1].val > 0.0) != (entries[i].val > 0.0)) { + double ttt = entries[i - 1].val / (entries[i - 1].val - entries[i].val); + int xt = x + (int)rint((i - .5 + ttt) * bwidth); + fl_polygon(x0, zeroh, x0, yy0, xt, zeroh); + fl_polygon(xt, zeroh, x1, yy1, x1, zeroh); + } else { + fl_polygon(x0, zeroh, x0, yy0, x1, yy1, x1, zeroh); } + fl_color(textcolor); + fl_line(x0, yy0, x1, yy1); + } } - /* Draw base line */ + // Draw base line fl_color(textcolor); - fl_line(x,zeroh,x+w,zeroh); - /* Draw the labels */ - for (i=0; i<numb; i++) - fl_draw(entries[i].str, - x+(int)rint((i+.5)*bwidth), zeroh - (int)rint(entries[i].val*incr),0,0, - entries[i].val>=0 ? FL_ALIGN_BOTTOM : FL_ALIGN_TOP); + fl_line(x, zeroh, x + w, zeroh); + // Draw the labels + for (i = 0; i < numb; i++) + fl_draw(entries[i].str, x + (int)rint((i + .5) * bwidth), + zeroh - (int)rint(entries[i].val * incr), 0, 0, + entries[i].val >= 0 ? FL_ALIGN_BOTTOM : FL_ALIGN_TOP); } -static void draw_piechart(int x,int y,int w,int h, - int numb, FL_CHART_ENTRY entries[], int special, - Fl_Color textcolor) -/* Draws a pie chart. x,y,w,h is the bounding box, entries the array of - numb entries */ -{ + +/** + Draws a pie chart. + + \param[in] x,y,w,h bounding box + \param[in] numb number of chart entries + \param[in] entries array of chart entries + \param[in] special special (?) + \param[in] textcolor text color +*/ +void Fl_Chart::draw_piechart(int x, int y, int w, int h, int numb, FL_CHART_ENTRY entries[], + int special, Fl_Color textcolor) { int i; - double xc,yc,rad; /* center and radius */ - double tot; /* sum of values */ - double incr; /* increment in angle */ - double curang; /* current angle we are drawing */ - double txc,tyc; /* temporary center */ + double xc, yc, rad; // center and radius + double tot; // sum of values + double incr; // increment in angle + double curang; // current angle we are drawing + double txc, tyc; // temporary center double lh = fl_height(); - /* compute center and radius */ + + // compute center and radius double h_denom = (special ? 2.3 : 2.0); - rad = (h - 2*lh)/h_denom/1.1; - xc = x+w/2.0; yc = y+h-1.1*rad-lh; - /* compute sum of values */ + rad = (h - 2 * lh) / h_denom / 1.1; + xc = x + w / 2.0; + yc = y + h - 1.1 * rad - lh; + + // compute sum of values tot = 0.0; - for (i=0; i<numb; i++) - if (entries[i].val > 0.0) tot += entries[i].val; - if (tot == 0.0) return; - incr = 360.0/tot; - /* Draw the pie */ - curang = 0.0; - for (i=0; i<numb; i++) + for (i = 0; i < numb; i++) { if (entries[i].val > 0.0) - { - txc = xc; tyc = yc; - /* Correct for special pies */ - if (special && i==0) - { - txc += 0.3*rad*cos(ARCINC*(curang+0.5*incr*entries[i].val)); - tyc -= 0.3*rad*sin(ARCINC*(curang+0.5*incr*entries[i].val)); + tot += entries[i].val; + } + if (tot == 0.0) + return; + incr = 360.0 / tot; + // Draw the pie + curang = 0.0; + for (i = 0; i < numb; i++) { + if (entries[i].val > 0.0) { + txc = xc; + tyc = yc; + // Correct for special pies + if (special && i == 0) { + txc += 0.3 * rad * cos(ARCINC * (curang + 0.5 * incr * entries[i].val)); + tyc -= 0.3 * rad * sin(ARCINC * (curang + 0.5 * incr * entries[i].val)); } fl_color((Fl_Color)entries[i].col); - fl_begin_polygon(); fl_vertex(txc,tyc); - fl_arc(txc,tyc,rad,curang, curang+incr*entries[i].val); + fl_begin_polygon(); + fl_vertex(txc, tyc); + fl_arc(txc, tyc, rad, curang, curang + incr * entries[i].val); fl_end_polygon(); fl_color(textcolor); - fl_begin_loop(); fl_vertex(txc,tyc); - fl_arc(txc,tyc,rad,curang, curang+incr*entries[i].val); + fl_begin_loop(); + fl_vertex(txc, tyc); + fl_arc(txc, tyc, rad, curang, curang + incr * entries[i].val); fl_end_loop(); curang += 0.5 * incr * entries[i].val; - /* draw the label */ - double xl = txc + 1.1*rad*cos(ARCINC*curang); - fl_draw(entries[i].str, - (int)rint(xl), - (int)rint(tyc - 1.1*rad*sin(ARCINC*curang)), - 0, 0, - xl<txc ? FL_ALIGN_RIGHT : FL_ALIGN_LEFT); + // draw the label + double xl = txc + 1.1 * rad * cos(ARCINC * curang); + fl_draw(entries[i].str, (int)rint(xl), (int)rint(tyc - 1.1 * rad * sin(ARCINC * curang)), 0, + 0, xl < txc ? FL_ALIGN_RIGHT : FL_ALIGN_LEFT); curang += 0.5 * incr * entries[i].val; } + } } +/** + Draws the Fl_Chart widget. +*/ void Fl_Chart::draw() { - draw_box(); - Fl_Boxtype b = box(); - int xx = x()+Fl::box_dx(b); // was 9 instead of dx... - int yy = y()+Fl::box_dy(b); - int ww = w()-Fl::box_dw(b); - int hh = h()-Fl::box_dh(b); - fl_push_clip(xx, yy, ww, hh); - - ww--; hh--; // adjust for line thickness - - if (min >= max) { - min = max = 0.0; - for (int i=0; i<numb; i++) { - if (entries[i].val < min) min = entries[i].val; - if (entries[i].val > max) max = entries[i].val; - } + draw_box(); + Fl_Boxtype b = box(); + int xx = x() + Fl::box_dx(b); // was 9 instead of dx... + int yy = y() + Fl::box_dy(b); + int ww = w() - Fl::box_dw(b); + int hh = h() - Fl::box_dh(b); + fl_push_clip(xx, yy, ww, hh); + + ww--; + hh--; // adjust for line thickness + + if (min >= max) { + min = max = 0.0; + for (int i = 0; i < numb; i++) { + if (entries[i].val < min) + min = entries[i].val; + if (entries[i].val > max) + max = entries[i].val; } + } - fl_font(textfont(),textsize()); + fl_font(textfont(), textsize()); - switch (type()) { + switch (type()) { case FL_BAR_CHART: - ww++; // makes the bars fill box correctly - draw_barchart(xx,yy,ww,hh, numb, entries, min, max, - autosize(), maxnumb, textcolor()); - break; + ww++; // makes the bars fill box correctly + draw_barchart(xx, yy, ww, hh, numb, entries, min, max, autosize(), maxnumb, textcolor()); + break; case FL_HORBAR_CHART: - hh++; // makes the bars fill box correctly - draw_horbarchart(xx,yy,ww,hh, numb, entries, min, max, - autosize(), maxnumb, textcolor()); - break; + hh++; // makes the bars fill box correctly + draw_horbarchart(xx, yy, ww, hh, numb, entries, min, max, autosize(), maxnumb, textcolor()); + break; case FL_PIE_CHART: - draw_piechart(xx,yy,ww,hh,numb,entries,0, textcolor()); - break; + draw_piechart(xx, yy, ww, hh, numb, entries, 0, textcolor()); + break; case FL_SPECIALPIE_CHART: - draw_piechart(xx,yy,ww,hh,numb,entries,1,textcolor()); - break; + draw_piechart(xx, yy, ww, hh, numb, entries, 1, textcolor()); + break; default: - draw_linechart(type(),xx,yy,ww,hh, numb, entries, min, max, - autosize(), maxnumb, textcolor()); - break; - } - draw_label(); - fl_pop_clip(); + draw_linechart(type(), xx, yy, ww, hh, numb, entries, min, max, autosize(), maxnumb, + textcolor()); + break; + } + draw_label(); + fl_pop_clip(); } -/*------------------------------*/ - -#define FL_CHART_BOXTYPE FL_BORDER_BOX -#define FL_CHART_COL1 FL_COL1 -#define FL_CHART_LCOL FL_LCOL -#define FL_CHART_ALIGN FL_ALIGN_BOTTOM /** Create a new Fl_Chart widget using the given position, size and label string. + The default boxstyle is \c FL_NO_BOX. + \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label - */ -Fl_Chart::Fl_Chart(int X, int Y, int W, int H,const char *L) : -Fl_Widget(X,Y,W,H,L) { +*/ +Fl_Chart::Fl_Chart(int X, int Y, int W, int H, const char *L) + : Fl_Widget(X, Y, W, H, L) { box(FL_BORDER_BOX); align(FL_ALIGN_BOTTOM); - numb = 0; - maxnumb = 0; - sizenumb = FL_CHART_MAX; - autosize_ = 1; - min = max = 0; - textfont_ = FL_HELVETICA; - textsize_ = 10; + numb = 0; + maxnumb = 0; + sizenumb = FL_CHART_MAX; + autosize_ = 1; + min = max = 0; + textfont_ = FL_HELVETICA; + textsize_ = 10; textcolor_ = FL_FOREGROUND_COLOR; - entries = (FL_CHART_ENTRY *)calloc(sizeof(FL_CHART_ENTRY), FL_CHART_MAX + 1); + entries = (FL_CHART_ENTRY *)calloc(sizeof(FL_CHART_ENTRY), FL_CHART_MAX + 1); } /** Destroys the Fl_Chart widget and all of its data. - */ +*/ Fl_Chart::~Fl_Chart() { free(entries); } /** Removes all values from the chart. - */ +*/ void Fl_Chart::clear() { numb = 0; min = max = 0; @@ -312,14 +369,15 @@ void Fl_Chart::clear() { } /** - Add the data value \p val with optional label \p str and color \p col + Adds the data value \p val with optional label \p str and color \p col to the chart. + \param[in] val data value \param[in] str optional data label \param[in] col optional data color - */ +*/ void Fl_Chart::add(double val, const char *str, unsigned col) { - /* Allocate more entries if required */ + // Allocate more entries if required if (numb >= sizenumb) { sizenumb += FL_CHART_MAX; entries = (FL_CHART_ENTRY *)realloc(entries, sizeof(FL_CHART_ENTRY) * (sizenumb + 1)); @@ -327,73 +385,82 @@ void Fl_Chart::add(double val, const char *str, unsigned col) { // Shift entries as needed if (numb >= maxnumb && maxnumb > 0) { memmove(entries, entries + 1, sizeof(FL_CHART_ENTRY) * (numb - 1)); - numb --; + numb--; } entries[numb].val = float(val); entries[numb].col = col; - if (str) { - strlcpy(entries[numb].str,str,FL_CHART_LABEL_MAX + 1); - } else { - entries[numb].str[0] = 0; - } + if (str) { + strlcpy(entries[numb].str, str, FL_CHART_LABEL_MAX + 1); + } else { + entries[numb].str[0] = 0; + } numb++; redraw(); } /** Inserts a data value \p val at the given position \p ind. + Position 1 is the first data value. + \param[in] ind insertion position \param[in] val data value \param[in] str optional data label \param[in] col optional data color - */ +*/ void Fl_Chart::insert(int ind, double val, const char *str, unsigned col) { int i; - if (ind < 1 || ind > numb+1) return; - /* Allocate more entries if required */ + if (ind < 1 || ind > numb + 1) + return; + // Allocate more entries if required if (numb >= sizenumb) { sizenumb += FL_CHART_MAX; entries = (FL_CHART_ENTRY *)realloc(entries, sizeof(FL_CHART_ENTRY) * (sizenumb + 1)); } // Shift entries as needed - for (i=numb; i >= ind; i--) entries[i] = entries[i-1]; - if (numb < maxnumb || maxnumb == 0) numb++; - /* Fill in the new entry */ - entries[ind-1].val = float(val); - entries[ind-1].col = col; + for (i = numb; i >= ind; i--) + entries[i] = entries[i - 1]; + if (numb < maxnumb || maxnumb == 0) + numb++; + // Fill in the new entry + entries[ind - 1].val = float(val); + entries[ind - 1].col = col; if (str) { - strlcpy(entries[ind-1].str,str,FL_CHART_LABEL_MAX+1); + strlcpy(entries[ind - 1].str, str, FL_CHART_LABEL_MAX + 1); } else { - entries[ind-1].str[0] = 0; + entries[ind - 1].str[0] = 0; } redraw(); } /** - Replace a data value \p val at the given position \p ind. + Replaces a data value \p val at the given position \p ind. + Position 1 is the first data value. + \param[in] ind insertion position \param[in] val data value \param[in] str optional data label \param[in] col optional data color - */ -void Fl_Chart::replace(int ind,double val, const char *str, unsigned col) { - if (ind < 1 || ind > numb) return; - entries[ind-1].val = float(val); - entries[ind-1].col = col; +*/ +void Fl_Chart::replace(int ind, double val, const char *str, unsigned col) { + if (ind < 1 || ind > numb) + return; + entries[ind - 1].val = float(val); + entries[ind - 1].col = col; if (str) { - strlcpy(entries[ind-1].str,str,FL_CHART_LABEL_MAX+1); + strlcpy(entries[ind - 1].str, str, FL_CHART_LABEL_MAX + 1); } else { - entries[ind-1].str[0] = 0; + entries[ind - 1].str[0] = 0; } redraw(); } /** Sets the lower and upper bounds of the chart values. + \param[in] a, b are used to set lower, upper - */ +*/ void Fl_Chart::bounds(double a, double b) { this->min = a; this->max = b; @@ -401,21 +468,24 @@ void Fl_Chart::bounds(double a, double b) { } /** - Set the maximum number of data values for a chart. + Sets the maximum number of data values for a chart. + If you do not call this method then the chart will be allowed to grow to any size depending on available memory. + \param[in] m maximum number of data values allowed. - */ +*/ void Fl_Chart::maxsize(int m) { int i; - /* Fill in the new number */ - if (m < 0) return; + // Fill in the new number + if (m < 0) + return; maxnumb = m; - /* Shift entries if required */ + // Shift entries if required if (numb > maxnumb) { - for (i = 0; i<maxnumb; i++) - entries[i] = entries[i+numb-maxnumb]; - numb = maxnumb; - redraw(); + for (i = 0; i < maxnumb; i++) + entries[i] = entries[i + numb - maxnumb]; + numb = maxnumb; + redraw(); } } |
