Changeset 208
- Timestamp:
- 17/08/09 20:42:41 (4 years ago)
- Location:
- trunk/src
- Files:
-
- 4 edited
-
simple_pie_plot.cpp (modified) (8 diffs)
-
simple_pie_plot.h (modified) (2 diffs)
-
statistics_dialog.cpp (modified) (3 diffs)
-
statistics_dialog.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/simple_pie_plot.cpp
r207 r208 22 22 #include <boost/foreach.hpp> 23 23 #include <memory> 24 #include <algorithm> 24 25 #include <cmath> 25 26 using namespace std; … … 59 60 { 60 61 m_highlight = -1; 62 63 m_max_legend_width = 0; 64 m_max_legend_height = 0; 65 m_legend_width = 0; 66 61 67 Connect(this->GetId(), wxEVT_PAINT, wxPaintEventHandler(SimplePiePlot::OnPaint)); 62 68 Connect(this->GetId(), wxEVT_SIZE, wxSizeEventHandler(SimplePiePlot::OnResize)); … … 71 77 auto_ptr<wxGraphicsContext> dc(wxGraphicsContext::Create(pdc)); 72 78 wxBrush color_brush; 73 int width, height; 74 75 GetClientSize(&width, &height); 76 77 // radius should be set so it fits exactly 78 double radius = (width>height? height : width)/2.0; 79 79 80 if (!m_max_legend_width || !m_max_legend_height) { 81 CalculateLegendDimensions(dc.get()); 82 // This might have caused a new minimum size to occure, tell 83 // parent about it by refitting. See also comment in 84 // GetMinSize() 85 if (this->GetParent() && this->GetParent()->GetSizer()) 86 this->GetParent()->GetSizer()->SetSizeHints(this->GetParent()); 87 } 88 CalculatePiePlotLocation(); 89 90 91 dc->SetPen(*wxTRANSPARENT_PEN); 80 92 for (int i = 1; i<m_angles.size(); i++) { 81 93 // create brush … … 83 95 dc->SetBrush(color_brush); 84 96 85 DrawPieSlice( width/2.0, height/2.0,radius, m_angles[i-1],97 DrawPieSlice(m_pie_x, m_pie_y, m_radius, m_angles[i-1], 86 98 m_angles[i], dc.get()); 87 99 } 100 101 DrawLegend(dc.get()); 102 } 103 104 void SimplePiePlot::CalculatePiePlotLocation() 105 { 106 double pie_width; 107 int width, height; 108 109 assert(m_legend_width); 110 111 GetClientSize(&width, &height); 112 // m_max_legend_height* for the color box and it's right padding 113 pie_width = width - m_legend_width - m_legend_left_padding; 114 m_pie_x = pie_width/2.0; 115 m_pie_y = height/2.0; 116 m_radius = min(pie_width,(double)height)/2.0; 88 117 } 89 118 … … 94 123 } 95 124 96 void SimplePiePlot::SetData(vector<double> d) 97 { 125 void SimplePiePlot::SetData(vector<double> d, vector<wxString> labels) 126 { 127 // number of values should match number of labels 128 assert(labels.size() == d.size()); 129 98 130 m_data.clear(); 99 131 m_data_total = 0; 100 132 BOOST_FOREACH(double tmp, d) { 133 // we can't plot negative values 134 assert(tmp >= 0); 101 135 m_data_total += tmp; 102 if (tmp!=0) 103 m_data.push_back(tmp); 104 } 136 m_data.push_back(tmp); 137 } 138 m_labels.assign(labels.begin(), labels.end()); 139 CalculateAngles(); 140 141 // this will cause the legend size to be re-calculated 142 m_max_legend_width = 0; 143 m_max_legend_height = 0; 144 } 145 146 void SimplePiePlot::CalculateAngles() 147 { 148 double new_angle = 0; 105 149 106 150 m_angles.clear(); 107 double new_angle = 0;108 151 m_angles.push_back(new_angle); 109 152 BOOST_FOREACH(double tmp, m_data) { … … 113 156 } 114 157 158 void SimplePiePlot::CalculateLegendDimensions(wxGraphicsContext *dc) 159 { 160 double tmp_height; 161 double tmp_width; 162 m_max_legend_width = 0; 163 m_max_legend_height = 0; 164 165 dc->SetFont(*wxNORMAL_FONT, *wxBLACK); 166 167 BOOST_FOREACH(wxString label, m_labels) { 168 dc->GetTextExtent(label, &tmp_width, &tmp_height, NULL, NULL); 169 m_max_legend_width = max(m_max_legend_width, tmp_width); 170 m_max_legend_height = max(m_max_legend_height, tmp_height); 171 } 172 173 m_legend_width = m_max_legend_width + 2*m_max_legend_height; 174 m_legend_line_height = 1.5 * m_max_legend_height; 175 } 176 177 void SimplePiePlot::DrawLegend(wxGraphicsContext *dc) 178 { 179 wxBrush color_brush; 180 int width, height; 181 GetClientSize(&width, &height); 182 183 assert(m_legend_width); 184 double legend_x = width - m_legend_width; 185 186 dc->SetPen(*wxTRANSPARENT_PEN); 187 dc->SetFont(*wxNORMAL_FONT, *wxBLACK); 188 189 for (int i = 0; i<m_labels.size(); i++) { 190 color_brush.SetColour(GetSegmentColor(i)); 191 dc->SetBrush(color_brush); 192 193 dc->DrawRectangle(legend_x, i * m_legend_line_height, 194 m_max_legend_height, m_max_legend_height); 195 dc->DrawText(m_labels[i], legend_x + 2*m_max_legend_height, 196 i * m_legend_line_height); 197 } 198 199 } 200 115 201 wxColour SimplePiePlot::GetSegmentColor(int i) 116 202 { 117 203 double hue_step = 1.0/(m_data.size()); 118 204 double hue = i * hue_step; 119 double value = m_highlight == i ? 1.0 : 0. 8;205 double value = m_highlight == i ? 1.0 : 0.9; 120 206 wxColour color; 121 207 wxImage::RGBValue rgb; … … 132 218 int width, height; 133 219 GetClientSize(&width, &height); 134 // radius should be set so it fits exactly 135 const double radius = (width>height? height : width)/2.0; 136 137 const double dist_mouse = (width/2.0-event.m_x)*(width/2.0-event.m_x) + 138 (height/2.0-event.m_y)*(height/2.0-event.m_y); 139 if (dist_mouse > (radius*radius)) { 140 ClearHighlight(); 220 221 const double dist_mouse = (m_pie_x-event.m_x)*(m_pie_x-event.m_x) + 222 (m_pie_y-event.m_y)*(m_pie_y-event.m_y); 223 if (dist_mouse <= (m_radius*m_radius)) { 224 //angles are clockwise from the x-axis 225 double angle = acos((event.m_x-m_pie_x)/sqrt(dist_mouse)); 226 if (event.m_y < m_pie_y) 227 angle = 2*PI - angle; 228 int i; 229 for (i = 1; i<m_angles.size(); i++) { 230 if (angle<=m_angles[i]) 231 break; 232 } 233 Highlight(i-1); 141 234 return; 142 } 143 144 //angles are clockwise from the x-axis 145 double angle = acos((event.m_x-width/2.0)/sqrt(dist_mouse)); 146 if (event.m_y < height/2.0) 147 angle = 2*PI - angle; 148 int i; 149 for (i = 1; i<m_angles.size(); i++) { 150 if (angle<=m_angles[i]) 151 break; 152 } 153 Highlight(i-1); 235 } else if (event.m_x >= width-m_legend_width){ 236 int i = (int) (event.m_y / m_legend_line_height); 237 if (i<m_labels.size()){ 238 Highlight(i); 239 return; 240 } 241 } 242 243 ClearHighlight(); 154 244 } 155 245 … … 172 262 } 173 263 } 264 265 wxSize SimplePiePlot::GetMinSize() const 266 { 267 // In the first call to GetMinSize, m_legend_line_height and 268 // m_legend_width may not be populated yet (set to zero), this 269 // is a result of not being able to call CalculateLegendDimensions() 270 // at this point due to constness. In order to workaround this issue, 271 // if CalculateLegendDimensions() gets called in OnPaint() (this 272 // happens also after setting new data), OnPaint() also notifies the 273 // parent's sizer (is such exist) to update the size hints 274 // accordingly. 275 const double total_legend_height = m_labels.size() * m_legend_line_height; 276 const double total_width = total_legend_height + m_legend_width + 277 m_legend_left_padding; 278 return wxSize((int)ceil(total_width),(int)ceil(total_legend_height)); 279 } 280 -
trunk/src/simple_pie_plot.h
r207 r208 32 32 const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, 33 33 long style = wxNO_BORDER, const wxString& name = wxPanelNameStr); 34 void SetData(std::vector<double> d );34 void SetData(std::vector<double> d, std::vector<wxString> labels); 35 35 void OnPaint(wxPaintEvent& event); 36 36 void OnResize(wxSizeEvent& event); 37 37 void OnMouseLeaveWindow(wxMouseEvent& event); 38 38 void OnMouseMove(wxMouseEvent& event); 39 wxSize GetMinSize() const; 39 40 private: 40 41 /** … … 44 45 wxColour GetSegmentColor(int i); 45 46 47 /** 48 * Calculate the angles in the plot and populate the m_angles array. 49 */ 50 void CalculateAngles(); 51 52 /** 53 * Calculate the maximum widht and height for a label in the legend. 54 */ 55 void CalculateLegendDimensions(wxGraphicsContext *dc); 56 57 /** 58 * Calculate the location and radius of the pie plot. 59 */ 60 void CalculatePiePlotLocation(); 61 62 void DrawLegend(wxGraphicsContext *dc); 63 46 64 void Highlight(int i); 47 65 void ClearHighlight(); 48 66 49 67 std::vector<double> m_data; 68 std::vector<wxString> m_labels; 50 69 std::vector<double> m_angles; 51 70 double m_data_total; 52 71 int m_highlight; 72 73 /// maximum width for a label in the legend. 74 double m_max_legend_width; 75 /// maximum height for a label in the legend. 76 double m_max_legend_height; 77 /// total width of the legend 78 double m_legend_width; 79 /// the line height of each legend entry including padding 80 double m_legend_line_height; 81 82 static const double m_legend_left_padding = 10; 83 84 // The center point of the pie plot 85 double m_pie_x; 86 double m_pie_y; 87 double m_radius; 88 53 89 }; 54 90 -
trunk/src/statistics_dialog.cpp
r206 r208 46 46 games_started = new wxStaticText(this, wxID_ANY, wxT("")); 47 47 games_finished = new wxStaticText(this, wxID_ANY, wxT("")); 48 histogram= new simple_pie_plot::SimplePiePlot(this, wxID_ANY);48 pie_plot = new simple_pie_plot::SimplePiePlot(this, wxID_ANY); 49 49 statistics_reset_date = new wxStaticText(this, wxID_ANY, wxT("")); 50 50 } … … 64 64 65 65 vector<int> score_dist = m_stats->score_distribution(); 66 vector<double> dist (score_dist.begin(), score_dist.end()); 67 histogram->SetData(dist); 66 vector<double> dist; 67 vector<wxString> labels; 68 for (int i; i<score_dist.size(); i++) { 69 if (score_dist[i]) { 70 assert(score_dist[i]>0); 71 dist.push_back(score_dist[i]); 72 tmp = wxString::Format(wxT("%i - %i"), 73 i*statistics::score_distribution_granuality, 74 (i+1)*statistics::score_distribution_granuality); 75 labels.push_back(tmp); 76 } 77 } 78 pie_plot->SetData(dist, labels); 68 79 } 69 80 … … 79 90 80 91 wxStaticBoxSizer* score_distribution = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxT("Score Distribution") ), wxHORIZONTAL); 81 score_distribution->Add( histogram, 1, wxEXPAND, 10);92 score_distribution->Add(pie_plot, 1, wxEXPAND, 10); 82 93 top_sizer->Add(score_distribution,10,wxEXPAND, 10); 83 94 -
trunk/src/statistics_dialog.h
r206 r208 47 47 wxStaticText *games_finished; 48 48 wxStaticText *statistics_reset_date; 49 simple_pie_plot::SimplePiePlot* histogram;49 simple_pie_plot::SimplePiePlot* pie_plot; 50 50 51 51 statistics::Statistics* m_stats;
Note: See TracChangeset
for help on using the changeset viewer.
