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.

272 lines
8.4KB

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