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.

237 lines
7.9KB

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