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.

274 lines
8.7KB

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