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.

401 lines
11KB

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