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.

316 lines
13KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 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 __JUCE_CODEEDITORCOMPONENT_JUCEHEADER__
  19. #define __JUCE_CODEEDITORCOMPONENT_JUCEHEADER__
  20. #include "../juce_Component.h"
  21. #include "../layout/juce_ScrollBar.h"
  22. #include "../keyboard/juce_TextInputTarget.h"
  23. #include "../keyboard/juce_CaretComponent.h"
  24. #include "juce_CodeDocument.h"
  25. #include "juce_CodeTokeniser.h"
  26. //==============================================================================
  27. /**
  28. A text editor component designed specifically for source code.
  29. This is designed to handle syntax highlighting and fast editing of very large
  30. files.
  31. */
  32. class JUCE_API CodeEditorComponent : public Component,
  33. public TextInputTarget,
  34. public Timer,
  35. public ScrollBar::Listener,
  36. public CodeDocument::Listener,
  37. public AsyncUpdater
  38. {
  39. public:
  40. //==============================================================================
  41. /** Creates an editor for a document.
  42. The tokeniser object is optional - pass 0 to disable syntax highlighting.
  43. The object that you pass in is not owned or deleted by the editor - you must
  44. make sure that it doesn't get deleted while this component is still using it.
  45. @see CodeDocument
  46. */
  47. CodeEditorComponent (CodeDocument& document,
  48. CodeTokeniser* codeTokeniser);
  49. /** Destructor. */
  50. ~CodeEditorComponent();
  51. //==============================================================================
  52. /** Returns the code document that this component is editing. */
  53. CodeDocument& getDocument() const noexcept { return document; }
  54. /** Loads the given content into the document.
  55. This will completely reset the CodeDocument object, clear its undo history,
  56. and fill it with this text.
  57. */
  58. void loadContent (const String& newContent);
  59. //==============================================================================
  60. /** Returns the standard character width. */
  61. float getCharWidth() const noexcept { return charWidth; }
  62. /** Returns the height of a line of text, in pixels. */
  63. int getLineHeight() const noexcept { return lineHeight; }
  64. /** Returns the number of whole lines visible on the screen,
  65. This doesn't include a cut-off line that might be visible at the bottom if the
  66. component's height isn't an exact multiple of the line-height.
  67. */
  68. int getNumLinesOnScreen() const noexcept { return linesOnScreen; }
  69. /** Returns the number of whole columns visible on the screen.
  70. This doesn't include any cut-off columns at the right-hand edge.
  71. */
  72. int getNumColumnsOnScreen() const noexcept { return columnsOnScreen; }
  73. /** Returns the current caret position. */
  74. const CodeDocument::Position getCaretPos() const { return caretPos; }
  75. /** Returns the position of the caret, relative to the editor's origin. */
  76. const Rectangle<int> getCaretRectangle();
  77. /** Moves the caret.
  78. If selecting is true, the section of the document between the current
  79. caret position and the new one will become selected. If false, any currently
  80. selected region will be deselected.
  81. */
  82. void moveCaretTo (const CodeDocument::Position& newPos, bool selecting);
  83. /** Returns the on-screen position of a character in the document.
  84. The rectangle returned is relative to this component's top-left origin.
  85. */
  86. const Rectangle<int> getCharacterBounds (const CodeDocument::Position& pos) const;
  87. /** Finds the character at a given on-screen position.
  88. The co-ordinates are relative to this component's top-left origin.
  89. */
  90. const CodeDocument::Position getPositionAt (int x, int y);
  91. //==============================================================================
  92. bool moveCaretLeft (bool moveInWholeWordSteps, bool selecting);
  93. bool moveCaretRight (bool moveInWholeWordSteps, bool selecting);
  94. bool moveCaretUp (bool selecting);
  95. bool moveCaretDown (bool selecting);
  96. bool scrollDown();
  97. bool scrollUp();
  98. bool pageUp (bool selecting);
  99. bool pageDown (bool selecting);
  100. bool moveCaretToTop (bool selecting);
  101. bool moveCaretToStartOfLine (bool selecting);
  102. bool moveCaretToEnd (bool selecting);
  103. bool moveCaretToEndOfLine (bool selecting);
  104. bool deleteBackwards (bool moveInWholeWordSteps);
  105. bool deleteForwards (bool moveInWholeWordSteps);
  106. bool copyToClipboard();
  107. bool cutToClipboard();
  108. bool pasteFromClipboard();
  109. bool undo();
  110. bool redo();
  111. bool selectAll();
  112. void deselectAll();
  113. void scrollToLine (int newFirstLineOnScreen);
  114. void scrollBy (int deltaLines);
  115. void scrollToColumn (int newFirstColumnOnScreen);
  116. void scrollToKeepCaretOnScreen();
  117. void insertTextAtCaret (const String& textToInsert);
  118. void insertTabAtCaret();
  119. //==============================================================================
  120. const Range<int> getHighlightedRegion() const;
  121. void setHighlightedRegion (const Range<int>& newRange);
  122. const String getTextInRange (const Range<int>& range) const;
  123. //==============================================================================
  124. /** Changes the current tab settings.
  125. This lets you change the tab size and whether pressing the tab key inserts a
  126. tab character, or its equivalent number of spaces.
  127. */
  128. void setTabSize (int numSpacesPerTab, bool insertSpacesInsteadOfTabCharacters);
  129. /** Returns the current number of spaces per tab.
  130. @see setTabSize
  131. */
  132. int getTabSize() const noexcept { return spacesPerTab; }
  133. /** Returns true if the tab key will insert spaces instead of actual tab characters.
  134. @see setTabSize
  135. */
  136. bool areSpacesInsertedForTabs() const { return useSpacesForTabs; }
  137. /** Changes the font.
  138. Make sure you only use a fixed-width font, or this component will look pretty nasty!
  139. */
  140. void setFont (const Font& newFont);
  141. /** Returns the font that the editor is using. */
  142. const Font& getFont() const noexcept { return font; }
  143. /** Resets the syntax highlighting colours to the default ones provided by the
  144. code tokeniser.
  145. @see CodeTokeniser::getDefaultColour
  146. */
  147. void resetToDefaultColours();
  148. /** Changes one of the syntax highlighting colours.
  149. The token type values are dependent on the tokeniser being used - use
  150. CodeTokeniser::getTokenTypes() to get a list of the token types.
  151. @see getColourForTokenType
  152. */
  153. void setColourForTokenType (int tokenType, const Colour& colour);
  154. /** Returns one of the syntax highlighting colours.
  155. The token type values are dependent on the tokeniser being used - use
  156. CodeTokeniser::getTokenTypes() to get a list of the token types.
  157. @see setColourForTokenType
  158. */
  159. const Colour getColourForTokenType (int tokenType) const;
  160. //==============================================================================
  161. /** A set of colour IDs to use to change the colour of various aspects of the editor.
  162. These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
  163. methods.
  164. @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
  165. */
  166. enum ColourIds
  167. {
  168. backgroundColourId = 0x1004500, /**< A colour to use to fill the editor's background. */
  169. highlightColourId = 0x1004502, /**< The colour to use for the highlighted background under
  170. selected text. */
  171. defaultTextColourId = 0x1004503 /**< The colour to use for text when no syntax colouring is
  172. enabled. */
  173. };
  174. //==============================================================================
  175. /** Changes the size of the scrollbars. */
  176. void setScrollbarThickness (int thickness);
  177. /** Returns the thickness of the scrollbars. */
  178. int getScrollbarThickness() const noexcept { return scrollbarThickness; }
  179. //==============================================================================
  180. /** @internal */
  181. void resized();
  182. /** @internal */
  183. void paint (Graphics& g);
  184. /** @internal */
  185. bool keyPressed (const KeyPress& key);
  186. /** @internal */
  187. void mouseDown (const MouseEvent& e);
  188. /** @internal */
  189. void mouseDrag (const MouseEvent& e);
  190. /** @internal */
  191. void mouseUp (const MouseEvent& e);
  192. /** @internal */
  193. void mouseDoubleClick (const MouseEvent& e);
  194. /** @internal */
  195. void mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY);
  196. /** @internal */
  197. void focusGained (FocusChangeType cause);
  198. /** @internal */
  199. void focusLost (FocusChangeType cause);
  200. /** @internal */
  201. void timerCallback();
  202. /** @internal */
  203. void scrollBarMoved (ScrollBar* scrollBarThatHasMoved, double newRangeStart);
  204. /** @internal */
  205. void handleAsyncUpdate();
  206. /** @internal */
  207. void codeDocumentChanged (const CodeDocument::Position& affectedTextStart,
  208. const CodeDocument::Position& affectedTextEnd);
  209. /** @internal */
  210. bool isTextInputActive() const;
  211. /** @internal */
  212. void setTemporaryUnderlining (const Array <Range<int> >&);
  213. private:
  214. //==============================================================================
  215. CodeDocument& document;
  216. Font font;
  217. int firstLineOnScreen, gutter, spacesPerTab;
  218. float charWidth;
  219. int lineHeight, linesOnScreen, columnsOnScreen;
  220. int scrollbarThickness, columnToTryToMaintain;
  221. bool useSpacesForTabs;
  222. double xOffset;
  223. CodeDocument::Position caretPos;
  224. CodeDocument::Position selectionStart, selectionEnd;
  225. ScopedPointer<CaretComponent> caret;
  226. ScrollBar verticalScrollBar, horizontalScrollBar;
  227. enum DragType
  228. {
  229. notDragging,
  230. draggingSelectionStart,
  231. draggingSelectionEnd
  232. };
  233. DragType dragType;
  234. //==============================================================================
  235. CodeTokeniser* codeTokeniser;
  236. Array <Colour> coloursForTokenCategories;
  237. class CodeEditorLine;
  238. OwnedArray <CodeEditorLine> lines;
  239. void rebuildLineTokens();
  240. OwnedArray <CodeDocument::Iterator> cachedIterators;
  241. void clearCachedIterators (int firstLineToBeInvalid);
  242. void updateCachedIterators (int maxLineNum);
  243. void getIteratorForPosition (int position, CodeDocument::Iterator& result);
  244. void moveLineDelta (int delta, bool selecting);
  245. //==============================================================================
  246. void updateCaretPosition();
  247. void updateScrollBars();
  248. void scrollToLineInternal (int line);
  249. void scrollToColumnInternal (double column);
  250. void newTransaction();
  251. void cut();
  252. int indexToColumn (int line, int index) const noexcept;
  253. int columnToIndex (int line, int column) const noexcept;
  254. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CodeEditorComponent);
  255. };
  256. #endif // __JUCE_CODEEDITORCOMPONENT_JUCEHEADER__