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.

218 lines
7.6KB

  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. #ifndef __JUCER_COMPONENTEDITORCODEVIEW_H_CA5124B0__
  19. #define __JUCER_COMPONENTEDITORCODEVIEW_H_CA5124B0__
  20. //==============================================================================
  21. class ComponentEditor::CodeEditorHolder : public Component,
  22. public ButtonListener
  23. {
  24. public:
  25. //==============================================================================
  26. CodeEditorHolder (ComponentEditor& editor_)
  27. : editor (editor_), switchFileButton (String::empty), showingHeader (true)
  28. {
  29. addAndMakeVisible (&viewport);
  30. viewport.setScrollBarsShown (true, false);
  31. addAndMakeVisible (&switchFileButton);
  32. buttonClicked (0);
  33. switchFileButton.addButtonListener (this);
  34. }
  35. ~CodeEditorHolder()
  36. {
  37. }
  38. void resized()
  39. {
  40. viewport.setBounds (getLocalBounds());
  41. int visWidth = viewport.getMaximumVisibleWidth();
  42. dynamic_cast <ContentHolder*> (viewport.getViewedComponent())->updateSize (visWidth);
  43. if (viewport.getMaximumVisibleWidth() != visWidth)
  44. dynamic_cast <ContentHolder*> (viewport.getViewedComponent())->updateSize (viewport.getMaximumVisibleWidth());
  45. switchFileButton.setBounds (getWidth() - 150, 4, 120, 20);
  46. }
  47. void buttonClicked (Button*)
  48. {
  49. showingHeader = ! showingHeader;
  50. viewport.setViewedComponent (new ContentHolder (editor.getDocument(), showingHeader));
  51. resized();
  52. switchFileButton.setButtonText (showingHeader ? "Show CPP file" : "Show header file");
  53. }
  54. private:
  55. enum { updateCommandId = 0x23427fa1 };
  56. //==============================================================================
  57. class EditorHolder : public Component,
  58. public CodeDocument::Listener
  59. {
  60. public:
  61. EditorHolder (const CodeGenerator::CustomCodeList::CodeDocumentRef::Ptr doc,
  62. const String& textBefore, const String& textAfter)
  63. : document (doc), cppTokeniser(), codeEditor (doc->getDocument(), &cppTokeniser)
  64. {
  65. linesBefore.addLines (textBefore);
  66. linesAfter.addLines (textAfter);
  67. addAndMakeVisible (&codeEditor);
  68. doc->getDocument().addListener (this);
  69. }
  70. ~EditorHolder()
  71. {
  72. document->getDocument().removeListener (this);
  73. }
  74. void paint (Graphics& g)
  75. {
  76. g.setFont (codeEditor.getFont());
  77. g.setColour (Colours::darkgrey);
  78. const int fontHeight = codeEditor.getLineHeight();
  79. const int fontAscent = (int) codeEditor.getFont().getAscent();
  80. const int textX = 5;
  81. int i;
  82. for (i = 0; i < linesBefore.size(); ++i)
  83. g.drawSingleLineText (linesBefore[i], textX, i * fontHeight + fontAscent);
  84. for (i = 0; i < linesAfter.size(); ++i)
  85. g.drawSingleLineText (linesAfter[i], textX, codeEditor.getBottom() + i * fontHeight + fontAscent);
  86. }
  87. void updateSize (int width)
  88. {
  89. const int fontHeight = codeEditor.getLineHeight();
  90. codeEditor.setBounds (0, fontHeight * linesBefore.size() + 1,
  91. width, 2 + codeEditor.getScrollbarThickness()
  92. + fontHeight * jlimit (1, 50, document->getDocument().getNumLines()));
  93. setSize (width, (linesBefore.size() + linesAfter.size()) * fontHeight + codeEditor.getHeight());
  94. }
  95. void codeDocumentChanged (const CodeDocument::Position&, const CodeDocument::Position&)
  96. {
  97. int oldHeight = getHeight();
  98. updateSize (getWidth());
  99. if (getHeight() != oldHeight)
  100. getParentComponent()->handleCommandMessage (updateCommandId);
  101. }
  102. private:
  103. const CodeGenerator::CustomCodeList::CodeDocumentRef::Ptr document;
  104. CPlusPlusCodeTokeniser cppTokeniser;
  105. CodeEditorComponent codeEditor;
  106. StringArray linesBefore, linesAfter;
  107. };
  108. //==============================================================================
  109. class ContentHolder : public Component,
  110. public ChangeListener
  111. {
  112. public:
  113. ContentHolder (ComponentDocument& document_, bool isHeader_)
  114. : document (document_), isHeader (isHeader_)
  115. {
  116. setOpaque (true);
  117. document.getCustomCodeList().addChangeListener (this);
  118. changeListenerCallback (0);
  119. }
  120. ~ContentHolder()
  121. {
  122. document.getCustomCodeList().removeChangeListener (this);
  123. }
  124. void paint (Graphics& g)
  125. {
  126. g.fillAll (Colours::lightgrey);
  127. }
  128. void updateSize (int width)
  129. {
  130. int y = 2;
  131. for (int i = 0; i < editors.size(); ++i)
  132. {
  133. EditorHolder* const ed = editors.getUnchecked(i);
  134. ed->updateSize (width - 8);
  135. ed->setTopLeftPosition (4, y + 1);
  136. y = ed->getBottom() + 1;
  137. }
  138. setSize (width, y + 2);
  139. }
  140. void changeListenerCallback (void*)
  141. {
  142. editors.clear();
  143. CodeGenerator::CustomCodeList::Iterator iter (isHeader ? document.getHeaderContent()
  144. : document.getCppContent(),
  145. document.getCustomCodeList());
  146. while (iter.next())
  147. {
  148. EditorHolder* ed = new EditorHolder (iter.codeDocument, iter.textBefore, iter.textAfter);
  149. editors.add (ed);
  150. addAndMakeVisible (ed);
  151. }
  152. updateSize (getWidth());
  153. }
  154. void handleCommandMessage (int commandId)
  155. {
  156. if (commandId == updateCommandId)
  157. updateSize (getWidth());
  158. else
  159. Component::handleCommandMessage (commandId);
  160. }
  161. private:
  162. OwnedArray <EditorHolder> editors;
  163. ComponentDocument& document;
  164. bool isHeader;
  165. };
  166. //==============================================================================
  167. ComponentEditor& editor;
  168. Viewport viewport;
  169. TextButton switchFileButton;
  170. bool showingHeader;
  171. };
  172. #endif // __JUCER_COMPONENTEDITORCODEVIEW_H_CA5124B0__