2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-10 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #ifndef __JUCER_APPLICATION_H_6595C2A8__
27 #define __JUCER_APPLICATION_H_6595C2A8__
29 #include "../jucer_Headers.h"
30 #include "jucer_MainWindow.h"
31 #include "jucer_JuceUpdater.h"
32 #include "../Project/jucer_NewProjectWizard.h"
35 //==============================================================================
36 class JucerApplication
: public JUCEApplication
39 //==============================================================================
41 ~JucerApplication() {}
43 //==============================================================================
44 void initialise (const String
& commandLine
)
46 /* Running a command-line of the form "Jucer --resave foobar.jucer" will try to load that
47 jucer file and re-export all of its projects.
49 if (commandLine
.startsWithIgnoreCase ("-resave ") || commandLine
.startsWithIgnoreCase ("--resave "))
51 Project::resaveJucerFile (File::getCurrentWorkingDirectory()
52 .getChildFile (commandLine
.fromFirstOccurrenceOf (" ", false, false).unquoted()));
57 commandManager
= new ApplicationCommandManager();
58 commandManager
->registerAllCommandsForTarget (this);
60 menuModel
= new MainMenuModel();
62 MainWindow
* main
= createNewMainWindow (false);
63 doExtraInitialisation();
65 ImageCache::setCacheTimeout (30 * 1000);
67 if (commandLine
.trim().isNotEmpty() && ! commandLine
.trim().startsWithChar ('-'))
69 anotherInstanceStarted (commandLine
);
73 Array
<File
> projects (StoredSettings::getInstance()->getLastProjects());
75 for (int i
= 0; i
< projects
.size(); ++ i
)
76 openFile (projects
.getReference(i
));
80 MenuBarModel::setMacMainMenu (menuModel
);
83 main
->setVisible (true);
89 MenuBarModel::setMacMainMenu (nullptr);
93 StoredSettings::deleteInstance();
96 OpenDocumentManager::deleteInstance();
97 deleteAndZero (commandManager
);
100 //==============================================================================
101 void systemRequestedQuit()
103 while (mainWindows
.size() > 0)
105 if (! mainWindows
[0]->closeCurrentProject())
108 mainWindows
.remove (0);
114 void closeWindow (MainWindow
* w
)
116 jassert (mainWindows
.contains (w
));
117 mainWindows
.removeObject (w
);
120 if (mainWindows
.size() == 0)
121 systemRequestedQuit();
124 updateRecentProjectList();
127 //==============================================================================
128 const String
getApplicationName()
130 return String (ProjectInfo::projectName
) + " " + getApplicationVersion();
133 const String
getApplicationVersion()
135 return ProjectInfo::versionString
;
138 bool moreThanOneInstanceAllowed()
143 return true; //xxx should be false but doesn't work on linux..
147 void anotherInstanceStarted (const String
& commandLine
)
149 openFile (commandLine
.unquoted());
152 virtual void doExtraInitialisation() {}
154 //==============================================================================
155 class MainMenuModel
: public MenuBarModel
160 setApplicationCommandManagerToWatch (commandManager
);
163 const StringArray
getMenuBarNames()
165 const char* const names
[] = { "File", "Edit", "View", "Window", "Update", 0 };
166 return StringArray ((const char**) names
);
169 const PopupMenu
getMenuForIndex (int topLevelMenuIndex
, const String
& menuName
)
173 if (topLevelMenuIndex
== 0) // "File" menu
175 menu
.addCommandItem (commandManager
, CommandIDs::newProject
);
177 menu
.addCommandItem (commandManager
, CommandIDs::open
);
179 PopupMenu recentFiles
;
180 StoredSettings::getInstance()->recentFiles
.createPopupMenuItems (recentFiles
, 100, true, true);
181 menu
.addSubMenu ("Open recent file", recentFiles
);
184 menu
.addCommandItem (commandManager
, CommandIDs::closeDocument
);
185 menu
.addCommandItem (commandManager
, CommandIDs::saveDocument
);
186 menu
.addCommandItem (commandManager
, CommandIDs::saveDocumentAs
);
188 menu
.addCommandItem (commandManager
, CommandIDs::closeProject
);
189 menu
.addCommandItem (commandManager
, CommandIDs::saveProject
);
190 menu
.addCommandItem (commandManager
, CommandIDs::saveProjectAs
);
192 menu
.addCommandItem (commandManager
, CommandIDs::openInIDE
);
193 menu
.addCommandItem (commandManager
, CommandIDs::saveAndOpenInIDE
);
197 menu
.addCommandItem (commandManager
, StandardApplicationCommandIDs::quit
);
200 else if (topLevelMenuIndex
== 1) // "Edit" menu
202 menu
.addCommandItem (commandManager
, CommandIDs::undo
);
203 menu
.addCommandItem (commandManager
, CommandIDs::redo
);
205 menu
.addCommandItem (commandManager
, StandardApplicationCommandIDs::cut
);
206 menu
.addCommandItem (commandManager
, StandardApplicationCommandIDs::copy
);
207 menu
.addCommandItem (commandManager
, StandardApplicationCommandIDs::paste
);
208 menu
.addCommandItem (commandManager
, StandardApplicationCommandIDs::del
);
209 menu
.addCommandItem (commandManager
, StandardApplicationCommandIDs::selectAll
);
210 menu
.addCommandItem (commandManager
, StandardApplicationCommandIDs::deselectAll
);
212 menu
.addCommandItem (commandManager
, CommandIDs::toFront
);
213 menu
.addCommandItem (commandManager
, CommandIDs::toBack
);
215 menu
.addCommandItem (commandManager
, CommandIDs::group
);
216 menu
.addCommandItem (commandManager
, CommandIDs::ungroup
);
218 menu
.addCommandItem (commandManager
, CommandIDs::bringBackLostItems
);
220 else if (topLevelMenuIndex
== 2) // "View" menu
222 menu
.addCommandItem (commandManager
, CommandIDs::showProjectSettings
);
225 menu
.addCommandItem (commandManager
, CommandIDs::test
);
228 menu
.addCommandItem (commandManager
, CommandIDs::showGrid
);
229 menu
.addCommandItem (commandManager
, CommandIDs::enableSnapToGrid
);
232 menu
.addCommandItem (commandManager
, CommandIDs::zoomIn
);
233 menu
.addCommandItem (commandManager
, CommandIDs::zoomOut
);
234 menu
.addCommandItem (commandManager
, CommandIDs::zoomNormal
);
237 menu
.addCommandItem (commandManager
, CommandIDs::useTabbedWindows
);
239 else if (topLevelMenuIndex
== 3) // "Window" menu
241 menu
.addCommandItem (commandManager
, CommandIDs::closeWindow
);
244 const int numDocs
= jmin (50, OpenDocumentManager::getInstance()->getNumOpenDocuments());
246 for (int i
= 0; i
< numDocs
; ++i
)
248 OpenDocumentManager::Document
* doc
= OpenDocumentManager::getInstance()->getOpenDocument(i
);
250 menu
.addItem (300 + i
, doc
->getName());
254 menu
.addCommandItem (commandManager
, CommandIDs::closeAllDocuments
);
256 else if (topLevelMenuIndex
== 4) // "Juce" menu
258 menu
.addCommandItem (commandManager
, CommandIDs::showJuceVersion
);
264 void menuItemSelected (int menuItemID
, int topLevelMenuIndex
)
266 if (menuItemID
>= 100 && menuItemID
< 200)
268 // open a file from the "recent files" menu
269 const File
file (StoredSettings::getInstance()->recentFiles
.getFile (menuItemID
- 100));
271 getApp()->openFile (file
);
273 else if (menuItemID
>= 300 && menuItemID
< 400)
275 OpenDocumentManager::Document
* doc
= OpenDocumentManager::getInstance()->getOpenDocument (menuItemID
- 300);
276 getApp()->getOrCreateFrontmostWindow (true)->getProjectContentComponent()->showDocument (doc
);
281 JucerApplication
* getApp() const
283 return static_cast<JucerApplication
*> (JUCEApplication::getInstance());
287 //==============================================================================
288 void getAllCommands (Array
<CommandID
>& commands
)
290 JUCEApplication::getAllCommands (commands
);
292 const CommandID ids
[] = { CommandIDs::newProject
,
294 CommandIDs::showPrefs
,
295 CommandIDs::closeAllDocuments
,
297 CommandIDs::showJuceVersion
};
299 commands
.addArray (ids
, numElementsInArray (ids
));
302 void getCommandInfo (CommandID commandID
, ApplicationCommandInfo
& result
)
306 case CommandIDs::newProject
:
307 result
.setInfo ("New Project...", "Creates a new Jucer project", CommandCategories::general
, 0);
308 result
.defaultKeypresses
.add (KeyPress ('o', ModifierKeys::commandModifier
, 0));
311 case CommandIDs::open
:
312 result
.setInfo ("Open...", "Opens a Jucer project", CommandCategories::general
, 0);
313 result
.defaultKeypresses
.add (KeyPress ('o', ModifierKeys::commandModifier
, 0));
316 case CommandIDs::showPrefs
:
317 result
.setInfo ("Preferences...", "Shows the preferences panel.", CommandCategories::general
, 0);
318 result
.defaultKeypresses
.add (KeyPress (',', ModifierKeys::commandModifier
, 0));
321 case CommandIDs::closeAllDocuments
:
322 result
.setInfo ("Close All Documents", "Closes all open documents", CommandCategories::general
, 0);
323 result
.setActive (OpenDocumentManager::getInstance()->getNumOpenDocuments() > 0);
326 case CommandIDs::saveAll
:
327 result
.setInfo ("Save All", "Saves all open documents", CommandCategories::general
, 0);
328 result
.setActive (OpenDocumentManager::getInstance()->anyFilesNeedSaving());
331 case CommandIDs::showJuceVersion
:
332 result
.setInfo ("Download the latest JUCE version", "Checks online for any Juce updates", CommandCategories::general
, 0);
336 JUCEApplication::getCommandInfo (commandID
, result
);
341 bool perform (const InvocationInfo
& info
)
343 switch (info
.commandID
)
345 case CommandIDs::newProject
: createNewProject(); break;
346 case CommandIDs::open
: askUserToOpenFile(); break;
347 case CommandIDs::showPrefs
: showPrefsPanel(); break;
348 case CommandIDs::saveAll
: OpenDocumentManager::getInstance()->saveAll(); break;
349 case CommandIDs::closeAllDocuments
: closeAllDocuments (true); break;
350 case CommandIDs::showJuceVersion
: JuceUpdater::show (mainWindows
[0]); break;
351 default: return JUCEApplication::perform (info
);
357 //==============================================================================
358 void showPrefsPanel()
363 void createNewProject()
365 MainWindow
* mw
= createNewMainWindow (false);
366 ScopedPointer
<Project
> newProj (NewProjectWizard::runNewProjectWizard (mw
));
368 if (newProj
!= nullptr)
370 mw
->setProject (newProj
.release());
371 mw
->setVisible (true);
379 void askUserToOpenFile()
381 FileChooser
fc ("Open File");
383 if (fc
.browseForFileToOpen())
384 openFile (fc
.getResult());
387 bool openFile (const File
& file
)
389 for (int j
= mainWindows
.size(); --j
>= 0;)
391 if (mainWindows
.getUnchecked(j
)->getProject() != nullptr
392 && mainWindows
.getUnchecked(j
)->getProject()->getFile() == file
)
394 mainWindows
.getUnchecked(j
)->toFront (true);
399 if (file
.hasFileExtension (Project::projectFileExtension
))
401 ScopedPointer
<Project
> newDoc (new Project (file
));
403 if (file
== File::nonexistent
? newDoc
->loadFromUserSpecifiedFile (true)
404 : newDoc
->loadFrom (file
, true))
406 MainWindow
* w
= getOrCreateEmptyWindow (false);
407 w
->setProject (newDoc
.release());
408 w
->restoreWindowPosition();
409 w
->setVisible (true);
413 else if (file
.exists())
415 return getOrCreateFrontmostWindow (true)->openFile (file
);
421 bool closeAllDocuments (bool askUserToSave
)
423 for (int i
= OpenDocumentManager::getInstance()->getNumOpenDocuments(); --i
>= 0;)
425 OpenDocumentManager::Document
* doc
= OpenDocumentManager::getInstance()->getOpenDocument (i
);
427 for (int j
= mainWindows
.size(); --j
>= 0;)
428 mainWindows
.getUnchecked(j
)->getProjectContentComponent()->hideDocument (doc
);
430 if (! OpenDocumentManager::getInstance()->closeDocument (i
, askUserToSave
))
437 void updateRecentProjectList()
439 Array
<File
> projects
;
441 for (int i
= 0; i
< mainWindows
.size(); ++i
)
443 MainWindow
* mw
= mainWindows
[i
];
445 if (mw
!= nullptr && mw
->getProject() != nullptr)
446 projects
.add (mw
->getProject()->getFile());
449 StoredSettings::getInstance()->setLastProjects (projects
);
452 ScopedPointer
<MainMenuModel
> menuModel
;
455 OwnedArray
<MainWindow
> mainWindows
;
457 MainWindow
* createNewMainWindow (bool makeVisible
)
459 MainWindow
* mw
= new MainWindow();
461 for (int i
= mainWindows
.size(); --i
>= 0;)
462 if (mw
->getBounds() == mainWindows
.getUnchecked(i
)->getBounds())
463 mw
->setBounds (mw
->getBounds().translated (20, 20));
465 mainWindows
.add (mw
);
468 mw
->setVisible (true);
470 mw
->restoreWindowPosition();
474 MainWindow
* getOrCreateFrontmostWindow (bool makeVisible
)
476 if (mainWindows
.size() == 0)
477 return createNewMainWindow (makeVisible
);
479 for (int i
= Desktop::getInstance().getNumComponents(); --i
>= 0;)
481 MainWindow
* mw
= dynamic_cast <MainWindow
*> (Desktop::getInstance().getComponent (i
));
482 if (mainWindows
.contains (mw
))
486 return mainWindows
.getLast();
489 MainWindow
* getOrCreateEmptyWindow (bool makeVisible
)
491 if (mainWindows
.size() == 0)
492 return createNewMainWindow (makeVisible
);
494 for (int i
= Desktop::getInstance().getNumComponents(); --i
>= 0;)
496 MainWindow
* mw
= dynamic_cast <MainWindow
*> (Desktop::getInstance().getComponent (i
));
497 if (mainWindows
.contains (mw
) && mw
->getProject() == nullptr)
501 return createNewMainWindow (makeVisible
);
506 #endif // __JUCER_APPLICATION_H_6595C2A8__