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.

357 lines
10KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "../jucer_Headers.h"
  19. #include "jucer_JucerDocument.h"
  20. //==============================================================================
  21. BinaryResources::BinaryResources()
  22. {
  23. }
  24. BinaryResources::~BinaryResources()
  25. {
  26. }
  27. BinaryResources& BinaryResources::operator= (const BinaryResources& other)
  28. {
  29. for (int i = 0; i < other.resources.size(); ++i)
  30. add (other.resources[i]->name,
  31. other.resources[i]->originalFilename,
  32. other.resources[i]->data);
  33. return *this;
  34. }
  35. void BinaryResources::changed()
  36. {
  37. if (document != nullptr)
  38. {
  39. document->changed();
  40. document->refreshAllPropertyComps();
  41. }
  42. }
  43. //==============================================================================
  44. void BinaryResources::clear()
  45. {
  46. if (resources.size() > 0)
  47. {
  48. resources.clear();
  49. changed();
  50. }
  51. }
  52. StringArray BinaryResources::getResourceNames() const
  53. {
  54. StringArray s;
  55. for (int i = 0; i < resources.size(); ++i)
  56. s.add (resources.getUnchecked(i)->name);
  57. return s;
  58. }
  59. BinaryResources::BinaryResource* BinaryResources::findResource (const String& name) const noexcept
  60. {
  61. for (int i = resources.size(); --i >= 0;)
  62. if (resources.getUnchecked(i)->name == name)
  63. return resources.getUnchecked(i);
  64. return 0;
  65. }
  66. const BinaryResources::BinaryResource* BinaryResources::getResource (const String& name) const
  67. {
  68. return findResource (name);
  69. }
  70. const BinaryResources::BinaryResource* BinaryResources::getResourceForFile (const File& file) const
  71. {
  72. for (int i = resources.size(); --i >= 0;)
  73. if (resources.getUnchecked(i)->originalFilename == file.getFullPathName())
  74. return resources.getUnchecked(i);
  75. return 0;
  76. }
  77. bool BinaryResources::add (const String& name, const File& file)
  78. {
  79. MemoryBlock mb;
  80. if (! file.loadFileAsData (mb))
  81. return false;
  82. add (name, file.getFullPathName(), mb);
  83. return true;
  84. }
  85. void BinaryResources::add (const String& name, const String& originalFileName, const MemoryBlock& data)
  86. {
  87. BinaryResource* r = findResource (name);
  88. if (r == 0)
  89. {
  90. resources.add (r = new BinaryResource());
  91. r->name = name;
  92. }
  93. r->originalFilename = originalFileName;
  94. r->data = data;
  95. deleteAndZero (r->drawable);
  96. changed();
  97. }
  98. bool BinaryResources::reload (const int index)
  99. {
  100. return resources[index] != 0
  101. && add (resources [index]->name,
  102. File (resources [index]->originalFilename));
  103. }
  104. String BinaryResources::browseForResource (const String& title,
  105. const String& wildcard,
  106. const File& fileToStartFrom,
  107. const String& resourceToReplace)
  108. {
  109. FileChooser fc (title, fileToStartFrom, wildcard);
  110. if (fc.browseForFileToOpen())
  111. {
  112. String name (resourceToReplace);
  113. if (name.isEmpty())
  114. name = findUniqueName (fc.getResult().getFileName());
  115. if (! add (name, fc.getResult()))
  116. {
  117. AlertWindow::showMessageBox (AlertWindow::WarningIcon,
  118. TRANS("Adding Resource"),
  119. TRANS("Failed to load the file!"));
  120. name = String::empty;
  121. }
  122. return name;
  123. }
  124. return String::empty;
  125. }
  126. String BinaryResources::findUniqueName (const String& rootName) const
  127. {
  128. String nameRoot (CodeHelpers::makeValidIdentifier (rootName, true, true, false));
  129. String name (nameRoot);
  130. const StringArray names (getResourceNames());
  131. int suffix = 1;
  132. while (names.contains (name))
  133. name = nameRoot + String (++suffix);
  134. return name;
  135. }
  136. void BinaryResources::remove (const int i)
  137. {
  138. if (resources[i] != 0)
  139. {
  140. resources.remove (i);
  141. changed();
  142. }
  143. }
  144. const Drawable* BinaryResources::getDrawable (const String& name) const
  145. {
  146. BinaryResources::BinaryResource* const res = const_cast <BinaryResources::BinaryResource*> (getResource (name));
  147. if (res == 0)
  148. return 0;
  149. if (res->drawable == 0 && res->data.getSize() > 0)
  150. res->drawable = Drawable::createFromImageData (res->data.getData(), res->data.getSize());
  151. return res->drawable;
  152. }
  153. Image BinaryResources::getImageFromCache (const String& name) const
  154. {
  155. if (const BinaryResources::BinaryResource* const res = getResource (name))
  156. if (res->data.getSize() > 0)
  157. return ImageCache::getFromMemory (res->data.getData(), (int) res->data.getSize());
  158. return Image();
  159. }
  160. void BinaryResources::loadFromCpp (const File& cppFileLocation, const String& cppFile)
  161. {
  162. StringArray cpp;
  163. cpp.addLines (cppFile);
  164. clear();
  165. for (int i = 0; i < cpp.size(); ++i)
  166. {
  167. if (cpp[i].contains ("JUCER_RESOURCE:"))
  168. {
  169. StringArray tokens;
  170. tokens.addTokens (cpp[i].fromFirstOccurrenceOf (":", false, false), ",", "\"'");
  171. tokens.trim();
  172. tokens.removeEmptyStrings();
  173. const String resourceName (tokens[0]);
  174. const int size = tokens[1].getIntValue();
  175. const String originalFileName (cppFileLocation.getSiblingFile (tokens[2].unquoted()).getFullPathName());
  176. jassert (resourceName.isNotEmpty() && size > 0);
  177. if (resourceName.isNotEmpty() && size > 0)
  178. {
  179. const int firstLine = i;
  180. while (i < cpp.size())
  181. if (cpp [i++].contains ("}"))
  182. break;
  183. const String dataString (cpp.joinIntoString (" ", firstLine, i - firstLine)
  184. .fromFirstOccurrenceOf ("{", false, false));
  185. MemoryOutputStream out;
  186. String::CharPointerType t (dataString.getCharPointer());
  187. int n = 0;
  188. while (! t.isEmpty())
  189. {
  190. const juce_wchar c = t.getAndAdvance();
  191. if (c >= '0' && c <= '9')
  192. n = n * 10 + (c - '0');
  193. else if (c == ',')
  194. {
  195. out.writeByte ((char) n);
  196. n = 0;
  197. }
  198. else if (c == '}')
  199. break;
  200. }
  201. jassert (size < (int) out.getDataSize() && size > (int) out.getDataSize() - 2);
  202. MemoryBlock mb (out.getData(), out.getDataSize());
  203. mb.setSize (size);
  204. add (resourceName, originalFileName, mb);
  205. }
  206. }
  207. }
  208. }
  209. //==============================================================================
  210. void BinaryResources::fillInGeneratedCode (GeneratedCode& code) const
  211. {
  212. if (resources.size() > 0)
  213. {
  214. code.publicMemberDeclarations << "// Binary resources:\n";
  215. String defs;
  216. defs << "//==============================================================================\n";
  217. defs << "// Binary resources - be careful not to edit any of these sections!\n\n";
  218. for (int i = 0; i < resources.size(); ++i)
  219. {
  220. code.publicMemberDeclarations
  221. << "static const char* "
  222. << resources[i]->name
  223. << ";\nstatic const int "
  224. << resources[i]->name
  225. << "Size;\n";
  226. const String name (resources[i]->name);
  227. const MemoryBlock& mb = resources[i]->data;
  228. defs << "// JUCER_RESOURCE: " << name << ", " << (int) mb.getSize()
  229. << ", \""
  230. << File (resources[i]->originalFilename)
  231. .getRelativePathFrom (code.document->getCppFile())
  232. .replaceCharacter ('\\', '/')
  233. << "\"\n";
  234. String line1;
  235. line1 << "static const unsigned char resource_"
  236. << code.className << "_" << name << "[] = { ";
  237. defs += line1;
  238. MemoryOutputStream out (65536);
  239. int charsOnLine = line1.length();
  240. for (size_t j = 0; j < mb.getSize(); ++j)
  241. {
  242. const int num = ((int) (unsigned char) mb[j]);
  243. out << num << ',';
  244. charsOnLine += 2;
  245. if (num >= 10)
  246. ++charsOnLine;
  247. if (num >= 100)
  248. ++charsOnLine;
  249. if (charsOnLine >= 200)
  250. {
  251. charsOnLine = 0;
  252. out << '\n';
  253. }
  254. }
  255. out << (char) 0;
  256. defs
  257. << (const char*) out.getData()
  258. << "0,0};\n\nconst char* "
  259. << code.className << "::" << name
  260. << " = (const char*) resource_" << code.className << "_" << name
  261. << ";\nconst int "
  262. << code.className << "::" << name << "Size = "
  263. << (int) mb.getSize()
  264. << ";\n\n";
  265. }
  266. code.staticMemberDefinitions += defs;
  267. }
  268. }
  269. BinaryResources::BinaryResource::BinaryResource()
  270. : drawable (0)
  271. {
  272. }
  273. BinaryResources::BinaryResource::~BinaryResource()
  274. {
  275. deleteAndZero (drawable);
  276. }