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.

277 lines
8.3KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. #include "../JuceDemoHeader.h"
  20. //==============================================================================
  21. /** The Note class contains text editor used to display and edit the note's contents and will
  22. also listen to changes in the text and mark the FileBasedDocument as 'dirty'. This 'dirty'
  23. flag is used to promt the user to save the note when it is closed.
  24. */
  25. class Note : public Component,
  26. public FileBasedDocument,
  27. private TextEditor::Listener
  28. {
  29. public:
  30. Note (const String& name, const String& contents)
  31. : FileBasedDocument (".jnote", "*.jnote",
  32. "Browse for note to load",
  33. "Choose file to save note to"),
  34. textValueObject (contents)
  35. {
  36. // we need to use an separate Value object as our text source so it doesn't get marked
  37. // as changed immediately
  38. setName (name);
  39. editor.setMultiLine (true);
  40. editor.setReturnKeyStartsNewLine (true);
  41. editor.getTextValue().referTo (textValueObject);
  42. addAndMakeVisible (editor);
  43. editor.addListener (this);
  44. }
  45. ~Note()
  46. {
  47. editor.removeListener (this);
  48. }
  49. void resized() override
  50. {
  51. editor.setBounds (getLocalBounds());
  52. }
  53. String getDocumentTitle() override
  54. {
  55. return getName();
  56. }
  57. Result loadDocument (const File& file) override
  58. {
  59. editor.setText (file.loadFileAsString());
  60. return Result::ok();
  61. }
  62. Result saveDocument (const File& file) override
  63. {
  64. // attempt to save the contents into the given file
  65. FileOutputStream os (file);
  66. if (os.openedOk())
  67. os.writeText (editor.getText(), false, false);
  68. return Result::ok();
  69. }
  70. File getLastDocumentOpened() override
  71. {
  72. // not interested in this for now
  73. return {};
  74. }
  75. void setLastDocumentOpened (const File& /*file*/) override
  76. {
  77. // not interested in this for now
  78. }
  79. #if JUCE_MODAL_LOOPS_PERMITTED
  80. File getSuggestedSaveAsFile (const File&) override
  81. {
  82. return File::getSpecialLocation (File::userDesktopDirectory).getChildFile (getName()).withFileExtension ("jnote");
  83. }
  84. #endif
  85. private:
  86. Value textValueObject;
  87. TextEditor editor;
  88. void textEditorTextChanged (TextEditor& ed) override
  89. {
  90. // let our FileBasedDocument know we've changed
  91. if (&ed == &editor)
  92. changed();
  93. }
  94. void textEditorReturnKeyPressed (TextEditor&) override {}
  95. void textEditorEscapeKeyPressed (TextEditor&) override {}
  96. void textEditorFocusLost (TextEditor&) override {}
  97. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Note)
  98. };
  99. //==============================================================================
  100. /** Simple MultiDocumentPanel that just tries to save our notes when they are closed.
  101. */
  102. class DemoMultiDocumentPanel : public MultiDocumentPanel
  103. {
  104. public:
  105. DemoMultiDocumentPanel()
  106. {
  107. }
  108. ~DemoMultiDocumentPanel()
  109. {
  110. closeAllDocuments (true);
  111. }
  112. bool tryToCloseDocument (Component* component) override
  113. {
  114. #if JUCE_MODAL_LOOPS_PERMITTED
  115. if (Note* note = dynamic_cast<Note*> (component))
  116. return note->saveIfNeededAndUserAgrees() != FileBasedDocument::failedToWriteToFile;
  117. #else
  118. ignoreUnused (component);
  119. #endif
  120. return true;
  121. }
  122. private:
  123. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DemoMultiDocumentPanel)
  124. };
  125. //==============================================================================
  126. /** Simple multi-document panel that manages a number of notes that you can store to files.
  127. By default this will look for notes saved to the desktop and load them up.
  128. */
  129. class MDIDemo : public Component,
  130. public FileDragAndDropTarget,
  131. private Button::Listener
  132. {
  133. public:
  134. MDIDemo()
  135. {
  136. setOpaque (true);
  137. showInTabsButton.setButtonText ("Show with tabs");
  138. showInTabsButton.setToggleState (false, dontSendNotification);
  139. showInTabsButton.addListener (this);
  140. addAndMakeVisible (showInTabsButton);
  141. addNoteButton.setButtonText ("Create a new note");
  142. addNoteButton.addListener (this);
  143. addAndMakeVisible (addNoteButton);
  144. addAndMakeVisible (multiDocumentPanel);
  145. multiDocumentPanel.setBackgroundColour (Colours::transparentBlack);
  146. updateLayoutMode();
  147. addNote ("Notes Demo", "You can drag-and-drop text files onto this page to open them as notes..");
  148. addExistingNotes();
  149. }
  150. ~MDIDemo()
  151. {
  152. addNoteButton.removeListener (this);
  153. showInTabsButton.removeListener (this);
  154. }
  155. void paint (Graphics& g) override
  156. {
  157. g.fillAll (getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::windowBackground));
  158. }
  159. void resized() override
  160. {
  161. Rectangle<int> area (getLocalBounds());
  162. Rectangle<int> buttonArea (area.removeFromTop (28).reduced (2));
  163. addNoteButton.setBounds (buttonArea.removeFromRight (150));
  164. showInTabsButton.setBounds (buttonArea);
  165. multiDocumentPanel.setBounds (area);
  166. }
  167. bool isInterestedInFileDrag (const StringArray&) override
  168. {
  169. return true;
  170. }
  171. void filesDropped (const StringArray& filenames, int /* x */, int /* y */) override
  172. {
  173. Array<File> files;
  174. for (int i = 0; i < filenames.size(); ++i)
  175. files.add (File (filenames[i]));
  176. createNotesForFiles (files);
  177. }
  178. void createNotesForFiles (const Array<File>& files)
  179. {
  180. for (int i = 0; i < files.size(); ++i)
  181. {
  182. const File file (files[i]);
  183. String content = file.loadFileAsString();
  184. if (content.length() > 20000)
  185. content = "Too long!";
  186. addNote (file.getFileName(), content);
  187. }
  188. }
  189. private:
  190. ToggleButton showInTabsButton;
  191. TextButton addNoteButton;
  192. DemoMultiDocumentPanel multiDocumentPanel;
  193. void updateLayoutMode()
  194. {
  195. multiDocumentPanel.setLayoutMode (showInTabsButton.getToggleState() ? MultiDocumentPanel::MaximisedWindowsWithTabs
  196. : MultiDocumentPanel::FloatingWindows);
  197. }
  198. void addNote (const String& name, const String& content)
  199. {
  200. Note* newNote = new Note (name, content);
  201. newNote->setSize (200, 200);
  202. multiDocumentPanel.addDocument (newNote, Colours::lightblue.withAlpha (0.6f), true);
  203. }
  204. void addExistingNotes()
  205. {
  206. Array<File> files;
  207. File::getSpecialLocation (File::userDesktopDirectory).findChildFiles (files, File::findFiles, false, "*.jnote");
  208. createNotesForFiles (files);
  209. }
  210. void buttonClicked (Button* b) override
  211. {
  212. if (b == &showInTabsButton)
  213. updateLayoutMode();
  214. else if (b == &addNoteButton)
  215. addNote (String ("Note ") + String (multiDocumentPanel.getNumDocuments() + 1), "Hello World!");
  216. }
  217. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MDIDemo)
  218. };
  219. // This static object will register this demo type in a global list of demos..
  220. static JuceDemoType<MDIDemo> demo ("10 Components: MDI");