ultimatepp/uppsrc/ScatterDraw/PieDraw.cpp
koldo e91394665c ScatterDraw: PieCtrl legend width and height is automatic
git-svn-id: svn://ultimatepp.org/upp/trunk@10659 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2017-01-06 23:02:06 +00:00

219 lines
6.6 KiB
C++

#include "PieDraw.h"
static void DrawPie(Draw& w, double c_x, double c_y, double r, int start, int alpha, int width = 0,
Color fill = Null, Color outline = Black, uint64 pattern = 0, Color background = White) {
const int dalpha = 1;
int n = alpha/dalpha;
Vector <Point> vP;
Point centre = Point(int(c_x), int(c_y));
vP << centre;
int ix;
int iy;
for (int i = 0; i <= n; i++) {
double x = c_x + r*cos((start+i*dalpha)*M_PI/1800);
ix = fround(x);
double y = c_y + r*sin((start+i*dalpha)*M_PI/1800);
iy = fround(y);
double dxy = (x-ix)*(x-ix) + (y-iy)*(y-iy);
if(dxy < 0.1 || i == 0 || i == n)
vP << Point(ix,iy);
if(w.IsGui())
w.DrawRect(ix, iy, 1, 1, Blend(fill, background, 150));
}
vP << centre;
w.DrawPolygon(vP, fill, width, outline, pattern, Null);
}
void PieDraw::AddCategory(const String& name, const double& value, const Color& catcolor) {
vNames.Add(name);
vValues.Add(value);
vColors.Add(catcolor);
Refresh();
}
void PieDraw::RemoveCategory(const int& index) {
ASSERT(!vValues.IsEmpty() && vValues.GetCount() > index);
vNames.Remove(index);
vValues.Remove(index);
vColors.Remove(index);
Refresh();
}
PieDraw& PieDraw::SetCatValue(const int& index, const double& value) {
ASSERT(!vValues.IsEmpty() && vValues.GetCount() > index);
vValues[index] = value;
Refresh();
return *this;
}
PieDraw& PieDraw::SetCatName(const int& index, const String& name) {
ASSERT(!vNames.IsEmpty() && vNames.GetCount() > index);
vNames[index] = name;
Refresh();
return *this;
}
PieDraw& PieDraw::SetCatColor(const int& index, const Color& catcolor) {
ASSERT(!vColors.IsEmpty() && vColors.GetCount() > index);
vColors[index] = catcolor;
Refresh();
return *this;
}
double PieDraw::GetCatValue(const int& index) const {
ASSERT(!vValues.IsEmpty() && vValues.GetCount() > index);
return vValues[index];
}
String PieDraw::GetCatName(const int& index) const {
ASSERT(!vNames.IsEmpty() && vNames.GetCount() > index);
return vNames[index];
}
Color PieDraw::GetCatColor(const int& index) const {
ASSERT(!vColors.IsEmpty() && vColors.GetCount() > index);
return vColors[index];
}
void PieDraw::PaintPie(Draw& w, int scale) {
Size sz = scale*GetSize();
w.DrawRect(sz, backColor);
Size textsize;
textsize.cx = 0;
textsize.cy = 0;
if(!title.IsEmpty()) {
Upp::Font FontTitle6;
FontTitle6 = titleFont;
FontTitle6.Height(scale*titleFont.GetHeight());
FontTitle6.Width(scale*titleFont.GetWidth());
textsize = GetTextSize(title, FontTitle6);
if(titlePos == TOP)
w.DrawText((scale*GetSize().cx - textsize.cx)/2, scale*titleGap, title, FontTitle6,titleColor);
else
w.DrawText((scale*GetSize().cx - textsize.cx)/2, scale*(GetSize().cy - titleFont.GetHeight() - titleGap),
title, FontTitle6,titleColor);
}
if(vValues.IsEmpty())
return;
int alfa0 = -900 + (int)pieAngle;
int a0 = 0;
double sum = 0;
for(int i = 0; i < vValues.GetCount(); i++)
sum += vValues[i];
double circWidth = sz.cx - pieMarginLeft - pieMarginRight;
if (circWidth < 0)
circWidth = 0;
double circHeight = sz.cy - pieMarginTop - textsize.cy - pieMarginBottom;
if (circHeight < 0)
circHeight = 0;
double circ_r;
if (circWidth > circHeight)
circ_r = circHeight/2.;
else
circ_r = circWidth/2.;
double circ_x = pieMarginLeft + circWidth/2.;
double circ_y;
if(titlePos == TOP)
circ_y = pieMarginTop + titleGap + textsize.cy + circHeight/2.;
else
circ_y = pieMarginTop + circHeight/2.;
circ_x *= scale;
circ_y *= scale;
circ_r *= scale;
Color bc;
if (IsNull(backColor))
bc = LtGray;
else
bc = backColor;
for(int i = 0; i < vValues.GetCount(); i++) {
DrawPie(w, circ_x*scale, circ_y*scale, circ_r*scale, alfa0, fround(3600.0*vValues.At(i)/sum),
1*scale, vColors.At(i), vColors.At(i), 0, bc);
alfa0 += fround(3600.0*vValues[i]/sum);
}
if(showPercent) {
alfa0 = -900 + (int)pieAngle;
for(int i = 0; i < vValues.GetCount(); i++) {
a0 = alfa0;
alfa0 += fround(3600.0*vValues[i]/sum);
String percent = GetPercent(vValues[i],sum);
Upp::Font scaledFont;
scaledFont.Height(scale*StdFont().GetHeight());
scaledFont.Width(scale*StdFont().GetWidth());
Size sz = GetTextSize(percent, scaledFont);
int px = int(circ_x + scale*circ_r*cos(M_PI*(alfa0+a0)/3600)/1.3 - sz.cx/2.);
int py = int(circ_y + scale*circ_r*sin(M_PI*(alfa0+a0)/3600)/1.3 - sz.cy/2.);
w.DrawRect(px, py, sz.cx, 1, percentBack);
w.DrawRect(px-1, py + 1, sz.cx + 2, sz.cy-2, percentBack);
w.DrawRect(px, py + sz.cy - 1, sz.cx, 1, percentBack);
w.DrawText(px, py, percent, scaledFont);
}
}
if(showLegend) {
Upp::Font scaledFont;
scaledFont.Height(scale*legendFont.GetHeight());
scaledFont.Width(scale*legendFont.GetWidth());
int fh = scale*legendFont.GetHeight();
int nr = GetCatCount();
int legendWidth = 0;
int legendHeight = (1 + nr)*scaledFont.GetHeight();
for(int i = 0; i < nr; i++)
legendWidth = max<int>(legendWidth, GetTextSize(vNames[i], scaledFont).cx);
legendWidth += fround(2.2*fh);
double leg_x = -legendLeft + sz.cx - legendWidth;
double leg_y;
if (IsNull(legendTop))
leg_y = int(circ_y - scale*legendHeight/2.);
else
leg_y = legendTop*scale;
w.DrawRect(int(leg_x), int(leg_y), scale*legendWidth, scale*legendHeight, legendBackColor);
int dly = scale*legendHeight/nr;
for(int i = 0; i < nr; i++) {
w.DrawRect(int(leg_x) + 2*scale, int(leg_y + i*dly + dly/2. - fh/2.), fh, fh, vColors[i]);
w.DrawText(int(leg_x) + fround(1.8*fh), int(leg_y) + i*dly + int((dly - scaledFont.GetLineHeight())/2),
vNames[i], scaledFont, legendTextColor);
}
}
}
String PieDraw::GetPercent(double a, double total) {
double p = a*100/total;
return FormatDouble(p, 1) + '%';
}
Drawing PieDraw::GetDrawing(int scale) {
DrawingDraw ddw(scale*GetSize());
PaintPie(ddw, scale);
return ddw;
}
Image PieDraw::GetImage(int scale) {
DrawingDraw idraw(scale*GetSize());
PaintPie(idraw,scale);
return Image(idraw.GetResult());
}
PieDraw::PieDraw(): backColor(White), titleFont(StdFont(16)), titleColor(Black), titlePos(TOP),
titleGap(2), showPercent(true), percentBack(Null),
legendFont(StdFont()), legendTextColor(Black), legendBackColor(Null),
showLegend(true), legendLeft(10), legendTop(Null), pieAngle(0),
pieMarginLeft(40), pieMarginTop(40),
pieMarginRight(40), pieMarginBottom(40)
{}
PieDraw::~PieDraw(){}