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.

481 lines
15KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-10 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_Headers.h"
  19. #include "jucer_MainWindow.h"
  20. #include "jucer_OpenDocumentManager.h"
  21. #include "Code Editor/jucer_SourceCodeEditor.h"
  22. #include "../model/Project/jucer_ProjectWizard.h"
  23. //==============================================================================
  24. MainWindow::MainWindow()
  25. : DocumentWindow (JUCEApplication::getInstance()->getApplicationName(),
  26. Colour::greyLevel (0.6f),
  27. DocumentWindow::allButtons)
  28. {
  29. setUsingNativeTitleBar (true);
  30. setContentComponent (new ProjectContentComponent());
  31. setApplicationCommandManagerToWatch (commandManager);
  32. #if JUCE_MAC
  33. setMacMainMenu (this);
  34. #else
  35. setMenuBar (this);
  36. #endif
  37. setResizable (true, false);
  38. centreWithSize (700, 600);
  39. // restore the last size and position from our settings file..
  40. restoreWindowStateFromString (StoredSettings::getInstance()->getProps()
  41. .getValue ("lastMainWindowPos"));
  42. // Register all the app commands..
  43. {
  44. commandManager->registerAllCommandsForTarget (this);
  45. // use a temporary one of these to harvest its commands..
  46. ProjectContentComponent pcc;
  47. commandManager->registerAllCommandsForTarget (&pcc);
  48. DocumentEditorComponent dec (0);
  49. commandManager->registerAllCommandsForTarget (&dec);
  50. }
  51. commandManager->getKeyMappings()->resetToDefaultMappings();
  52. ScopedPointer <XmlElement> keys (StoredSettings::getInstance()->getProps().getXmlValue ("keyMappings"));
  53. if (keys != 0)
  54. commandManager->getKeyMappings()->restoreFromXml (*keys);
  55. addKeyListener (commandManager->getKeyMappings());
  56. // don't want the window to take focus when the title-bar is clicked..
  57. setWantsKeyboardFocus (false);
  58. //getPeer()->setCurrentRenderingEngine (0);
  59. setVisible (true);
  60. }
  61. MainWindow::~MainWindow()
  62. {
  63. #if JUCE_MAC
  64. setMacMainMenu (0);
  65. #else
  66. setMenuBar (0);
  67. #endif
  68. removeKeyListener (commandManager->getKeyMappings());
  69. // save the current size and position to our settings file..
  70. StoredSettings::getInstance()->getProps()
  71. .setValue ("lastMainWindowPos", getWindowStateAsString());
  72. setContentComponent (0);
  73. currentProject = 0;
  74. }
  75. ProjectContentComponent* MainWindow::getProjectContentComponent() const
  76. {
  77. return dynamic_cast <ProjectContentComponent*> (getContentComponent());
  78. }
  79. void MainWindow::closeButtonPressed()
  80. {
  81. JUCEApplication::getInstance()->systemRequestedQuit();
  82. }
  83. bool MainWindow::closeProject (Project* project)
  84. {
  85. jassert (project == currentProject && project != 0);
  86. if (project == 0)
  87. return true;
  88. if (! OpenDocumentManager::getInstance()->closeAllDocumentsUsingProject (*project, true))
  89. return false;
  90. FileBasedDocument::SaveResult r = project->saveIfNeededAndUserAgrees();
  91. if (r == FileBasedDocument::savedOk)
  92. {
  93. setProject (0);
  94. return true;
  95. }
  96. return false;
  97. }
  98. bool MainWindow::closeCurrentProject()
  99. {
  100. return currentProject == 0 || closeProject (currentProject);
  101. }
  102. bool MainWindow::closeAllDocuments (bool askUserToSave)
  103. {
  104. for (int i = OpenDocumentManager::getInstance()->getNumOpenDocuments(); --i >= 0;)
  105. {
  106. OpenDocumentManager::Document* doc = OpenDocumentManager::getInstance()->getOpenDocument (i);
  107. getProjectContentComponent()->hideDocument (doc);
  108. if (! OpenDocumentManager::getInstance()->closeDocument (i, askUserToSave))
  109. return false;
  110. }
  111. return true;
  112. }
  113. void MainWindow::setProject (Project* newProject)
  114. {
  115. if (newProject != 0)
  116. StoredSettings::getInstance()->setLastProject (newProject->getFile());
  117. getProjectContentComponent()->setProject (newProject);
  118. currentProject = newProject;
  119. commandManager->commandStatusChanged();
  120. }
  121. void MainWindow::reloadLastProject()
  122. {
  123. openFile (StoredSettings::getInstance()->getLastProject());
  124. }
  125. void MainWindow::askUserToOpenFile()
  126. {
  127. FileChooser fc ("Open File");
  128. if (fc.browseForFileToOpen())
  129. openFile (fc.getResult());
  130. }
  131. bool MainWindow::canOpenFile (const File& file) const
  132. {
  133. return file.hasFileExtension (Project::projectFileExtension)
  134. || OpenDocumentManager::getInstance()->canOpenFile (file);
  135. }
  136. bool MainWindow::openFile (const File& file)
  137. {
  138. if (file.hasFileExtension (Project::projectFileExtension))
  139. {
  140. ScopedPointer <Project> newDoc (new Project (file));
  141. if (file == File::nonexistent ? newDoc->loadFromUserSpecifiedFile (true)
  142. : newDoc->loadFrom (file, true))
  143. {
  144. if (closeCurrentProject())
  145. {
  146. setProject (newDoc.release());
  147. return true;
  148. }
  149. }
  150. }
  151. else if (file.exists())
  152. {
  153. return getProjectContentComponent()->showEditorForFile (file);
  154. }
  155. return false;
  156. }
  157. void MainWindow::createNewProject()
  158. {
  159. ScopedPointer <Project> newProj (ProjectWizard::runNewProjectWizard (this));
  160. if (newProj != 0 && closeCurrentProject())
  161. setProject (newProj.release());
  162. }
  163. bool MainWindow::isInterestedInFileDrag (const StringArray& filenames)
  164. {
  165. for (int i = filenames.size(); --i >= 0;)
  166. if (canOpenFile (filenames[i]))
  167. return true;
  168. return false;
  169. }
  170. void MainWindow::filesDropped (const StringArray& filenames, int mouseX, int mouseY)
  171. {
  172. for (int i = filenames.size(); --i >= 0;)
  173. {
  174. const File f (filenames[i]);
  175. if (canOpenFile (f) && openFile (f))
  176. break;
  177. }
  178. }
  179. void MainWindow::activeWindowStatusChanged()
  180. {
  181. DocumentWindow::activeWindowStatusChanged();
  182. if (getProjectContentComponent() != 0)
  183. getProjectContentComponent()->updateMissingFileStatuses();
  184. OpenDocumentManager::getInstance()->reloadModifiedFiles();
  185. }
  186. void MainWindow::updateTitle (const String& documentName)
  187. {
  188. String name (JUCEApplication::getInstance()->getApplicationName());
  189. if (documentName.isNotEmpty())
  190. name = documentName + " - " + name;
  191. setName (name);
  192. }
  193. //==============================================================================
  194. const StringArray MainWindow::getMenuBarNames()
  195. {
  196. const char* const names[] = { "File", "Edit", "View", "Window", 0 };
  197. return StringArray ((const char**) names);
  198. }
  199. const PopupMenu MainWindow::getMenuForIndex (int topLevelMenuIndex,
  200. const String& menuName)
  201. {
  202. PopupMenu menu;
  203. if (topLevelMenuIndex == 0)
  204. {
  205. // "File" menu
  206. menu.addCommandItem (commandManager, CommandIDs::newProject);
  207. menu.addSeparator();
  208. menu.addCommandItem (commandManager, CommandIDs::open);
  209. PopupMenu recentFiles;
  210. StoredSettings::getInstance()->recentFiles.createPopupMenuItems (recentFiles, 100, true, true);
  211. menu.addSubMenu ("Open recent file", recentFiles);
  212. menu.addSeparator();
  213. menu.addCommandItem (commandManager, CommandIDs::closeDocument);
  214. menu.addCommandItem (commandManager, CommandIDs::saveDocument);
  215. menu.addCommandItem (commandManager, CommandIDs::saveDocumentAs);
  216. menu.addSeparator();
  217. menu.addCommandItem (commandManager, CommandIDs::closeProject);
  218. menu.addCommandItem (commandManager, CommandIDs::saveProject);
  219. menu.addCommandItem (commandManager, CommandIDs::saveProjectAs);
  220. menu.addSeparator();
  221. menu.addCommandItem (commandManager, CommandIDs::openProjectInIDE);
  222. #if ! JUCE_MAC
  223. menu.addSeparator();
  224. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::quit);
  225. #endif
  226. }
  227. else if (topLevelMenuIndex == 1)
  228. {
  229. // "Edit" menu
  230. menu.addCommandItem (commandManager, CommandIDs::undo);
  231. menu.addCommandItem (commandManager, CommandIDs::redo);
  232. menu.addSeparator();
  233. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::cut);
  234. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::copy);
  235. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::paste);
  236. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::del);
  237. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::selectAll);
  238. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::deselectAll);
  239. menu.addSeparator();
  240. menu.addCommandItem (commandManager, CommandIDs::toFront);
  241. menu.addCommandItem (commandManager, CommandIDs::toBack);
  242. menu.addSeparator();
  243. menu.addCommandItem (commandManager, CommandIDs::group);
  244. menu.addCommandItem (commandManager, CommandIDs::ungroup);
  245. menu.addSeparator();
  246. menu.addCommandItem (commandManager, CommandIDs::bringBackLostItems);
  247. }
  248. else if (topLevelMenuIndex == 2)
  249. {
  250. // "View" menu
  251. menu.addCommandItem (commandManager, CommandIDs::showProjectSettings);
  252. menu.addSeparator();
  253. menu.addCommandItem (commandManager, CommandIDs::test);
  254. menu.addSeparator();
  255. menu.addCommandItem (commandManager, CommandIDs::showGrid);
  256. menu.addCommandItem (commandManager, CommandIDs::enableSnapToGrid);
  257. menu.addSeparator();
  258. menu.addCommandItem (commandManager, CommandIDs::zoomIn);
  259. menu.addCommandItem (commandManager, CommandIDs::zoomOut);
  260. menu.addCommandItem (commandManager, CommandIDs::zoomNormal);
  261. /* menu.addSeparator();
  262. PopupMenu overlays;
  263. overlays.addCommandItem (commandManager, CommandIDs::compOverlay0);
  264. overlays.addCommandItem (commandManager, CommandIDs::compOverlay33);
  265. overlays.addCommandItem (commandManager, CommandIDs::compOverlay66);
  266. overlays.addCommandItem (commandManager, CommandIDs::compOverlay100);
  267. menu.addSubMenu ("Component Overlay", overlays,
  268. getActiveDocument() != 0 && getActiveDocument()->getComponentLayout() != 0);*/
  269. menu.addSeparator();
  270. menu.addCommandItem (commandManager, CommandIDs::useTabbedWindows);
  271. //menu.addSeparator();
  272. //menu.addCommandItem (commandManager, CommandIDs::showPrefs);
  273. }
  274. else if (topLevelMenuIndex == 3)
  275. {
  276. // "Window" menu
  277. const int numDocs = jmin (50, OpenDocumentManager::getInstance()->getNumOpenDocuments());
  278. for (int i = 0; i < numDocs; ++i)
  279. {
  280. OpenDocumentManager::Document* doc = OpenDocumentManager::getInstance()->getOpenDocument(i);
  281. menu.addItem (300 + i, doc->getName());
  282. }
  283. menu.addSeparator();
  284. menu.addCommandItem (commandManager, CommandIDs::closeAllDocuments);
  285. }
  286. return menu;
  287. }
  288. void MainWindow::menuItemSelected (int menuItemID,
  289. int topLevelMenuIndex)
  290. {
  291. if (menuItemID >= 100 && menuItemID < 200)
  292. {
  293. // open a file from the "recent files" menu
  294. const File file (StoredSettings::getInstance()->recentFiles.getFile (menuItemID - 100));
  295. openFile (file);
  296. }
  297. else if (menuItemID == 201)
  298. {
  299. LookAndFeel::setDefaultLookAndFeel (0);
  300. }
  301. else if (menuItemID >= 300 && menuItemID < 400)
  302. {
  303. OpenDocumentManager::Document* doc = OpenDocumentManager::getInstance()->getOpenDocument (menuItemID - 300);
  304. getProjectContentComponent()->showDocument (doc);
  305. }
  306. }
  307. //==============================================================================
  308. ApplicationCommandTarget* MainWindow::getNextCommandTarget()
  309. {
  310. return 0;
  311. }
  312. void MainWindow::getAllCommands (Array <CommandID>& commands)
  313. {
  314. const CommandID ids[] = { CommandIDs::newProject,
  315. CommandIDs::open,
  316. CommandIDs::showPrefs,
  317. CommandIDs::closeAllDocuments,
  318. CommandIDs::saveAll };
  319. commands.addArray (ids, numElementsInArray (ids));
  320. }
  321. void MainWindow::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result)
  322. {
  323. switch (commandID)
  324. {
  325. case CommandIDs::newProject:
  326. result.setInfo ("New Project...",
  327. "Creates a new Jucer project",
  328. CommandCategories::general, 0);
  329. result.defaultKeypresses.add (KeyPress ('o', ModifierKeys::commandModifier, 0));
  330. break;
  331. case CommandIDs::open:
  332. result.setInfo ("Open...",
  333. "Opens a Jucer project",
  334. CommandCategories::general, 0);
  335. result.defaultKeypresses.add (KeyPress ('o', ModifierKeys::commandModifier, 0));
  336. break;
  337. case CommandIDs::showPrefs:
  338. result.setInfo ("Preferences...",
  339. "Shows the preferences panel.",
  340. CommandCategories::general, 0);
  341. result.defaultKeypresses.add (KeyPress (',', ModifierKeys::commandModifier, 0));
  342. break;
  343. case CommandIDs::closeAllDocuments:
  344. result.setInfo ("Close All Documents",
  345. "Closes all open documents",
  346. CommandCategories::general, 0);
  347. result.setActive (OpenDocumentManager::getInstance()->getNumOpenDocuments() > 0);
  348. break;
  349. case CommandIDs::saveAll:
  350. result.setInfo ("Save All",
  351. "Saves all open documents",
  352. CommandCategories::general, 0);
  353. result.setActive (OpenDocumentManager::getInstance()->anyFilesNeedSaving());
  354. break;
  355. default:
  356. break;
  357. }
  358. }
  359. bool MainWindow::perform (const InvocationInfo& info)
  360. {
  361. switch (info.commandID)
  362. {
  363. case CommandIDs::newProject:
  364. createNewProject();
  365. break;
  366. case CommandIDs::open:
  367. askUserToOpenFile();
  368. break;
  369. case CommandIDs::showPrefs:
  370. // PrefsPanel::show();
  371. break;
  372. case CommandIDs::saveAll:
  373. OpenDocumentManager::getInstance()->saveAll();
  374. break;
  375. case CommandIDs::closeAllDocuments:
  376. closeAllDocuments (true);
  377. break;
  378. default:
  379. return false;
  380. }
  381. return true;
  382. }