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.

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