From 29e5dd20e214c55b42fc33447bc4a51f655d7501 Mon Sep 17 00:00:00 2001 From: jules Date: Tue, 25 Sep 2012 22:23:14 +0100 Subject: [PATCH] Introjucer: editor updates --- .../Application/jucer_OpenDocumentManager.cpp | 16 +- .../Code Editor/jucer_SourceCodeEditor.cpp | 183 +++++++++--------- .../Code Editor/jucer_SourceCodeEditor.h | 25 ++- .../Source/Utility/jucer_FileHelpers.cpp | 50 +++++ .../Source/Utility/jucer_FileHelpers.h | 4 + .../code_editor/juce_CodeEditorComponent.cpp | 3 + 6 files changed, 176 insertions(+), 105 deletions(-) diff --git a/extras/Introjucer/Source/Application/jucer_OpenDocumentManager.cpp b/extras/Introjucer/Source/Application/jucer_OpenDocumentManager.cpp index 690680aeb5..05baf3951d 100644 --- a/extras/Introjucer/Source/Application/jucer_OpenDocumentManager.cpp +++ b/extras/Introjucer/Source/Application/jucer_OpenDocumentManager.cpp @@ -33,8 +33,8 @@ class UnknownDocument : public OpenDocumentManager::Document { public: - UnknownDocument (Project* project_, const File& file_) - : project (project_), file (file_) + UnknownDocument (Project* p, const File& f) + : project (p), file (f) { reloadFromFile(); } @@ -48,8 +48,8 @@ public: //============================================================================== bool loadedOk() const { return true; } - bool isForFile (const File& file_) const { return file == file_; } - bool isForNode (const ValueTree& node_) const { return false; } + bool isForFile (const File& f) const { return file == f; } + bool isForNode (const ValueTree&) const { return false; } bool refersToProject (Project& p) const { return project == &p; } Project* getProject() const { return project; } bool needsSaving() const { return false; } @@ -191,9 +191,7 @@ FileBasedDocument::SaveResult OpenDocumentManager::saveIfNeededAndUserAgrees (Op bool OpenDocumentManager::closeDocument (int index, bool saveIfNeeded) { - Document* doc = documents [index]; - - if (doc != nullptr) + if (Document* doc = documents [index]) { if (saveIfNeeded) { @@ -386,9 +384,7 @@ static void restoreDocList (Project& project, Array restoreState (e->getStringAttribute ("state")); diff --git a/extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.cpp b/extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.cpp index 6eafd57951..01cb0b8cb5 100644 --- a/extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.cpp +++ b/extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.cpp @@ -115,7 +115,7 @@ void SourceCodeEditor::createEditor (CodeDocument& codeDocument) if (document->getFile().hasFileExtension (sourceOrHeaderFileExtensions)) setEditor (new CppCodeEditorComponent (document->getFile(), codeDocument)); else - setEditor (new CodeEditorComponent (codeDocument, nullptr)); + setEditor (new GenericCodeEditorComponent (document->getFile(), codeDocument, nullptr)); } void SourceCodeEditor::setEditor (CodeEditorComponent* newEditor) @@ -169,82 +169,18 @@ void SourceCodeEditor::valueTreeRedirected (ValueTree&) //============================================================================== -static CPlusPlusCodeTokeniser cppTokeniser; - -CppCodeEditorComponent::CppCodeEditorComponent (const File& f, CodeDocument& codeDocument) - : CodeEditorComponent (codeDocument, &cppTokeniser), file (f) +GenericCodeEditorComponent::GenericCodeEditorComponent (const File& f, CodeDocument& codeDocument, + CodeTokeniser* tokeniser) + : CodeEditorComponent (codeDocument, tokeniser), file (f) { setCommandManager (commandManager); } -CppCodeEditorComponent::~CppCodeEditorComponent() -{ -} - -void CppCodeEditorComponent::handleReturnKey() -{ - CodeEditorComponent::handleReturnKey(); - - CodeDocument::Position pos (getCaretPos()); - - String blockIndent, lastLineIndent; - CodeHelpers::getIndentForCurrentBlock (pos, getTabString (getTabSize()), blockIndent, lastLineIndent); - - const String remainderOfBrokenLine (pos.getLineText()); - const int numLeadingWSChars = CodeHelpers::getLeadingWhitespace (remainderOfBrokenLine).length(); - - if (numLeadingWSChars > 0) - getDocument().deleteSection (pos, pos.movedBy (numLeadingWSChars)); - - if (remainderOfBrokenLine.trimStart().startsWithChar ('}')) - insertTextAtCaret (blockIndent); - else - insertTextAtCaret (lastLineIndent); - - const String previousLine (pos.movedByLines (-1).getLineText()); - const String trimmedPreviousLine (previousLine.trim()); - - if ((trimmedPreviousLine.startsWith ("if ") - || trimmedPreviousLine.startsWith ("if(") - || trimmedPreviousLine.startsWith ("for ") - || trimmedPreviousLine.startsWith ("for(") - || trimmedPreviousLine.startsWith ("while(") - || trimmedPreviousLine.startsWith ("while ")) - && trimmedPreviousLine.endsWithChar (')')) - { - insertTabAtCaret(); - } -} - -void CppCodeEditorComponent::insertTextAtCaret (const String& newText) -{ - if (getHighlightedRegion().isEmpty()) - { - const CodeDocument::Position pos (getCaretPos()); - - if ((newText == "{" || newText == "}") - && pos.getLineNumber() > 0 - && pos.getLineText().trim().isEmpty()) - { - moveCaretToStartOfLine (true); - - String blockIndent, lastLineIndent; - if (CodeHelpers::getIndentForCurrentBlock (pos, getTabString (getTabSize()), blockIndent, lastLineIndent)) - { - CodeEditorComponent::insertTextAtCaret (blockIndent); - - if (newText == "{") - insertTabAtCaret(); - } - } - } - - CodeEditorComponent::insertTextAtCaret (newText); -} +GenericCodeEditorComponent::~GenericCodeEditorComponent() {} enum { showInFinderID = 0x2fe821e3 }; -void CppCodeEditorComponent::addPopupMenuItems (PopupMenu& menu, const MouseEvent* e) +void GenericCodeEditorComponent::addPopupMenuItems (PopupMenu& menu, const MouseEvent* e) { menu.addItem (showInFinderID, #if JUCE_MAC @@ -257,7 +193,7 @@ void CppCodeEditorComponent::addPopupMenuItems (PopupMenu& menu, const MouseEven CodeEditorComponent::addPopupMenuItems (menu, e); } -void CppCodeEditorComponent::performPopupMenuAction (int menuItemID) +void GenericCodeEditorComponent::performPopupMenuAction (int menuItemID) { if (menuItemID == showInFinderID) file.revealToUser(); @@ -265,7 +201,7 @@ void CppCodeEditorComponent::performPopupMenuAction (int menuItemID) CodeEditorComponent::performPopupMenuAction (menuItemID); } -void CppCodeEditorComponent::getAllCommands (Array & commands) +void GenericCodeEditorComponent::getAllCommands (Array & commands) { CodeEditorComponent::getAllCommands (commands); @@ -277,7 +213,7 @@ void CppCodeEditorComponent::getAllCommands (Array & commands) commands.addArray (ids, numElementsInArray (ids)); } -void CppCodeEditorComponent::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result) +void GenericCodeEditorComponent::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result) { const bool anythingSelected = isHighlightActive(); @@ -311,7 +247,7 @@ void CppCodeEditorComponent::getCommandInfo (const CommandID commandID, Applicat } } -bool CppCodeEditorComponent::perform (const InvocationInfo& info) +bool GenericCodeEditorComponent::perform (const InvocationInfo& info) { switch (info.commandID) { @@ -326,9 +262,9 @@ bool CppCodeEditorComponent::perform (const InvocationInfo& info) } //============================================================================== -class CppCodeEditorComponent::FindPanel : public Component, - private TextEditor::Listener, - private Button::Listener +class GenericCodeEditorComponent::FindPanel : public Component, + private TextEditor::Listener, + private Button::Listener { public: FindPanel() @@ -426,7 +362,18 @@ public: TextButton findPrev, findNext; }; -void CppCodeEditorComponent::showFindPanel() +void GenericCodeEditorComponent::resized() +{ + CodeEditorComponent::resized(); + + if (findPanel != nullptr) + { + findPanel->setSize (jmin (260, getWidth() - 32), 100); + findPanel->setTopRightPosition (getWidth() - 16, 8); + } +} + +void GenericCodeEditorComponent::showFindPanel() { if (findPanel == nullptr) { @@ -441,12 +388,12 @@ void CppCodeEditorComponent::showFindPanel() findPanel->editor.selectAll(); } -void CppCodeEditorComponent::hideFindPanel() +void GenericCodeEditorComponent::hideFindPanel() { findPanel = nullptr; } -void CppCodeEditorComponent::findSelection() +void GenericCodeEditorComponent::findSelection() { const String selected (getTextInRange (getHighlightedRegion())); @@ -457,7 +404,7 @@ void CppCodeEditorComponent::findSelection() } } -void CppCodeEditorComponent::findNext (bool forwards, bool skipCurrentSelection) +void GenericCodeEditorComponent::findNext (bool forwards, bool skipCurrentSelection) { const Range highlight (getHighlightedRegion()); const CodeDocument::Position startPos (getDocument(), skipCurrentSelection ? highlight.getEnd() @@ -510,19 +457,79 @@ void CppCodeEditorComponent::findNext (bool forwards, bool skipCurrentSelection) } } -void CppCodeEditorComponent::handleEscapeKey() +void GenericCodeEditorComponent::handleEscapeKey() { CodeEditorComponent::handleEscapeKey(); hideFindPanel(); } -void CppCodeEditorComponent::resized() -{ - CodeEditorComponent::resized(); +//============================================================================== +static CPlusPlusCodeTokeniser cppTokeniser; - if (findPanel != nullptr) +CppCodeEditorComponent::CppCodeEditorComponent (const File& f, CodeDocument& doc) + : GenericCodeEditorComponent (f, doc, &cppTokeniser) +{ +} + +CppCodeEditorComponent::~CppCodeEditorComponent() {} + +void CppCodeEditorComponent::handleReturnKey() +{ + GenericCodeEditorComponent::handleReturnKey(); + + CodeDocument::Position pos (getCaretPos()); + + String blockIndent, lastLineIndent; + CodeHelpers::getIndentForCurrentBlock (pos, getTabString (getTabSize()), blockIndent, lastLineIndent); + + const String remainderOfBrokenLine (pos.getLineText()); + const int numLeadingWSChars = CodeHelpers::getLeadingWhitespace (remainderOfBrokenLine).length(); + + if (numLeadingWSChars > 0) + getDocument().deleteSection (pos, pos.movedBy (numLeadingWSChars)); + + if (remainderOfBrokenLine.trimStart().startsWithChar ('}')) + insertTextAtCaret (blockIndent); + else + insertTextAtCaret (lastLineIndent); + + const String previousLine (pos.movedByLines (-1).getLineText()); + const String trimmedPreviousLine (previousLine.trim()); + + if ((trimmedPreviousLine.startsWith ("if ") + || trimmedPreviousLine.startsWith ("if(") + || trimmedPreviousLine.startsWith ("for ") + || trimmedPreviousLine.startsWith ("for(") + || trimmedPreviousLine.startsWith ("while(") + || trimmedPreviousLine.startsWith ("while ")) + && trimmedPreviousLine.endsWithChar (')')) { - findPanel->setSize (jmin (260, getWidth() - 32), 100); - findPanel->setTopRightPosition (getWidth() - 16, 8); + insertTabAtCaret(); } } + +void CppCodeEditorComponent::insertTextAtCaret (const String& newText) +{ + if (getHighlightedRegion().isEmpty()) + { + const CodeDocument::Position pos (getCaretPos()); + + if ((newText == "{" || newText == "}") + && pos.getLineNumber() > 0 + && pos.getLineText().trim().isEmpty()) + { + moveCaretToStartOfLine (true); + + String blockIndent, lastLineIndent; + if (CodeHelpers::getIndentForCurrentBlock (pos, getTabString (getTabSize()), blockIndent, lastLineIndent)) + { + GenericCodeEditorComponent::insertTextAtCaret (blockIndent); + + if (newText == "{") + insertTabAtCaret(); + } + } + } + + GenericCodeEditorComponent::insertTextAtCaret (newText); +} diff --git a/extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.h b/extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.h index f07d266a8c..9cb0899502 100644 --- a/extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.h +++ b/extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.h @@ -165,15 +165,11 @@ private: //============================================================================== -class CppCodeEditorComponent : public CodeEditorComponent +class GenericCodeEditorComponent : public CodeEditorComponent { public: - CppCodeEditorComponent (const File& file, CodeDocument& codeDocument); - ~CppCodeEditorComponent(); - - void handleReturnKey(); - void handleEscapeKey(); - void insertTextAtCaret (const String& newText); + GenericCodeEditorComponent (const File&, CodeDocument&, CodeTokeniser*); + ~GenericCodeEditorComponent(); void addPopupMenuItems (PopupMenu&, const MouseEvent*); void performPopupMenuAction (int menuItemID); @@ -186,6 +182,7 @@ public: void hideFindPanel(); void findSelection(); void findNext (bool forwards, bool skipCurrentSelection); + void handleEscapeKey(); void resized(); @@ -199,6 +196,20 @@ private: class FindPanel; ScopedPointer findPanel; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GenericCodeEditorComponent); +}; + +//============================================================================== +class CppCodeEditorComponent : public GenericCodeEditorComponent +{ +public: + CppCodeEditorComponent (const File& file, CodeDocument& codeDocument); + ~CppCodeEditorComponent(); + + void handleReturnKey(); + void insertTextAtCaret (const String& newText); + +private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CppCodeEditorComponent); }; diff --git a/extras/Introjucer/Source/Utility/jucer_FileHelpers.cpp b/extras/Introjucer/Source/Utility/jucer_FileHelpers.cpp index f121643d1e..ff04e6b786 100644 --- a/extras/Introjucer/Source/Utility/jucer_FileHelpers.cpp +++ b/extras/Introjucer/Source/Utility/jucer_FileHelpers.cpp @@ -165,4 +165,54 @@ namespace FileHelpers return file.getRelativePathFrom (sourceFolder); } + + // removes "/../" bits from the middle of the path + String simplifyPath (String::CharPointerType p) + { + #if JUCE_WINDOWS + if (CharacterFunctions::indexOf (p, CharPointer_ASCII ("/../")) >= 0 + || CharacterFunctions::indexOf (p, CharPointer_ASCII ("\\..\\")) >= 0) + #else + if (CharacterFunctions::indexOf (p, CharPointer_ASCII ("/../")) >= 0) + #endif + { + StringArray toks; + + #if JUCE_WINDOWS + toks.addTokens (p, "\\/", String::empty); + #else + toks.addTokens (p, "/", String::empty); + #endif + + while (toks[0] == ".") + toks.remove (0); + + for (int i = 1; i < toks.size(); ++i) + { + if (toks[i] == ".." && toks [i - 1] != "..") + { + toks.removeRange (i - 1, 2); + i = jmax (0, i - 2); + } + } + + return toks.joinIntoString ("/"); + } + else + { + return p; + } + } + + String simplifyPath (const String& path) + { + #if JUCE_WINDOWS + if (path.contains ("\\..\\") || path.contains ("/../")) + #else + if (path.contains ("/../")) + #endif + return simplifyPath (path.getCharPointer()); + + return path; + } } diff --git a/extras/Introjucer/Source/Utility/jucer_FileHelpers.h b/extras/Introjucer/Source/Utility/jucer_FileHelpers.h index ac6c0c9e5b..2ec5537bda 100644 --- a/extras/Introjucer/Source/Utility/jucer_FileHelpers.h +++ b/extras/Introjucer/Source/Utility/jucer_FileHelpers.h @@ -48,6 +48,10 @@ namespace FileHelpers // A windows-aware version of File::getRelativePath() String getRelativePathFrom (const File& file, const File& sourceFolder); + + // removes "/../" bits from the middle of the path + String simplifyPath (String::CharPointerType path); + String simplifyPath (const String& path); } //============================================================================== diff --git a/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp b/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp index d34a82c5d0..930a85d096 100644 --- a/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp +++ b/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp @@ -1332,6 +1332,8 @@ void CodeEditorComponent::mouseDown (const MouseEvent& e) if (e.mods.isPopupMenu()) { + setMouseCursor (MouseCursor::NormalCursor); + if (getHighlightedRegion().isEmpty()) { CodeDocument::Position start, end; @@ -1366,6 +1368,7 @@ void CodeEditorComponent::mouseUp (const MouseEvent&) newTransaction(); beginDragAutoRepeat (0); dragType = notDragging; + setMouseCursor (MouseCursor::IBeamCursor); } void CodeEditorComponent::mouseDoubleClick (const MouseEvent& e)