| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- /*
- * Copyright (C) 2013 by Domingo Alvarez Duarte <[email protected]>
- *
- * Licensed under GPLv3, see http://www.gnu.org/licenses/gpl.html.
- */
-
- class Fl_Bar_Chart extends Fl_Box {
- _bars = null; //{label, value, color}
- _bar_depth = null;
- _bar_update_count = null;
- _bar_num_format_decimals = null;
- _bar_color = null;
-
- constructor(X, Y, W, H, L = null) {
- base.constructor(X,Y,W,H,L);
- color(FL_WHITE);
- align(FL_ALIGN_RIGHT);
- labeltype(FL_NO_LABEL);
- _bars = [];
- _bar_color = FL_BLUE;
- _bar_depth = 8;
- _bar_update_count = 0;
- _bar_num_format_decimals = 0;
- }
- function bar_count(){return _bars.size();}
- function bar_add(bheader, bvalue, bcolor=FL_BLUE) {
- _bars.push( [bheader, bvalue, bcolor]);
- }
- function bar_get(idx) { return _bars[idx];}
- function bar_depth(depth=null){
- if(depth==null) return _depth;
- if(_bar_depth == depth) return;
- _bar_depth = depth;
- update_bar_chart();
- }
- function bar_num_format_decimals(decimals=null) {
- if(decimals==null) return _bar_num_format_decimals;
- if(_bar_num_format_decimals == decimals) return;
- _bar_num_format_decimals = decimals;
- update_bar_chart();
- }
- function bar_begin_update() {return ++_bar_update_count;}
- function bar_end_update() {
- if(_bar_update_count == 0) throw("update count underflow");
- if(--_bar_update_count == 0) update_bar_chart();
- }
- function update_bar_chart() {
- if(_bar_update_count == 0) redraw();
- }
- function bar_clear(){
- _bars.clear();
- update_bar_chart();
- }
- function normalize_scale_units(oldScale) {
- local result = oldScale;
- if(result < 2) result = 2;
- else if(result <= 5) result = 5;
- else if(result <= 10) result = 10;
- else
- {
- local str = result.tostring();
- local t = str[0] - '0';
- do
- {
- result = result / 10;
- t *= 10;
- }
- while(result >= 10);
- return t;
- }
- return result;
- }
- function draw_mypolygon(x1, y1, x2, y2, x3, y3, x4, y4, line_color, fill_color) {
- fl_color(fill_color);
- fl_polygon(x1, y1, x2, y2, x3, y3, x4, y4);
- fl_color(line_color);
- fl_line_style(FL_SOLID, 1, NULL);
- fl_loop(x1, y1, x2, y2, x3, y3, x4, y4);
- }
- function draw_mybar(pbx, pby, pw, ph, pdepth, line_color, fill_color) {
- local lbx2 = pbx+pw;
- local lbx3 = lbx2+pdepth;
- local lby2 = pby+ph;
- local lby3 = pby-pdepth;
- // face rect
- draw_mypolygon(
- pbx, pby,
- lbx2, pby,
- lbx2, lby2,
- pbx, lby2,
- line_color,
- fill_color);
- // top polygon
- draw_mypolygon(
- pbx, pby,
- lbx2, pby,
- lbx3, lby3,
- pbx+pdepth, lby3,
- line_color,
- fill_color);
- // side polygon
- draw_mypolygon(
- lbx2, pby,
- lbx3, lby3,
- lbx3, lby2-pdepth,
- lbx2, lby2,
- line_color,
- fill_color);
- }
- function draw() {
- //set font size, color and clear
- fl_font(labelfont(), labelsize());
- fl_color(color());
- fl_rectf(x(), y(), w(), h());
- local measure = {};
- fl_measure("W", measure, false);
- local char_width = measure.width, char_height = measure.height;
-
- local inner_padding = char_height;
- local box_x = x();
- local box_y = y() + char_height;
- local str;
- local nf_buf;
- local bars_box_x, bars_box_y, bars_box_width, bars_box_height;
- local box_label_width = inner_padding;
- local value_max = 0.0;
- foreach(bar in _bars)
- {
- local max_value_str_width = fl_width(bar[0] /*label*/, bar[0].size());
- if(max_value_str_width > box_label_width) box_label_width = max_value_str_width;
- if(bar[1] /*value*/ > value_max) value_max = bar[1];
- }
- box_label_width += inner_padding *2;
- bars_box_x = box_x + box_label_width;
- bars_box_y = box_y + inner_padding;
- bars_box_height = h() - inner_padding - 3 * char_height;
- bars_box_width = w() - box_label_width - 3 * _bar_depth - inner_padding;
- draw_mypolygon(
- bars_box_x, bars_box_y+_bar_depth,
- bars_box_x, bars_box_y+_bar_depth+bars_box_height,
- bars_box_x+_bar_depth, bars_box_y+bars_box_height,
- bars_box_x+_bar_depth, bars_box_y,
- FL_BLACK,
- FL_YELLOW
- );
- draw_mypolygon(
- bars_box_x, bars_box_y+_bar_depth+bars_box_height,
- bars_box_x+bars_box_width+_bar_depth, bars_box_y+_bar_depth+bars_box_height,
- bars_box_x+bars_box_width+_bar_depth*2, bars_box_y+bars_box_height,
- bars_box_x+_bar_depth, bars_box_y+bars_box_height,
- FL_BLACK,
- FL_WHITE
- );
- fl_color(FL_BLACK);
- fl_line_style(FL_SOLID, 1, NULL);
- fl_rect(bars_box_x+_bar_depth, bars_box_y, bars_box_width+_bar_depth, bars_box_height+1);
- fl_line_style(FL_SOLID, 3, NULL);
- fl_line(bars_box_x, bars_box_y+_bar_depth, bars_box_x, bars_box_y+_bar_depth+bars_box_height, bars_box_x+bars_box_width+_bar_depth, bars_box_y+_bar_depth+bars_box_height);
- local my_label = label();
- if(my_label) fl_draw(my_label, my_label.len(), x() + (w() - fl_width(my_label))/2, box_y);
- str = value_max.tostring();
- fl_measure(str, measure, false);
- local max_value_str_width = measure.width, max_value_str_height = measure.height;
- local pixelPerUnit, nScaleLines, scaleUnits, itmp;
- if(value_max == 0) {
- pixelPerUnit = 1;
- nScaleLines = 1;
- }
- else
- {
- itmp = bars_box_width-max_value_str_width-_bar_depth;
- pixelPerUnit = itmp / value_max;
- nScaleLines = math.ceil(itmp / (2*max_value_str_width));
- }
- if(nScaleLines == 0) scaleUnits = value_max +1;
- else
- {
- scaleUnits = math.floor(value_max / nScaleLines) +1;
- }
- scaleUnits = normalize_scale_units(scaleUnits);
- if(scaleUnits == 0) nScaleLines = 1;
- else nScaleLines = (value_max / scaleUnits)+1;
- fl_color(FL_DARK3);
- fl_line_style(FL_DASH, 1, "\0x05\0x05");
- local half_max_value_str_width = math.floor(max_value_str_width / 2);
- local bars_box_bottom = bars_box_y+_bar_depth+bars_box_height+2;
- local str_zero = "0";
- local function draw_scaleLine(dk,s) {
- local lx, ly, lx2, ly2;
- lx = bars_box_x + dk + _bar_depth;
- ly = bars_box_y + bars_box_height;
- lx2 = bars_box_x + dk;
- ly2 = bars_box_y + _bar_depth+bars_box_height;
- fl_line(lx, bars_box_y, lx, ly, lx2, ly2);
- fl_line(lx2, ly2, lx2, ly2 + 2);
- local oldcolor = fl_color();
- fl_color(FL_BLACK);
- fl_draw(s, s.len(), bars_box_x + dk - half_max_value_str_width, bars_box_bottom+char_height);
- fl_color(oldcolor);
- }
- if(value_max == 0)
- {
- local ik = math.floor(bars_box_width / 2);
- draw_scaleLine(ik,str_zero);
- }
- else
- {
- fl_color(FL_BLACK);
- fl_draw(str_zero, str_zero.len(), bars_box_x, bars_box_bottom+char_height);
- fl_color(FL_DARK3);
- }
- local _num_buf;
- for(local ik=0; ik < nScaleLines; ik++)
- {
- local xs = math.floor(scaleUnits*pixelPerUnit*ik);
- _num_buf = math.number_format(ik*scaleUnits, _bar_num_format_decimals);
- draw_scaleLine(xs, _num_buf);
- }
- local bar_height, bar_y;
- if(_bars.size() == 0) bar_height = 0;
- else bar_height = ((bars_box_height- _bar_depth) / ((2.0*_bars.size()+1)));
- bars_box_bottom -= 2*bar_height + _bar_depth;
- local ikl = 0;
- foreach(bar in _bars) {
- bar_y = bars_box_bottom - (2*ikl*bar_height) ;
- local value = bar[1]; //bar value
- local bar_width = math.floor(value*pixelPerUnit);
- draw_mybar(bars_box_x, bar_y, bar_width, bar_height, _bar_depth, FL_DARK3, bar[2] /*color*/);
- _num_buf = math.number_format(value, _bar_num_format_decimals);
- local rcenter = math.floor(bar_y+(bar_height-_bar_depth) / 2);
- fl_color(FL_DARK3);
- fl_line(bars_box_x+bar_width+_bar_depth/2,rcenter, bars_box_x+bar_width+_bar_depth*2, rcenter);
- fl_measure(_num_buf, measure, false);
- local str_width = measure.width, str_height = measure.height;
- local rc_x = bars_box_x+bar_width+_bar_depth*2;
- local rc_w = str_width+_bar_depth;
- local rc_y = rcenter - str_height/2;
- local rc_h = str_height * 1.1;
- fl_color(FL_YELLOW);
- fl_line_style(FL_SOLID, 2);
- fl_rectf(rc_x, rc_y, rc_w, rc_h);
- fl_color(FL_BLACK);
- fl_draw(_num_buf, _num_buf.len(), rc_x+_bar_depth/2, rcenter + str_height/3);
- str = bar[0]; //bar header
- fl_measure(str, measure, false);
- str_width = measure.width;
- str_height = measure.height;
- local str_x, str_y;
- fl_color(FL_BLACK);
- switch(align()){
- case FL_ALIGN_CENTER:
- {
- str_x = box_x+(box_label_width/2) - (str_width / 2);
- str_y = rcenter + str_height/3;
- }
- break;
- case FL_ALIGN_RIGHT:
- {
- str_x = bars_box_x-str_width-inner_padding;
- str_y = rcenter + str_height/3;
- }
- break;
- default:
- {
- str_x = box_x + inner_padding;
- str_y = rcenter + str_height/3;
- }
- }
- fl_draw(str, str.len(), str_x, str_y);
- ++ikl;
- }
- fl_line_style(0);
- }
- };
- /*
- math.number_format_set_thousand_sep(".");
- math.number_format_set_dec_point(",");
- math.mynumber_format <- function (value, decp=2){
- value = value.tofloat();
- local fvalue, neg, intp;
- fvalue = format("%.0" + decp + "f", value);
- if (decp > 0){
- if (value < 0) intp = fvalue.slice(1, -(decp+1));
- else intp = fvalue.slice(0, -(decp+1));
- }
- else intp = fvalue;
- local thousands_rep = "%1" + math.thousand_separator();
- local thousandsp = intp.reverse().gsub("(%d%d%d)",thousands_rep);
- if ((intp.len() % 3) == 0) thousandsp = thousandsp.slice(0,-1);
- if (decp > 0) fvalue = thousandsp.reverse() + math.decimal_separator() + fvalue.slice(-decp);
- else fvalue = thousandsp.reverse();
- if (value < 0) return "-" + fvalue;
- else return fvalue;
- }
- function blank_when_zero(snum) {return snum.tofloat();}
- local win = Fl_Double_Window(10,50, 800, 560, "My Barchart");
- local mychart = Fl_Bar_Chart(20,20, 760, 520, "My Barchart");
- win->end();
- mychart->labelsize(18);
- local function rand_value(){return math.rand() % 300;}
- mychart.bar_add("January", rand_value());
- mychart->bar_add("Febrary", rand_value());
- mychart->bar_add("March", rand_value());
- mychart->bar_add("April", rand_value());
- mychart->bar_add("May", rand_value());
- mychart->bar_add("June", rand_value(), FL_RED);
- mychart->bar_add("July", rand_value(), FL_GREEN);
- mychart->bar_add("August", rand_value());
- mychart->bar_add("September", rand_value());
- mychart->bar_add("November", rand_value());
- mychart->bar_add("Dicember", rand_value());
- win->resizable(mychart);
- win->show_main();
- Fl.run();
- */
|