DISTRHO Plugin Framework
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

441 lines
13KB

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