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.

295 lines
9.1KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. #include "../../Application/jucer_Headers.h"
  20. #include "jucer_ResourceEditorPanel.h"
  21. //==============================================================================
  22. class ResourceListButton : public Component,
  23. private Button::Listener
  24. {
  25. public:
  26. ResourceListButton (JucerDocument& doc)
  27. : document (doc), reloadButton ("Reload"), row (0)
  28. {
  29. setInterceptsMouseClicks (false, true);
  30. addAndMakeVisible (reloadButton);
  31. reloadButton.addListener (this);
  32. }
  33. void update (int newRow)
  34. {
  35. row = newRow;
  36. reloadButton.setVisible (document.getResources() [row] != nullptr);
  37. }
  38. void resized()
  39. {
  40. reloadButton.setBoundsInset (BorderSize<int> (2));
  41. }
  42. void buttonClicked (Button*)
  43. {
  44. if (const BinaryResources::BinaryResource* const r = document.getResources() [row])
  45. document.getResources()
  46. .browseForResource ("Select a file to replace this resource",
  47. "*",
  48. File (r->originalFilename),
  49. r->name);
  50. }
  51. private:
  52. JucerDocument& document;
  53. TextButton reloadButton;
  54. int row;
  55. };
  56. //==============================================================================
  57. ResourceEditorPanel::ResourceEditorPanel (JucerDocument& doc)
  58. : document (doc),
  59. addButton ("Add new resource..."),
  60. reloadAllButton ("Reload all resources"),
  61. delButton ("Delete selected resources")
  62. {
  63. addAndMakeVisible (addButton);
  64. addButton.addListener (this);
  65. addAndMakeVisible (reloadAllButton);
  66. reloadAllButton.addListener (this);
  67. addAndMakeVisible (delButton);
  68. delButton.addListener (this);
  69. delButton.setEnabled (false);
  70. addAndMakeVisible (listBox = new TableListBox (String(), this));
  71. listBox->getHeader().addColumn ("name", 1, 150, 80, 400);
  72. listBox->getHeader().addColumn ("original file", 2, 350, 80, 800);
  73. listBox->getHeader().addColumn ("size", 3, 100, 40, 150);
  74. listBox->getHeader().addColumn ("reload", 4, 100, 100, 100, TableHeaderComponent::notResizableOrSortable);
  75. listBox->getHeader().setStretchToFitActive (true);
  76. listBox->setOutlineThickness (1);
  77. listBox->updateContent();
  78. document.addChangeListener (this);
  79. handleCommandMessage (1);
  80. lookAndFeelChanged();
  81. }
  82. ResourceEditorPanel::~ResourceEditorPanel()
  83. {
  84. document.removeChangeListener (this);
  85. }
  86. int ResourceEditorPanel::getNumRows()
  87. {
  88. return document.getResources().size();
  89. }
  90. void ResourceEditorPanel::paintRowBackground (Graphics& g, int /*rowNumber*/,
  91. int /*width*/, int /*height*/, bool rowIsSelected)
  92. {
  93. if (rowIsSelected)
  94. g.fillAll (findColour (defaultHighlightColourId));
  95. }
  96. void ResourceEditorPanel::paintCell (Graphics& g, int rowNumber, int columnId, int width, int height,
  97. bool rowIsSelected)
  98. {
  99. if (const BinaryResources::BinaryResource* const r = document.getResources() [rowNumber])
  100. {
  101. String text;
  102. if (columnId == 1)
  103. text = r->name;
  104. else if (columnId == 2)
  105. text = r->originalFilename;
  106. else if (columnId == 3)
  107. text = File::descriptionOfSizeInBytes ((int64) r->data.getSize());
  108. if (rowIsSelected)
  109. g.setColour (findColour (defaultHighlightedTextColourId));
  110. else
  111. g.setColour (findColour (defaultTextColourId));
  112. g.setFont (13.0f);
  113. g.drawText (text, 4, 0, width - 6, height, Justification::centredLeft, true);
  114. }
  115. }
  116. Component* ResourceEditorPanel::refreshComponentForCell (int rowNumber, int columnId, bool /*isRowSelected*/,
  117. Component* existingComponentToUpdate)
  118. {
  119. if (columnId != 4)
  120. return nullptr;
  121. if (existingComponentToUpdate == nullptr)
  122. existingComponentToUpdate = new ResourceListButton (document);
  123. ((ResourceListButton*) existingComponentToUpdate)->update (rowNumber);
  124. return existingComponentToUpdate;
  125. }
  126. int ResourceEditorPanel::getColumnAutoSizeWidth (int columnId)
  127. {
  128. if (columnId == 4)
  129. return 0;
  130. Font f (13.0f);
  131. int widest = 40;
  132. for (int i = document.getResources().size(); --i >= 0;)
  133. {
  134. const BinaryResources::BinaryResource* const r = document.getResources() [i];
  135. jassert (r != nullptr);
  136. String text;
  137. if (columnId == 1)
  138. text = r->name;
  139. else if (columnId == 2)
  140. text = r->originalFilename;
  141. else if (columnId == 3)
  142. text = File::descriptionOfSizeInBytes ((int64) r->data.getSize());
  143. widest = jmax (widest, f.getStringWidth (text));
  144. }
  145. return widest + 10;
  146. }
  147. void ResourceEditorPanel::lookAndFeelChanged()
  148. {
  149. listBox->setColour (ListBox::backgroundColourId, findColour (secondaryBackgroundColourId));
  150. listBox->setColour (ListBox::outlineColourId, Colours::transparentBlack);
  151. }
  152. //==============================================================================
  153. class ResourceSorter
  154. {
  155. public:
  156. ResourceSorter (const int columnId_, const bool forwards)
  157. : columnId (columnId_),
  158. direction (forwards ? 1 : -1)
  159. {
  160. }
  161. int compareElements (BinaryResources::BinaryResource* first, BinaryResources::BinaryResource* second)
  162. {
  163. if (columnId == 1) return direction * first->name.compare (second->name);
  164. if (columnId == 2) return direction * first->originalFilename.compare (second->originalFilename);
  165. if (columnId == 3) return direction * (int) first->data.getSize() - (int) second->data.getSize();
  166. return 0;
  167. }
  168. private:
  169. const int columnId, direction;
  170. ResourceSorter (const ResourceSorter&);
  171. ResourceSorter& operator= (const ResourceSorter&);
  172. };
  173. void ResourceEditorPanel::sortOrderChanged (int newSortColumnId, const bool isForwards)
  174. {
  175. ResourceSorter sorter (newSortColumnId, isForwards);
  176. document.getResources().sort (sorter);
  177. }
  178. //==============================================================================
  179. void ResourceEditorPanel::selectedRowsChanged (int /*lastRowSelected*/)
  180. {
  181. delButton.setEnabled (listBox->getNumSelectedRows() > 0);
  182. }
  183. void ResourceEditorPanel::resized()
  184. {
  185. auto bounds = getLocalBounds();
  186. auto buttonSlice = bounds.removeFromBottom (40).reduced (5, 5);
  187. addButton.setBounds (buttonSlice.removeFromLeft (125));
  188. buttonSlice.removeFromLeft (10);
  189. reloadAllButton.setBounds (buttonSlice.removeFromLeft (125));
  190. delButton.setBounds (buttonSlice.removeFromRight (125));
  191. listBox->setBounds (bounds);
  192. }
  193. void ResourceEditorPanel::paint (Graphics& g)
  194. {
  195. g.fillAll (findColour (secondaryBackgroundColourId));
  196. }
  197. void ResourceEditorPanel::visibilityChanged()
  198. {
  199. if (isVisible())
  200. listBox->updateContent();
  201. }
  202. void ResourceEditorPanel::changeListenerCallback (ChangeBroadcaster*)
  203. {
  204. if (isVisible())
  205. listBox->updateContent();
  206. }
  207. void ResourceEditorPanel::buttonClicked (Button* b)
  208. {
  209. if (b == &addButton)
  210. {
  211. document.getResources()
  212. .browseForResource ("Select a file to add as a resource",
  213. "*",
  214. File(),
  215. String());
  216. }
  217. else if (b == &delButton)
  218. {
  219. document.getResources().remove (listBox->getSelectedRow (0));
  220. }
  221. else if (b == &reloadAllButton)
  222. {
  223. StringArray failed;
  224. for (int i = 0; i < document.getResources().size(); ++i)
  225. {
  226. if (! document.getResources().reload (i))
  227. failed.add (document.getResources().getResourceNames() [i]);
  228. }
  229. if (failed.size() > 0)
  230. {
  231. AlertWindow::showMessageBox (AlertWindow::WarningIcon,
  232. TRANS("Reloading resources"),
  233. TRANS("The following resources couldn't be reloaded from their original files:\n\n")
  234. + failed.joinIntoString (", "));
  235. }
  236. }
  237. }