DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

Demo.cpp (13054B)


      1 /*
      2  * DISTRHO Plugin Framework (DPF)
      3  * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com>
      4  *
      5  * Permission to use, copy, modify, and/or distribute this software for any purpose with
      6  * or without fee is hereby granted, provided that the above copyright notice and this
      7  * permission notice appear in all copies.
      8  *
      9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
     10  * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
     11  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
     12  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
     13  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #include "tests.hpp"
     18 
     19 #include "widgets/ExampleColorWidget.hpp"
     20 #include "widgets/ExampleImagesWidget.hpp"
     21 #include "widgets/ExampleRectanglesWidget.hpp"
     22 #include "widgets/ExampleShapesWidget.hpp"
     23 #ifdef DGL_OPENGL
     24 #include "widgets/ExampleTextWidget.hpp"
     25 #endif
     26 #include "widgets/ResizeHandle.hpp"
     27 
     28 #include "demo_res/DemoArtwork.cpp"
     29 #include "images_res/CatPics.cpp"
     30 
     31 #ifdef DGL_CAIRO
     32 #include "../dgl/Cairo.hpp"
     33 typedef DGL_NAMESPACE::CairoImage DemoImage;
     34 #endif
     35 #ifdef DGL_OPENGL
     36 #include "../dgl/OpenGL.hpp"
     37 typedef DGL_NAMESPACE::OpenGLImage DemoImage;
     38 #endif
     39 #ifdef DGL_VULKAN
     40 #include "../dgl/Vulkan.hpp"
     41 typedef DGL_NAMESPACE::VulkanImage DemoImage;
     42 #endif
     43 
     44 START_NAMESPACE_DGL
     45 
     46 // Partial specialization is not allowed in C++, so we need to define these here
     47 template<> inline
     48 ExampleImagesWidget<SubWidget, DemoImage>::ExampleImagesWidget(Widget* const parentWidget)
     49 : SubWidget(parentWidget) { init(parentWidget->getApp()); }
     50 
     51 template<> inline
     52 ExampleImagesWidget<TopLevelWidget, DemoImage>::ExampleImagesWidget(Window& windowToMapTo)
     53 : TopLevelWidget(windowToMapTo) { init(windowToMapTo.getApp()); }
     54 
     55 template<>
     56 ExampleImagesWidget<StandaloneWindow, DemoImage>::ExampleImagesWidget(Application& app)
     57 : StandaloneWindow(app) { init(app); done(); }
     58 
     59 typedef ExampleImagesWidget<SubWidget, DemoImage> ExampleImagesSubWidget;
     60 typedef ExampleImagesWidget<TopLevelWidget, DemoImage> ExampleImagesTopLevelWidget;
     61 typedef ExampleImagesWidget<StandaloneWindow, DemoImage> ExampleImagesStandaloneWindow;
     62 
     63 // --------------------------------------------------------------------------------------------------------------------
     64 // Left side tab-like widget
     65 
     66 class LeftSideWidget : public SubWidget
     67 {
     68 public:
     69 #ifdef DGL_OPENGL
     70     static const int kPageCount = 5;
     71 #else
     72     static const int kPageCount = 4;
     73 #endif
     74 
     75     class Callback
     76     {
     77     public:
     78         virtual ~Callback() {}
     79         virtual void curPageChanged(int curPage) = 0;
     80     };
     81 
     82     LeftSideWidget(Widget* parent, Callback* const cb)
     83         : SubWidget(parent),
     84           callback(cb),
     85           curPage(0),
     86           curHover(-1)
     87     {
     88 
     89         using namespace DemoArtwork;
     90         img1.loadFromMemory(ico1Data, ico1Width, ico1Height, kImageFormatBGR);
     91         img2.loadFromMemory(ico2Data, ico2Width, ico2Height, kImageFormatBGR);
     92         img3.loadFromMemory(ico3Data, ico3Width, ico2Height, kImageFormatBGR);
     93         img4.loadFromMemory(ico4Data, ico4Width, ico4Height, kImageFormatBGR);
     94 
     95 #ifdef DGL_OPENGL
     96         img5.loadFromMemory(ico5Data, ico5Width, ico5Height, kImageFormatBGR);
     97 
     98         // for text
     99         nvg.loadSharedResources();
    100 #endif
    101     }
    102 
    103 protected:
    104     void onDisplay() override
    105     {
    106         const GraphicsContext& context(getGraphicsContext());
    107         const double scaleFactor = getWindow().getScaleFactor();
    108         const int iconSize = bgIcon.getWidth();
    109 
    110         Color(0.027f, 0.027f, 0.027f).setFor(context);
    111         Rectangle<uint>(0, 0, getSize()).draw(context);
    112 
    113         bgIcon.setY(curPage * iconSize + curPage * 3 * scaleFactor);
    114 
    115         Color(0.129f, 0.129f, 0.129f).setFor(context);
    116         bgIcon.draw(context);
    117 
    118         Color(0.184f, 0.184f, 0.184f).setFor(context);
    119         bgIcon.drawOutline(context);
    120 
    121         if (curHover != curPage && curHover != -1)
    122         {
    123             Rectangle<int> rHover(1 * scaleFactor, curHover * iconSize + curHover * 3 * scaleFactor,
    124                                   iconSize - 2 * scaleFactor, iconSize - 2 * scaleFactor);
    125 
    126             Color(0.071f, 0.071f, 0.071f).setFor(context);
    127             rHover.draw(context);
    128 
    129             Color(0.102f, 0.102f, 0.102f).setFor(context);
    130             rHover.drawOutline(context);
    131         }
    132 
    133         Color(0.184f, 0.184f, 0.184f).setFor(context);
    134         lineSep.draw(context);
    135 
    136         // reset color
    137         Color(1.0f, 1.0f, 1.0f, 1.0f).setFor(context, true);
    138 
    139         const int pad = iconSize/2 - DemoArtwork::ico1Width/2;
    140 
    141         img1.drawAt(context, pad, pad);
    142         img2.drawAt(context, pad, pad + 3 + iconSize);
    143         img3.drawAt(context, pad, pad + 6 + iconSize*2);
    144         img4.drawAt(context, pad, pad + 9 + iconSize*3);
    145 
    146 #ifdef DGL_OPENGL
    147         img5.drawAt(context, pad, pad + 12 + iconSize*4);
    148 
    149         // draw some text
    150         nvg.beginFrame(this);
    151 
    152         nvg.fontSize(23.0f * scaleFactor);
    153         nvg.textAlign(NanoVG::ALIGN_LEFT|NanoVG::ALIGN_TOP);
    154         //nvg.textLineHeight(20.0f);
    155 
    156         nvg.fillColor(220,220,220,220);
    157         nvg.textBox(10 * scaleFactor, 420 * scaleFactor, iconSize, "Haha,", nullptr);
    158         nvg.textBox(15 * scaleFactor, 440 * scaleFactor, iconSize, "Look!", nullptr);
    159 
    160         nvg.endFrame();
    161 #endif
    162     }
    163 
    164     bool onMouse(const MouseEvent& ev) override
    165     {
    166         if (ev.button != 1 || ! ev.press)
    167             return false;
    168         if (! contains(ev.pos))
    169             return false;
    170 
    171         const int iconSize = bgIcon.getWidth();
    172 
    173         for (int i=0; i<kPageCount; ++i)
    174         {
    175             bgIcon.setY(i*iconSize + i*3);
    176 
    177             if (bgIcon.contains(ev.pos))
    178             {
    179                 curPage = i;
    180                 callback->curPageChanged(i);
    181                 repaint();
    182                 break;
    183             }
    184         }
    185 
    186         return true;
    187     }
    188 
    189     bool onMotion(const MotionEvent& ev) override
    190     {
    191         if (contains(ev.pos))
    192         {
    193             const int iconSize = bgIcon.getWidth();
    194 
    195             for (int i=0; i<kPageCount; ++i)
    196             {
    197                 bgIcon.setY(i*iconSize + i*3);
    198 
    199                 if (bgIcon.contains(ev.pos))
    200                 {
    201                     if (curHover == i)
    202                         return true;
    203 
    204                     curHover = i;
    205                     repaint();
    206                     return true;
    207                 }
    208             }
    209 
    210             if (curHover == -1)
    211                 return true;
    212 
    213             curHover = -1;
    214             repaint();
    215             return true;
    216         }
    217         else
    218         {
    219             if (curHover == -1)
    220                 return false;
    221 
    222             curHover = -1;
    223             repaint();
    224             return true;
    225         }
    226     }
    227 
    228     void onResize(const ResizeEvent& ev) override
    229     {
    230         const uint width  = ev.size.getWidth();
    231         const uint height = ev.size.getHeight();
    232         const double scaleFactor = getWindow().getScaleFactor();
    233 
    234         bgIcon.setWidth(width - 4 * scaleFactor);
    235         bgIcon.setHeight(width - 4 * scaleFactor);
    236 
    237         lineSep.setStartPos(width, 0);
    238         lineSep.setEndPos(width, height);
    239     }
    240 
    241 private:
    242     Callback* const callback;
    243     int curPage, curHover;
    244     Rectangle<double> bgIcon;
    245     Line<int> lineSep;
    246     DemoImage img1, img2, img3, img4, img5;
    247 
    248 #ifdef DGL_OPENGL
    249     // for text
    250     NanoVG nvg;
    251 #endif
    252 };
    253 
    254 // --------------------------------------------------------------------------------------------------------------------
    255 // Main Demo Window, having a left-side tab-like widget and main area for current widget
    256 
    257 class DemoWindow : public StandaloneWindow,
    258                    public LeftSideWidget::Callback
    259 {
    260     static const int kSidebarWidth = 81;
    261 
    262 public:
    263 #ifdef DGL_CAIRO
    264     static constexpr const char* const kExampleWidgetName = "Demo - Cairo";
    265 #endif
    266 #ifdef DGL_OPENGL
    267     static constexpr const char* const kExampleWidgetName = "Demo - OpenGL";
    268 #endif
    269 #ifdef DGL_VULKAN
    270     static constexpr const char* const kExampleWidgetName = "Demo - Vulkan";
    271 #endif
    272 
    273     DemoWindow(Application& app)
    274         : StandaloneWindow(app),
    275           curWidget(nullptr)
    276     {
    277         const ScopedGraphicsContext sgc(*this);
    278         const double scaleFactor = getScaleFactor();
    279 
    280         wColor = new ExampleColorSubWidget(this);
    281         wColor->hide();
    282         wColor->setAbsoluteX(kSidebarWidth * scaleFactor);
    283 
    284         wImages = new ExampleImagesSubWidget(this);
    285         wImages->hide();
    286         wImages->setAbsoluteX(kSidebarWidth * scaleFactor);
    287 
    288         wRects = new ExampleRectanglesSubWidget(this);
    289         wRects->hide();
    290         wRects->setAbsoluteX(kSidebarWidth * scaleFactor);
    291 
    292         wShapes = new ExampleShapesSubWidget(this);
    293         wShapes->hide();
    294         wShapes->setAbsoluteX(kSidebarWidth * scaleFactor);
    295 
    296 #ifdef DGL_OPENGL
    297         wText = new ExampleTextSubWidget(this),
    298         wText->hide();
    299         wText->setAbsoluteX(kSidebarWidth * scaleFactor);
    300 #endif
    301         wLeft = new LeftSideWidget(this, this),
    302         wLeft->setAbsolutePos(2 * scaleFactor, 2 * scaleFactor);
    303 
    304         resizer = new ResizeHandle(this);
    305 
    306         curPageChanged(0);
    307         done();
    308     }
    309 
    310 protected:
    311     void curPageChanged(int curPage) override
    312     {
    313         if (curWidget != nullptr)
    314             curWidget->hide();
    315 
    316         switch (curPage)
    317         {
    318         case 0:
    319             curWidget = wColor;
    320             break;
    321         case 1:
    322             curWidget = wImages;
    323             break;
    324         case 2:
    325             curWidget = wRects;
    326             break;
    327         case 3:
    328             curWidget = wShapes;
    329             break;
    330 #ifdef DGL_OPENGL
    331         case 4:
    332             curWidget = wText;
    333             break;
    334 #endif
    335         default:
    336             curWidget = nullptr;
    337             break;
    338         }
    339 
    340         if (curWidget != nullptr)
    341             curWidget->show();
    342     }
    343 
    344     void onDisplay() override
    345     {
    346     }
    347 
    348     void onReshape(uint width, uint height) override
    349     {
    350         StandaloneWindow::onReshape(width, height);
    351 
    352         const double scaleFactor = getScaleFactor();
    353 
    354         if (width < kSidebarWidth * scaleFactor)
    355             return;
    356 
    357         const Size<uint> size(width - kSidebarWidth * scaleFactor, height);
    358         wColor->setSize(size);
    359         wImages->setSize(size);
    360         wRects->setSize(size);
    361         wShapes->setSize(size);
    362 #ifdef DGL_OPENGL
    363         wText->setSize(size);
    364 #endif
    365         wLeft->setSize((kSidebarWidth - 4) * scaleFactor, (height - 4) * scaleFactor);
    366     }
    367 
    368 private:
    369     ScopedPointer<ExampleColorSubWidget> wColor;
    370     ScopedPointer<ExampleImagesSubWidget> wImages;
    371     ScopedPointer<ExampleRectanglesSubWidget> wRects;
    372     ScopedPointer<ExampleShapesSubWidget> wShapes;
    373 #ifdef DGL_OPENGL
    374     ScopedPointer<ExampleTextSubWidget> wText;
    375 #endif
    376     ScopedPointer<LeftSideWidget> wLeft;
    377     ScopedPointer<ResizeHandle> resizer;
    378 
    379     Widget* curWidget;
    380 };
    381 
    382 // --------------------------------------------------------------------------------------------------------------------
    383 // Special handy function that runs a StandaloneWindow inside the function scope
    384 
    385 template <class ExampleWidgetStandaloneWindow>
    386 void createAndShowExampleWidgetStandaloneWindow(Application& app)
    387 {
    388     ExampleWidgetStandaloneWindow swin(app);
    389     const double scaleFactor = swin.getScaleFactor();
    390     swin.setGeometryConstraints(128 * scaleFactor, 128 * scaleFactor);
    391     swin.setResizable(true);
    392     swin.setSize(600 * scaleFactor, 500 * scaleFactor);
    393     swin.setTitle(ExampleWidgetStandaloneWindow::kExampleWidgetName);
    394     swin.show();
    395     app.exec();
    396 }
    397 
    398 // --------------------------------------------------------------------------------------------------------------------
    399 
    400 END_NAMESPACE_DGL
    401 
    402 int main(int argc, char* argv[])
    403 {
    404     USE_NAMESPACE_DGL;
    405     using DGL_NAMESPACE::Window;
    406 
    407     Application app;
    408 
    409     if (argc > 1)
    410     {
    411         /**/ if (std::strcmp(argv[1], "color") == 0)
    412             createAndShowExampleWidgetStandaloneWindow<ExampleColorStandaloneWindow>(app);
    413         else if (std::strcmp(argv[1], "images") == 0)
    414             createAndShowExampleWidgetStandaloneWindow<ExampleImagesStandaloneWindow>(app);
    415         else if (std::strcmp(argv[1], "rectangles") == 0)
    416             createAndShowExampleWidgetStandaloneWindow<ExampleRectanglesStandaloneWindow>(app);
    417         else if (std::strcmp(argv[1], "shapes") == 0)
    418             createAndShowExampleWidgetStandaloneWindow<ExampleShapesStandaloneWindow>(app);
    419 #ifdef DGL_OPENGL
    420         else if (std::strcmp(argv[1], "text") == 0)
    421             createAndShowExampleWidgetStandaloneWindow<ExampleTextStandaloneWindow>(app);
    422 #endif
    423         else
    424             d_stderr2("Invalid demo mode, must be one of: color, images, rectangles or shapes");
    425     }
    426     else
    427     {
    428         createAndShowExampleWidgetStandaloneWindow<DemoWindow>(app);
    429     }
    430 
    431     return 0;
    432 }
    433 
    434 // --------------------------------------------------------------------------------------------------------------------