initial commit, lordsawar source, slightly modified
[lordsawar] / src / gui / bar-chart.cpp
1 //  Copyright (C) 2007, 2008 Ben Asselstine
2 //
3 //  This program is free software; you can redistribute it and/or modify
4 //  it under the terms of the GNU General Public License as published by
5 //  the Free Software Foundation; either version 3 of the License, or
6 //  (at your option) any later version.
7 //
8 //  This program is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 //  GNU Library General Public License for more details.
12 //
13 //  You should have received a copy of the GNU General Public License
14 //  along with this program; if not, write to the Free Software
15 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
16 //  02110-1301, USA.
17 #include "bar-chart.h"
18 #include "ucompose.hpp"
19 #include <cairomm/context.h>
20
21 BarChart::BarChart(std::list<unsigned int> bars, std::list<Gdk::Color> colours,
22                    unsigned int max_value)
23 {
24   d_bars = bars;
25   d_colours = colours;
26   d_max_value = max_value;
27 }
28
29 BarChart::~BarChart()
30 {
31 }
32
33 bool BarChart::on_expose_event(GdkEventExpose* event)
34 {
35   // This is where we draw on the window
36   Glib::RefPtr<Gdk::Window> window = get_window();
37   if(window)
38   {
39     Gtk::Allocation allocation = get_allocation();
40     const int width = allocation.get_width();
41     const int height = allocation.get_height();
42
43     // coordinates for the center of the window
44     int xc, yc;
45     xc = width / 2;
46     yc = height / 2;
47
48     unsigned int lw = 10;
49     Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
50
51     // clip to the area indicated by the expose event so that we only redraw
52     // the portion of the window that needs to be redrawn
53     cr->rectangle(event->area.x, event->area.y,
54             event->area.width, event->area.height);
55     cr->clip();
56     cr->set_source_rgb (0.8, 0.8, 0.8);
57     cr->set_line_width(1000.0);
58     cr->move_to(0,0);
59     cr->line_to(width, height);
60     cr->stroke();
61     cr->set_line_width((double)lw);
62
63     unsigned int max = 0;
64     std::list<unsigned int>::iterator bit = d_bars.begin();
65     if (d_max_value == 0)
66       {
67         for (; bit != d_bars.end(); bit++)
68           {
69             if (*bit > max)
70               max = *bit;
71           }
72         if (max < 10)
73           max = 10;
74         else if (max < 100)
75           max = 100;
76         else if (max < 250)
77           max = 250;
78         else if (max < 500)
79           max = 500;
80         else if (max < 1000)
81           max = 1000;
82         else if (max < 1500)
83           max = 1500;
84         else if (max < 2500)
85           max = 2500;
86         else if (max < 3500)
87           max = 3500;
88         else if (max < 5000)
89           max = 5000;
90         else if (max < 7500)
91           max = 7500;
92         else if (max < 10000)
93           max = 10000;
94         else if (max < 25000)
95           max = 25000;
96         else if (max < 50000)
97           max = 50000;
98         else if (max < 100000)
99           max = 100000;
100       }
101     else
102       max = d_max_value;
103
104     unsigned int voffs = 15;
105     unsigned int hoffs = 15;
106     unsigned int d = 10;
107     cr->move_to(0, 0);
108     bit = d_bars.begin();
109     std::list<Gdk::Color>::iterator cit = d_colours.begin();
110     unsigned int i = 0;
111     for (; bit != d_bars.end(), cit != d_colours.end(); bit++, cit++, i+=(lw+d))
112       {
113         cr->move_to(hoffs, i + lw + voffs);
114         double red = (double)(*cit).get_red() /65535.0;
115         double green = (double)(*cit).get_green() /65535.0;
116         double blue = (double)(*cit).get_blue() /65535.0;
117         cr->set_source_rgb(red, green, blue);
118         cr->line_to(((float) *bit / (float)max) * (width - hoffs) + hoffs, 
119                     i + lw + voffs);
120         cr->stroke();
121       }
122     cr->set_source_rgb (0.2, 0.2, 0.2);
123     lw = 2;
124     cr->set_line_width((double)lw);
125
126     // draw the line across the bottom
127     cr->move_to(hoffs, i + lw + voffs);
128     cr->line_to(((float)max / (float)max) * (width - (hoffs * 2)), 
129                 i + lw + voffs);
130     cr->stroke();
131
132     //now the three ticks
133     cr->move_to(hoffs + 1, i + lw + voffs + 1);
134     cr->line_to(hoffs + 1, i + lw + voffs + (voffs / 2) + 1);
135     cr->stroke();
136     cr->move_to(((float)0.25 * ((float)width - (hoffs * 2.0))) + (hoffs / 2), i + lw + voffs + 1);
137     cr->line_to(((float)0.25 * ((float)width - (hoffs * 2.0))) + (hoffs / 2), 
138                 i + lw + voffs + (voffs / 4) + 1);
139     cr->stroke();
140     cr->move_to(((float)0.5 * ((float)width - (hoffs * 2.0))) + (hoffs / 2), i + lw + voffs + 1);
141     cr->line_to(((float)0.5 * ((float)width - (hoffs * 2.0))) + (hoffs / 2), 
142                 i + lw + voffs + (voffs / 2) + 1);
143     cr->stroke();
144     cr->move_to(((float)0.75 * ((float)width - (hoffs * 2.0))) + (hoffs / 2), i + lw + voffs + 1);
145     cr->line_to(((float)0.75 * ((float)width - (hoffs * 2.0))) + (hoffs / 2), 
146                 i + lw + voffs + (voffs / 4) + 1);
147     cr->stroke();
148     cr->move_to(((float)1.0 * ((float)width - ((float)hoffs * 2.0))) - 1, i + lw + voffs + 1);
149     cr->line_to(((float)1.0 * ((float)width - ((float)hoffs * 2.0))) - 1, 
150                 i + lw + voffs + (voffs / 2) + 1);
151     cr->stroke();
152
153     // now draw the labels
154     Glib::RefPtr<Pango::Layout> layout = Glib::wrap (pango_cairo_create_layout (cr->cobj ()));
155     std::string text_font = "Sans 8";
156     Pango::FontDescription font_desc (text_font);
157     layout->set_font_description (font_desc);
158     layout->set_text("0");
159     int w, h;
160     layout->get_pixel_size (w, h);
161     cr->move_to(hoffs + 1 - (w / 2), i + lw + voffs + (voffs / 2) + 1);
162     cr->set_source_rgb (0.0, 0.0, 0.0);
163     cr->set_operator (Cairo::OPERATOR_ATOP);
164     pango_cairo_show_layout (cr->cobj (), layout->gobj ());
165
166     layout->set_text(String::ucompose("%1", max / 2));
167     layout->get_pixel_size (w, h);
168     cr->move_to(((float)0.5 * ((float)width - (hoffs * 2.0))) + (hoffs / 2) - 
169                 ( w/2), i + lw + voffs + (voffs / 2) + 1);
170     cr->set_source_rgb (0.0, 0.0, 0.0);
171     cr->set_operator (Cairo::OPERATOR_ATOP);
172     pango_cairo_show_layout (cr->cobj (), layout->gobj ());
173
174     layout->set_text(String::ucompose("%1", max));
175     layout->get_pixel_size (w, h);
176     cr->move_to(((float)1.0 * ((float)width - ((float)hoffs * 2.0))) - 1 - 
177                 (w / 2), i + lw + voffs + (voffs / 2) + 1);
178     cr->set_source_rgb (0.0, 0.0, 0.0);
179     cr->set_operator (Cairo::OPERATOR_ATOP);
180     pango_cairo_show_layout (cr->cobj (), layout->gobj ());
181
182
183   }
184
185   return true;
186 }