From 78e28ccd83b9b7b99952a517287efba99f0e8395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Mon, 22 Jun 2020 02:29:05 -0300 Subject: [PATCH] UICodeEditor now acts as a client. A TextDocument can be consumed by any number of clients. This enables the possibility of editing the same file in several splits and tabs at the same time in the code editor. --- TODO.md | 2 - include/eepp/scene/event.hpp | 1 + include/eepp/ui/doc/textdocument.hpp | 5 + include/eepp/ui/uicodeeditor.hpp | 20 ++- include/eepp/ui/uitextedit.hpp | 2 + src/eepp/ui/doc/textdocument.cpp | 10 ++ src/eepp/ui/uicodeeditor.cpp | 231 +++++++++++++++------------ src/eepp/ui/uitabwidget.cpp | 1 + src/eepp/ui/uitextedit.cpp | 23 +-- src/tools/codeeditor/codeeditor.cpp | 164 ++++++++++++++----- src/tools/codeeditor/codeeditor.hpp | 2 + 11 files changed, 300 insertions(+), 161 deletions(-) diff --git a/TODO.md b/TODO.md index be1720470..ec8c03a76 100644 --- a/TODO.md +++ b/TODO.md @@ -23,8 +23,6 @@ Keep improving it: * Support single instance (when a new file is opened while a previous instance exists, open it in the first instance). -* Allow to open a document in any number of tabs. - ## UI Editor * Integrate the `UICodeEditor` into the editor in order to be able to edit the layouts and CSS in app. diff --git a/include/eepp/scene/event.hpp b/include/eepp/scene/event.hpp index cc9a30365..ddbc41fe4 100644 --- a/include/eepp/scene/event.hpp +++ b/include/eepp/scene/event.hpp @@ -31,6 +31,7 @@ class EE_API Event { OnAlphaChange, OnTextChanged, OnFontChanged, + OnDocumentChanged, OnFontStyleChanged, OnPressEnter, OnValueChange, diff --git a/include/eepp/ui/doc/textdocument.hpp b/include/eepp/ui/doc/textdocument.hpp index d49d5d33e..9fed2e61a 100644 --- a/include/eepp/ui/doc/textdocument.hpp +++ b/include/eepp/ui/doc/textdocument.hpp @@ -304,6 +304,10 @@ class EE_API TextDocument { void setTrimTrailingWhitespaces( bool trimTrailingWhitespaces ); + Client* getActiveClient() const; + + void setActiveClient( Client* activeClient ); + protected: friend class UndoStack; UndoStack mUndoStack; @@ -325,6 +329,7 @@ class EE_API TextDocument { Uint32 mPageSize{10}; std::map mCommands; String mNonWordChars; + Client* mActiveClient{nullptr}; void initializeCommands(); diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index 12fa38e7b..e132f4fde 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -135,10 +135,18 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void setColorScheme( const SyntaxColorScheme& colorScheme ); + /** If the document is managed by more than one client you need to NOT auto register base + * commands and implement your own logic for those commands, since are dependant of the client + * state. + * @see registerCommands */ + std::shared_ptr getDocumentRef() const; + const Doc::TextDocument& getDocument() const; Doc::TextDocument& getDocument(); + void setDocument( std::shared_ptr doc ); + bool isDirty() const; const bool& isLocked() const; @@ -265,16 +273,16 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { const bool& getShowWhitespaces() const; - void setShowWhitespaces(const bool& showWhitespaces); + void setShowWhitespaces( const bool& showWhitespaces ); - protected: + protected: struct LastXOffset { - TextPosition position; - Float offset; + TextPosition position; + Float offset; }; Font* mFont; UIFontStyleConfig mFontStyleConfig; - Doc::TextDocument mDoc; + std::shared_ptr mDoc; Vector2f mScrollPos; Clock mBlinkTimer; bool mDirtyEditor; @@ -432,6 +440,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { virtual void onFontChanged(); + virtual void onDocumentChanged(); + virtual Uint32 onMessage( const NodeMessage* msg ); void disableEditorFeatures(); diff --git a/include/eepp/ui/uitextedit.hpp b/include/eepp/ui/uitextedit.hpp index 366beb220..161b06afa 100644 --- a/include/eepp/ui/uitextedit.hpp +++ b/include/eepp/ui/uitextedit.hpp @@ -55,6 +55,8 @@ class EE_API UITextEdit : public UICodeEditor { virtual void drawCursor( const Vector2f& startScroll, const Float& lineHeight, const TextPosition& cursor ); + virtual void onDocumentChanged(); + void invalidateLinesCache(); void updateLineCache( const Int64& lineIndex ); diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index 6a9eb4e58..47fe5b4bc 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -219,6 +219,14 @@ void TextDocument::setTrimTrailingWhitespaces( bool trimTrailingWhitespaces ) { mTrimTrailingWhitespaces = trimTrailingWhitespaces; } +TextDocument::Client* TextDocument::getActiveClient() const { + return mActiveClient; +} + +void TextDocument::setActiveClient( Client* activeClient ) { + mActiveClient = activeClient; +} + bool TextDocument::loadFromFile( const std::string& path ) { if ( !FileSystem::fileExists( path ) && PackManager::instance()->isFallbackToPacksActive() ) { std::string pathFix( path ); @@ -713,6 +721,8 @@ void TextDocument::registerClient( Client* client ) { void TextDocument::unregisterClient( Client* client ) { mClients.erase( client ); + if ( mActiveClient == client ) + mActiveClient = nullptr; } void TextDocument::moveToPreviousChar() { diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index d040c91de..cc954cb85 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -32,6 +32,7 @@ UICodeEditor::UICodeEditor( const std::string& elementTag, const bool& autoRegis const bool& autoRegisterBaseKeybindings ) : UIWidget( elementTag ), mFont( FontManager::instance()->getByName( "monospace" ) ), + mDoc( std::make_shared() ), mDirtyEditor( false ), mCursorVisible( false ), mMouseDown( false ), @@ -49,7 +50,7 @@ UICodeEditor::UICodeEditor( const std::string& elementTag, const bool& autoRegis mFontSize( mFontStyleConfig.getFontCharacterSize() ), mLineNumberPaddingLeft( 8 ), mLineNumberPaddingRight( 8 ), - mHighlighter( &mDoc ), + mHighlighter( mDoc.get() ), mKeyBindings( getUISceneNode()->getWindow()->getInput() ), mFindLongestLineWidthUpdateFrequency( Seconds( 1 ) ) { mFlags |= UI_TAB_STOP; @@ -80,7 +81,7 @@ UICodeEditor::UICodeEditor( const std::string& elementTag, const bool& autoRegis setFontSize( getUISceneNode()->getUIThemeManager()->getDefaultFontSize() ); clipEnable(); - mDoc.registerClient( this ); + mDoc->registerClient( this ); subscribeScheduledUpdate(); if ( autoRegisterBaseCommands ) @@ -94,7 +95,7 @@ UICodeEditor::UICodeEditor( const bool& autoRegisterBaseCommands, UICodeEditor( "codeeditor", autoRegisterBaseCommands, autoRegisterBaseKeybindings ) {} UICodeEditor::~UICodeEditor() { - mDoc.unregisterClient( this ); + mDoc->unregisterClient( this ); } Uint32 UICodeEditor::getType() const { @@ -131,7 +132,7 @@ void UICodeEditor::draw() { Vector2f start( screenStart.x + lineNumberWidth, screenStart.y ); Vector2f startScroll( start - mScroll ); Primitives primitives; - TextPosition cursor( mDoc.getSelection().start() ); + TextPosition cursor( mDoc->getSelection().start() ); if ( !mLocked && mHighlightCurrentLine ) { primitives.setColor( Color( mCurrentLineBackgroundColor ).blendAlpha( mAlpha ) ); @@ -151,12 +152,12 @@ void UICodeEditor::draw() { drawMatchingBrackets( startScroll, lineHeight ); } - if ( mHighlightSelectionMatch && mDoc.hasSelection() && - mDoc.getSelection().start().line() == mDoc.getSelection().end().line() ) { + if ( mHighlightSelectionMatch && mDoc->hasSelection() && + mDoc->getSelection().start().line() == mDoc->getSelection().end().line() ) { drawSelectionMatch( lineRange, startScroll, lineHeight ); } - if ( mDoc.hasSelection() ) { + if ( mDoc->hasSelection() ) { drawSelection( lineRange, startScroll, lineHeight ); } @@ -218,27 +219,27 @@ void UICodeEditor::updateLongestLineWidth() { } void UICodeEditor::reset() { - mDoc.reset(); + mDoc->reset(); invalidateDraw(); } bool UICodeEditor::loadFromFile( const std::string& path ) { - bool ret = mDoc.loadFromFile( path ); + bool ret = mDoc->loadFromFile( path ); invalidateEditor(); updateLongestLineWidth(); return ret; } bool UICodeEditor::save() { - return mDoc.save(); + return mDoc->save(); } bool UICodeEditor::save( const std::string& path, const bool& utf8bom ) { - return mDoc.save( path, utf8bom ); + return mDoc->save( path, utf8bom ); } bool UICodeEditor::save( IOStreamFile& stream, const bool& utf8bom ) { - return mDoc.save( stream, utf8bom ); + return mDoc->save( stream, utf8bom ); } Font* UICodeEditor::getFont() const { @@ -262,6 +263,10 @@ UICodeEditor* UICodeEditor::setFont( Font* font ) { void UICodeEditor::onFontChanged() {} +void UICodeEditor::onDocumentChanged() { + sendCommonEvent( Event::OnDocumentChanged ); +} + Uint32 UICodeEditor::onMessage( const NodeMessage* msg ) { if ( msg->getMsg() == NodeMessage::MouseDown ) return 1; @@ -383,7 +388,7 @@ const Float& UICodeEditor::getLineNumberPaddingRight() const { } size_t UICodeEditor::getLineNumberDigits() const { - return eemax( 2UL, Math::countDigits( mDoc.linesCount() ) ); + return eemax( 2UL, Math::countDigits( mDoc->linesCount() ) ); } Float UICodeEditor::getLineNumberWidth() const { @@ -469,16 +474,32 @@ void UICodeEditor::setColorScheme( const SyntaxColorScheme& colorScheme ) { invalidateDraw(); } -const TextDocument& UICodeEditor::getDocument() const { +std::shared_ptr UICodeEditor::getDocumentRef() const { return mDoc; } +const TextDocument& UICodeEditor::getDocument() const { + return *mDoc.get(); +} + TextDocument& UICodeEditor::getDocument() { - return mDoc; + return *mDoc.get(); +} + +void UICodeEditor::setDocument( std::shared_ptr doc ) { + if ( mDoc.get() != doc.get() ) { + mDoc->unregisterClient( this ); + mDoc = doc; + mDoc->registerClient( this ); + mHighlighter.changeDoc( mDoc.get() ); + invalidateEditor(); + invalidateDraw(); + onDocumentChanged(); + } } bool UICodeEditor::isDirty() const { - return mDoc.isDirty(); + return mDoc->isDirty(); } void UICodeEditor::invalidateEditor() { @@ -494,6 +515,7 @@ Uint32 UICodeEditor::onFocus() { if ( !mLocked ) { getUISceneNode()->getWindow()->startTextInput(); resetCursor(); + mDoc->setActiveClient( this ); } return UIWidget::onFocus(); } @@ -502,6 +524,8 @@ Uint32 UICodeEditor::onFocusLoss() { mMouseDown = false; mCursorVisible = false; getSceneNode()->getWindow()->stopTextInput(); + if ( mDoc->getActiveClient() == this ) + mDoc->setActiveClient( nullptr ); return UIWidget::onFocusLoss(); } @@ -514,7 +538,7 @@ Uint32 UICodeEditor::onTextInput( const TextInputEvent& event ) { if ( input->isAltPressed() && !event.getText().empty() && event.getText()[0] == '\t' ) return 1; - mDoc.textInput( event.getText() ); + mDoc->textInput( event.getText() ); } return 1; } @@ -526,7 +550,7 @@ Uint32 UICodeEditor::onKeyDown( const KeyEvent& event ) { if ( !cmd.empty() ) { // Allow copy selection on locked mode if ( !mLocked || mUnlockedCmd.find( cmd ) != mUnlockedCmd.end() ) { - mDoc.execute( cmd ); + mDoc->execute( cmd ); return 0; } } @@ -541,7 +565,7 @@ TextPosition UICodeEditor::resolveScreenPosition( const Vector2f& position ) con localPos.x -= mRealPadding.Left + ( mShowLineNumber ? getLineNumberWidth() : 0.f ); localPos.y -= mRealPadding.Top; Int64 line = eeclamp( (Int64)eefloor( localPos.y / getLineHeight() ), 0, - ( Int64 )( mDoc.linesCount() - 1 ) ); + ( Int64 )( mDoc->linesCount() - 1 ) ); return TextPosition( line, getColFromXOffset( line, localPos.x ) ); } @@ -556,9 +580,10 @@ Vector2f UICodeEditor::getViewPortLineCount() const { Sizef UICodeEditor::getMaxScroll() const { Vector2f vplc( getViewPortLineCount() ); return Sizef( eemax( 0.f, mLongestLineWidth - getViewportWidth() ), - vplc.y > mDoc.linesCount() - 1 + vplc.y > mDoc->linesCount() - 1 ? 0.f - : eefloor( mDoc.linesCount() - getViewPortLineCount().y ) * getLineHeight() ); + : eefloor( mDoc->linesCount() - getViewPortLineCount().y ) * + getLineHeight() ); } Uint32 UICodeEditor::onMouseDown( const Vector2i& position, const Uint32& flags ) { @@ -568,9 +593,9 @@ Uint32 UICodeEditor::onMouseDown( const Vector2i& position, const Uint32& flags Input* input = getUISceneNode()->getWindow()->getInput(); input->captureMouse( true ); if ( input->isShiftPressed() ) { - mDoc.selectTo( resolveScreenPosition( position.asFloat() ) ); + mDoc->selectTo( resolveScreenPosition( position.asFloat() ) ); } else { - mDoc.setSelection( resolveScreenPosition( position.asFloat() ) ); + mDoc->setSelection( resolveScreenPosition( position.asFloat() ) ); } } return UIWidget::onMouseDown( position, flags ); @@ -579,9 +604,9 @@ Uint32 UICodeEditor::onMouseDown( const Vector2i& position, const Uint32& flags Uint32 UICodeEditor::onMouseMove( const Vector2i& position, const Uint32& flags ) { if ( isTextSelectionEnabled() && !getUISceneNode()->getEventDispatcher()->isNodeDragging() && NULL != mFont && mMouseDown && ( flags & EE_BUTTON_LMASK ) ) { - TextRange selection = mDoc.getSelection(); + TextRange selection = mDoc->getSelection(); selection.setStart( resolveScreenPosition( position.asFloat() ) ); - mDoc.setSelection( selection ); + mDoc->setSelection( selection ); } return UIWidget::onMouseMove( position, flags ); } @@ -616,7 +641,7 @@ Uint32 UICodeEditor::onMouseUp( const Vector2i& position, const Uint32& flags ) Uint32 UICodeEditor::onMouseClick( const Vector2i&, const Uint32& flags ) { if ( ( flags & EE_BUTTON_LMASK ) && mLastDoubleClick.getElapsedTime() < Milliseconds( 300.f ) ) { - mDoc.selectLine(); + mDoc->selectLine(); } return 1; } @@ -626,7 +651,7 @@ Uint32 UICodeEditor::onMouseDoubleClick( const Vector2i&, const Uint32& flags ) return 1; if ( flags & EE_BUTTON_LMASK ) { - mDoc.selectWord(); + mDoc->selectWord(); mLastDoubleClick.restart(); checkColorPickerAction(); } @@ -646,13 +671,13 @@ Uint32 UICodeEditor::onMouseLeave( const Vector2i& position, const Uint32& flags void UICodeEditor::checkColorPickerAction() { if ( !mEnableColorPickerOnSelection ) return; - String text( mDoc.getSelectedText() ); - TextRange range( mDoc.getSelection( true ) ); + String text( mDoc->getSelectedText() ); + TextRange range( mDoc->getSelection( true ) ); if ( range.start().line() != range.end().line() ) return; - const String& line = mDoc.line( range.end().line() ).getText(); + const String& line = mDoc->line( range.end().line() ).getText(); bool isHash = range.start().column() > 0 && - mDoc.line( range.start().line() ).getText()[range.start().column() - 1] == '#' && + mDoc->line( range.start().line() ).getText()[range.start().column() - 1] == '#' && ( text.size() == 6 || text.size() == 8 ) && String::isHexNotation( text ); bool isRgba = !isHash && text == "rgba" && range.end().column() < (Int64)line.size() - 1 && line[range.end().column()] == '('; @@ -661,19 +686,20 @@ void UICodeEditor::checkColorPickerAction() { if ( isHash || isRgb || isRgba ) { UIColorPicker* colorPicker = NULL; if ( isHash ) { - colorPicker = UIColorPicker::NewModal( - this, [&]( Color color ) { mDoc.replaceSelection( color.toHexString( false ) ); } ); + colorPicker = UIColorPicker::NewModal( this, [&]( Color color ) { + mDoc->replaceSelection( color.toHexString( false ) ); + } ); colorPicker->setColor( Color( '#' + text ) ); } else if ( isRgba || isRgb ) { - TextPosition position = mDoc.findCloseBracket( + TextPosition position = mDoc->findCloseBracket( {range.start().line(), static_cast( range.end().column() )}, '(', ')' ); if ( position.isValid() ) { - mDoc.setSelection( {position.line(), position.column() + 1}, range.start() ); + mDoc->setSelection( {position.line(), position.column() + 1}, range.start() ); colorPicker = UIColorPicker::NewModal( this, [&, isRgba]( Color color ) { - mDoc.replaceSelection( isRgba || color.a != 255 ? color.toRgbaString() - : color.toRgbString() ); + mDoc->replaceSelection( isRgba || color.a != 255 ? color.toRgbaString() + : color.toRgbString() ); } ); - colorPicker->setColor( Color::fromString( mDoc.getSelectedText() ) ); + colorPicker->setColor( Color::fromString( mDoc->getSelectedText() ) ); } } if ( colorPicker ) @@ -710,18 +736,18 @@ void UICodeEditor::onPaddingChange() { void UICodeEditor::findLongestLine() { if ( mHorizontalScrollBarEnabled ) { mLongestLineWidth = 0; - for ( size_t lineIndex = 0; lineIndex < mDoc.linesCount(); lineIndex++ ) { + for ( size_t lineIndex = 0; lineIndex < mDoc->linesCount(); lineIndex++ ) { mLongestLineWidth = eemax( mLongestLineWidth, getLineWidth( lineIndex ) ); } } } Float UICodeEditor::getLineWidth( const Int64& lineIndex ) { - return getTextWidth( mDoc.line( lineIndex ).getText() ); + return getTextWidth( mDoc->line( lineIndex ).getText() ); } void UICodeEditor::updateScrollBar() { - int notVisibleLineCount = (int)mDoc.linesCount() - (int)getViewPortLineCount().y; + int notVisibleLineCount = (int)mDoc->linesCount() - (int)getViewPortLineCount().y; if ( mLongestLineWidthDirty ) { updateLongestLineWidth(); @@ -747,7 +773,7 @@ void UICodeEditor::updateScrollBar() { } mVScrollBar->setPixelsPosition( mSize.getWidth() - mVScrollBar->getPixelsSize().getWidth(), 0 ); - mVScrollBar->setPageStep( getViewPortLineCount().y / (float)mDoc.linesCount() ); + mVScrollBar->setPageStep( getViewPortLineCount().y / (float)mDoc->linesCount() ); mVScrollBar->setClickStep( 0.2f ); mVScrollBar->setEnabled( notVisibleLineCount > 0 ); mVScrollBar->setVisible( notVisibleLineCount > 0 ); @@ -755,8 +781,9 @@ void UICodeEditor::updateScrollBar() { } void UICodeEditor::updateEditor() { - mDoc.setPageSize( getVisibleLinesCount() ); - scrollToMakeVisible( mDoc.getSelection().start() ); + mDoc->setPageSize( getVisibleLinesCount() ); + if ( mDoc->getActiveClient() == this ) + scrollToMakeVisible( mDoc->getSelection().start() ); updateScrollBar(); mDirtyEditor = false; } @@ -791,7 +818,7 @@ void UICodeEditor::onDocumentLineChanged( const Int64& lineIndex ) { std::pair UICodeEditor::getVisibleLineRange() { Float lineHeight = getLineHeight(); Float minLine = eemax( 0.f, eefloor( mScroll.y / lineHeight ) ); - Float maxLine = eemin( mDoc.linesCount() - 1.f, + Float maxLine = eemin( mDoc->linesCount() - 1.f, eefloor( ( mSize.getHeight() + mScroll.y ) / lineHeight ) + 1 ); return std::make_pair( (int)minLine, (int)maxLine ); } @@ -850,7 +877,7 @@ void UICodeEditor::setScrollY( const Float& val, bool emmitEvent ) { } Float UICodeEditor::getXOffsetCol( const TextPosition& position ) { - const String& line = mDoc.line( position.line() ).getText(); + const String& line = mDoc->line( position.line() ).getText(); Float glyphWidth = getGlyphWidth(); Float x = 0; for ( auto i = 0; i < position.column(); i++ ) { @@ -873,11 +900,11 @@ Float UICodeEditor::getTextWidth( const String& line ) const { } Float UICodeEditor::getColXOffset( TextPosition position ) { - position.setLine( eeclamp( position.line(), 0L, mDoc.linesCount() - 1 ) ); + position.setLine( eeclamp( position.line(), 0L, mDoc->linesCount() - 1 ) ); // This is different from sanitizePosition, sinze allows the last character. position.setColumn( eeclamp( position.column(), 0L, - eemax( 0, mDoc.line( position.line() ).size() ) ) ); - return getTextWidth( mDoc.line( position.line() ).substr( 0, position.column() ) ); + eemax( 0, mDoc->line( position.line() ).size() ) ) ); + return getTextWidth( mDoc->line( position.line() ).substr( 0, position.column() ) ); } const bool& UICodeEditor::isLocked() const { @@ -1196,13 +1223,13 @@ void UICodeEditor::setEnableColorPickerOnSelection( const bool& enableColorPicke } void UICodeEditor::setSyntaxDefinition( const SyntaxDefinition& definition ) { - mDoc.setSyntaxDefinition( definition ); + mDoc->setSyntaxDefinition( definition ); mHighlighter.reset(); invalidateDraw(); } const SyntaxDefinition& UICodeEditor::getSyntaxDefinition() const { - return mDoc.getSyntaxDefinition(); + return mDoc->getSyntaxDefinition(); } void UICodeEditor::checkMatchingBrackets() { @@ -1210,8 +1237,8 @@ void UICodeEditor::checkMatchingBrackets() { mMatchingBrackets = TextRange(); std::vector open{'{', '(', '['}; std::vector close{'}', ')', ']'}; - TextPosition pos = mDoc.getSelection().start(); - TextDocumentLine& line = mDoc.line( pos.line() ); + TextPosition pos = mDoc->getSelection().start(); + TextDocumentLine& line = mDoc->line( pos.line() ); auto isOpenIt = std::find( open.begin(), open.end(), line[pos.column()] ); auto isCloseIt = std::find( close.begin(), close.end(), line[pos.column()] ); if ( ( isOpenIt == open.end() && isCloseIt == close.end() ) && pos.column() > 0 ) { @@ -1227,13 +1254,13 @@ void UICodeEditor::checkMatchingBrackets() { size_t index = std::distance( open.begin(), isOpenIt ); String::StringBaseType openBracket = open[index]; String::StringBaseType closeBracket = close[index]; - TextPosition closePosition = mDoc.findCloseBracket( pos, openBracket, closeBracket ); + TextPosition closePosition = mDoc->findCloseBracket( pos, openBracket, closeBracket ); mMatchingBrackets = {pos, closePosition}; } else if ( isCloseIt != close.end() ) { size_t index = std::distance( close.begin(), isCloseIt ); String::StringBaseType openBracket = open[index]; String::StringBaseType closeBracket = close[index]; - TextPosition closePosition = mDoc.findOpenBracket( pos, openBracket, closeBracket ); + TextPosition closePosition = mDoc->findOpenBracket( pos, openBracket, closeBracket ); mMatchingBrackets = {pos, closePosition}; } } @@ -1242,8 +1269,8 @@ void UICodeEditor::checkMatchingBrackets() { Int64 UICodeEditor::getColFromXOffset( Int64 lineNumber, const Float& x ) const { if ( x <= 0 ) return 0; - TextPosition pos = mDoc.sanitizePosition( TextPosition( lineNumber, 0 ) ); - const String& line = mDoc.line( pos.line() ).getText(); + TextPosition pos = mDoc->sanitizePosition( TextPosition( lineNumber, 0 ) ); + const String& line = mDoc->line( pos.line() ).getText(); Int64 len = line.length(); Float glyphWidth = getGlyphWidth(); Float xOffset = 0; @@ -1291,31 +1318,31 @@ TextPosition UICodeEditor::moveToLineOffset( const TextPosition& position, int o } void UICodeEditor::moveToPreviousLine() { - TextPosition position = mDoc.getSelection().start(); + TextPosition position = mDoc->getSelection().start(); if ( position.line() == 0 ) - return mDoc.moveToStartOfDoc(); - mDoc.moveTo( moveToLineOffset( position, -1 ) ); + return mDoc->moveToStartOfDoc(); + mDoc->moveTo( moveToLineOffset( position, -1 ) ); } void UICodeEditor::moveToNextLine() { - TextPosition position = mDoc.getSelection().start(); - if ( position.line() == (Int64)mDoc.linesCount() - 1 ) - return mDoc.moveToEndOfDoc(); - mDoc.moveTo( moveToLineOffset( position, 1 ) ); + TextPosition position = mDoc->getSelection().start(); + if ( position.line() == (Int64)mDoc->linesCount() - 1 ) + return mDoc->moveToEndOfDoc(); + mDoc->moveTo( moveToLineOffset( position, 1 ) ); } void UICodeEditor::selectToPreviousLine() { - TextPosition position = mDoc.getSelection().start(); + TextPosition position = mDoc->getSelection().start(); if ( position.line() == 0 ) - return mDoc.moveToStartOfDoc(); - mDoc.selectTo( moveToLineOffset( position, -1 ) ); + return mDoc->moveToStartOfDoc(); + mDoc->selectTo( moveToLineOffset( position, -1 ) ); } void UICodeEditor::selectToNextLine() { - TextPosition position = mDoc.getSelection().start(); - if ( position.line() == (Int64)mDoc.linesCount() - 1 ) - return mDoc.moveToEndOfDoc(); - mDoc.selectTo( moveToLineOffset( position, 1 ) ); + TextPosition position = mDoc->getSelection().start(); + if ( position.line() == (Int64)mDoc->linesCount() - 1 ) + return mDoc->moveToEndOfDoc(); + mDoc->selectTo( moveToLineOffset( position, 1 ) ); } void UICodeEditor::moveScrollUp() { @@ -1330,7 +1357,7 @@ void UICodeEditor::indent() { UIEventDispatcher* eventDispatcher = static_cast( getUISceneNode()->getEventDispatcher() ); if ( !eventDispatcher->justGainedFocus() ) { - mDoc.indent(); + mDoc->indent(); } } @@ -1338,21 +1365,21 @@ void UICodeEditor::unindent() { UIEventDispatcher* eventDispatcher = static_cast( getUISceneNode()->getEventDispatcher() ); if ( !eventDispatcher->justGainedFocus() ) { - mDoc.unindent(); + mDoc->unindent(); } } void UICodeEditor::copy() { - getUISceneNode()->getWindow()->getClipboard()->setText( mDoc.getSelectedText() ); + getUISceneNode()->getWindow()->getClipboard()->setText( mDoc->getSelectedText() ); } void UICodeEditor::cut() { - getUISceneNode()->getWindow()->getClipboard()->setText( mDoc.getSelectedText() ); - mDoc.deleteSelection(); + getUISceneNode()->getWindow()->getClipboard()->setText( mDoc->getSelectedText() ); + mDoc->deleteSelection(); } void UICodeEditor::paste() { - mDoc.textInput( getUISceneNode()->getWindow()->getClipboard()->getText() ); + mDoc->textInput( getUISceneNode()->getWindow()->getClipboard()->getText() ); } void UICodeEditor::fontSizeGrow() { @@ -1417,20 +1444,20 @@ void UICodeEditor::drawMatchingBrackets( const Vector2f& startScroll, const Floa void UICodeEditor::drawSelectionMatch( const std::pair& lineRange, const Vector2f& startScroll, const Float& lineHeight ) { - if ( !mDoc.hasSelection() ) + if ( !mDoc->hasSelection() ) return; Primitives primitives; primitives.setForceDraw( false ); primitives.setColor( Color( mSelectionMatchColor ).blendAlpha( mAlpha ) ); - TextRange selection = mDoc.getSelection( true ); - const String& selectionLine = mDoc.line( selection.start().line() ).getText(); + TextRange selection = mDoc->getSelection( true ); + const String& selectionLine = mDoc->line( selection.start().line() ).getText(); String text( selectionLine.substr( selection.start().column(), selection.end().column() - selection.start().column() ) ); for ( auto ln = lineRange.first; ln <= lineRange.second; ln++ ) { - const String& line = mDoc.line( ln ).getText(); + const String& line = mDoc->line( ln ).getText(); size_t pos = 0; // Skip ridiculously long lines. if ( line.size() > 300 ) @@ -1484,13 +1511,13 @@ void UICodeEditor::drawSelection( const std::pair& lineRange, const Ve primitives.setColor( Color( mFontStyleConfig.getFontSelectionBackColor() ).blendAlpha( mAlpha ) ); - TextRange selection = mDoc.getSelection( true ); + TextRange selection = mDoc->getSelection( true ); int startLine = eemax( lineRange.first, selection.start().line() ); int endLine = eemin( lineRange.second, selection.end().line() ); for ( auto ln = startLine; ln <= endLine; ln++ ) { - const String& line = mDoc.line( ln ).getText(); + const String& line = mDoc->line( ln ).getText(); Rectf selRect; selRect.Top = startScroll.y + ln * lineHeight; selRect.Bottom = selRect.Top + lineHeight; @@ -1523,7 +1550,7 @@ void UICodeEditor::drawLineNumbers( const std::pair& lineRange, Primitives primitives; primitives.setColor( Color( mLineNumberBackgroundColor ).blendAlpha( mAlpha ) ); primitives.drawRectangle( Rectf( screenStart, Sizef( lineNumberWidth, mSize.getHeight() ) ) ); - TextRange selection = mDoc.getSelection( true ); + TextRange selection = mDoc->getSelection( true ); for ( int i = lineRange.first; i <= lineRange.second; i++ ) { Text line( String( String::toString( i + 1 ) ).padLeft( lineNumberDigits, ' ' ), mFont, fontSize ); @@ -1577,23 +1604,23 @@ void UICodeEditor::drawWhitespaces( const std::pair& lineRange, } void UICodeEditor::registerCommands() { - mDoc.setCommand( "move-to-previous-line", [&] { moveToPreviousLine(); } ); - mDoc.setCommand( "move-to-next-line", [&] { moveToNextLine(); } ); - mDoc.setCommand( "select-to-previous-line", [&] { selectToPreviousLine(); } ); - mDoc.setCommand( "select-to-next-line", [&] { selectToNextLine(); } ); - mDoc.setCommand( "move-scroll-up", [&] { moveScrollUp(); } ); - mDoc.setCommand( "move-scroll-down", [&] { moveScrollDown(); } ); - mDoc.setCommand( "indent", [&] { indent(); } ); - mDoc.setCommand( "unindent", [&] { unindent(); } ); - mDoc.setCommand( "copy", [&] { copy(); } ); - mDoc.setCommand( "cut", [&] { cut(); } ); - mDoc.setCommand( "paste", [&] { paste(); } ); - mDoc.setCommand( "font-size-grow", [&] { fontSizeGrow(); } ); - mDoc.setCommand( "font-size-shrink", [&] { fontSizeShrink(); } ); - mDoc.setCommand( "font-size-reset", [&] { fontSizeReset(); } ); - mDoc.setCommand( "lock", [&] { setLocked( true ); } ); - mDoc.setCommand( "unlock", [&] { setLocked( false ); } ); - mDoc.setCommand( "lock-toggle", [&] { setLocked( !isLocked() ); } ); + mDoc->setCommand( "move-to-previous-line", [&] { moveToPreviousLine(); } ); + mDoc->setCommand( "move-to-next-line", [&] { moveToNextLine(); } ); + mDoc->setCommand( "select-to-previous-line", [&] { selectToPreviousLine(); } ); + mDoc->setCommand( "select-to-next-line", [&] { selectToNextLine(); } ); + mDoc->setCommand( "move-scroll-up", [&] { moveScrollUp(); } ); + mDoc->setCommand( "move-scroll-down", [&] { moveScrollDown(); } ); + mDoc->setCommand( "indent", [&] { indent(); } ); + mDoc->setCommand( "unindent", [&] { unindent(); } ); + mDoc->setCommand( "copy", [&] { copy(); } ); + mDoc->setCommand( "cut", [&] { cut(); } ); + mDoc->setCommand( "paste", [&] { paste(); } ); + mDoc->setCommand( "font-size-grow", [&] { fontSizeGrow(); } ); + mDoc->setCommand( "font-size-shrink", [&] { fontSizeShrink(); } ); + mDoc->setCommand( "font-size-reset", [&] { fontSizeReset(); } ); + mDoc->setCommand( "lock", [&] { setLocked( true ); } ); + mDoc->setCommand( "unlock", [&] { setLocked( false ); } ); + mDoc->setCommand( "lock-toggle", [&] { setLocked( !isLocked() ); } ); mUnlockedCmd.insert( {"copy", "select-all"} ); } @@ -1656,7 +1683,7 @@ void UICodeEditor::registerKeybindings() { {{KEY_MINUS, KEYMOD_CTRL}, "font-size-shrink"}, {{KEY_KP_MINUS, KEYMOD_CTRL}, "font-size-shrink"}, {{KEY_0, KEYMOD_CTRL}, "font-size-reset"}, - {{KEY_KP_DIVIDE, KEYMOD_CTRL}, "toggle-line-comments" }, + {{KEY_KP_DIVIDE, KEYMOD_CTRL}, "toggle-line-comments"}, } ); } diff --git a/src/eepp/ui/uitabwidget.cpp b/src/eepp/ui/uitabwidget.cpp index fcc2166a4..50ef98af4 100644 --- a/src/eepp/ui/uitabwidget.cpp +++ b/src/eepp/ui/uitabwidget.cpp @@ -771,6 +771,7 @@ Uint32 UITabWidget::onMessage( const NodeMessage* msg ) { if ( tab->getTabWidget() != this ) { tab->getTabWidget()->removeTab( tab, false, false ); add( tab ); + setTabSelected( tab ); return 1; } } diff --git a/src/eepp/ui/uitextedit.cpp b/src/eepp/ui/uitextedit.cpp index 8024f6f49..ac8c6cd0e 100644 --- a/src/eepp/ui/uitextedit.cpp +++ b/src/eepp/ui/uitextedit.cpp @@ -66,17 +66,17 @@ void UITextEdit::shrinkText( const Float& maxWidth ) { text.setStyleConfig( mFontStyleConfig ); text.setString( getText() ); text.shrinkText( maxWidth ); - mDoc.reset(); - mDoc.textInput( text.getString() ); + mDoc->reset(); + mDoc->textInput( text.getString() ); } String UITextEdit::getText() const { - return mDoc.getText( {mDoc.startOfDoc(), mDoc.endOfDoc()} ); + return mDoc->getText( {mDoc->startOfDoc(), mDoc->endOfDoc()} ); } void UITextEdit::setText( const String& text ) { - mDoc.reset(); - mDoc.textInput( text ); + mDoc->reset(); + mDoc->textInput( text ); if ( mFlags & UI_WORD_WRAP ) { shrinkText( getViewportWidth( true ) ); } @@ -126,7 +126,7 @@ Float UITextEdit::getXOffsetCol( const TextPosition& position ) { return mLines[position.line()] .text .findCharacterPos( - ( position.column() == (Int64)mDoc.line( position.line() ).getText().size() ) + ( position.column() == (Int64)mDoc->line( position.line() ).getText().size() ) ? position.column() - 1 : position.column() ) .x; @@ -141,7 +141,7 @@ Float UITextEdit::getLineWidth( const Int64& lineIndex ) { void UITextEdit::ensureLineUpdated( const Int64& lineIndex ) { if ( mLines.find( lineIndex ) == mLines.end() || - mDoc.line( lineIndex ).getHash() != mLines[lineIndex].hash ) { + mDoc->line( lineIndex ).getHash() != mLines[lineIndex].hash ) { updateLineCache( lineIndex ); } } @@ -167,8 +167,8 @@ void UITextEdit::invalidateLinesCache() { } void UITextEdit::updateLineCache( const Int64& lineIndex ) { - if ( lineIndex >= 0 && lineIndex < (Int64)mDoc.linesCount() ) { - TextDocumentLine& line = mDoc.line( lineIndex ); + if ( lineIndex >= 0 && lineIndex < (Int64)mDoc->linesCount() ) { + TextDocumentLine& line = mDoc->line( lineIndex ); auto& cacheLine = mLines[lineIndex]; cacheLine.text.setStyleConfig( mFontStyleConfig ); cacheLine.text.setString( line.getText() ); @@ -188,4 +188,9 @@ void UITextEdit::drawCursor( const Vector2f& startScroll, const Float& lineHeigh } } +void UITextEdit::onDocumentChanged() { + UICodeEditor::onDocumentChanged(); + invalidateLinesCache(); +} + }} // namespace EE::UI diff --git a/src/tools/codeeditor/codeeditor.cpp b/src/tools/codeeditor/codeeditor.cpp index 92ad1686b..8855ddba3 100644 --- a/src/tools/codeeditor/codeeditor.cpp +++ b/src/tools/codeeditor/codeeditor.cpp @@ -191,11 +191,86 @@ void App::saveDoc() { } UICodeEditor* App::createCodeEditor() { - UICodeEditor* codeEditor = UICodeEditor::New(); + UICodeEditor* codeEditor = UICodeEditor::NewOpt( false, true ); codeEditor->setFontSize( 11 ); codeEditor->setEnableColorPickerOnSelection( true ); codeEditor->setColorScheme( mColorSchemes[mCurrentColorScheme] ); - codeEditor->getDocument().setCommand( "switch-to-previous-colorscheme", [&] { + TextDocument& doc = codeEditor->getDocument(); + + /* global commands */ + doc.setCommand( "move-to-previous-line", [&] { + if ( mCurEditor ) + mCurEditor->moveToPreviousLine(); + } ); + doc.setCommand( "move-to-next-line", [&] { + if ( mCurEditor ) + mCurEditor->moveToNextLine(); + } ); + doc.setCommand( "select-to-previous-line", [&] { + if ( mCurEditor ) + mCurEditor->selectToPreviousLine(); + } ); + doc.setCommand( "select-to-next-line", [&] { + if ( mCurEditor ) + mCurEditor->selectToNextLine(); + } ); + doc.setCommand( "move-scroll-up", [&] { + if ( mCurEditor ) + mCurEditor->moveScrollUp(); + } ); + doc.setCommand( "move-scroll-down", [&] { + if ( mCurEditor ) + mCurEditor->moveScrollDown(); + } ); + doc.setCommand( "indent", [&] { + if ( mCurEditor ) + mCurEditor->indent(); + } ); + doc.setCommand( "unindent", [&] { + if ( mCurEditor ) + mCurEditor->unindent(); + } ); + doc.setCommand( "copy", [&] { + if ( mCurEditor ) + mCurEditor->copy(); + } ); + doc.setCommand( "cut", [&] { + if ( mCurEditor ) + mCurEditor->cut(); + } ); + doc.setCommand( "paste", [&] { + if ( mCurEditor ) + mCurEditor->paste(); + } ); + doc.setCommand( "font-size-grow", [&] { + if ( mCurEditor ) + mCurEditor->fontSizeGrow(); + } ); + doc.setCommand( "font-size-shrink", [&] { + if ( mCurEditor ) + mCurEditor->fontSizeShrink(); + } ); + doc.setCommand( "font-size-reset", [&] { + if ( mCurEditor ) + mCurEditor->fontSizeReset(); + } ); + doc.setCommand( "lock", [&] { + if ( mCurEditor ) + mCurEditor->setLocked( true ); + } ); + doc.setCommand( "unlock", [&] { + if ( mCurEditor ) + mCurEditor->setLocked( false ); + } ); + doc.setCommand( "lock-toggle", [&] { + if ( mCurEditor ) + mCurEditor->setLocked( !mCurEditor->isLocked() ); + } ); + codeEditor->addUnlockedCommand( "copy" ); + codeEditor->addUnlockedCommand( "select-all" ); + /* global commands */ + + doc.setCommand( "switch-to-previous-colorscheme", [&] { auto it = mColorSchemes.find( mCurrentColorScheme ); auto prev = std::prev( it, 1 ); if ( prev != mColorSchemes.end() ) { @@ -204,7 +279,7 @@ UICodeEditor* App::createCodeEditor() { setColorScheme( mColorSchemes.rbegin()->first ); } } ); - codeEditor->getDocument().setCommand( "switch-to-next-colorscheme", [&] { + doc.setCommand( "switch-to-next-colorscheme", [&] { auto it = mColorSchemes.find( mCurrentColorScheme ); if ( ++it != mColorSchemes.end() ) mCurrentColorScheme = it->first; @@ -212,21 +287,18 @@ UICodeEditor* App::createCodeEditor() { mCurrentColorScheme = mColorSchemes.begin()->first; applyColorScheme( mColorSchemes[mCurrentColorScheme] ); } ); - codeEditor->getDocument().setCommand( "switch-to-previous-split", - [&] { switchPreviousSplit( mCurEditor ); } ); - codeEditor->getDocument().setCommand( "switch-to-next-split", - [&] { switchNextSplit( mCurEditor ); } ); - codeEditor->getDocument().setCommand( "save-doc", [&] { saveDoc(); } ); - codeEditor->getDocument().setCommand( "save-as-doc", [&] { saveFileDialog(); } ); - codeEditor->getDocument().setCommand( "find", [&] { showFindView(); } ); - codeEditor->getDocument().setCommand( "repeat-find", [&] { + doc.setCommand( "switch-to-previous-split", [&] { switchPreviousSplit( mCurEditor ); } ); + doc.setCommand( "switch-to-next-split", [&] { switchNextSplit( mCurEditor ); } ); + doc.setCommand( "save-doc", [&] { saveDoc(); } ); + doc.setCommand( "save-as-doc", [&] { saveFileDialog(); } ); + doc.setCommand( "find", [&] { showFindView(); } ); + doc.setCommand( "repeat-find", [&] { findNextText( "", mSearchBarLayout->find( "case_sensitive" )->isChecked() ); } ); - codeEditor->getDocument().setCommand( "close-app", [&] { closeApp(); } ); - codeEditor->getDocument().setCommand( "fullscreen-toggle", - [&]() { mWindow->toggleFullscreen(); } ); - codeEditor->getDocument().setCommand( "open-file", [&] { openFileDialog(); } ); - codeEditor->getDocument().setCommand( "console-toggle", [&] { + doc.setCommand( "close-app", [&] { closeApp(); } ); + doc.setCommand( "fullscreen-toggle", [&]() { mWindow->toggleFullscreen(); } ); + doc.setCommand( "open-file", [&] { openFileDialog(); } ); + doc.setCommand( "console-toggle", [&] { mConsole->toggle(); bool lock = mConsole->isActive(); for ( auto tabW : mTabWidgets ) { @@ -235,12 +307,12 @@ UICodeEditor* App::createCodeEditor() { } } } ); - codeEditor->getDocument().setCommand( "close-doc", [&] { tryTabClose( mCurEditor ); } ); - codeEditor->getDocument().setCommand( "create-new", [&] { + doc.setCommand( "close-doc", [&] { tryTabClose( mCurEditor ); } ); + doc.setCommand( "create-new", [&] { auto d = createCodeEditorInTabWidget( tabWidgetFromEditor( mCurEditor ) ); d.first->getTabWidget()->setTabSelected( d.first ); } ); - codeEditor->getDocument().setCommand( "next-doc", [&] { + doc.setCommand( "next-doc", [&] { UITabWidget* tabWidget = tabWidgetFromEditor( mCurEditor ); if ( tabWidget && tabWidget->getTabCount() > 1 ) { UITab* tab = (UITab*)mCurEditor->getData(); @@ -248,7 +320,7 @@ UICodeEditor* App::createCodeEditor() { switchToTab( ( tabIndex + 1 ) % tabWidget->getTabCount() ); } } ); - codeEditor->getDocument().setCommand( "previous-doc", [&] { + doc.setCommand( "previous-doc", [&] { UITabWidget* tabWidget = tabWidgetFromEditor( mCurEditor ); if ( tabWidget && tabWidget->getTabCount() > 1 ) { UITab* tab = (UITab*)mCurEditor->getData(); @@ -258,17 +330,12 @@ UICodeEditor* App::createCodeEditor() { } } ); for ( int i = 1; i <= 10; i++ ) - codeEditor->getDocument().setCommand( String::format( "switch-to-tab-%d", i ), - [&, i] { switchToTab( i - 1 ); } ); - codeEditor->getDocument().setCommand( - "split-right", [&] { splitEditor( SplitDirection::Right, mCurEditor ); } ); - codeEditor->getDocument().setCommand( - "split-bottom", [&] { splitEditor( SplitDirection::Bottom, mCurEditor ); } ); - codeEditor->getDocument().setCommand( - "split-left", [&] { splitEditor( SplitDirection::Left, mCurEditor ); } ); - codeEditor->getDocument().setCommand( "split-top", - [&] { splitEditor( SplitDirection::Top, mCurEditor ); } ); - codeEditor->getDocument().setCommand( "split-swap", [&] { + doc.setCommand( String::format( "switch-to-tab-%d", i ), [&, i] { switchToTab( i - 1 ); } ); + doc.setCommand( "split-right", [&] { splitEditor( SplitDirection::Right, mCurEditor ); } ); + doc.setCommand( "split-bottom", [&] { splitEditor( SplitDirection::Bottom, mCurEditor ); } ); + doc.setCommand( "split-left", [&] { splitEditor( SplitDirection::Left, mCurEditor ); } ); + doc.setCommand( "split-top", [&] { splitEditor( SplitDirection::Top, mCurEditor ); } ); + doc.setCommand( "split-swap", [&] { if ( UISplitter* splitter = splitterFromEditor( mCurEditor ) ) splitter->swap(); } ); @@ -447,12 +514,27 @@ std::pair App::createCodeEditorInTabWidget( UITabWidget* if ( NULL == tabWidget ) return std::make_pair( (UITab*)NULL, (UICodeEditor*)NULL ); UICodeEditor* editor = createCodeEditor(); + editor->addEventListener( Event::OnDocumentChanged, [&] (const Event* event) { + updateEditorTitle( event->getNode()->asType() ); + } ); UITab* tab = tabWidget->add( editor->getDocument().getFilename(), editor ); editor->setData( (UintPtr)tab ); return std::make_pair( tab, editor ); } +void App::removeUnusedTab( UITabWidget* tabWidget ) { + if ( tabWidget && tabWidget->getTabCount() == 2 && + tabWidget->getTab( 0 ) + ->getOwnedWidget() + ->asType() + ->getDocument() + .isEmpty() ) { + tabWidget->removeTab( (Uint32)0 ); + } +} + UITabWidget* App::createEditorWithTabWidget( Node* parent ) { + UICodeEditor* prevCurEditor = mCurEditor; UITabWidget* tabWidget = UITabWidget::New(); tabWidget->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); tabWidget->setParent( parent ); @@ -472,17 +554,11 @@ UITabWidget* App::createEditorWithTabWidget( Node* parent ) { tabWidget->addEventListener( Event::OnTabClosed, [&]( const Event* event ) { onTabClosed( static_cast( event ) ); } ); - tabWidget->addEventListener( Event::OnTabAdded, [&]( const Event* event ) { - UITabWidget* tabWidget = event->getNode()->asType(); - if ( tabWidget->getTabCount() == 2 && tabWidget->getTab( 0 ) - ->getOwnedWidget() - ->asType() - ->getDocument() - .isEmpty() ) { - tabWidget->removeTab( (Uint32)0 ); - } - } ); - createCodeEditorInTabWidget( tabWidget ); + auto editorData = createCodeEditorInTabWidget( tabWidget ); + // Open same document in the new split + if ( prevCurEditor && prevCurEditor != editorData.second && + !prevCurEditor->getDocument().isEmpty() ) + editorData.second->setDocument( prevCurEditor->getDocumentRef() ); mTabWidgets.push_back( tabWidget ); return tabWidget; } @@ -513,6 +589,7 @@ bool App::loadFileFromPath( const std::string& path, UICodeEditor* codeEditor ) updateEditorTitle( codeEditor ); if ( codeEditor == mCurEditor ) updateCurrentFiletype(); + removeUnusedTab( tabWidgetFromEditor( codeEditor ) ); return ret; } @@ -959,7 +1036,8 @@ void App::init( const std::string& file, const Float& pidelDensity ) { FontTrueType::New( "monospace", resPath + "assets/fonts/DejaVuSansMono.ttf" ); fontMono->setBoldAdvanceSameAsRegular( true ); - FontTrueType* iconFont = FontTrueType::New( "icon", resPath + "assets/fonts/remixicon.ttf" ); + FontTrueType* iconFont = + FontTrueType::New( "icon", resPath + "assets/fonts/remixicon.ttf" ); SceneManager::instance()->add( mUISceneNode ); diff --git a/src/tools/codeeditor/codeeditor.hpp b/src/tools/codeeditor/codeeditor.hpp index b1aa8c32b..f19bd5d19 100644 --- a/src/tools/codeeditor/codeeditor.hpp +++ b/src/tools/codeeditor/codeeditor.hpp @@ -153,6 +153,8 @@ class App { void updateEditorState(); void saveDoc(); + + void removeUnusedTab( UITabWidget* tabWidget ); }; #endif // EE_TOOLS_CODEEDITOR_HPP