The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

385 lines
14KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. #include "../jucedemo_headers.h"
  24. //==============================================================================
  25. static float randomNumber()
  26. {
  27. return Random::getSystemRandom().nextFloat() * 300.0f - 150.0f;
  28. }
  29. //==============================================================================
  30. class PathsAndTransformsDemo : public Component,
  31. public SliderListener,
  32. public ComboBoxListener
  33. {
  34. public:
  35. //==============================================================================
  36. PathsAndTransformsDemo()
  37. {
  38. setName (T("Paths"));
  39. // No parts of this component are semi-transparent, so calling setOpaque()
  40. // allows the redraw system to exploit this fact and optimise repainting.
  41. setOpaque (true);
  42. generateRandomShape();
  43. generateImage();
  44. generateDrawable();
  45. generateSVGDrawable();
  46. addAndMakeVisible (typeChooser = new ComboBox (T("type")));
  47. addAndMakeVisible (scaleSlider = new Slider (T("scale")));
  48. addAndMakeVisible (angleSlider = new Slider (T("angle")));
  49. addAndMakeVisible (xSlider = new Slider (T("x")));
  50. addAndMakeVisible (ySlider = new Slider (T("y")));
  51. addAndMakeVisible (opacitySlider = new Slider (T("opacity")));
  52. (new Label (String::empty, T("type:"))) ->attachToComponent (typeChooser, true);
  53. (new Label (String::empty, T("scale:"))) ->attachToComponent (scaleSlider, true);
  54. (new Label (String::empty, T("angle:"))) ->attachToComponent (angleSlider, true);
  55. (new Label (String::empty, T("x offset:"))) ->attachToComponent (xSlider, true);
  56. (new Label (String::empty, T("y offset:"))) ->attachToComponent (ySlider, true);
  57. (new Label (String::empty, T("opacity:"))) ->attachToComponent (opacitySlider, true);
  58. typeChooser->addItem (T("random shape - solid colour"), 1);
  59. typeChooser->addItem (T("random shape - linear gradient fill"), 2);
  60. typeChooser->addItem (T("random shape - radial gradient fill"), 3);
  61. typeChooser->addItem (T("random shape - tiled image fill"), 8);
  62. typeChooser->addItem (T("image - low quality"), 4);
  63. typeChooser->addItem (T("image - high quality"), 5);
  64. typeChooser->addItem (T("image - colour-filled alpha channel"), 6);
  65. typeChooser->addItem (T("image - gradient-filled alpha channel"), 7);
  66. typeChooser->addItem (T("image - alphamap-filled alpha channel"), 9);
  67. typeChooser->addItem (T("drawable object"), 10);
  68. typeChooser->addItem (T("SVG object"), 11);
  69. typeChooser->setSelectedId (11);
  70. typeChooser->addListener (this);
  71. scaleSlider ->addListener (this);
  72. angleSlider ->addListener (this);
  73. xSlider ->addListener (this);
  74. ySlider ->addListener (this);
  75. opacitySlider ->addListener (this);
  76. scaleSlider->setRange (0.01, 10.0, 0.001);
  77. scaleSlider->setValue (1.0);
  78. angleSlider->setRange (-1.0, 1.0, 0.001);
  79. angleSlider->setValue (0);
  80. xSlider->setRange (-10, 10, 0.001);
  81. xSlider->setValue (0);
  82. ySlider->setRange (-10, 10, 0.001);
  83. ySlider->setValue (0);
  84. opacitySlider->setRange (0, 1, 0.01);
  85. opacitySlider->setValue (1.0);
  86. }
  87. ~PathsAndTransformsDemo()
  88. {
  89. if (image != 0)
  90. delete image;
  91. delete drawable;
  92. delete svgDrawable;
  93. deleteAllChildren();
  94. }
  95. void paint (Graphics& g)
  96. {
  97. g.fillCheckerBoard (0, 0, getWidth(), getHeight(),
  98. 50, 50,
  99. Colour (0xffe0e0e0),
  100. Colours::white);
  101. const int type = typeChooser->getSelectedId();
  102. if (type == 1)
  103. {
  104. g.setColour (Colours::blue.withAlpha ((float) opacitySlider->getValue()));
  105. g.fillPath (shape, getTransform());
  106. }
  107. else if (type == 2 || type == 3)
  108. {
  109. GradientBrush gb (Colours::blue.withAlpha ((float) opacitySlider->getValue()),
  110. getWidth() * 0.5f, getHeight() * 0.5f,
  111. Colours::red.withAlpha ((float) opacitySlider->getValue()),
  112. getWidth() * 0.6f, getHeight() * 0.7f,
  113. type == 3);
  114. g.setBrush (&gb);
  115. g.fillPath (shape, getTransform());
  116. }
  117. else if (type == 8)
  118. {
  119. ImageBrush ib (image, 100, 100, (float) opacitySlider->getValue());
  120. g.setBrush (&ib);
  121. g.fillPath (shape, getTransform());
  122. }
  123. else if (type == 4 || type == 5)
  124. {
  125. if (type == 4)
  126. g.setImageResamplingQuality (Graphics::lowResamplingQuality);
  127. else
  128. g.setImageResamplingQuality (Graphics::mediumResamplingQuality);
  129. g.setOpacity ((float) opacitySlider->getValue());
  130. if (image != 0)
  131. {
  132. g.drawImageTransformed (image,
  133. 0, 0, image->getWidth(), image->getHeight(),
  134. AffineTransform::translation (-0.5f * image->getWidth(), -0.5f * image->getHeight())
  135. .followedBy (getTransform()),
  136. false);
  137. }
  138. }
  139. else if (type == 6)
  140. {
  141. g.setColour (Colours::blue.withAlpha ((float) opacitySlider->getValue()));
  142. if (image != 0)
  143. {
  144. g.drawImageTransformed (image,
  145. 0, 0, image->getWidth(), image->getHeight(),
  146. AffineTransform::translation (-0.5f * image->getWidth(), -0.5f * image->getHeight())
  147. .followedBy (getTransform()),
  148. true);
  149. }
  150. }
  151. else if (type == 7)
  152. {
  153. GradientBrush gb (Colours::blue.withAlpha ((float) opacitySlider->getValue()),
  154. getWidth() * 0.5f, getHeight() * 0.5f,
  155. Colours::red.withAlpha ((float) opacitySlider->getValue()),
  156. getWidth() * 0.6f, getHeight() * 0.7f,
  157. false);
  158. g.setBrush (&gb);
  159. if (image != 0)
  160. {
  161. g.drawImageTransformed (image,
  162. 0, 0, image->getWidth(), image->getHeight(),
  163. AffineTransform::translation (-0.5f * image->getWidth(), -0.5f * image->getHeight())
  164. .followedBy (getTransform()),
  165. true);
  166. }
  167. }
  168. else if (type == 9)
  169. {
  170. ImageBrush ib (image, 100, 100, (float) opacitySlider->getValue());
  171. g.setBrush (&ib);
  172. if (image != 0)
  173. {
  174. g.drawImageTransformed (image,
  175. 0, 0, image->getWidth(), image->getHeight(),
  176. AffineTransform::translation (-0.5f * image->getWidth(),
  177. -0.5f * image->getHeight())
  178. .followedBy (getTransform()),
  179. true);
  180. }
  181. }
  182. else if (type == 10)
  183. {
  184. g.setOpacity ((float) opacitySlider->getValue());
  185. float x, y, w, h;
  186. drawable->getBounds (x, y, w, h);
  187. drawable->draw (g, AffineTransform::translation (-x - 0.5f * w,
  188. -y - 0.5f * h)
  189. .followedBy (getTransform()));
  190. }
  191. else if (type == 11)
  192. {
  193. g.setOpacity ((float) opacitySlider->getValue());
  194. float x, y, w, h;
  195. svgDrawable->getBounds (x, y, w, h);
  196. svgDrawable->draw (g, AffineTransform::translation (-x - 0.5f * w,
  197. -y - 0.5f * h)
  198. .followedBy (getTransform()));
  199. }
  200. }
  201. void resized()
  202. {
  203. const int x = 100;
  204. int y = 4;
  205. typeChooser->setBounds (x, y, 300, 24);
  206. y += 28;
  207. scaleSlider->setBounds (x, y, 300, 24);
  208. y += 28;
  209. angleSlider->setBounds (x, y, 300, 24);
  210. y += 28;
  211. xSlider->setBounds (x, y, 300, 24);
  212. y += 28;
  213. ySlider->setBounds (x, y, 300, 24);
  214. y += 28;
  215. opacitySlider->setBounds (x, y, 300, 24);
  216. }
  217. void sliderValueChanged (Slider*)
  218. {
  219. repaint();
  220. }
  221. void comboBoxChanged (ComboBox*)
  222. {
  223. repaint();
  224. }
  225. private:
  226. Path shape;
  227. Image* image;
  228. Drawable* drawable;
  229. DrawableComposite* svgDrawable;
  230. ComboBox* typeChooser;
  231. Slider* scaleSlider;
  232. Slider* angleSlider;
  233. Slider* xSlider;
  234. Slider* ySlider;
  235. Slider* opacitySlider;
  236. void generateRandomShape()
  237. {
  238. shape.startNewSubPath (randomNumber(), randomNumber());
  239. for (int i = 0; i < 7; ++i)
  240. {
  241. shape.lineTo (randomNumber(), randomNumber());
  242. shape.quadraticTo (randomNumber(), randomNumber(),
  243. randomNumber(), randomNumber());
  244. }
  245. shape.closeSubPath();
  246. }
  247. void generateImage()
  248. {
  249. image = ImageFileFormat::loadFrom (BinaryData::juce_png, BinaryData::juce_pngSize);
  250. }
  251. void generateDrawable()
  252. {
  253. // create a composite drawable object..
  254. DrawableComposite* dc = new DrawableComposite();
  255. drawable = dc;
  256. // ..add a paths drawable to it...
  257. DrawablePath dp;
  258. dp.setPath (shape);
  259. dp.setOutline (4.0f, Colours::blue);
  260. GradientBrush gb (ColourGradient (Colours::red.withAlpha (0.4f), -100.0f, -100.0f,
  261. Colours::green.withAlpha (0.6f), 100.0f, 100.0f, false));
  262. dp.setFillBrush (gb);
  263. dc->insertDrawable (dp);
  264. // ..add an image drawable..
  265. DrawableImage di;
  266. di.setImage (image, false);
  267. dc->insertDrawable (di, AffineTransform::scale (0.3f, 0.8f));
  268. // ..and a text object
  269. DrawableText dt;
  270. dt.setText (T("JUCE Drawables"), Font (30.0f, Font::bold));
  271. dt.setColour (Colours::green);
  272. dc->insertDrawable (dt, AffineTransform::translation (-80.0f, -20.0f)
  273. .scaled (2.0f, 0.8f)
  274. .rotated (-1.3f));
  275. }
  276. void generateSVGDrawable()
  277. {
  278. svgDrawable = 0;
  279. MemoryInputStream iconsFileStream (BinaryData::icons_zip, BinaryData::icons_zipSize, false);
  280. ZipFile icons (&iconsFileStream, false);
  281. // Load a random SVG file from our embedded icons.zip file.
  282. InputStream* svgFileStream
  283. = icons.createStreamForEntry (Random::getSystemRandom().nextInt (icons.getNumEntries()));
  284. if (svgFileStream != 0)
  285. {
  286. Drawable* loadedSVG = Drawable::createFromImageDataStream (*svgFileStream);
  287. if (loadedSVG != 0)
  288. {
  289. // to make our icon the right size, we'll put it inside a DrawableComposite, and apply
  290. // a transform to get it to the size we want.
  291. float x, y, w, h;
  292. loadedSVG->getBounds (x, y, w, h);
  293. const float scaleFactor = 300.0f / jmax (w, h);
  294. svgDrawable = new DrawableComposite();
  295. svgDrawable->insertDrawable (loadedSVG, AffineTransform::scale (scaleFactor, scaleFactor));
  296. }
  297. delete svgFileStream;
  298. }
  299. }
  300. const AffineTransform getTransform() const
  301. {
  302. return AffineTransform::rotation (float_Pi * 2.0f * (float) angleSlider->getValue())
  303. .scaled ((float) scaleSlider->getValue(),
  304. (float) scaleSlider->getValue())
  305. .translated (getWidth() * 0.5f + (float) xSlider->getValue(),
  306. getHeight() * 0.5f + (float) ySlider->getValue());
  307. }
  308. };
  309. Component* createPathsAndTransformsDemo()
  310. {
  311. return new PathsAndTransformsDemo();
  312. }