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.

347 lines
11KB

  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_ProjectContentComponent.h"
  19. #include "../Application/jucer_MainWindow.h"
  20. #include "../Code Editor/jucer_SourceCodeEditor.h"
  21. #include "jucer_ProjectInformationComponent.h"
  22. #include "jucer_TreeViewTypes.h"
  23. #include "../Project Saving/jucer_ProjectExporter.h"
  24. //==============================================================================
  25. ProjectContentComponent::ProjectContentComponent()
  26. : project (nullptr),
  27. currentDocument (nullptr)
  28. {
  29. setOpaque (true);
  30. setWantsKeyboardFocus (true);
  31. treeSizeConstrainer.setMinimumWidth (100);
  32. treeSizeConstrainer.setMaximumWidth (500);
  33. }
  34. ProjectContentComponent::~ProjectContentComponent()
  35. {
  36. setProject (nullptr);
  37. contentView = nullptr;
  38. jassert (getNumChildComponents() == 0);
  39. }
  40. void ProjectContentComponent::paint (Graphics& g)
  41. {
  42. g.fillAll (Colour::greyLevel (0.8f));
  43. }
  44. void ProjectContentComponent::setProject (Project* newProject)
  45. {
  46. if (project != newProject)
  47. {
  48. if (project != nullptr)
  49. project->removeChangeListener (this);
  50. contentView = nullptr;
  51. resizerBar = nullptr;
  52. if (projectTree != nullptr)
  53. {
  54. StoredSettings::getInstance()->getProps().setValue ("projectTreeviewWidth", projectTree->getWidth());
  55. projectTree->deleteRootItem();
  56. projectTree = nullptr;
  57. }
  58. project = newProject;
  59. if (project != nullptr)
  60. {
  61. addAndMakeVisible (projectTree = new TreeView());
  62. projectTree->setComponentID ("tree");
  63. projectTree->setRootItemVisible (true);
  64. projectTree->setMultiSelectEnabled (true);
  65. projectTree->setDefaultOpenness (true);
  66. projectTree->setColour (TreeView::backgroundColourId, Colour::greyLevel (0.93f));
  67. projectTree->setIndentSize (14);
  68. projectTree->setRootItem (new GroupTreeViewItem (project->getMainGroup()));
  69. projectTree->getRootItem()->setOpen (true);
  70. String lastTreeWidth (StoredSettings::getInstance()->getProps().getValue ("projectTreeviewWidth"));
  71. if (lastTreeWidth.getIntValue() < 150)
  72. lastTreeWidth = "250";
  73. projectTree->setBounds ("0, 0, left + " + lastTreeWidth + ", parent.height");
  74. addAndMakeVisible (resizerBar = new ResizableEdgeComponent (projectTree, &treeSizeConstrainer,
  75. ResizableEdgeComponent::rightEdge));
  76. resizerBar->setComponentID ("resizer");
  77. resizerBar->setBounds ("tree.right, 0, tree.right + 4, parent.height");
  78. project->addChangeListener (this);
  79. if (currentDocument == nullptr)
  80. invokeDirectly (CommandIDs::showProjectSettings, true);
  81. updateMissingFileStatuses();
  82. }
  83. }
  84. }
  85. void ProjectContentComponent::changeListenerCallback (ChangeBroadcaster*)
  86. {
  87. updateMissingFileStatuses();
  88. }
  89. void ProjectContentComponent::updateMissingFileStatuses()
  90. {
  91. if (projectTree != nullptr)
  92. {
  93. ProjectTreeViewBase* p = dynamic_cast <ProjectTreeViewBase*> (projectTree->getRootItem());
  94. if (p != nullptr)
  95. p->checkFileStatus();
  96. }
  97. }
  98. bool ProjectContentComponent::showEditorForFile (const File& f)
  99. {
  100. return showDocument (OpenDocumentManager::getInstance()->openFile (project, f));
  101. }
  102. bool ProjectContentComponent::showDocument (OpenDocumentManager::Document* doc)
  103. {
  104. if (doc == nullptr)
  105. return false;
  106. OpenDocumentManager::getInstance()->moveDocumentToTopOfStack (doc);
  107. if (doc->hasFileBeenModifiedExternally())
  108. doc->reloadFromFile();
  109. return setEditorComponent (doc->createEditor(), doc);
  110. }
  111. void ProjectContentComponent::hideDocument (OpenDocumentManager::Document* doc)
  112. {
  113. if (doc == currentDocument)
  114. {
  115. currentDocument = nullptr;
  116. contentView = nullptr;
  117. updateMainWindowTitle();
  118. commandManager->commandStatusChanged();
  119. }
  120. }
  121. bool ProjectContentComponent::setEditorComponent (Component* editor, OpenDocumentManager::Document* doc)
  122. {
  123. if (editor != nullptr)
  124. {
  125. contentView = editor;
  126. currentDocument = doc;
  127. addAndMakeVisible (editor);
  128. editor->setBounds ("resizer.right, 0, parent.right, parent.height");
  129. updateMainWindowTitle();
  130. commandManager->commandStatusChanged();
  131. return true;
  132. }
  133. updateMainWindowTitle();
  134. return false;
  135. }
  136. void ProjectContentComponent::updateMainWindowTitle()
  137. {
  138. MainWindow* mw = Component::findParentComponentOfClass ((MainWindow*) 0);
  139. if (mw != nullptr)
  140. mw->updateTitle (currentDocument != nullptr ? currentDocument->getName() : String::empty);
  141. }
  142. ApplicationCommandTarget* ProjectContentComponent::getNextCommandTarget()
  143. {
  144. return findFirstTargetParentComponent();
  145. }
  146. void ProjectContentComponent::getAllCommands (Array <CommandID>& commands)
  147. {
  148. const CommandID ids[] = { CommandIDs::saveProject,
  149. CommandIDs::saveProjectAs,
  150. CommandIDs::closeProject,
  151. CommandIDs::openInIDE,
  152. CommandIDs::saveAndOpenInIDE,
  153. CommandIDs::showProjectSettings,
  154. StandardApplicationCommandIDs::del};
  155. commands.addArray (ids, numElementsInArray (ids));
  156. }
  157. void ProjectContentComponent::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result)
  158. {
  159. switch (commandID)
  160. {
  161. case CommandIDs::saveProject:
  162. result.setInfo ("Save Project",
  163. "Saves the current project",
  164. CommandCategories::general, 0);
  165. result.setActive (project != nullptr);
  166. result.defaultKeypresses.add (KeyPress ('s', ModifierKeys::commandModifier, 0));
  167. break;
  168. case CommandIDs::saveProjectAs:
  169. result.setInfo ("Save Project As...",
  170. "Saves the current project to a different filename",
  171. CommandCategories::general, 0);
  172. result.setActive (project != nullptr);
  173. result.defaultKeypresses.add (KeyPress ('s', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0));
  174. break;
  175. case CommandIDs::closeProject:
  176. result.setInfo ("Close Project",
  177. "Closes the current project",
  178. CommandCategories::general, 0);
  179. result.setActive (project != nullptr);
  180. break;
  181. case CommandIDs::openInIDE:
  182. #if JUCE_MAC
  183. result.setInfo ("Open in XCode...",
  184. #elif JUCE_WINDOWS
  185. result.setInfo ("Open in Visual Studio...",
  186. #else
  187. result.setInfo ("Open as a Makefile...",
  188. #endif
  189. "Launches the project in an external IDE",
  190. CommandCategories::general, 0);
  191. result.setActive (project != nullptr);
  192. break;
  193. case CommandIDs::saveAndOpenInIDE:
  194. #if JUCE_MAC
  195. result.setInfo ("Save Project and Open in XCode...",
  196. #elif JUCE_WINDOWS
  197. result.setInfo ("Save Project and Open in Visual Studio...",
  198. #else
  199. result.setInfo ("Save Project and Open as a Makefile...",
  200. #endif
  201. "Saves the project and launches it in an external IDE",
  202. CommandCategories::general, 0);
  203. result.setActive (project != nullptr);
  204. result.defaultKeypresses.add (KeyPress ('l', ModifierKeys::commandModifier, 0));
  205. break;
  206. case CommandIDs::showProjectSettings:
  207. result.setInfo ("Show Project Build Settings",
  208. "Shows the build options for the project",
  209. CommandCategories::general, 0);
  210. result.setActive (project != nullptr);
  211. result.defaultKeypresses.add (KeyPress ('i', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0));
  212. break;
  213. case StandardApplicationCommandIDs::del:
  214. result.setInfo ("Delete", String::empty, CommandCategories::general, 0);
  215. result.defaultKeypresses.add (KeyPress (KeyPress::deleteKey, 0, 0));
  216. result.defaultKeypresses.add (KeyPress (KeyPress::backspaceKey, 0, 0));
  217. result.setActive (projectTree != nullptr);
  218. break;
  219. default:
  220. break;
  221. }
  222. }
  223. bool ProjectContentComponent::isCommandActive (const CommandID commandID)
  224. {
  225. return project != nullptr;
  226. }
  227. bool ProjectContentComponent::perform (const InvocationInfo& info)
  228. {
  229. switch (info.commandID)
  230. {
  231. case CommandIDs::saveProject:
  232. if (project != nullptr)
  233. project->save (true, true);
  234. break;
  235. case CommandIDs::saveProjectAs:
  236. if (project != nullptr)
  237. project->saveAsInteractive (true);
  238. break;
  239. case CommandIDs::closeProject:
  240. {
  241. MainWindow* mw = Component::findParentComponentOfClass ((MainWindow*) 0);
  242. if (mw != nullptr)
  243. mw->closeCurrentProject();
  244. }
  245. break;
  246. case CommandIDs::openInIDE:
  247. if (project != nullptr)
  248. {
  249. ScopedPointer <ProjectExporter> exporter (ProjectExporter::createPlatformDefaultExporter (*project));
  250. if (exporter != nullptr)
  251. exporter->launchProject();
  252. }
  253. break;
  254. case CommandIDs::saveAndOpenInIDE:
  255. if (project != nullptr && project->save (true, true) == FileBasedDocument::savedOk)
  256. {
  257. ScopedPointer <ProjectExporter> exporter (ProjectExporter::createPlatformDefaultExporter (*project));
  258. if (exporter != nullptr)
  259. exporter->launchProject();
  260. }
  261. break;
  262. case CommandIDs::showProjectSettings:
  263. if (projectTree != nullptr)
  264. projectTree->getRootItem()->setSelected (true, true);
  265. break;
  266. case StandardApplicationCommandIDs::del:
  267. if (projectTree != nullptr)
  268. {
  269. ProjectTreeViewBase* p = dynamic_cast <ProjectTreeViewBase*> (projectTree->getRootItem());
  270. if (p != nullptr)
  271. p->deleteAllSelectedItems();
  272. }
  273. break;
  274. default:
  275. return false;
  276. }
  277. return true;
  278. }