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.

435 lines
13KB

  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. #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. #ifdef DGL_CAIRO
  211. static constexpr const char* const kExampleWidgetName = "Demo - Cairo";
  212. #endif
  213. #ifdef DGL_OPENGL
  214. static constexpr const char* const kExampleWidgetName = "Demo - OpenGL";
  215. #endif
  216. #ifdef DGL_VULKAN
  217. static constexpr const char* const kExampleWidgetName = "Demo - Vulkan";
  218. #endif
  219. DemoWindow(Application& app)
  220. : StandaloneWindow(app),
  221. curWidget(nullptr)
  222. {
  223. const ScopedGraphicsContext sgc(*this);
  224. const double scaleFactor = getScaleFactor();
  225. wColor = new ExampleColorSubWidget(this);
  226. wColor->hide();
  227. wColor->setAbsoluteX(kSidebarWidth * scaleFactor);
  228. wImages = new ExampleImagesSubWidget(this);
  229. wImages->hide();
  230. wImages->setAbsoluteX(kSidebarWidth * scaleFactor);
  231. wRects = new ExampleRectanglesSubWidget(this);
  232. wRects->hide();
  233. wRects->setAbsoluteX(kSidebarWidth * scaleFactor);
  234. wShapes = new ExampleShapesSubWidget(this);
  235. wShapes->hide();
  236. wShapes->setAbsoluteX(kSidebarWidth * scaleFactor);
  237. #ifdef DGL_OPENGL
  238. wText = new ExampleTextSubWidget(this),
  239. wText->hide();
  240. wText->setAbsoluteX(kSidebarWidth * scaleFactor);
  241. #endif
  242. wLeft = new LeftSideWidget(this, this),
  243. wLeft->setAbsolutePos(2 * scaleFactor, 2 * scaleFactor);
  244. resizer = new ResizeHandle(this);
  245. curPageChanged(0);
  246. done();
  247. }
  248. protected:
  249. void curPageChanged(int curPage) override
  250. {
  251. if (curWidget != nullptr)
  252. curWidget->hide();
  253. switch (curPage)
  254. {
  255. case 0:
  256. curWidget = wColor;
  257. break;
  258. case 1:
  259. curWidget = wImages;
  260. break;
  261. case 2:
  262. curWidget = wRects;
  263. break;
  264. case 3:
  265. curWidget = wShapes;
  266. break;
  267. #ifdef DGL_OPENGL
  268. case 4:
  269. curWidget = wText;
  270. break;
  271. #endif
  272. default:
  273. curWidget = nullptr;
  274. break;
  275. }
  276. if (curWidget != nullptr)
  277. curWidget->show();
  278. }
  279. void onDisplay() override
  280. {
  281. }
  282. void onReshape(uint width, uint height) override
  283. {
  284. StandaloneWindow::onReshape(width, height);
  285. const double scaleFactor = getScaleFactor();
  286. if (width < kSidebarWidth * scaleFactor)
  287. return;
  288. const Size<uint> size(width - kSidebarWidth * scaleFactor, height);
  289. wColor->setSize(size);
  290. wImages->setSize(size);
  291. wRects->setSize(size);
  292. wShapes->setSize(size);
  293. #ifdef DGL_OPENGL
  294. wText->setSize(size);
  295. #endif
  296. wLeft->setSize((kSidebarWidth - 4) * scaleFactor, (height - 4) * scaleFactor);
  297. }
  298. private:
  299. ScopedPointer<ExampleColorSubWidget> wColor;
  300. ScopedPointer<ExampleImagesSubWidget> wImages;
  301. ScopedPointer<ExampleRectanglesSubWidget> wRects;
  302. ScopedPointer<ExampleShapesSubWidget> wShapes;
  303. #ifdef DGL_OPENGL
  304. ScopedPointer<ExampleTextSubWidget> wText;
  305. #endif
  306. ScopedPointer<LeftSideWidget> wLeft;
  307. ScopedPointer<ResizeHandle> resizer;
  308. Widget* curWidget;
  309. };
  310. // --------------------------------------------------------------------------------------------------------------------
  311. // Special handy function that runs a StandaloneWindow inside the function scope
  312. template <class ExampleWidgetStandaloneWindow>
  313. void createAndShowExampleWidgetStandaloneWindow(Application& app)
  314. {
  315. ExampleWidgetStandaloneWindow swin(app);
  316. const double scaleFactor = swin.getScaleFactor();
  317. swin.setGeometryConstraints(128 * scaleFactor, 128 * scaleFactor);
  318. swin.setResizable(true);
  319. swin.setSize(600 * scaleFactor, 500 * scaleFactor);
  320. swin.setTitle(ExampleWidgetStandaloneWindow::kExampleWidgetName);
  321. swin.show();
  322. app.exec();
  323. }
  324. // --------------------------------------------------------------------------------------------------------------------
  325. END_NAMESPACE_DGL
  326. int main(int argc, char* argv[])
  327. {
  328. USE_NAMESPACE_DGL;
  329. using DGL_NAMESPACE::Window;
  330. Application app;
  331. if (argc > 1)
  332. {
  333. /**/ if (std::strcmp(argv[1], "color") == 0)
  334. createAndShowExampleWidgetStandaloneWindow<ExampleColorStandaloneWindow>(app);
  335. else if (std::strcmp(argv[1], "images") == 0)
  336. createAndShowExampleWidgetStandaloneWindow<ExampleImagesStandaloneWindow>(app);
  337. else if (std::strcmp(argv[1], "rectangles") == 0)
  338. createAndShowExampleWidgetStandaloneWindow<ExampleRectanglesStandaloneWindow>(app);
  339. else if (std::strcmp(argv[1], "shapes") == 0)
  340. createAndShowExampleWidgetStandaloneWindow<ExampleShapesStandaloneWindow>(app);
  341. #ifdef DGL_OPENGL
  342. else if (std::strcmp(argv[1], "text") == 0)
  343. createAndShowExampleWidgetStandaloneWindow<ExampleTextStandaloneWindow>(app);
  344. #endif
  345. else
  346. d_stderr2("Invalid demo mode, must be one of: color, images, rectangles or shapes");
  347. }
  348. else
  349. {
  350. createAndShowExampleWidgetStandaloneWindow<DemoWindow>(app);
  351. }
  352. return 0;
  353. }
  354. // --------------------------------------------------------------------------------------------------------------------