Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
UppHub
Status & Roadmap
FAQ
Authors & License
Forums
Funding U++
Search on this site











SourceForge.net Logo

SourceForge.net Logo

GitHub Logo

Discord Logo

GeoFun

 

Spirograph Plotting

Description

Application that main goal is to provide GUI interface for exploring "Sprirographs".

More information about Spriographs can be found on Wikipedia.

Result

 

 

 

GeoFun.h

 

#ifndef _GeoFun_GeoFun_h

#define _GeoFun_GeoFun_h

 

#include <CtrlLib/CtrlLib.h>

#include <Painter/Painter.h>

#include <Report/Report.h>

#include <RichText/RichText.h>

#include <plugin/jpg/jpg.h>

 

namespace Upp {

 

#define IMAGECLASS GFImg

#define IMAGEFILE <GeoFun/GeoFun.iml>

#include <Draw/iml_header.h>

 

#define TOPICFILE <GeoFun/app.tpp/all.i>

#include <Core/topic_group.h>

 

#define LAYOUTFILE <GeoFun/GeoFun.lay>

#include <CtrlCore/lay.h>

 

bool cfgAvailable;

 

class DrawCanvas : public ParentCtrl {

    typedef DrawCanvas CLASSNAME;

 

public:

    virtual void Paint(Draw& drw);

    DrawCanvas();

    template <class T>

    void DoPaint0(T& sw, int idraw = 0);

    void DoPaint(Painter& sw);

 

    struct ColorPolygon : Moveable<ColorPolygon> {

        Vector<Pointf> point;

        Vector<Pointf> CenR;

        Color lcolor;

        Color fcolorM1, fcolorM2;

        int penwidth;

        bool filled;

    };

 

    Vector<ColorPolygon> data;

 

    Color fcolorB1, fcolorB2;

    bool ShowGradient, ColorFill, Zoomed, ShowAnimation;

 

    double Radius1, BaseR, RollR;

    int ShowTo, AnimSpeed;

};

 

class GeoFun : public WithGeoFunLayout<TopWindow> {

public:

    typedef GeoFun CLASSNAME;

    GeoFun();

 

    double ArmLen;

 

    DrawCanvas dc1;

 

    WithInputLayout<ParentCtrl> InputPane;

 

    Splitter sp1;

    QtfRichObject qtfim;

 

    TimeCallback Animate;

 

    int ValP, ValQ, PenW, CurvT, GradientY;

    Color PenC, M1C, M2C, B1C, B2C;

 

    bool First;

    bool EpiCyclo, HypoCyclo, EpiTroch, HypoTroch, AnimMn;

 

    // Functions

    void About();

 

    void Exit();

 

    void FirstDraw();

 

    Image GetImage();

 

    void Help();

 

    virtual void Layout();

 

    void OptionColorFill();

    void OptionGradient();

    void OptionZoom();

 

    void PrepareData();

 

    void Print();

 

    void SaveToImageFile(String fileName);

    void SaveToAutoCadScript(String fileName);

    void SaveToSVG(String fileName);

    void SetAnimation();

    void SetAnimationSpeed();

    void SetCurveType(int CrvType);

 

    void SetCurveTypeMenu(int CrvType);

    void Serialize(Stream& s);

    void ShowAnimated();

 

    // Menu Functions

    void MainMenu(Bar& menu);

 

    void CurvesMenu(Bar& bar);

    void FileMenu(Bar& bar);

    void HelpMenu(Bar& bar);

    void SettingsMenu(Bar& bar);

};

 

} // namespace Upp

 

#endif

 

 

 

GeoFun.cpp

 

#include "GeoFun.h"

 

using namespace Upp;

 

#define IMAGECLASS GFImg

#define IMAGEFILE <GeoFun/GeoFun.iml>

#include <Draw/iml_source.h>

 

// When idraw = 1 it will create image at actual size based on radius values

// Else image created to screen window diaplay size

template <class T>

void DrawCanvas::DoPaint0(T& sw, int idraw)

{

    double x1, y1;

    int cnt1, cnt2;

    int RunTo;

 

    Sizef sz;

 

    if(idraw == 1) {

        sz = Sizef(2 * Radius1 + 20, 2 * Radius1 + 20);

    }

 

    else {

        sz = GetSize();

    }

 

    sw.Clear(White());

 

    x1 = sz.cx / 2;

    y1 = sz.cy / 2;

 

    // Show color fill. Draw bacground circle with color

 

    if(ColorFill) {

        if(ShowGradient) {

            sw.Ellipse(x1, y1, Radius1, Radius1).Fill(x1, y1, fcolorB1, Radius1, fcolorB2);

        }

 

        else {

            sw.Ellipse(x1, y1, Radius1, Radius1).Fill(fcolorB1);

        }

    }

 

    cnt1 = data.GetCount();

 

    for(int i = 0; i < data.GetCount(); i++) {

        Vector<Pointf>& p = data[i].point;

        sw.Move(x1 + p[0].x, y1 + p[0].y);

 

        cnt2 = p.GetCount();

 

        // If animation flag set do incremental display of curve

        // elase show all curve points.

 

        RunTo = ShowAnimation ? ShowTo : cnt2;

 

        if(RunTo > cnt2)

            RunTo = cnt2;

 

        for(int j = 1; j < RunTo; j++)

            sw.Line(x1 + p[j].x, y1 + p[j].y);

 

        sw.Stroke(data[i].penwidth, data[i].lcolor);

 

        sw.EvenOdd(true);

 

        if(ColorFill) {

            if(ShowGradient) {

                sw.Fill(x1, y1, data[i].fcolorM1, Radius1, data[i].fcolorM2, GRADIENT_REFLECT);

            }

 

            else {

                sw.Fill(data[i].fcolorM1);

            }

        }

 

        // Show if option animation set

 

        if(ShowAnimation) {

            sw.BeginOnPath(1.0);

            sw.DrawImage(0, -GFImg::Bee().GetHeight() / 2, GFImg::Bee());

            sw.End();

 

            sw.Ellipse(x1, y1, BaseR, BaseR).Stroke(3, Blue());

            sw.Ellipse(x1 + data[i].CenR[RunTo - 2].x, y1 + data[i].CenR[RunTo - 2].y, RollR,

                       RollR)

                .Stroke(3, LtBlue());

 

            sw.Move(x1, y1);

            sw.Line(x1 + data[i].CenR[RunTo - 2].x, y1 + data[i].CenR[RunTo - 2].y);

            sw.Line(x1 + data[i].point[RunTo - 2].x, y1 + data[i].point[RunTo - 2].y);

            sw.Stroke(3, Red());

            ColorFill = false; // this is required to stop colorfill if other options are

                               // changed during animation

        }

    }

}

 

DrawCanvas::DrawCanvas() {}

 

// at present this function is redundant but kept here to improve printing in future

void DrawCanvas::DoPaint(Painter& sw)

{

    bool painting = false;

 

    if(painting) {

        PaintingPainter h(4000, 4000);

        DoPaint0(h, 0);

        sw.Paint(h);

    }

 

    else

 

        DoPaint0(sw, 0);

}

 

void DrawCanvas::Paint(Draw& drw)

{

    Size sz = GetSize();

    ImageBuffer ib(sz);

    BufferPainter sw(ib);

 

    bool transparent = false;

 

    DoPaint(sw);

    drw.DrawImage(0, 0, ib);

}

 

Image GeoFun::GetImage()

{

    Size sz = Size(int(dc1.Radius1 * 2 + 20), int(dc1.Radius1 * 2 + 20));

    ImageBuffer ib(sz);

    BufferPainter bp(ib, MODE_ANTIALIASED);

    dc1.DoPaint0(bp, 1);

 

    return ib;

}

 

void GeoFun::SaveToImageFile(String fileName)

{

    GuiLock __;

 

    if(IsNull(fileName)) {

        FileSel fs;

 

        fs.Type("PNG file", "*.png");

        fs.Type("JPEG file", "*.jpg");

 

        if(!fs.ExecuteSaveAs(t_("Saving plot to PNG or JPEG file"))) {

            Exclamation(t_("Plot has not been saved"));

            return;

        }

 

        fileName = fs;

    }

 

    if(GetFileExt(fileName) == ".png") {

        PNGEncoder encoder;

        encoder.SaveFile(fileName, GetImage());

    }

 

    else if(GetFileExt(fileName) == ".jpg") {

        JPGEncoder encoder(90);

        encoder.SaveFile(fileName, GetImage());

    }

 

    else

        Exclamation(Format(t_("File format \"%s\" not found"), GetFileExt(fileName)));

}

 

void GeoFun::SaveToAutoCadScript(String fileName)

{

    if(IsNull(fileName)) {

        FileSel fs;

 

        fs.Type("SCR file", "*.scr");

 

        if(!fs.ExecuteSaveAs(t_("Saving plot to Polyline -- AutoCAD Script "))) {

            Exclamation(t_("Plot has not been saved"));

            return;

        }

 

        fileName = fs;

    }

 

    if(GetFileExt(fileName) == ".scr") {

 

        String sScr;

 

        for(int i = 0; i < dc1.data.GetCount(); i++) {

            sScr << "PLINE\n";

            Vector<Pointf>& p = dc1.data[i].point;

 

            for(int j = 0; j < p.GetCount(); j++)

                sScr << p[j].x << "," << p[j].y << "\n";

 

            sScr << "\nZ\nE\n";

        }

 

        FileOut fo;

 

        fo.Open(fileName);

        fo.Put(sScr);

        fo.Close();

    }

}

 

void GeoFun::SaveToSVG(String fileName)

{

    if(IsNull(fileName)) {

        FileSel fs;

 

        fs.Type("SVG file", "*.svg");

 

        if(!fs.ExecuteSaveAs(t_("Saving as SVG file "))) {

            Exclamation(t_("SVG has not been saved"));

            return;

        }

 

        fileName = fs;

    }

 

    if(GetFileExt(fileName) == ".svg") {

        String sXML;

 

        sXML.Clear();

 

        sXML << "<?xml version=\"1.0\" standalone=\"no\"?>";

        sXML << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" ";

        sXML << "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">";

        sXML << "<svg width=\"100%\" height=\"100%\" version=\"1.1\" ";

        sXML << "xmlns=\"http://www.w3.org/2000/svg\"> \n  \n";

 

        for(int i = 0; i < dc1.data.GetCount(); i++) {

            sXML << "\n<polygon points=\" ";

            Vector<Pointf>& p = dc1.data[i].point;

 

            for(int j = 0; j < p.GetCount(); j++)

                sXML << Format("%0.4f", p[j].x) << "," << Format("%0.4f", p[j].y) << " ";

 

            sXML << "\" style=\"fill:none;stroke:#00C000;stroke-width:0.4\" />\n";

        }

 

        sXML << "</svg>\n";

 

        FileOut fo;

        fo.Open(fileName);

        fo.Put(sXML);

        fo.Close();

    }

}

 

void GeoFun::Print()

{

    Report r;

    String sQtf;

 

    r.SetPageSize(4400, 4400);

 

    Size sz = Size(4200, 4200);

    Image im = GetImage();

 

    qtfim = CreatePNGObject(im, Size(600, 600), sz);

 

    sQtf << "[s0;= ";

    sQtf << qtfim << " ]";

 

    r << sQtf;

 

    Perform(r);

}

 

// This function calculates curve data points for display

void GeoFun::PrepareData()

{

    int p, q, pw;

 

    double a, b, h;

    double x, y;

    double Period, step, t;

 

    step = 1.0; // value in deg

 

    int q1 = InputPane.edValP;

 

    if(q1 > 0) {

        p = InputPane.edValP;

    }

 

    else {

        p = 1;

        InputPane.edValP.SetData(p);

    }

 

    q1 = InputPane.edValQ;

 

    if(q1 > 0) {

        q = InputPane.edValQ;

    }

 

    else {

        q = 1;

        InputPane.edValQ.SetData(q);

    }

 

    q1 = InputPane.edPenWidth;

 

    if(q1 > 0) {

        pw = InputPane.edPenWidth;

    }

 

    else {

        pw = 1;

        InputPane.edPenWidth.SetData(pw);

    }

 

    Period = 2 * M_PI * p;

 

    int iCrv = ~InputPane.CurveType;

 

    if((iCrv == 1) || (iCrv == 3)) {

        p = -p;

    }

 

    double tmp = InputPane.edBaseCircleRad;

 

    if(tmp < 10) {

        a = 10;

        InputPane.edBaseCircleRad.SetData(a);

    }

 

    else {

        a = InputPane.edBaseCircleRad;

    }

 

    b = (double)p * a / (double)q;

 

    dc1.BaseR = a;

    dc1.RollR = fabs(b);

 

    if(iCrv < 2) {

        h = fabs(b);

    }

 

    else {

        tmp = InputPane.edArmLength;

 

        if(tmp < 0) {

            h = 0;

            InputPane.edArmLength.SetData(h);

        }

 

        else {

            h = InputPane.edArmLength;

        }

    }

 

    dc1.Radius1 = fabs(a + b) + h;

 

    InputPane.RollingRad = "Rolling Radius : " + Format("%0.2f", b);

 

    dc1.Zoomed = InputPane.optZoom.GetData();

 

    if(dc1.Zoomed) {

        Size sz = dc1.GetSize();

        double dmax = sz.cx;

 

        if(sz.cy < dmax)

            dmax = sz.cy;

 

        dmax -= 10;

 

        double zScale = fabs(dmax / (2 * dc1.Radius1));

 

        a = a * zScale;

 

        h = h * zScale;

 

        b = b * zScale;

 

        dc1.BaseR = a;

 

        dc1.RollR = fabs(b);

 

        dc1.Radius1 = fabs(a + b) + h;

    }

 

    dc1.data.Clear();

 

    dc1.data.Add();

    dc1.data[0].point.Clear();

    dc1.data[0].CenR.Clear();

    dc1.data[0].lcolor = ~InputPane.LineColor;

    dc1.data[0].fcolorM1 = ~InputPane.FillColorM1;

    dc1.data[0].fcolorM2 = ~InputPane.FillColorM2;

    dc1.data[0].penwidth = pw;

 

    dc1.fcolorB1 = ~InputPane.FillColorB1;

    dc1.fcolorB2 = ~InputPane.FillColorB2;

 

    dc1.ShowGradient = ~InputPane.optGradient;

    dc1.ColorFill = ~InputPane.optColorFill;

 

    int NumSteps = abs((int)(2.0 * (double)p * 180.0 / step)) + 1;

 

    for(int i = 0; i < NumSteps; i++) {

        t = (double)i / (double)NumSteps * Period;

        x = (a + b) * cos(t) + h * cos(((a + b) / b) * t);

        y = (a + b) * sin(t) + h * sin(((a + b) / b) * t);

 

        Pointf p1;

        p1.Clear();

        p1.x = x;

        p1.y = y;

        dc1.data[0].point.Add(p1);

 

        p1.Clear();

        x = (a + b) * cos(t);

        y = (a + b) * sin(t);

        p1.x = x;

        p1.y = y;

        dc1.data[0].CenR.Add(p1);

    }

 

    Pointf p1;

 

    p1.x = dc1.data[0].point[0].x;

    p1.y = dc1.data[0].point[0].y;

    dc1.data[0].point.Add(p1);

 

    dc1.Refresh();

}

 

void GeoFun::ShowAnimated()

{

    int MaxCnt = dc1.data[0].point.GetCount();

 

    if(dc1.ShowAnimation) {

        if(dc1.ShowTo < MaxCnt) {

            dc1.Refresh();

            dc1.ShowTo += dc1.AnimSpeed;

        }

 

        else {

            dc1.ShowAnimation = false;

        }

    }

 

    else {

        Animate.Kill();

        PrepareData();

    }

}

 

void GeoFun::SetAnimation()

{

    dc1.AnimSpeed = InputPane.edAnimSpeed.GetData();

    dc1.ShowTo = 5;

 

    dc1.ShowAnimation = dc1.ShowAnimation ? false : true;

    dc1.ColorFill = false;

 

    if(dc1.ShowAnimation) {

        InputPane.btnShowAnimation.SetLabel("Stop Animation");

    }

 

    else {

        InputPane.btnShowAnimation.SetLabel("Start Animation");

    }

 

    Animate.KillSet(-50, [=] { ShowAnimated(); });

}

 

void GeoFun::FirstDraw()

{

    First = false;

    PrepareData();

 

    DUMP("First Draw");

}

 

void GeoFun::Serialize(Stream& s)

{

    s % InputPane.edArmLength % InputPane.edBaseCircleRad % InputPane.edPenWidth

 

        % InputPane.edValP % InputPane.edValQ

 

        % InputPane.LineColor

 

        % InputPane.FillColorM1 % InputPane.FillColorM2 % InputPane.FillColorB1 %

        InputPane.FillColorB2

 

        % InputPane.optGradient % InputPane.optColorFill % InputPane.CurveType %

        InputPane.optZoom

 

        % InputPane.edAnimSpeed;

 

    SerializePlacement(s);

}

 

// Using layout to redraw on windows resize

void GeoFun::Layout()

{

    if(!First) {

        PrepareData();

    }

 

    TopWindow::Layout();

}

 

void GeoFun::About()

{

    WithAboutLayout<TopWindow> dlg;

    dlg.AboutText = GetTopic("topic://GeoFun/app/About$en-us").text;

    CtrlLayoutOK(dlg, "About");

    dlg.CenterScreen();

    dlg.Run();

}

 

void GeoFun::Help()

{

    HelpWindow helpme;

    helpme.GoTo("topic://GeoFun/app/Help$en-us");

    helpme.Execute();

}

 

void GeoFun::Exit() { Close(); }

 

void GeoFun::SetAnimationSpeed()

{

    dc1.AnimSpeed = InputPane.edAnimSpeed.GetData();

 

    if(dc1.AnimSpeed < 1)

        dc1.AnimSpeed = 1;

 

    if(dc1.AnimSpeed > 20)

        dc1.AnimSpeed = 20;

 

    InputPane.edAnimSpeed.SetData(dc1.AnimSpeed);

}

 

void GeoFun::OptionColorFill()

{

    int i = InputPane.optColorFill.Get();

    i = i ? 0 : 1;

    InputPane.optColorFill.Set(i);

    PrepareData();

}

 

void GeoFun::OptionGradient()

{

    int i = InputPane.optGradient.Get();

    i = i ? 0 : 1;

    InputPane.optGradient.Set(i);

    PrepareData();

}

 

void GeoFun::OptionZoom()

{

    int i = InputPane.optZoom.Get();

    i = i ? 0 : 1;

    InputPane.optZoom.Set(i);

    PrepareData();

}

 

void GeoFun::SetCurveType(int CrvType)

{

    InputPane.CurveType.SetData(CrvType);

    SetCurveTypeMenu(CrvType);

}

 

void GeoFun::SetCurveTypeMenu(int CrvType)

{

    EpiCyclo = HypoCyclo = EpiTroch = HypoTroch = false;

 

    switch(CrvType) {

 

    case 1:

        HypoCyclo = true;

        break;

 

    case 2:

        EpiTroch = true;

        break;

 

    case 3:

        HypoTroch = true;

        break;

 

    default:

        EpiCyclo = true;

    }

 

    PrepareData();

}

 

// Menu Functions

 

void GeoFun::SettingsMenu(Bar& bar)

{

    bar.Add(t_("Color Fill"), [=] { OptionColorFill(); })

        .Check(dc1.ColorFill)

        .Help(t_("Change settings"));

    bar.Add(t_("Gradient Fill"), [=] { OptionGradient(); })

        .Check(dc1.ShowGradient)

        .Help(t_("Change settings"));

    bar.Add(t_("Zoom Fit"), [=] { OptionZoom(); })

        .Check(dc1.Zoomed)

        .Help(t_("Zoom fit to window area"));

}

 

void GeoFun::FileMenu(Bar& bar)

{

    bar.Add(t_("Save Image"), CtrlImg::save_as(), [=] { SaveToImageFile(""); })

        .Help(t_("Save Image as PNG or JPG"));

    bar.Add(t_("Save AutoCAD Script"), CtrlImg::save(), [=] { SaveToAutoCadScript(""); })

        .Help(t_("Save as AutoCAD Script (.scr) file"));

    bar.Add(t_("Save as SVG"), CtrlImg::save(), [=] { SaveToSVG(""); })

        .Help(t_("Save as Scalable vector graphics (.svg) file"));

    bar.Separator();

    bar.Add(t_("Print"), CtrlImg::print(), [=] { Print(); })

        .Help(t_("Print the image , will fit to A4 page"));

    bar.Separator();

    bar.Add(t_("Exit"), [=] { Exit(); }).Help(t_("Exit the application"));

}

 

void GeoFun::CurvesMenu(Bar& bar)

{

    bar.Add(t_("Epicycloid"), [=] { SetCurveType(0); })

        .Help(t_("Plot Epicycloid curve"))

        .Check(EpiCyclo);

    bar.Add(t_("Hypocycloid"), [=] { SetCurveType(1); })

        .Help(t_("Plot Hypocycloid curve"))

        .Check(HypoCyclo);

    bar.Add(t_("Epitrochoid"), [=] { SetCurveType(2); })

        .Help(t_("Plot Epitrochoid curve"))

        .Check(EpiTroch);

    bar.Add(t_("Hypotrochoid"), [=] { SetCurveType(3); })

        .Help(t_("Plot Hypotrochoid curve"))

        .Check(HypoTroch);

    bar.Separator();

    bar.Add(t_("Animated Plot"), [=] { SetAnimation(); })

        .Help(t_("Show animation of the curve drawing"))

        .Check(AnimMn);

}

 

void GeoFun::MainMenu(Bar& bar)

{

    bar.Sub(t_("File"), [=](Bar& bar) { FileMenu(bar); });

    bar.Sub(t_("Curves"), [=](Bar& bar) { CurvesMenu(bar); });

    bar.Sub(t_("Options"), [=](Bar& bar) { SettingsMenu(bar); });

    bar.Sub(t_("Assist"), [=](Bar& bar) { HelpMenu(bar); });

}

 

void GeoFun::HelpMenu(Bar& bar)

{

    bar.Add(t_("About"), [=] { About(); }).Help(t_("About GeoFun"));

    bar.Separator();

    bar.Add(t_("Help"), CtrlImg::help(), [=] { Help(); }).Help(t_("Help GeoFun"));

}

 

GeoFun::GeoFun()

{

    CtrlLayout(*this, "GeoFun : Enjoy Geometric Curves");

 

    Icon(GFImg::gficon());

 

    CtrlLayout(InputPane);

 

    Sizeable().Zoomable();

 

    InputPane.btnImg << [=] { SaveToImageFile(""); };

    InputPane.btnPrint << [=] { Print(); };

    InputPane.btnShowAnimation << [=] { SetAnimation(); };

 

    Add(dc1.HSizePosZ(5, 160).VSizePosZ(25, 5));

    Add(InputPane.RightPosZ(5, 150).VSizePosZ(2, 5));

    BackPaint();

 

    dc1.data.Clear();

 

    // Check config file available else set default data

    if(!cfgAvailable) {

        InputPane.edArmLength.SetData(112);

        InputPane.edBaseCircleRad.SetData(145);

        InputPane.edPenWidth.SetData(3);

        InputPane.edValP.SetData(5);

        InputPane.edValQ.SetData(12);

        InputPane.edAnimSpeed.SetData(5);

 

        InputPane.LineColor.SetData(Blue());

        InputPane.FillColorM1.SetData(LtGreen());

        InputPane.FillColorM2.SetData(Yellow());

        InputPane.FillColorB1.SetData(Blue());

        InputPane.FillColorB2.SetData(LtCyan());

 

        InputPane.optGradient.Set(1);

        InputPane.optColorFill.Set(1);

        InputPane.CurveType.SetData(2);

    }

 

    InputPane.CurveType.WhenAction

        << [=] { SetCurveTypeMenu((int)InputPane.CurveType.GetData()); };

 

    InputPane.optGradient.WhenAction << [=] { PrepareData(); };

    InputPane.optColorFill.WhenAction << [=] { PrepareData(); };

 

    InputPane.FillColorB1.WhenAction << [=] { PrepareData(); };

    InputPane.FillColorB2.WhenAction << [=] { PrepareData(); };

    InputPane.FillColorM1.WhenAction << [=] { PrepareData(); };

    InputPane.FillColorM2.WhenAction << [=] { PrepareData(); };

    InputPane.LineColor.WhenAction << [=] { PrepareData(); };

 

    InputPane.edPenWidth.WhenAction << [=] { PrepareData(); };

    InputPane.edValP.WhenAction << [=] { PrepareData(); };

    InputPane.edValQ.WhenAction << [=] { PrepareData(); };

    InputPane.edArmLength.WhenAction << [=] { PrepareData(); };

    InputPane.edBaseCircleRad.WhenAction << [=] { PrepareData(); };

    InputPane.edAnimSpeed.WhenAction << [=] { SetAnimationSpeed(); };

    InputPane.optZoom.WhenAction << [=] { PrepareData(); };

 

    // Set timercallback to do first painting with calculations

    // You can not call this directly from constructor

    SetTimeCallback(200, [=] { FirstDraw(); });

 

    dc1.ShowTo = 5; // start point of animation.

 

    menu.Set([=](Bar& bar) { MainMenu(bar); });

    dc1.ShowAnimation = false;

}

 

GUI_APP_MAIN

{

    GeoFun gf;

    gf.First = true;

    String cfgfile = ConfigFile();

 

    if(FileExists(cfgfile)) {

        cfgAvailable = true;

 

        if(!LoadFromFile(gf, cfgfile)) {

            cfgAvailable = false;

            Exclamation("Error loading configuration file!");

        }

    }

 

    else {

        cfgAvailable = false;

    }

 

    gf.Run();

 

    StoreToFile(gf);

}

 

 

 

GeoFun.lay

 

LAYOUT(GeoFunLayout, 680, 484)

    ITEM(MenuBar, menu, LeftPosZ(4, 536).TopPosZ(4, 20))

END_LAYOUT

 

LAYOUT(InputLayout, 150, 464)

    ITEM(Upp::EditDoubleSpin, edBaseCircleRad, SetInc(5).AlignRight(true).LeftPosZ(84, 60).TopPosZ(16, 19))

    ITEM(Upp::EditDoubleSpin, edArmLength, SetInc(5).AlignRight(true).LeftPosZ(84, 60).TopPosZ(36, 19))

    ITEM(Upp::EditIntSpin, edValP, AlignRight(true).LeftPosZ(84, 60).TopPosZ(56, 19))

    ITEM(Upp::EditIntSpin, edValQ, AlignRight(true).LeftPosZ(84, 60).TopPosZ(76, 19))

    ITEM(Upp::EditIntSpin, edPenWidth, AlignRight(true).LeftPosZ(84, 60).TopPosZ(96, 19))

    ITEM(Upp::Switch, CurveType, SetLabel(t_("Epicycloid\nHypocycloid\nEpitrochoid\nHypotrochoid")).LeftPosZ(8, 128).TopPosZ(260, 64))

    ITEM(Upp::LabelBox, InputData, SetLabel(t_("Input Data")).LeftPosZ(4, 144).TopPosZ(0, 324))

    ITEM(Upp::Option, optZoom, SetLabel(t_("Zoom to Fit")).LeftPosZ(12, 124).TopPosZ(224, 16))

    ITEM(Upp::Option, optGradient, SetLabel(t_("Gradient Fill")).LeftPosZ(12, 124).TopPosZ(208, 16))

    ITEM(Upp::Option, optColorFill, SetLabel(t_("Color Fill")).LeftPosZ(12, 124).TopPosZ(192, 16))

    ITEM(Upp::ColorPusher, LineColor, LeftPosZ(84, 28).TopPosZ(124, 16))

    ITEM(Upp::ColorPusher, FillColorM1, LeftPosZ(84, 28).TopPosZ(144, 16))

    ITEM(Upp::ColorPusher, FillColorM2, HSizePosZ(112, 10).TopPosZ(144, 16))

    ITEM(Upp::ColorPusher, FillColorB1, LeftPosZ(84, 28).TopPosZ(168, 16))

    ITEM(Upp::ColorPusher, FillColorB2, HSizePosZ(112, 10).TopPosZ(168, 16))

    ITEM(Upp::Label, dv___15, SetLabel(t_("Fill Color Back")).SetAlign(Upp::ALIGN_RIGHT).LeftPosZ(0, 76).TopPosZ(164, 20))

    ITEM(Upp::Label, dv___16, SetLabel(t_("Fill Color Main")).SetAlign(Upp::ALIGN_RIGHT).LeftPosZ(0, 76).TopPosZ(144, 16))

    ITEM(Upp::Label, dv___17, SetLabel(t_("Curve Type")).SetFont(Upp::StdFont().Bold()).LeftPosZ(8, 128).TopPosZ(240, 18))

    ITEM(Upp::Label, dv___18, SetLabel(t_("Line Color")).SetAlign(Upp::ALIGN_RIGHT).LeftPosZ(0, 76).TopPosZ(124, 16))

    ITEM(Upp::Label, dv___19, SetLabel(t_("Vertex Points")).SetAlign(Upp::ALIGN_RIGHT).LeftPosZ(0, 76).TopPosZ(72, 26))

    ITEM(Upp::Label, dv___20, SetLabel(t_("Draw Radius")).SetAlign(Upp::ALIGN_RIGHT).LeftPosZ(0, 76).TopPosZ(32, 26))

    ITEM(Upp::Label, dv___21, SetLabel(t_("Revolutions")).SetAlign(Upp::ALIGN_RIGHT).LeftPosZ(0, 76).TopPosZ(52, 26))

    ITEM(Upp::Label, dv___22, SetLabel(t_("Base Radius")).SetAlign(Upp::ALIGN_RIGHT).LeftPosZ(8, 68).TopPosZ(12, 26))

    ITEM(Upp::Label, dv___23, SetLabel(t_("Width")).SetAlign(Upp::ALIGN_RIGHT).LeftPosZ(0, 76).TopPosZ(96, 20))

    ITEM(Upp::EditIntSpin, edAnimSpeed, LeftPosZ(84, 44).TopPosZ(412, 28))

    ITEM(Upp::Label, dv___25, SetLabel(t_("Animation\nSpeed")).SetAlign(Upp::ALIGN_RIGHT).LeftPosZ(0, 76).TopPosZ(412, 28))

    ITEM(Upp::Label, RollingRad, SetLabel(t_("Rolling Radius")).LeftPosZ(4, 140).TopPosZ(440, 20))

    ITEM(Upp::Button, btnImg, SetLabel(t_("Save as Image")).HSizePosZ(4, 6).TopPosZ(356, 24))

    ITEM(Upp::Button, btnPrint, SetLabel(t_("Print")).HSizePosZ(4, 6).TopPosZ(384, 24))

    ITEM(Upp::Button, btnShowAnimation, SetLabel(t_("Animated Plot")).HSizePosZ(4, 6).TopPosZ(328, 24))

END_LAYOUT

 

LAYOUT(HelpDialogLayout, 400, 200)

END_LAYOUT

 

LAYOUT(AboutLayout, 480, 328)

    ITEM(Upp::LabelBox, dv___0, SetLabel(t_("GeoFun")).HSizePosZ(4, 4).VSizePosZ(4, 28))

    ITEM(Upp::RichTextCtrl, AboutText, HSizePosZ(8, 8).VSizePosZ(20, 32))

    ITEM(Upp::Button, ok, SetLabel(t_("OK")).LeftPosZ(4, 472).BottomPosZ(5, 19))

END_LAYOUT

 

 

 

 

 

Do you want to contribute?