34 class SafeParentPointer
38 : ptr (parent), shouldCheck (
isAsync)
41 Pimpl* operator->()
const noexcept
46 bool operator== (
Pimpl*
object)
const noexcept {
return ptr.get() == object; }
47 bool operator!= (
Pimpl*
object)
const noexcept {
return ptr.get() != object; }
49 bool shouldExitAsyncCallback()
const noexcept
51 return shouldCheck && ptr ==
nullptr;
56 bool shouldCheck =
false;
75 bool hasChangedSinceSaved()
const
77 return changedSinceSave;
91 changedSinceSave =
true;
98 SafeParentPointer parent {
this,
false };
100 loadFromImpl (parent,
104 [
this] (
const File& file,
const auto& callback) { callback (document.
loadDocument (file)); },
105 [&result] (
Result r) { result = r; });
113 SafeParentPointer parent {
this,
true };
114 loadFromImpl (parent,
118 [parent] (
const File& file,
auto cb)
120 if (parent !=
nullptr)
121 parent->document.loadDocumentAsync (file, std::move (
cb));
123 std::move (callback));
127 #if JUCE_MODAL_LOOPS_PERMITTED
134 if (
fc.browseForFileToOpen())
143 asyncFc = std::make_unique<FileChooser> (openFileDialogTitle,
161 if (parent !=
nullptr)
162 NullCheckedInvocation::invoke (
cb, result);
170 #if JUCE_MODAL_LOOPS_PERMITTED
174 return saveAs (documentFile,
185 saveAsAsync (documentFile,
189 std::move (callback));
193 #if JUCE_MODAL_LOOPS_PERMITTED
196 SafeParentPointer parent {
this,
false };
198 saveIfNeededAndUserAgreesImpl (parent,
208 SafeParentPointer parent {
this,
true };
210 saveIfNeededAndUserAgreesImpl (parent,
211 std::move (callback),
212 [] (SafeParentPointer ptr,
auto cb)
215 ptr->askToSaveChangesAsync (ptr, std::move (
cb));
221 if (parent !=
nullptr)
229 #if JUCE_MODAL_LOOPS_PERMITTED
231 bool warnAboutOverwritingExistingFiles,
234 bool showWaitCursor =
true)
236 SafeParentPointer parent {
this,
false };
240 warnAboutOverwritingExistingFiles,
250 bool warnAboutOverwritingExistingFiles,
255 SafeParentPointer parent {
this,
true };
256 saveAsAsyncImpl (parent,
258 warnAboutOverwritingExistingFiles,
261 std::move (callback),
266 #if JUCE_MODAL_LOOPS_PERMITTED
269 SafeParentPointer parent {
this,
false };
272 warnAboutOverwritingExistingFiles,
278 void saveAsInteractiveAsync (
bool warnAboutOverwritingExistingFiles,
281 SafeParentPointer parent {
this,
true };
282 saveAsInteractiveAsyncImpl (parent,
283 warnAboutOverwritingExistingFiles,
284 std::move (callback));
288 const File& getFile()
const
303 const String& getFileExtension()
const
305 return fileExtension;
310 template <
typename DoLoadDocument>
311 void loadFromImpl (SafeParentPointer parent,
318 if (parent.shouldExitAsyncCallback())
329 if (parent.shouldExitAsyncCallback())
332 parent->documentFile =
oldFile;
340 TRANS (
"Failed to open file..."),
341 TRANS (
"There was an error while trying to load the file: FLNM")
342 .replace (
"FLNM",
"\n" +
newFile.getFullPathName())
344 + result.getErrorMessage());
348 NullCheckedInvocation::invoke (
completed, result);
361 parent->setChangedFlag (
false);
366 parent->document.setLastDocumentOpened (
newFile);
367 NullCheckedInvocation::invoke (
cb, result);
383 template <
typename DoAskToSaveChanges,
typename DoSave>
384 void saveIfNeededAndUserAgreesImpl (SafeParentPointer parent,
389 if (parent.shouldExitAsyncCallback())
392 if (! hasChangedSinceSaved())
399 cb = std::move (
completed)] (SafeParentPointer ptr,
402 if (ptr.shouldExitAsyncCallback())
410 if (ptr.shouldExitAsyncCallback())
413 NullCheckedInvocation::invoke (
cb, result);
418 NullCheckedInvocation::invoke (
cb,
savedOk);
432 TRANS (
"Closing document..."),
433 TRANS (
"Do you want to save the changes to \"DCNM\"?")
436 TRANS (
"Discard changes"),
440 void askToSaveChangesAsync (SafeParentPointer parent,
446 if (parent !=
nullptr)
451 #if JUCE_MODAL_LOOPS_PERMITTED
454 return AlertWindow::show (getAskToSaveChangesOptions());
459 template <
typename DoSaveDocument>
460 void saveInternal (SafeParentPointer parent,
480 if (parent.shouldExitAsyncCallback())
483 MouseCursor::hideWaitCursor();
490 parent->setChangedFlag (false);
493 MouseCursor::hideWaitCursor();
495 parent->document.sendChangeMessage();
497 NullCheckedInvocation::invoke (after, savedOk);
501 parent->documentFile =
oldFile;
509 TRANS (
"Error writing to file..."),
510 TRANS (
"An error occurred while trying to save \"DCNM\" to the file: FLNM")
511 .replace (
"DCNM", parent->document.getDocumentTitle())
512 .replace (
"FLNM",
"\n" +
newFile.getFullPathName())
518 parent->document.sendChangeMessage();
523 template <
typename DoSaveAsInteractive,
typename DoAskToOverwriteFile,
typename DoSaveDocument>
524 void saveAsImpl (SafeParentPointer parent,
526 bool warnAboutOverwritingExistingFiles,
535 if (parent.shouldExitAsyncCallback())
560 if (! parent.shouldExitAsyncCallback())
561 parent->saveInternal (parent,
569 if (warnAboutOverwritingExistingFiles &&
newFile.exists())
575 if (ptr.shouldExitAsyncCallback())
590 void saveAsAsyncImpl (SafeParentPointer parent,
592 bool warnAboutOverwritingExistingFiles,
600 warnAboutOverwritingExistingFiles,
603 std::move (callback),
605 [] (SafeParentPointer ptr,
bool warnAboutOverwriting,
auto cb)
608 ptr->saveAsInteractiveAsyncImpl (ptr, warnAboutOverwriting, std::move (
cb));
613 ptr->askToOverwriteFileAsync (ptr, destination, std::move (
cb));
617 if (parent !=
nullptr)
618 parent->document.saveDocumentAsync (destination, std::move (
cb));
623 void saveAsInteractiveAsyncImpl (SafeParentPointer parent,
624 bool warnAboutOverwritingExistingFiles,
627 if (parent ==
nullptr)
630 saveAsInteractiveImpl (parent,
631 warnAboutOverwritingExistingFiles,
632 std::move (callback),
633 [] (SafeParentPointer ptr,
bool warnAboutOverwriting,
auto cb)
636 ptr->getSaveAsFilenameAsync (ptr, warnAboutOverwriting, std::move (
cb));
638 [] (SafeParentPointer ptr,
640 bool warnAboutOverwriting,
647 ptr->saveAsAsyncImpl (ptr,
649 warnAboutOverwriting,
655 [] (SafeParentPointer ptr,
const File& destination,
auto cb)
658 ptr->askToOverwriteFileAsync (ptr, destination, std::move (
cb));
666 TRANS (
"File already exists"),
667 TRANS (
"There's already a file called: FLNM")
668 .replace (
"FLNM",
newFile.getFullPathName())
670 +
TRANS (
"Are you sure you want to overwrite it?"),
675 void askToOverwriteFileAsync (SafeParentPointer parent,
679 if (parent ==
nullptr)
683 [parent,
cb = std::move (callback)] (
int r)
685 if (parent !=
nullptr)
686 NullCheckedInvocation::invoke (
cb, parent, r != 1);
690 #if JUCE_MODAL_LOOPS_PERMITTED
693 return AlertWindow::show (getAskToOverwriteFileOptions (
newFile));
698 void getSaveAsFilenameAsync (SafeParentPointer parent,
699 bool warnAboutOverwritingExistingFiles,
702 asyncFc = getInteractiveFileChooser();
706 if (warnAboutOverwritingExistingFiles)
709 asyncFc->launchAsync (flags, [parent,
cb = std::move (callback)] (
const FileChooser&
fc)
711 cb (parent,
fc.getResult());
716 template <
typename DoSelectFilename,
typename DoSaveAs,
typename DoAskToOverwriteFile>
717 void saveAsInteractiveImpl (SafeParentPointer parent,
718 bool warnAboutOverwritingExistingFiles,
725 warnAboutOverwritingExistingFiles,
748 if (
chosen.getFileExtension().isEmpty())
785 f = (f.existsAsFile() || f.getParentDirectory().isDirectory())
791 return std::make_unique<FileChooser> (saveFileDialogTitle,
797 #if JUCE_MODAL_LOOPS_PERMITTED
800 template <
typename... Ts>
801 void operator() (Ts&&... ts)
const noexcept
803 p.saveAsInteractiveSyncImpl (std::forward<Ts> (ts)...);
811 template <
typename... Ts>
812 void operator() (Ts&&... ts)
const noexcept
814 p.askToOverwriteFileSync (std::forward<Ts> (ts)...);
822 template <
typename... Ts>
823 void operator() (Ts&&... ts)
const noexcept
825 p.askToSaveChangesSync (std::forward<Ts> (ts)...);
833 template <
typename... Ts>
834 void operator() (Ts&&... ts)
const noexcept
836 p.saveSync (std::forward<Ts> (ts)...);
844 template <
typename... Ts>
845 void operator() (Ts&&... ts)
const noexcept
847 p.getSaveAsFilenameSync (std::forward<Ts> (ts)...);
855 template <
typename... Ts>
856 void operator() (Ts&&... ts)
const noexcept
858 p.saveAsSyncImpl (std::forward<Ts> (ts)...);
867 bool warnAboutOverwritingExistingFiles,
875 warnAboutOverwritingExistingFiles,
878 std::move (callback),
886 template <
typename Callback>
894 bool warnAboutOverwritingExistingFiles,
897 saveAsInteractiveImpl (parent,
898 warnAboutOverwritingExistingFiles,
899 std::move (callback),
906 template <
typename Callback>
915 template <
typename Callback>
924 template <
typename Callback>
926 bool warnAboutOverwritingExistingFiles,
929 auto fc = getInteractiveFileChooser();
931 if (
fc->browseForFileToSave (warnAboutOverwritingExistingFiles))
933 callback (parent,
fc->getResult());
937 callback (parent, {});
945 bool changedSinceSave =
false;
946 String fileExtension, fileWildcard, openFileDialogTitle, saveFileDialogTitle;