ultimatepp/bazaar/Controls4U/DrawingCanvas.h
koldo a6401f5a8f Controls4U: NAMESPACE changes
git-svn-id: svn://ultimatepp.org/upp/trunk@5109 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2012-07-03 22:45:17 +00:00

613 lines
16 KiB
C++

#ifndef _Controls4U_DrawingCanvas_h_
#define _Controls4U_DrawingCanvas_h_
class Svg2DTransform {
public:
Svg2DTransform() {Init();}
Svg2DTransform(Svg2DTransform &transf) {*this = transf;}
void Init() {
transX = transY = 0;
angle = 0;
scaleX = scaleY = 1;
}
void Apply(Painter &sw) {
sw.End();
sw.Begin();
sw.Translate(transX, transY);
sw.Scale(scaleX, scaleY);
sw.Rotate(angle);
}
void Translate(double x, double y) {
transX += x;
transY += y;
}
void Scale(double x, double y) {
scaleX *= x;
scaleY *= y;
}
void Rotate(double ang) {
angle += ang;
}
Svg2DTransform &operator=(const Svg2DTransform &transf) {
if (this == &transf) // Same object?
return *this;
transX = transf.transX;
transY = transf.transY;
angle = transf.angle;
scaleX = transf.scaleX;
scaleY = transf.scaleY;
return *this;
}
Svg2DTransform &operator+=(const Svg2DTransform &transf) {
if (this == &transf) // Same object?
return *this;
transX += transf.transX;
transY += transf.transY;
angle += transf.angle;
scaleX *= transf.scaleX;
scaleY *= transf.scaleY;
return *this;
}
Svg2DTransform &SetTranslate(double x, double y) {
transX = x;
transY = y;
return *this;
}
Svg2DTransform &SetScale(double x, double y) {
scaleX = x;
scaleY = y;
return *this;
}
Svg2DTransform &SetRotate(double a) {
angle = a;
return *this;
}
void Xmlize(XmlIO &xml) {xml ("transX", transX)("transY", transY)("angle", angle)("scaleX", scaleX)("scaleY", scaleY);}
private:
double transX;
double transY;
double angle;
double scaleX;
double scaleY;
};
class SvgStyle {
public:
SvgStyle() {Init();}
SvgStyle(SvgStyle &transf) {*this = transf;}
void Init() {
strokeWidth = Null;
strokeColor = Null;
fill = Null;
opacity = Null;
}
void Set(String str);
void Apply(Painter &sw);
SvgStyle &operator=(const SvgStyle &style);
SvgStyle &operator+=(const SvgStyle &style);
SvgStyle &SetStrokeWidth(double c) {strokeWidth = c; return *this;}
SvgStyle &SetStrokeColor(Color c) {strokeColor = c; return *this;}
SvgStyle &SetFill(Color c) {fill = c; return *this;}
SvgStyle &SetOpacity(double c) {opacity = c; return *this;}
void Xmlize(XmlIO &xml) {xml ("strokeWidth", strokeWidth)("strokeColor", strokeColor)
("fill", fill)("opacity", opacity);}
public:
double strokeWidth;
Color strokeColor;
Color fill;
double opacity;
};
class GraphElemLimits : public Rectf {
public:
GraphElemLimits() {
Reset();
}
void Reset() {
left = top = -DOUBLE_NULL_LIM;
right = bottom = DOUBLE_NULL_LIM;
}
void UpdateLimits(const Pointf &p) {
UpdateLimitsH(p.x);
UpdateLimitsV(p.y);
}
void UpdateLimitsH(double x) {
if (x > right)
right = x;
if (x < left)
left = x;
}
void UpdateLimitsV(double y) {
if (y > bottom)
bottom = y;
if (y < top)
top = y;
}
void Cubic(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel) {
/*DoMove0();
CubicData& m = PathAdd<CubicData>(CUBIC);
m.p1 = PathPoint(p1, rel);
ccontrol = m.p2 = PathPoint(p2, rel);
m.p = EndPoint(p, rel);*/
//UpdateLimits(p1);
UpdateLimits(p2);
UpdateLimits(p);
}
};
class GraphElem : public WithPolyXML<GraphElem>, public Pte<GraphElem> {
public:
GraphElem() {}
GraphElem(const GraphElem &graph);
virtual void Paint(Painter &sw, Svg2DTransform transf, SvgStyle style, bool firstLayer) {};
virtual void SetLimits() {};
virtual void PaintLimits(Painter &sw) {
if (limits == GraphElemLimits())
return;
sw.Rectangle(limits.left, limits.top, limits.GetWidth(), limits.GetHeight())
.Opacity(0.3).Stroke(0.5, Black()).Fill(LtBlue());
sw.Move(limits.left, limits.top);
sw.Line(limits.right, limits.bottom).Opacity(0.3).Stroke(0.5, Black());
sw.Move(limits.right, limits.top);
sw.Line(limits.left, limits.bottom).Opacity(0.3).Stroke(0.5, Black());
}
virtual ~GraphElem() {};
virtual void Xmlize(XmlIO &xml) {xml ("transf", transf)("style", style)("limits", limits);}
Svg2DTransform transf;
SvgStyle style;
GraphElemLimits limits;
};
class LineElem : public GraphElem {
public:
virtual void Paint(Painter &sw, Svg2DTransform _transf, SvgStyle _style, bool) {
_transf += transf;
_transf.Apply(sw);
sw.Move(x1, y1);
sw.Line(x2, y2);
_style += style;
_style.Apply(sw);
//PaintLimits(sw);
}
virtual void SetLimits() {
limits.left = x1;
limits.top = y1;
limits.right = x2;
limits.bottom = y2;
}
LineElem(double x1, double y1, double x2, double y2) : x1(x1), y1(y1), x2(x2), y2(y2) {SetLimits();}
LineElem() {x1 = x2 = y1 = y2 = 0;}
void Xmlize(XmlIO &xml) {xml ("x1", x1)("y1", y1)("x2", x2)("y2", y2); }
//private:
double x1, y1, x2, y2;
};
class RectElem : public GraphElem {
public:
virtual void Paint(Painter &sw, Svg2DTransform _transf, SvgStyle _style, bool) {
_transf += transf;
_transf.Apply(sw);
sw.Rectangle(x, y, width, height);
_style += style;
_style.Apply(sw);
//PaintLimits(sw);
}
virtual void SetLimits() {
limits.left = x;
limits.top = y;
limits.right = x + width;
limits.bottom = y + height;
}
RectElem(double x, double y, double width, double height) : x(x), y(y), width(width), height(height) {SetLimits();}
RectElem(const Rect &rect) : x(rect.left), y(rect.top), width(rect.right - rect.left), height(rect.bottom - rect.top) {SetLimits();}
RectElem() {x = y = width = height = 0;}
void Xmlize(XmlIO &xml) {xml ("x", x)("y", y)("width", width)("height", height);}
//private:
double x, y, width, height;
};
class EllipseElem : public GraphElem {
public:
virtual void Paint(Painter &sw, Svg2DTransform _transf, SvgStyle _style, bool) {
_transf += transf;
_transf.Apply(sw);
sw.Ellipse(x, y, width, height);
_style += style;
_style.Apply(sw);
//PaintLimits(sw);
}
virtual void SetLimits() {
limits.left = x - width;
limits.top = y - height;
limits.right = x + width;
limits.bottom = y + height;
}
EllipseElem(double x, double y, double width, double height) : x(x), y(y), width(width), height(height) {SetLimits();}
EllipseElem() {x = y = width = height = 0;}
void Xmlize(XmlIO &xml) {xml ("x", x)("y", y)("width", width)("height", height);}
//private:
double x, y, width, height;
};
class ImageElem : public GraphElem {
public:
virtual void Paint(Painter &sw, Svg2DTransform _transf, SvgStyle _style, bool) {
if (IsNull(img))
img = StreamRaster::LoadFileAny(fileName);
_transf += transf;
_transf.Apply(sw);
sw.Rectangle(x, y, width, height).Fill(img, x, y, width, 0).Stroke(0, Black());
_style += style;
_style.Apply(sw);
PaintLimits(sw);
}
virtual void SetLimits() {
limits.left = x;
limits.top = y;
limits.right = x + width;
limits.bottom = y + height;
}
ImageElem(double x, double y, double width, double height, String fileName) : x(x), y(y),
width(width), height(height), fileName(fileName) {img = Null; SetLimits();}
ImageElem() {x = y = width = height = 0; img = Null;}
void Xmlize(XmlIO &xml) {xml ("x", x)("y", y)("width", width)("height", height)
("fileName", fileName)("img", img);}
//private:
double x, y, width, height;
String fileName;
Image img;
};
class PolygonElem : public GraphElem {
public:
virtual void Paint(Painter &sw, Svg2DTransform _transf, SvgStyle _style, bool) {
_transf += transf;
_transf.Apply(sw);
sw.Move(points[0].x, points[0].y);
for (int i = 1; i < points.GetCount(); ++i)
sw.Line(points[i].x, points[i].y);
_style += style;
_style.Apply(sw);
//PaintLimits(sw);
}
virtual void SetLimits() {
limits.Reset();
for (int i = 0; i < points.GetCount(); ++i)
limits.UpdateLimits(points[i]);
}
PolygonElem() {}
void Xmlize(XmlIO &xml) {xml ("points", points);}
//private:
Array<Pointf> points;
};
class TextElem : public GraphElem {
public:
virtual void Paint(Painter &sw, Svg2DTransform _transf, SvgStyle _style, bool) {
_transf.Translate(x, y-f.GetHeight()/factor);
_transf.Scale(1./factor, 1./factor);
_transf += transf;
_transf.Apply(sw);
sw.Text(0, 0, text, f);
_style += style;
_style.Apply(sw);
//PaintLimits(sw);
}
virtual void SetLimits() {
limits.left = 0;
limits.top = 0;
FontInfo fi = f.Info();
limits.right = limits.left;
WString wtext(text);
for (int i = 0; i < wtext.GetCount(); ++i)
limits.right += fi[wtext[i]];
limits.bottom = limits.top + f.GetHeight();
}
TextElem(double x, double y, String text, Font f) : x(x), y(y), text(text), f(f) {factor = 1; SetLimits();}
TextElem() {
factor = 1;
f.Face(Font::ARIAL);
f.Height(12);
}
void Xmlize(XmlIO &xml) {xml ("x", x)("y", y)("text", text)("font", font)("f", f)("factor", factor);}
//private:
double x, y;
String text;
String font;
Font f;
int factor;
};
class PathElem : public GraphElem {
public:
virtual void Paint(Painter &sw, Svg2DTransform _transf, SvgStyle _style, bool) {
_transf += transf;
_transf.Apply(sw);
if (!path.IsEmpty())
sw.Path(path);
_style += style;
_style.Apply(sw);
//PaintLimits(sw);
}
bool ReadBool(CParser& p) { // Painter::
while(p.Char(','));
if(p.Char('1')) return true;
p.Char('0');
return false;
}
double ReadDouble(CParser& p) { // Painter::
while(p.Char(','));
return p.IsDouble() ? p.ReadDouble() : 0;
}
Pointf ReadPoint(CParser& p) { // Painter::
Pointf t;
t.x = ReadDouble(p);
t.y = ReadDouble(p);
return t;
}
virtual void SetLimits() {
CParser p(path);
limits.Reset();
while(!p.IsEof()) {
int c = p.GetChar();
p.Spaces();
bool rel = IsLower(c);
Pointf t, t1, t2;
switch(ToUpper(c)) {
case 'M':
t = ReadPoint(p);
//Move(t, rel);
limits.UpdateLimits(t);
case 'L':
while(p.IsDouble()) {
t = ReadPoint(p);
//Line(t, rel);
limits.UpdateLimits(t);
}
break;
case 'Z':
//Close();
break;
case 'H':
while(p.IsDouble())
//Line(p.ReadDouble(), Null, rel);
limits.UpdateLimitsH(p.ReadDouble());
break;
case 'V':
while(p.IsDouble())
//Line(Null, p.ReadDouble(), rel);
limits.UpdateLimitsV(p.ReadDouble());
;
break;
case 'C':
while(p.IsDouble()) {
t1 = ReadPoint(p);
t2 = ReadPoint(p);
t = ReadPoint(p);
limits.Cubic(t1, t2, t, rel);
//Cubic(t1, t2, t, rel);
}
break;
case 'S':
while(p.IsDouble()) {
t2 = ReadPoint(p);
t = ReadPoint(p);
//Cubic(t2, t, rel);
//limits.UpdateLimits(t2);
limits.UpdateLimits(t);
}
break;
case 'Q':
while(p.IsDouble()) {
t1 = ReadPoint(p);
t = ReadPoint(p);
//Quadratic(t1, t, rel);
//limits.UpdateLimits(t1);
limits.UpdateLimits(t);
}
break;
case 'T':
while(p.IsDouble()) {
t = ReadPoint(p);
//Quadratic(t, rel);
limits.UpdateLimits(t);
}
break;
case 'A':
while(p.IsDouble()) {
t1 = ReadPoint(p);
//double xangle = ReadDouble(p);
//bool large = ReadBool(p);
//bool sweep = ReadBool(p);
t = ReadPoint(p);
//SvgArc(t1, xangle * M_PI / 180.0, large, sweep, t, rel);
}
break;
default:
return;
}
}
}
PathElem() {}
void Xmlize(XmlIO &xml) {xml ("path", path);}
//private:
String path;
};
class GraphElemList : public GraphElem {
public:
PolyXMLArray<GraphElem> elems;
String title;
void Paint(Painter &sw, Svg2DTransform transf, SvgStyle style, bool firstLayer = false);
void Clear();
void Xmlize(XmlIO &xml) {xml ("elems", elems);}
};
/*
class CanvasSelector {
typedef CanvasSelector CLASSNAME;
public:
};
class DrawingCanvas : public Ctrl {
typedef DrawingCanvas CLASSNAME;
public:
DrawingCanvas();
GraphElemList elemList;
protected:
virtual void Paint(Draw& draw);
private:
double translateX, translateY;
double rotate;
double scale;
bool transparent;
double opacity;
int linejoin, linecap;
int quality;
double scaleFactor;
void DoPaint(Painter& sw);
virtual void MouseMove(Point p, dword keyflags);
virtual void MouseWheel(Point p, int zdelta, dword keyflags);
virtual void MiddleDown(Point p, dword keyflags);
virtual void MiddleUp(Point p, dword keyflags);
virtual void MouseLeave();
struct FocusMove {
bool focusMoving;
Point lastFocusPoint;
} focusMove;
virtual void LeftDown(Point p, dword keyflags);
virtual void LeftUp(Point p, dword keyflags);
struct SelectionWindow {
bool isSelected;
Rect selected;
} selectionWindow;
};
bool LoadSvg(DrawingCanvas &canvas, String fileName);
*/
class PainterCanvas : public Ctrl {
typedef PainterCanvas CLASSNAME;
public:
PainterCanvas();
void SetCanvasSize(Size sz) {canvasSize = sz;};
Size GetCanvasSize() const {return canvasSize;};
void Zoom(double factor);
void Scroll(double factorX, double factorY);
void FitInCanvas();
Image GetImage(Size sz = Null);
PainterCanvas &SetBackground(Color color) {backColor = color; Refresh(); return *this;};
PainterCanvas &SetBackground(const Image image);
PainterCanvas &SetBackground(const String &imageFilename);
Image GetBackground() {return backImage;}
PainterCanvas &SetColorUnderBackgroundImage(bool set) {colorUnderBackgroundImage = set; return *this;};
PainterCanvas &SetScale(double factor) {scale *= factor; Refresh(); return *this;};
PainterCanvas &SetAlwaysFitInCanvas(bool fit = true){alwaysFitInCanvas = fit; Refresh(); return *this;}
PainterCanvas &SetMode(int md = MODE_ANTIALIASED) {mode = md; return *this;}
PainterCanvas &SetShowWindow(bool sw = true) {showWindow = sw; return *this;};
PainterCanvas &SetCursorImage(const Image &img) {cursorImage = img; return *this;};
PainterCanvas &SetLegend(bool _legendShowXY = true, Font _legendFont = StdFont());
GraphElemList elemList;
double GetScale() {return scale;};
Callback1 <Painter &> WhenPaint;
Callback2 <Point, Pointf> WhenMouseMove;
Callback2 <Point, Pointf> WhenMouseLeft;
void Xmlize(XmlIO &xml) {xml ("elemList", elemList)("translateX", translateX)
("translateY", translateY)("rotate", rotate)("scale", scale)("opacity", opacity)
("linejoin", linejoin)("linecap", linecap)("mode", mode)("scaleFactor", scaleFactor)
("backImage", backImage)("backColor", backColor)("canvasSize", canvasSize)
("colorUnderBackgroundImage", colorUnderBackgroundImage)
("alwaysFitInCanvas", alwaysFitInCanvas)("showWindow", showWindow);}
protected:
virtual void Paint(Draw& draw);
virtual void Layout();
private:
double translateX, translateY;
double rotate;
double scale;
double opacity;
int linejoin, linecap;
int mode;
double scaleFactor;
Image backImage;
Color backColor;
Size canvasSize;
bool colorUnderBackgroundImage;
bool alwaysFitInCanvas;
bool showWindow;
virtual void MouseMove(Point p, dword keyflags);
virtual void MouseWheel(Point p, int zdelta, dword keyflags);
virtual void MiddleDown(Point p, dword keyflags);
virtual void MiddleUp(Point p, dword keyflags);
virtual void RightDown(Point p, dword keyflags);
virtual void LeftDown(Point p, dword keyflags);
virtual void MouseLeave();
virtual Image CursorImage(Point p, dword keyflags);
struct FocusMove {
bool focusMoving;
Point lastFocusPoint;
} focusMove;
void ContextMenu(Bar& bar);
void SaveToFile(String fileName);
void SaveToClipboard();
void Load(String fileName);
void DoPaint(Painter& sw);
Image cursorImage;
Font legendFont;
bool legendShowFilename;
bool legendShowXY;
String legendText;
Size legendLastSize;
};
#endif