initial commit, lordsawar source, slightly modified
[lordsawar] / src / gui / bar-chart.cpp
diff --git a/src/gui/bar-chart.cpp b/src/gui/bar-chart.cpp
new file mode 100644 (file)
index 0000000..c2eeae2
--- /dev/null
@@ -0,0 +1,186 @@
+//  Copyright (C) 2007, 2008 Ben Asselstine
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU Library General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
+//  02110-1301, USA.
+#include "bar-chart.h"
+#include "ucompose.hpp"
+#include <cairomm/context.h>
+
+BarChart::BarChart(std::list<unsigned int> bars, std::list<Gdk::Color> colours,
+                  unsigned int max_value)
+{
+  d_bars = bars;
+  d_colours = colours;
+  d_max_value = max_value;
+}
+
+BarChart::~BarChart()
+{
+}
+
+bool BarChart::on_expose_event(GdkEventExpose* event)
+{
+  // This is where we draw on the window
+  Glib::RefPtr<Gdk::Window> window = get_window();
+  if(window)
+  {
+    Gtk::Allocation allocation = get_allocation();
+    const int width = allocation.get_width();
+    const int height = allocation.get_height();
+
+    // coordinates for the center of the window
+    int xc, yc;
+    xc = width / 2;
+    yc = height / 2;
+
+    unsigned int lw = 10;
+    Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
+
+    // clip to the area indicated by the expose event so that we only redraw
+    // the portion of the window that needs to be redrawn
+    cr->rectangle(event->area.x, event->area.y,
+            event->area.width, event->area.height);
+    cr->clip();
+    cr->set_source_rgb (0.8, 0.8, 0.8);
+    cr->set_line_width(1000.0);
+    cr->move_to(0,0);
+    cr->line_to(width, height);
+    cr->stroke();
+    cr->set_line_width((double)lw);
+
+    unsigned int max = 0;
+    std::list<unsigned int>::iterator bit = d_bars.begin();
+    if (d_max_value == 0)
+      {
+       for (; bit != d_bars.end(); bit++)
+         {
+           if (*bit > max)
+             max = *bit;
+         }
+       if (max < 10)
+         max = 10;
+       else if (max < 100)
+         max = 100;
+       else if (max < 250)
+         max = 250;
+       else if (max < 500)
+         max = 500;
+       else if (max < 1000)
+         max = 1000;
+       else if (max < 1500)
+         max = 1500;
+       else if (max < 2500)
+         max = 2500;
+       else if (max < 3500)
+         max = 3500;
+       else if (max < 5000)
+         max = 5000;
+       else if (max < 7500)
+         max = 7500;
+       else if (max < 10000)
+         max = 10000;
+       else if (max < 25000)
+         max = 25000;
+       else if (max < 50000)
+         max = 50000;
+       else if (max < 100000)
+         max = 100000;
+      }
+    else
+      max = d_max_value;
+
+    unsigned int voffs = 15;
+    unsigned int hoffs = 15;
+    unsigned int d = 10;
+    cr->move_to(0, 0);
+    bit = d_bars.begin();
+    std::list<Gdk::Color>::iterator cit = d_colours.begin();
+    unsigned int i = 0;
+    for (; bit != d_bars.end(), cit != d_colours.end(); bit++, cit++, i+=(lw+d))
+      {
+       cr->move_to(hoffs, i + lw + voffs);
+       double red = (double)(*cit).get_red() /65535.0;
+       double green = (double)(*cit).get_green() /65535.0;
+       double blue = (double)(*cit).get_blue() /65535.0;
+       cr->set_source_rgb(red, green, blue);
+       cr->line_to(((float) *bit / (float)max) * (width - hoffs) + hoffs, 
+                   i + lw + voffs);
+       cr->stroke();
+      }
+    cr->set_source_rgb (0.2, 0.2, 0.2);
+    lw = 2;
+    cr->set_line_width((double)lw);
+
+    // draw the line across the bottom
+    cr->move_to(hoffs, i + lw + voffs);
+    cr->line_to(((float)max / (float)max) * (width - (hoffs * 2)), 
+               i + lw + voffs);
+    cr->stroke();
+
+    //now the three ticks
+    cr->move_to(hoffs + 1, i + lw + voffs + 1);
+    cr->line_to(hoffs + 1, i + lw + voffs + (voffs / 2) + 1);
+    cr->stroke();
+    cr->move_to(((float)0.25 * ((float)width - (hoffs * 2.0))) + (hoffs / 2), i + lw + voffs + 1);
+    cr->line_to(((float)0.25 * ((float)width - (hoffs * 2.0))) + (hoffs / 2), 
+               i + lw + voffs + (voffs / 4) + 1);
+    cr->stroke();
+    cr->move_to(((float)0.5 * ((float)width - (hoffs * 2.0))) + (hoffs / 2), i + lw + voffs + 1);
+    cr->line_to(((float)0.5 * ((float)width - (hoffs * 2.0))) + (hoffs / 2), 
+               i + lw + voffs + (voffs / 2) + 1);
+    cr->stroke();
+    cr->move_to(((float)0.75 * ((float)width - (hoffs * 2.0))) + (hoffs / 2), i + lw + voffs + 1);
+    cr->line_to(((float)0.75 * ((float)width - (hoffs * 2.0))) + (hoffs / 2), 
+               i + lw + voffs + (voffs / 4) + 1);
+    cr->stroke();
+    cr->move_to(((float)1.0 * ((float)width - ((float)hoffs * 2.0))) - 1, i + lw + voffs + 1);
+    cr->line_to(((float)1.0 * ((float)width - ((float)hoffs * 2.0))) - 1, 
+               i + lw + voffs + (voffs / 2) + 1);
+    cr->stroke();
+
+    // now draw the labels
+    Glib::RefPtr<Pango::Layout> layout = Glib::wrap (pango_cairo_create_layout (cr->cobj ()));
+    std::string text_font = "Sans 8";
+    Pango::FontDescription font_desc (text_font);
+    layout->set_font_description (font_desc);
+    layout->set_text("0");
+    int w, h;
+    layout->get_pixel_size (w, h);
+    cr->move_to(hoffs + 1 - (w / 2), i + lw + voffs + (voffs / 2) + 1);
+    cr->set_source_rgb (0.0, 0.0, 0.0);
+    cr->set_operator (Cairo::OPERATOR_ATOP);
+    pango_cairo_show_layout (cr->cobj (), layout->gobj ());
+
+    layout->set_text(String::ucompose("%1", max / 2));
+    layout->get_pixel_size (w, h);
+    cr->move_to(((float)0.5 * ((float)width - (hoffs * 2.0))) + (hoffs / 2) - 
+               ( w/2), i + lw + voffs + (voffs / 2) + 1);
+    cr->set_source_rgb (0.0, 0.0, 0.0);
+    cr->set_operator (Cairo::OPERATOR_ATOP);
+    pango_cairo_show_layout (cr->cobj (), layout->gobj ());
+
+    layout->set_text(String::ucompose("%1", max));
+    layout->get_pixel_size (w, h);
+    cr->move_to(((float)1.0 * ((float)width - ((float)hoffs * 2.0))) - 1 - 
+               (w / 2), i + lw + voffs + (voffs / 2) + 1);
+    cr->set_source_rgb (0.0, 0.0, 0.0);
+    cr->set_operator (Cairo::OPERATOR_ATOP);
+    pango_cairo_show_layout (cr->cobj (), layout->gobj ());
+
+
+  }
+
+  return true;
+}