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.

275 lines
8.7KB

  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. {
  24. public:
  25. ResourceListButton (JucerDocument& doc)
  26. : document (doc), reloadButton ("Reload"), row (0)
  27. {
  28. setInterceptsMouseClicks (false, true);
  29. addAndMakeVisible (reloadButton);
  30. reloadButton.onClick = [this]
  31. {
  32. if (auto* r = document.getResources() [row])
  33. document.getResources().browseForResource ("Select a file to replace this resource", "*",
  34. File (r->originalFilename), r->name);
  35. };
  36. }
  37. void update (int newRow)
  38. {
  39. row = newRow;
  40. reloadButton.setVisible (document.getResources() [row] != nullptr);
  41. }
  42. void resized()
  43. {
  44. reloadButton.setBoundsInset (BorderSize<int> (2));
  45. }
  46. private:
  47. JucerDocument& document;
  48. TextButton reloadButton;
  49. int row;
  50. };
  51. //==============================================================================
  52. ResourceEditorPanel::ResourceEditorPanel (JucerDocument& doc)
  53. : document (doc),
  54. addButton ("Add new resource..."),
  55. reloadAllButton ("Reload all resources"),
  56. delButton ("Delete selected resources")
  57. {
  58. addAndMakeVisible (addButton);
  59. addButton.onClick = [this] { document.getResources().browseForResource ("Select a file to add as a resource", "*", {}, {}); };
  60. addAndMakeVisible (reloadAllButton);
  61. reloadAllButton.onClick = [this] { reloadAll(); };
  62. addAndMakeVisible (delButton);
  63. delButton.setEnabled (false);
  64. delButton.onClick = [this] { document.getResources().remove (listBox->getSelectedRow (0)); };
  65. listBox.reset (new TableListBox (String(), this));
  66. addAndMakeVisible (listBox.get());
  67. listBox->getHeader().addColumn ("name", 1, 150, 80, 400);
  68. listBox->getHeader().addColumn ("original file", 2, 350, 80, 800);
  69. listBox->getHeader().addColumn ("size", 3, 100, 40, 150);
  70. listBox->getHeader().addColumn ("reload", 4, 100, 100, 100, TableHeaderComponent::notResizableOrSortable);
  71. listBox->getHeader().setStretchToFitActive (true);
  72. listBox->setOutlineThickness (1);
  73. listBox->updateContent();
  74. document.addChangeListener (this);
  75. handleCommandMessage (1);
  76. lookAndFeelChanged();
  77. }
  78. ResourceEditorPanel::~ResourceEditorPanel()
  79. {
  80. document.removeChangeListener (this);
  81. }
  82. int ResourceEditorPanel::getNumRows()
  83. {
  84. return document.getResources().size();
  85. }
  86. void ResourceEditorPanel::paintRowBackground (Graphics& g, int /*rowNumber*/,
  87. int /*width*/, int /*height*/, bool rowIsSelected)
  88. {
  89. if (rowIsSelected)
  90. g.fillAll (findColour (defaultHighlightColourId));
  91. }
  92. void ResourceEditorPanel::paintCell (Graphics& g, int rowNumber, int columnId, int width, int height,
  93. bool rowIsSelected)
  94. {
  95. if (const BinaryResources::BinaryResource* const r = document.getResources() [rowNumber])
  96. {
  97. String text;
  98. if (columnId == 1)
  99. text = r->name;
  100. else if (columnId == 2)
  101. text = r->originalFilename;
  102. else if (columnId == 3)
  103. text = File::descriptionOfSizeInBytes ((int64) r->data.getSize());
  104. if (rowIsSelected)
  105. g.setColour (findColour (defaultHighlightedTextColourId));
  106. else
  107. g.setColour (findColour (defaultTextColourId));
  108. g.setFont (13.0f);
  109. g.drawText (text, 4, 0, width - 6, height, Justification::centredLeft, true);
  110. }
  111. }
  112. Component* ResourceEditorPanel::refreshComponentForCell (int rowNumber, int columnId, bool /*isRowSelected*/,
  113. Component* existingComponentToUpdate)
  114. {
  115. if (columnId != 4)
  116. return nullptr;
  117. if (existingComponentToUpdate == nullptr)
  118. existingComponentToUpdate = new ResourceListButton (document);
  119. ((ResourceListButton*) existingComponentToUpdate)->update (rowNumber);
  120. return existingComponentToUpdate;
  121. }
  122. int ResourceEditorPanel::getColumnAutoSizeWidth (int columnId)
  123. {
  124. if (columnId == 4)
  125. return 0;
  126. Font f (13.0f);
  127. int widest = 40;
  128. for (int i = document.getResources().size(); --i >= 0;)
  129. {
  130. const BinaryResources::BinaryResource* const r = document.getResources() [i];
  131. jassert (r != nullptr);
  132. String text;
  133. if (columnId == 1)
  134. text = r->name;
  135. else if (columnId == 2)
  136. text = r->originalFilename;
  137. else if (columnId == 3)
  138. text = File::descriptionOfSizeInBytes ((int64) r->data.getSize());
  139. widest = jmax (widest, f.getStringWidth (text));
  140. }
  141. return widest + 10;
  142. }
  143. void ResourceEditorPanel::lookAndFeelChanged()
  144. {
  145. listBox->setColour (ListBox::backgroundColourId, findColour (secondaryBackgroundColourId));
  146. listBox->setColour (ListBox::outlineColourId, Colours::transparentBlack);
  147. }
  148. //==============================================================================
  149. class ResourceSorter
  150. {
  151. public:
  152. ResourceSorter (const int columnId_, const bool forwards)
  153. : columnId (columnId_),
  154. direction (forwards ? 1 : -1)
  155. {
  156. }
  157. int compareElements (BinaryResources::BinaryResource* first, BinaryResources::BinaryResource* second)
  158. {
  159. if (columnId == 1) return direction * first->name.compare (second->name);
  160. if (columnId == 2) return direction * first->originalFilename.compare (second->originalFilename);
  161. if (columnId == 3) return direction * (int) first->data.getSize() - (int) second->data.getSize();
  162. return 0;
  163. }
  164. private:
  165. const int columnId, direction;
  166. ResourceSorter (const ResourceSorter&);
  167. ResourceSorter& operator= (const ResourceSorter&);
  168. };
  169. void ResourceEditorPanel::sortOrderChanged (int newSortColumnId, const bool isForwards)
  170. {
  171. ResourceSorter sorter (newSortColumnId, isForwards);
  172. document.getResources().sort (sorter);
  173. }
  174. //==============================================================================
  175. void ResourceEditorPanel::selectedRowsChanged (int /*lastRowSelected*/)
  176. {
  177. delButton.setEnabled (listBox->getNumSelectedRows() > 0);
  178. }
  179. void ResourceEditorPanel::resized()
  180. {
  181. auto bounds = getLocalBounds();
  182. auto buttonSlice = bounds.removeFromBottom (40).reduced (5, 5);
  183. addButton.setBounds (buttonSlice.removeFromLeft (125));
  184. buttonSlice.removeFromLeft (10);
  185. reloadAllButton.setBounds (buttonSlice.removeFromLeft (125));
  186. delButton.setBounds (buttonSlice.removeFromRight (125));
  187. listBox->setBounds (bounds);
  188. }
  189. void ResourceEditorPanel::paint (Graphics& g)
  190. {
  191. g.fillAll (findColour (secondaryBackgroundColourId));
  192. }
  193. void ResourceEditorPanel::visibilityChanged()
  194. {
  195. if (isVisible())
  196. listBox->updateContent();
  197. }
  198. void ResourceEditorPanel::changeListenerCallback (ChangeBroadcaster*)
  199. {
  200. if (isVisible())
  201. listBox->updateContent();
  202. }
  203. void ResourceEditorPanel::reloadAll()
  204. {
  205. StringArray failed;
  206. for (int i = 0; i < document.getResources().size(); ++i)
  207. {
  208. if (! document.getResources().reload (i))
  209. failed.add (document.getResources().getResourceNames() [i]);
  210. }
  211. if (failed.size() > 0)
  212. {
  213. AlertWindow::showMessageBox (AlertWindow::WarningIcon,
  214. TRANS("Reloading resources"),
  215. TRANS("The following resources couldn't be reloaded from their original files:\n\n")
  216. + failed.joinIntoString (", "));
  217. }
  218. }