diff --git a/include/eepp/scene/event.hpp b/include/eepp/scene/event.hpp index 1eea7cd23..2841bdfee 100644 --- a/include/eepp/scene/event.hpp +++ b/include/eepp/scene/event.hpp @@ -51,6 +51,7 @@ class EE_API Event { OnControlClear, MsgBoxConfirmClick, OnTabSelected, + OnTabClosed, OnClose, // Warning: Only some controls will report this event. OnDragStart, OnDragStop, diff --git a/include/eepp/scene/mouseevent.hpp b/include/eepp/scene/mouseevent.hpp index f1b9ea776..2a98553e8 100644 --- a/include/eepp/scene/mouseevent.hpp +++ b/include/eepp/scene/mouseevent.hpp @@ -9,7 +9,7 @@ namespace EE { namespace Scene { class EE_API MouseEvent : public Event { public: - MouseEvent( Node* node, const Uint32& EventNum, const Vector2i& Pos, const Uint32& getFlags ); + MouseEvent( Node* node, const Uint32& EventNum, const Vector2i& Pos, const Uint32& flags ); ~MouseEvent(); diff --git a/include/eepp/scene/node.hpp b/include/eepp/scene/node.hpp index 2d987ae1a..1c62ec970 100644 --- a/include/eepp/scene/node.hpp +++ b/include/eepp/scene/node.hpp @@ -370,6 +370,8 @@ class EE_API Node : public Transformable { bool isClosing() const; + virtual Node* overFind( const Vector2f& Point ); + protected: typedef std::map> EventsMap; friend class EventDispatcher; @@ -460,8 +462,6 @@ class EE_API Node : public Transformable { virtual void onAlphaChange(); - virtual Node* overFind( const Vector2f& Point ); - virtual void onSceneChange(); void clipStart(); @@ -484,11 +484,11 @@ class EE_API Node : public Transformable { void childDeleteAll(); - void childAdd( Node* ChildCtrl ); + void childAdd( Node* node ); - void childAddAt( Node* ChildCtrl, Uint32 position ); + void childAddAt( Node* node, Uint32 index ); - void childRemove( Node* ChildCtrl ); + void childRemove( Node* node ); Rectf getScreenBounds(); diff --git a/include/eepp/ui.hpp b/include/eepp/ui.hpp index 89143fe08..7ee26a579 100644 --- a/include/eepp/ui.hpp +++ b/include/eepp/ui.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -47,7 +49,6 @@ #include #include #include -#include #include diff --git a/include/eepp/ui/doc/textdocument.hpp b/include/eepp/ui/doc/textdocument.hpp index 8a313e30b..7505c138b 100644 --- a/include/eepp/ui/doc/textdocument.hpp +++ b/include/eepp/ui/doc/textdocument.hpp @@ -40,6 +40,8 @@ class EE_API TextDocument { TextDocument(); + bool isEmpty(); + void reset(); void loadFromStream( IOStream& path ); @@ -52,7 +54,7 @@ class EE_API TextDocument { bool save( IOStream& stream, const bool& utf8bom = false ); - const std::string getFilename() const; + std::string getFilename() const; void setSelection( TextPosition position ); diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index 0a0ec6162..d5baa21c5 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -190,7 +190,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { virtual std::string getPropertyString( const PropertyDefinition* propertyDef, const Uint32& propertyIndex = 0 ); - protected: + + protected: struct LastXOffset { TextPosition position; Float offset; diff --git a/include/eepp/ui/uihelper.hpp b/include/eepp/ui/uihelper.hpp index d87404f59..290ba99d9 100644 --- a/include/eepp/ui/uihelper.hpp +++ b/include/eepp/ui/uihelper.hpp @@ -83,7 +83,7 @@ enum UINodeType { UI_TYPE_LAYOUT, UI_TYPE_VIEWPAGER, UI_TYPE_ITEMCONTAINER, - UI_TYPE_CODEEDIT, + UI_TYPE_CODEEDITOR, UI_TYPE_SPLITTER, UI_TYPE_USER = 10000 }; diff --git a/include/eepp/ui/uiitemcontainer.hpp b/include/eepp/ui/uiitemcontainer.hpp index 4f8cc696a..4871319b9 100644 --- a/include/eepp/ui/uiitemcontainer.hpp +++ b/include/eepp/ui/uiitemcontainer.hpp @@ -22,7 +22,6 @@ template class UIItemContainer : public UIWidget { virtual void onChildCountChange( Node* child, const bool& removed ); - protected: Node* overFind( const Vector2f& Point ); }; diff --git a/include/eepp/ui/uitab.hpp b/include/eepp/ui/uitab.hpp index 891653bfb..ac8e41a7d 100644 --- a/include/eepp/ui/uitab.hpp +++ b/include/eepp/ui/uitab.hpp @@ -34,6 +34,8 @@ class EE_API UITab : public UISelectButton { virtual std::string getPropertyString( const PropertyDefinition* propertyDef, const Uint32& propertyIndex = 0 ); + UITabWidget* getTabWidget(); + protected: friend class UITabWidget; @@ -49,8 +51,6 @@ class EE_API UITab : public UISelectButton { virtual void onAutoSize(); - UITabWidget* getTabWidget(); - virtual void onParentChange(); virtual void onSizeChange(); diff --git a/include/eepp/ui/uitabwidget.hpp b/include/eepp/ui/uitabwidget.hpp index 375d50159..52d9ae6f7 100644 --- a/include/eepp/ui/uitabwidget.hpp +++ b/include/eepp/ui/uitabwidget.hpp @@ -7,6 +7,17 @@ namespace EE { namespace UI { +class EE_API TabEvent : public Event { + public: + TabEvent( Node* node, UITab* tabEvent, const Uint32& eventType ) : + Event( node, eventType ), tab( tabEvent ) {} + + UITab* getTab() const { return tab; } + + protected: + UITab* tab; +}; + class EE_API UITabWidget : public UIWidget { public: class StyleConfig { @@ -32,7 +43,7 @@ class EE_API UITabWidget : public UIWidget { virtual bool isType( const Uint32& type ) const; - UITabWidget* add( const String& Text, UINode* CtrlOwned, Drawable* Icon = NULL ); + UITab* add( const String& Text, UINode* CtrlOwned, Drawable* Icon = NULL ); UITabWidget* add( UITab* Tab ); @@ -44,7 +55,7 @@ class EE_API UITabWidget : public UIWidget { Uint32 getTabCount() const; - void removeTab( const Uint32& Index ); + void removeTab( const Uint32& index ); void removeTab( UITab* Tab ); @@ -109,9 +120,9 @@ class EE_API UITabWidget : public UIWidget { void selectNextTab(); - void setTabSelected( UITab* Tab ); + UITab* setTabSelected( UITab* Tab ); - void setTabSelected( const Uint32& tabIndex ); + UITab* setTabSelected( const Uint32& tabIndex ); protected: friend class UITab; diff --git a/projects/linux/ee.files b/projects/linux/ee.files index 6b57641cb..6d5371f79 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -961,6 +961,7 @@ ../../src/thirdparty/SOIL2/src/SOIL2/stbi_pvr_c.h ../../src/thirdparty/SOIL2/src/SOIL2/stbi_pvr.h ../../src/tools/codeeditor/codeeditor.cpp +../../src/tools/codeeditor/codeeditor.hpp ../../src/tools/mapeditor/mapeditor.cpp ../../src/tools/textureatlaseditor/textureatlaseditor.cpp ../../src/tools/texturepacker/texturepacker.cpp diff --git a/src/eepp/scene/mouseevent.cpp b/src/eepp/scene/mouseevent.cpp index f8189dafc..8901bc2ff 100644 --- a/src/eepp/scene/mouseevent.cpp +++ b/src/eepp/scene/mouseevent.cpp @@ -4,8 +4,8 @@ namespace EE { namespace Scene { MouseEvent::MouseEvent( Node* node, const Uint32& EventNum, const Vector2i& Pos, - const Uint32& Flags ) : - Event( node, EventNum ), mPos( Pos ), mFlags( Flags ) {} + const Uint32& flags ) : + Event( node, EventNum ), mPos( Pos ), mFlags( flags ) {} MouseEvent::~MouseEvent() {} diff --git a/src/eepp/scene/node.cpp b/src/eepp/scene/node.cpp index 3046cda90..c881bbdef 100644 --- a/src/eepp/scene/node.cpp +++ b/src/eepp/scene/node.cpp @@ -578,97 +578,106 @@ void Node::childDeleteAll() { } } -void Node::childAdd( Node* ChildCtrl ) { +void Node::childAdd( Node* node ) { if ( NULL == mChild ) { - mChild = ChildCtrl; - mChildLast = ChildCtrl; + mChild = node; + mChildLast = node; } else { - mChildLast->mNext = ChildCtrl; - ChildCtrl->mPrev = mChildLast; - ChildCtrl->mNext = NULL; - mChildLast = ChildCtrl; + mChildLast->mNext = node; + node->mPrev = mChildLast; + node->mNext = NULL; + mChildLast = node; } - onChildCountChange( ChildCtrl, false ); + eeASSERT( !( NULL == mChildLast && NULL != mChild ) ); + + onChildCountChange( node, false ); } -void Node::childAddAt( Node* ChildCtrl, Uint32 Pos ) { - eeASSERT( NULL != ChildCtrl ); +void Node::childAddAt( Node* node, Uint32 index ) { + eeASSERT( NULL != node ); - Node* ChildLoop = mChild; + Node* nodeLoop = mChild; - ChildCtrl->setParent( this ); + node->setParent( this ); - childRemove( ChildCtrl ); + childRemove( node ); - ChildCtrl->mParentCtrl = this; - ChildCtrl->mSceneNode = ChildCtrl->findSceneNode(); + node->mParentCtrl = this; + node->mSceneNode = node->findSceneNode(); - if ( ChildLoop == NULL ) { - mChild = ChildCtrl; - mChildLast = ChildCtrl; - ChildCtrl->mNext = NULL; - ChildCtrl->mPrev = NULL; + if ( nodeLoop == NULL ) { + mChild = node; + mChildLast = node; + node->mNext = NULL; + node->mPrev = NULL; } else { - if ( Pos == 0 ) { + if ( index == 0 ) { if ( NULL != mChild ) { - mChild->mPrev = ChildCtrl; + mChild->mPrev = node; } - ChildCtrl->mNext = mChild; - ChildCtrl->mPrev = NULL; - mChild = ChildCtrl; + node->mNext = mChild; + node->mPrev = NULL; + mChild = node; + + if ( mChild->mNext == NULL ) + mChildLast = mChild; } else { Uint32 i = 0; - while ( NULL != ChildLoop->mNext && i < Pos ) { - ChildLoop = ChildLoop->mNext; + while ( NULL != nodeLoop->mNext && i < index ) { + nodeLoop = nodeLoop->mNext; i++; } - Node* ChildTmp = ChildLoop->mNext; - ChildLoop->mNext = ChildCtrl; - ChildCtrl->mPrev = ChildLoop; - ChildCtrl->mNext = ChildTmp; + Node* ChildTmp = nodeLoop->mNext; + nodeLoop->mNext = node; + node->mPrev = nodeLoop; + node->mNext = ChildTmp; if ( NULL != ChildTmp ) { - ChildTmp->mPrev = ChildCtrl; + ChildTmp->mPrev = node; } else { - mChildLast = ChildCtrl; + mChildLast = node; } } } - onChildCountChange( ChildCtrl, false ); + eeASSERT( !( NULL == mChildLast && NULL != mChild ) ); + + onChildCountChange( node, false ); } -void Node::childRemove( Node* ChildCtrl ) { - if ( ChildCtrl == mChild ) { +void Node::childRemove( Node* node ) { + if ( node == mChild ) { mChild = mChild->mNext; if ( NULL != mChild ) { mChild->mPrev = NULL; - if ( ChildCtrl == mChildLast ) + if ( node == mChildLast ) mChildLast = mChild; } else { mChildLast = NULL; } } else { - if ( mChildLast == ChildCtrl ) + if ( mChildLast == node ) mChildLast = mChildLast->mPrev; - ChildCtrl->mPrev->mNext = ChildCtrl->mNext; + node->mPrev->mNext = node->mNext; - if ( NULL != ChildCtrl->mNext ) { - ChildCtrl->mNext->mPrev = ChildCtrl->mPrev; - ChildCtrl->mNext = NULL; + if ( NULL != node->mNext ) { + node->mNext->mPrev = node->mPrev; + node->mNext = NULL; } - ChildCtrl->mPrev = NULL; + node->mPrev = NULL; } - onChildCountChange( ChildCtrl, true ); + eeASSERT( !( NULL == mChildLast && NULL != mChild ) ); + + onChildCountChange( node, true ); } void Node::childsCloseAll() { @@ -1092,7 +1101,7 @@ void Node::onParentSizeChange( const Vector2f& ) { invalidateDraw(); } -void Node::onChildCountChange( Node* child, const bool& removed ) { +void Node::onChildCountChange( Node*, const bool& ) { invalidateDraw(); } @@ -1633,7 +1642,7 @@ bool Node::isDrawInvalidator() const { return false; } -void Node::invalidate( Node* invalidator ) { +void Node::invalidate( Node* ) { if ( mVisible && mAlpha != 0.f ) { writeNodeFlag( NODE_FLAG_VIEW_DIRTY, 1 ); } diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index ba42bc39a..a842be566 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -29,6 +29,10 @@ TextDocument::TextDocument() : reset(); } +bool TextDocument::isEmpty() { + return linesCount() == 1 && line( 0 ).size() == 1; +} + void TextDocument::reset() { mFilePath = mDefaultFileName; mSelection.set( {0, 0}, {0, 0} ); @@ -188,8 +192,8 @@ bool TextDocument::save() { return save( mFilePath, mIsBOM ); } -const std::string TextDocument::getFilename() const { - return mFilePath; +std::string TextDocument::getFilename() const { + return FileSystem::fileNameFromPath( mFilePath ); } void TextDocument::setSelection( TextPosition position ) { diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index c2f218a25..d845a6f04 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -66,7 +66,7 @@ UICodeEditor::~UICodeEditor() { } Uint32 UICodeEditor::getType() const { - return UI_TYPE_CODEEDIT; + return UI_TYPE_CODEEDITOR; } bool UICodeEditor::isType( const Uint32& type ) const { diff --git a/src/eepp/ui/uisplitter.cpp b/src/eepp/ui/uisplitter.cpp index 05c6803f4..3080416c5 100644 --- a/src/eepp/ui/uisplitter.cpp +++ b/src/eepp/ui/uisplitter.cpp @@ -5,7 +5,6 @@ namespace EE { namespace UI { class UISplitterSeparator : public UIWidget { - public: static UISplitterSeparator* NewWithTag( const std::string& tag, UISplitter* parent ) { return eeNew( UISplitterSeparator, ( tag, parent ) ); @@ -63,9 +62,9 @@ UISplitter* UISplitter::New() { UISplitter::UISplitter() : UILayout( "splitter" ), mOrientation( UIOrientation::Horizontal ), - mSplitOnlyWhenNeeded( false ), + mSplitOnlyWhenNeeded( true ), mAlwaysShowSplitter( true ), - mDivisionSplit( 1.f ), + mDivisionSplit( 0.5f ), mFirstWidget( NULL ), mLastWidget( NULL ) { mFlags |= UI_OWNS_CHILDS_POSITION; @@ -131,8 +130,6 @@ void UISplitter::setDivisionSplit( const Float& divisionSplit ) { } void UISplitter::onChildCountChange( Node* child, const bool& removed ) { - UILayout::onChildCountChange( child, removed ); - if ( child != mSplitter && !removed ) { if ( !child->isWidget() ) { child->close(); @@ -142,6 +139,7 @@ void UISplitter::onChildCountChange( Node* child, const bool& removed ) { if ( getChildCount() > 3 ) { child->close(); + return; } else { if ( NULL == mFirstWidget ) { mFirstWidget = childWidget; @@ -151,6 +149,8 @@ void UISplitter::onChildCountChange( Node* child, const bool& removed ) { mSplitter->toFront(); } } + + UILayout::onChildCountChange( child, removed ); } void UISplitter::updateFromDrag() { @@ -167,17 +167,17 @@ void UISplitter::updateFromDrag() { } if ( UIOrientation::Horizontal == mOrientation ) { - Float firstWidgetMinSize = - mFirstWidget ? mFirstWidget->getCurrentMinSize().getWidth() : 0.f; - if ( mSplitter->getPosition().x < mPadding.Left + firstWidgetMinSize ) { - mSplitter->setPosition( mPadding.Left + firstWidgetMinSize, - mSplitter->getPosition().y ); + Float fMinSize = mFirstWidget ? mFirstWidget->getCurrentMinSize().getWidth() : 0.f; + + if ( mSplitter->getPosition().x < mPadding.Left + fMinSize ) { + mSplitter->setPosition( mPadding.Left + fMinSize, mSplitter->getPosition().y ); } - Float lastWidgetMinSize = mLastWidget ? mLastWidget->getCurrentMinSize().getWidth() : 0.f; + Float lMinSize = mLastWidget ? mLastWidget->getCurrentMinSize().getWidth() : 0.f; + if ( mSplitter->getPosition().x + mSplitter->getSize().getWidth() > - mDpSize.getWidth() - mPadding.Right - lastWidgetMinSize ) { - mSplitter->setPosition( mDpSize.getWidth() - mPadding.Right - lastWidgetMinSize - + mDpSize.getWidth() - mPadding.Right - lMinSize ) { + mSplitter->setPosition( mDpSize.getWidth() - mPadding.Right - lMinSize - mSplitter->getSize().getWidth(), mSplitter->getPosition().y ); } @@ -185,17 +185,17 @@ void UISplitter::updateFromDrag() { mSplitter->setPixelsSize( mSplitter->getPixelsSize().getWidth(), mSize.getHeight() - mRealPadding.Top - mRealPadding.Bottom ); } else { - Float firstWidgetMinSize = - mFirstWidget ? mFirstWidget->getCurrentMinSize().getHeight() : 0.f; - if ( mSplitter->getPosition().y < mPadding.Top + firstWidgetMinSize ) { - mSplitter->setPosition( mSplitter->getPosition().x, mPadding.Top + firstWidgetMinSize ); + Float fMinSize = mFirstWidget ? mFirstWidget->getCurrentMinSize().getHeight() : 0.f; + + if ( mSplitter->getPosition().y < mPadding.Top + fMinSize ) { + mSplitter->setPosition( mSplitter->getPosition().x, mPadding.Top + fMinSize ); } - Float lastWidgetMinSize = mLastWidget ? mLastWidget->getCurrentMinSize().getHeight() : 0.f; - if ( mSplitter->getPosition().y > - mDpSize.getHeight() - mPadding.Bottom - lastWidgetMinSize ) { + Float lMinSize = mLastWidget ? mLastWidget->getCurrentMinSize().getHeight() : 0.f; + + if ( mSplitter->getPosition().y > mDpSize.getHeight() - mPadding.Bottom - lMinSize ) { mSplitter->setPosition( mSplitter->getPosition().x, - mDpSize.getHeight() - mPadding.Bottom - lastWidgetMinSize - + mDpSize.getHeight() - mPadding.Bottom - lMinSize - +mSplitter->getSize().getHeight() ); } @@ -249,15 +249,56 @@ void UISplitter::updateFromDrag() { } void UISplitter::updateLayout() { + mDirtyLayout = true; + + if ( !getParent()->isLayout() && !getParent()->asType()->ownsChildPosition() ) { + bool sizeChanged = false; + Sizef size( getSize() ); + + if ( getLayoutWidthPolicy() == SizePolicy::MatchParent && 0 == getLayoutWeight() ) { + Float w = getParent()->getSize().getWidth() - mLayoutMargin.Left - mLayoutMargin.Right; + + if ( getParent()->isType( UI_TYPE_LAYOUT ) ) { + UILayout* pLay = static_cast( getParent() ); + w = w - pLay->getPadding().Left - pLay->getPadding().Right; + } + + if ( (int)w != (int)getSize().getWidth() ) { + sizeChanged = true; + size.setWidth( w ); + } + } + + if ( getLayoutHeightPolicy() == SizePolicy::MatchParent ) { + Float h = getParent()->getSize().getHeight() - mLayoutMargin.Top - mLayoutMargin.Bottom; + + if ( getParent()->isType( UI_TYPE_LAYOUT ) ) { + UILayout* pLay = static_cast( getParent() ); + h = h - pLay->getPadding().Top - pLay->getPadding().Bottom; + } + + if ( (int)h != (int)getSize().getHeight() ) { + sizeChanged = true; + size.setHeight( h ); + } + } + + if ( sizeChanged ) { + setInternalSize( size ); + } + } + if ( mSplitOnlyWhenNeeded && !mLastWidget ) { mSplitter->setVisible( false )->setEnabled( false ); if ( mFirstWidget ) { - mFirstWidget->setPosition( mRealPadding.Left, mRealPadding.Top ); + mFirstWidget->setPixelsPosition( mRealPadding.Left, mRealPadding.Top ); mFirstWidget->setPixelsSize( mSize.getWidth() - mRealPadding.Left - mRealPadding.Right, mSize.getHeight() - mRealPadding.Top - mRealPadding.Bottom ); } + + mDirtyLayout = false; return; } @@ -277,21 +318,31 @@ void UISplitter::updateLayout() { if ( mFirstWidget ) { mFirstWidget->setPixelsPosition( mRealPadding.Left, mRealPadding.Top ); - if ( UIOrientation::Horizontal == mOrientation ) { - mFirstWidget->setPixelsSize( firstSplit, mSize.getHeight() - mRealPadding.Top - - mRealPadding.Bottom ); - } else { - mFirstWidget->setPixelsSize( mSize.getWidth() - mRealPadding.Left - mRealPadding.Right, - firstSplit ); - } if ( UIOrientation::Horizontal == mOrientation ) { + Float fMinSize = mFirstWidget ? mFirstWidget->getCurrentMinSize().getWidth() : 0.f; + + firstSplit = eemax( firstSplit, fMinSize ); + secondSplit = totalSpace - firstSplit; + + mFirstWidget->setPixelsSize( firstSplit, mSize.getHeight() - mRealPadding.Top - + mRealPadding.Bottom ); + mSplitter->setPixelsPosition( mFirstWidget->getPixelsPosition().x + mFirstWidget->getPixelsSize().getWidth(), mRealPadding.Top ); mSplitter->setPixelsSize( mSplitter->getPixelsSize().getWidth(), mSize.getHeight() - mRealPadding.Top - mRealPadding.Bottom ); } else { + + Float fMinSize = mFirstWidget ? mFirstWidget->getCurrentMinSize().getHeight() : 0.f; + + firstSplit = eemax( firstSplit, fMinSize ); + secondSplit = totalSpace - firstSplit; + + mFirstWidget->setPixelsSize( mSize.getWidth() - mRealPadding.Left - mRealPadding.Right, + firstSplit ); + mSplitter->setPixelsPosition( mRealPadding.Left, mFirstWidget->getPixelsPosition().y + mFirstWidget->getPixelsSize().getHeight() ); @@ -322,7 +373,9 @@ void UISplitter::updateLayout() { Uint32 UISplitter::onMessage( const NodeMessage* Msg ) { switch ( Msg->getMsg() ) { case NodeMessage::LayoutAttributeChange: { - tryUpdateLayout(); + if ( !mSplitter->isDragging() ) { + tryUpdateLayout(); + } return 1; } } diff --git a/src/eepp/ui/uitab.cpp b/src/eepp/ui/uitab.cpp index 8b34b7dfa..ee67bd688 100644 --- a/src/eepp/ui/uitab.cpp +++ b/src/eepp/ui/uitab.cpp @@ -13,7 +13,7 @@ UITab::UITab() : UISelectButton( "tab" ), mOwnedWidget( NULL ) { mTextBox->setElementTag( mTag + "::text" ); mIcon->setElementTag( mTag + "::icon" ); applyDefaultTheme(); - auto cb = [&]( const Event* event ) { onSizeChange(); }; + auto cb = [&]( const Event* ) { onSizeChange(); }; mTextBox->addEventListener( Event::OnSizeChange, cb ); mIcon->addEventListener( Event::OnSizeChange, cb ); } diff --git a/src/eepp/ui/uitabwidget.cpp b/src/eepp/ui/uitabwidget.cpp index 714c3575f..caa38c6b1 100644 --- a/src/eepp/ui/uitabwidget.cpp +++ b/src/eepp/ui/uitabwidget.cpp @@ -88,7 +88,7 @@ void UITabWidget::setContainerSize() { Sizef s( mSize.getWidth() - mRealPadding.Left - mRealPadding.Right, mSize.getHeight() - PixelDensity::dpToPx( mStyleConfig.TabHeight ) - mRealPadding.Top - mRealPadding.Bottom ); - if ( s != mCtrlContainer->getSize() ) { + if ( s != mCtrlContainer->getPixelsSize() ) { mCtrlContainer->setPixelsSize( s ); for ( auto& tab : mTabs ) { @@ -374,8 +374,10 @@ UITab* UITabWidget::createTab( const String& Text, UINode* ownedWidget, Drawable return tab; } -UITabWidget* UITabWidget::add( const String& Text, UINode* CtrlOwned, Drawable* Icon ) { - return add( createTab( Text, CtrlOwned, Icon ) ); +UITab* UITabWidget::add( const String& Text, UINode* CtrlOwned, Drawable* Icon ) { + UITab* tab = createTab( Text, CtrlOwned, Icon ); + add( tab ); + return tab; } UITabWidget* UITabWidget::add( UITab* Tab ) { @@ -423,25 +425,22 @@ Uint32 UITabWidget::getTabCount() const { return mTabs.size(); } -void UITabWidget::removeTab( const Uint32& Index ) { - eeASSERT( Index < mTabs.size() ); +void UITabWidget::removeTab( const Uint32& index ) { + eeASSERT( index < mTabs.size() ); - if ( mTabs[Index] == mTabSelected ) { - mTabSelected->getOwnedWidget()->setVisible( false ); - mTabSelected->getOwnedWidget()->setEnabled( false ); - } + UITab* tab = mTabs[index]; - mTabs[Index]->close(); - mTabs[Index]->setVisible( false ); - mTabs[Index]->setEnabled( false ); - mTabs[Index] = NULL; + tab->close(); + tab->setVisible( false ); + tab->setEnabled( false ); + tab->getOwnedWidget()->close(); + tab->getOwnedWidget()->setVisible( false ); + tab->getOwnedWidget()->setEnabled( false ); - mTabs.erase( mTabs.begin() + Index ); + mTabs.erase( mTabs.begin() + index ); - mTabSelected = NULL; - - if ( Index == mTabSelectedIndex ) { - if ( mTabs.size() > 0 ) { + if ( index == mTabSelectedIndex ) { + if ( !mTabs.empty() ) { if ( mTabSelectedIndex < mTabs.size() ) { setTabSelected( mTabs[mTabSelectedIndex] ); } else { @@ -455,9 +454,14 @@ void UITabWidget::removeTab( const Uint32& Index ) { mTabSelected = NULL; mTabSelectedIndex = eeINDEX_NOT_FOUND; } + } else { + mTabSelectedIndex = getTabIndex( mTabSelected ); } orderTabs(); + + TabEvent tabEvent( this, tab, Event::OnTabClosed ); + sendEvent( &tabEvent ); } void UITabWidget::removeTab( UITab* Tab ) { @@ -465,11 +469,16 @@ void UITabWidget::removeTab( UITab* Tab ) { } void UITabWidget::removeAllTabs() { + std::deque tabs = mTabs; + for ( Uint32 i = 0; i < mTabs.size(); i++ ) { if ( NULL != mTabs[i] ) { mTabs[i]->close(); mTabs[i]->setVisible( false ); mTabs[i]->setEnabled( false ); + mTabs[i]->getOwnedWidget()->close(); + mTabs[i]->getOwnedWidget()->setVisible( false ); + mTabs[i]->getOwnedWidget()->setEnabled( false ); } } @@ -479,6 +488,13 @@ void UITabWidget::removeAllTabs() { mTabSelectedIndex = eeINDEX_NOT_FOUND; orderTabs(); + + for ( Uint32 i = 0; i < tabs.size(); i++ ) { + if ( NULL != tabs[i] ) { + TabEvent tabEvent( this, tabs[i], Event::OnTabClosed ); + sendEvent( &tabEvent ); + } + } } void UITabWidget::insertTab( const String& Text, UINode* CtrlOwned, Drawable* Icon, @@ -494,18 +510,18 @@ void UITabWidget::insertTab( UITab* Tab, const Uint32& Index ) { orderTabs(); } -void UITabWidget::setTabSelected( UITab* Tab ) { +UITab* UITabWidget::setTabSelected( UITab* Tab ) { if ( NULL == Tab ) - return; + return NULL; if ( std::find( mTabs.begin(), mTabs.end(), Tab ) == mTabs.end() ) - return; + return NULL; invalidateDraw(); if ( Tab == mTabSelected ) { refreshOwnedWidget( Tab ); - return; + return NULL; } if ( NULL != mTabSelected ) { @@ -531,12 +547,15 @@ void UITabWidget::setTabSelected( UITab* Tab ) { sendCommonEvent( Event::OnTabSelected ); } + + return Tab; } -void UITabWidget::setTabSelected( const Uint32& tabIndex ) { +UITab* UITabWidget::setTabSelected( const Uint32& tabIndex ) { if ( tabIndex < mTabs.size() ) { - setTabSelected( mTabs[tabIndex] ); + return setTabSelected( mTabs[tabIndex] ); } + return NULL; } void UITabWidget::refreshOwnedWidget( UITab* tab ) { diff --git a/src/tools/codeeditor/codeeditor.cpp b/src/tools/codeeditor/codeeditor.cpp index 00dfc66d3..f0491bba4 100644 --- a/src/tools/codeeditor/codeeditor.cpp +++ b/src/tools/codeeditor/codeeditor.cpp @@ -1,60 +1,219 @@ +#include "codeeditor.hpp" #include -#include -EE::Window::Window* win = NULL; -UISceneNode* uiSceneNode = NULL; -UICodeEditor* codeEditor = NULL; -Console* console = NULL; -std::string curFile = "untitled"; -const std::string& windowTitle = "eepp - Code Editor"; -bool docDirtyState = false; -UIMessageBox* MsgBox = NULL; -String lastSearch; +App* appInstance = NULL; -bool onCloseRequestCallback( EE::Window::Window* ) { - if ( NULL != codeEditor && codeEditor->isDirty() ) { - MsgBox = UIMessageBox::New( +void appLoop() { + appInstance->mainLoop(); +} + +bool App::onCloseRequestCallback( EE::Window::Window* ) { + if ( NULL != mCurEditor && mCurEditor->isDirty() ) { + mMsgBox = UIMessageBox::New( UIMessageBox::OK_CANCEL, "Do you really want to close the code editor?\nAll changes will be lost." ); - MsgBox->addEventListener( Event::MsgBoxConfirmClick, []( const Event* ) { win->close(); } ); - MsgBox->addEventListener( Event::OnClose, []( const Event* ) { MsgBox = NULL; } ); - MsgBox->setTitle( "Close Code Editor?" ); - MsgBox->center(); - MsgBox->show(); + mMsgBox->addEventListener( Event::MsgBoxConfirmClick, + [&]( const Event* ) { mWindow->close(); } ); + mMsgBox->addEventListener( Event::OnClose, [&]( const Event* ) { mMsgBox = NULL; } ); + mMsgBox->setTitle( "Close Code Editor?" ); + mMsgBox->center(); + mMsgBox->show(); return false; } else { return true; } } -void setAppTitle( const std::string& title ) { - win->setTitle( windowTitle + String( title.empty() ? "" : " - " + title ) ); +void App::splitEditor( const UIOrientation& orientation ) { + UITabWidget* tabWidget = tabWidgetFromEditor( mCurEditor ); + if ( tabWidget ) { + UISplitter* splitter = (UISplitter*)tabWidget->getParent(); + if ( splitter->getChildCount() < 3 ) { + splitter->setOrientation( orientation ); + createEditorSplitter( splitter ); + } + } } -void loadFileFromPath( const std::string& path ) { +UICodeEditor* App::createCodeEditor() { + UICodeEditor* codeEditor = UICodeEditor::New(); + codeEditor->setFontSize( 11 ); + codeEditor->getDocument().setCommand( "find", [&]() { findTextMessageBox(); } ); + codeEditor->getDocument().setCommand( "repeat-find", [&] { findText(); } ); + codeEditor->getDocument().setCommand( "close-app", [&] { closeApp(); } ); + codeEditor->getDocument().setCommand( "fullscreen-toggle", + [&]() { mWindow->toggleFullscreen(); } ); + codeEditor->getDocument().setCommand( "open-file", [&] { openFileDialog(); } ); + codeEditor->getDocument().setCommand( "console-toggle", [&] { mConsole->toggle(); } ); + codeEditor->getDocument().setCommand( "close-doc", [&] { + if ( mCurEditor ) { + UITabWidget* tabWidget = tabWidgetFromEditor( mCurEditor ); + if ( tabWidget ) { + tabWidget->removeTab( (UITab*)mCurEditor->getData() ); + if ( tabWidget->getTabCount() > 0 ) { + tabWidget->setTabSelected( tabWidget->getTabCount() - 1 ); + tabWidget->getSelectedTab()->getOwnedWidget()->setFocus(); + } + } + } + } ); + codeEditor->getDocument().setCommand( "create-new", [&] { + auto d = createCodeEditorInTabWidget( tabWidgetFromEditor( mCurEditor ) ); + d.first->getTabWidget()->setTabSelected( d.first ); + d.second->setFocus(); + } ); + codeEditor->getDocument().setCommand( "next-doc", [&] { + UITabWidget* tabWidget = tabWidgetFromEditor( mCurEditor ); + if ( tabWidget && tabWidget->getTabCount() > 1 ) { + UITab* tab = (UITab*)mCurEditor->getData(); + Uint32 tabIndex = tabWidget->getTabIndex( tab ); + if ( tabIndex + 1 == tabWidget->getTabCount() ) { + tab = tabWidget->setTabSelected( (Uint32)0 ); + } else { + tab = tabWidget->setTabSelected( ( Uint32 )( tabIndex + 1 ) ); + } + if ( tab ) + tab->getOwnedWidget()->setFocus(); + } + } ); + codeEditor->getDocument().setCommand( "previous-doc", [&] { + UITabWidget* tabWidget = tabWidgetFromEditor( mCurEditor ); + if ( tabWidget && tabWidget->getTabCount() > 1 ) { + UITab* tab = (UITab*)mCurEditor->getData(); + Uint32 tabIndex = tabWidget->getTabIndex( tab ); + if ( tabIndex == 0 ) { + tab = tabWidget->setTabSelected( (Uint32)tabWidget->getTabCount() - 1 ); + } else { + tab = tabWidget->setTabSelected( ( Uint32 )( tabIndex - 1 ) ); + } + if ( tab ) + tab->getOwnedWidget()->setFocus(); + } + } ); + codeEditor->getDocument().setCommand( "split-horizontal", + [&] { splitEditor( UIOrientation::Horizontal ); } ); + codeEditor->getDocument().setCommand( "split-vertical", + [&] { splitEditor( UIOrientation::Vertical ); } ); + codeEditor->addKeyBindingString( "escape", "close-app", true ); + codeEditor->addKeyBindingString( "f2", "open-file", true ); + codeEditor->addKeyBindingString( "f3", "repeat-find", false ); + codeEditor->addKeyBindingString( "f12", "console-toggle", true ); + codeEditor->addKeyBindingString( "alt+return", "fullscreen-toggle", true ); + codeEditor->addKeyBindingString( "ctrl+s", "save", false ); + codeEditor->addKeyBindingString( "ctrl+f", "find", false ); + codeEditor->addKeyBindingString( "ctrl+q", "close-app", true ); + codeEditor->addKeyBindingString( "ctrl+o", "open-file", true ); + codeEditor->addKeyBindingString( "ctrl+l", "lock-toggle", true ); + codeEditor->addKeyBindingString( "ctrl+t", "create-new", true ); + codeEditor->addKeyBindingString( "ctrl+w", "close-doc", true ); + codeEditor->addKeyBindingString( "ctrl+tab", "next-doc", true ); + codeEditor->addKeyBindingString( "ctrl+shift+tab", "previous-doc", true ); + codeEditor->addKeyBindingString( "ctrl+shift+l", "split-horizontal", true ); + codeEditor->addKeyBindingString( "ctrl+shift+k", "split-vertical", true ); + codeEditor->addEventListener( Event::OnFocus, [&]( const Event* event ) { + mCurEditor = event->getNode()->asType(); + setAppTitle( mCurEditor->getDocument().getFilename() ); + } ); + if ( NULL == mCurEditor ) { + mCurEditor = codeEditor; + } + return codeEditor; +} + +std::pair App::createCodeEditorInTabWidget( UITabWidget* tabWidget ) { + if ( NULL == tabWidget ) + return std::make_pair( (UITab*)NULL, (UICodeEditor*)NULL ); + UICodeEditor* editor = createCodeEditor(); + UITab* tab = tabWidget->add( editor->getDocument().getFilename(), editor ); + tabWidget->addEventListener( Event::OnTabClosed, [&]( const Event* event ) { + const TabEvent* tabEvent = static_cast( event ); + if ( tabEvent->getTab()->getOwnedWidget() == mCurEditor ) { + mCurEditor = NULL; + } + UITabWidget* tabWidget = tabEvent->getTab()->getTabWidget(); + if ( tabWidget->getTabCount() == 0 ) { + auto d = createCodeEditorInTabWidget( tabWidget ); + d.first->getTabWidget()->setTabSelected( d.first ); + d.second->setFocus(); + } + } ); + editor->setData( (UintPtr)tab ); + return std::make_pair( tab, editor ); +} + +UITabWidget* App::createEditorWithTabWidget( UISplitter* splitter ) { + UITabWidget* tabWidget = UITabWidget::New(); + tabWidget->setParent( splitter ); + tabWidget->setTabsClosable( true ); + tabWidget->addEventListener( Event::OnTabSelected, [&]( const Event* event ) { + UITabWidget* tabWidget = event->getNode()->asType(); + mCurEditor = tabWidget->getSelectedTab()->getOwnedWidget()->asType(); + setAppTitle( tabWidget->getSelectedTab()->getText() ); + } ); + createCodeEditorInTabWidget( tabWidget ); + return tabWidget; +} + +UISplitter* App::createEditorSplitter( Node* parent ) { + if ( NULL == parent ) + return NULL; + UISplitter* splitter = UISplitter::New(); + splitter->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); + splitter->setParent( parent ); + auto d = createEditorWithTabWidget( splitter ); + d->getSelectedTab()->getOwnedWidget()->setFocus(); + return splitter; +} + +UITabWidget* App::tabWidgetFromEditor( UICodeEditor* editor ) { + if ( editor ) + return ( (UITab*)editor->getData() )->getTabWidget(); + return NULL; +} + +void App::setAppTitle( const std::string& title ) { + mWindow->setTitle( mWindowTitle + String( title.empty() ? "" : " - " + title ) ); +} + +void App::loadFileFromPath( const std::string& path, UICodeEditor* codeEditor ) { + if ( NULL == codeEditor ) + codeEditor = mCurEditor; codeEditor->loadFromFile( path ); - curFile = FileSystem::fileNameFromPath( path ); - setAppTitle( curFile ); + String title( codeEditor->getDocument().getFilename() ); + setAppTitle( title ); + UITab* tab = ( (UITab*)codeEditor->getData() ); + tab->setText( title ); } -void openFileDialog() { +void App::openFileDialog() { UICommonDialog* TGDialog = UICommonDialog::New( UI_CDL_DEFAULT_FLAGS, "*" ); TGDialog->setWinFlags( UI_WIN_DEFAULT_FLAGS | UI_WIN_MAXIMIZE_BUTTON | UI_WIN_MODAL ); TGDialog->setTitle( "Open layout..." ); - TGDialog->addEventListener( Event::OpenFile, []( const Event* event ) { - loadFileFromPath( event->getNode()->asType()->getFullPath() ); + TGDialog->addEventListener( Event::OpenFile, [&]( const Event* event ) { + auto d = createCodeEditorInTabWidget( tabWidgetFromEditor( mCurEditor ) ); + UITabWidget* tabWidget = d.first->getTabWidget(); + UITab* addedTab = d.first; + loadFileFromPath( event->getNode()->asType()->getFullPath(), d.second ); + tabWidget->setTabSelected( addedTab ); + UITab* firstTab = tabWidget->getTab( 0 ); + if ( addedTab != firstTab ) { + UICodeEditor* editor = (UICodeEditor*)firstTab->getOwnedWidget(); + if ( editor->getDocument().isEmpty() ) { + tabWidget->removeTab( firstTab ); + } + } } ); TGDialog->center(); TGDialog->show(); } -void findText( String text = "" ) { +void App::findText( String text ) { if ( text.empty() ) - text = lastSearch; + text = mLastSearch; if ( text.empty() ) return; - lastSearch = text; - TextDocument& doc = codeEditor->getDocument(); + mLastSearch = text; + TextDocument& doc = mCurEditor->getDocument(); TextPosition found = doc.find( text, doc.getSelection( true ).end() ); if ( found.isValid() ) { doc.setSelection( {{found.line(), found.column() + (Int64)text.size()}, found} ); @@ -66,59 +225,139 @@ void findText( String text = "" ) { } } -void findTextMessageBox() { +void App::findTextMessageBox() { UIMessageBox* inputSearch = UIMessageBox::New( UIMessageBox::INPUT, "Find text..." ); inputSearch->getTextInput()->setHint( "Find text..." ); inputSearch->setCloseWithKey( KEY_ESCAPE ); - inputSearch->addEventListener( Event::MsgBoxConfirmClick, []( const Event* event ) { + inputSearch->addEventListener( Event::MsgBoxConfirmClick, [&]( const Event* event ) { findText( event->getNode()->asType()->getTextInput()->getText() ); } ); - inputSearch->addEventListener( Event::OnClose, []( const Event* ) { codeEditor->setFocus(); } ); + inputSearch->addEventListener( Event::OnClose, + [&]( const Event* ) { mCurEditor->setFocus(); } ); inputSearch->setTitle( "Find" ); inputSearch->getButtonOK()->setText( "Search" ); inputSearch->center(); inputSearch->show(); } -void closeApp() { - if ( NULL == MsgBox && onCloseRequestCallback( win ) ) { - win->close(); +void App::closeApp() { + if ( NULL == mMsgBox && onCloseRequestCallback( mWindow ) ) { + mWindow->close(); } } -void mainLoop() { - Input* input = win->getInput(); +void App::mainLoop() { + Input* input = mWindow->getInput(); input->update(); - if ( codeEditor->isDirty() != docDirtyState ) { - docDirtyState = codeEditor->isDirty(); - setAppTitle( docDirtyState ? curFile + "*" : curFile ); + if ( mCurEditor && mCurEditor->isDirty() != mDocDirtyState ) { + mDocDirtyState = mCurEditor->isDirty(); + setAppTitle( mCurEditor->getDocument().getFilename() + ( mDocDirtyState ? "*" : "" ) ); } if ( input->isKeyUp( KEY_F6 ) ) { - uiSceneNode->setHighlightFocus( !uiSceneNode->getHighlightFocus() ); - uiSceneNode->setHighlightOver( !uiSceneNode->getHighlightOver() ); + mUISceneNode->setHighlightFocus( !mUISceneNode->getHighlightFocus() ); + mUISceneNode->setHighlightOver( !mUISceneNode->getHighlightOver() ); } if ( input->isKeyUp( KEY_F7 ) ) { - uiSceneNode->setDrawBoxes( !uiSceneNode->getDrawBoxes() ); + mUISceneNode->setDrawBoxes( !mUISceneNode->getDrawBoxes() ); } if ( input->isKeyUp( KEY_F8 ) ) { - uiSceneNode->setDrawDebugData( !uiSceneNode->getDrawDebugData() ); + mUISceneNode->setDrawDebugData( !mUISceneNode->getDrawDebugData() ); } SceneManager::instance()->update(); - if ( SceneManager::instance()->getUISceneNode()->invalidated() || console->isActive() || - console->isFading() ) { - win->clear(); + if ( SceneManager::instance()->getUISceneNode()->invalidated() || mConsole->isActive() || + mConsole->isFading() ) { + mWindow->clear(); SceneManager::instance()->draw(); - console->draw(); - win->display(); + mConsole->draw(); + mWindow->display(); } else { - Sys::sleep( Milliseconds( win->isVisible() ? 1 : 16 ) ); + Sys::sleep( Milliseconds( mWindow->isVisible() ? 1 : 16 ) ); + } +} + +App::~App() { + eeSAFE_DELETE( mConsole ); +} + +void App::init( const std::string& file ) { + DisplayManager* displayManager = Engine::instance()->getDisplayManager(); + Display* currentDisplay = displayManager->getDisplayIndex( 0 ); + Float pixelDensity = currentDisplay->getPixelDensity(); + + displayManager->enableScreenSaver(); + displayManager->enableMouseFocusClickThrough(); + + std::string resPath( Sys::getProcessPath() ); + + mWindow = Engine::instance()->createWindow( + WindowSettings( 1280, 720, mWindowTitle, WindowStyle::Default, WindowBackend::Default, 32, + resPath + "assets/icon/ee.png", pixelDensity ), + ContextSettings( true ) ); + + if ( mWindow->isOpen() ) { + mWindow->setCloseRequestCallback( + [&]( auto* win ) -> bool { return onCloseRequestCallback( win ); } ); + + mWindow->getInput()->pushCallback( [&]( InputEvent* event ) { + if ( NULL == mCurEditor ) + return; + + if ( event->Type == InputEvent::FileDropped ) { + Vector2f mousePos( mUISceneNode->getEventDispatcher()->getMousePosf() ); + Node* node = mUISceneNode->overFind( mousePos ); + UICodeEditor* codeEditor = mCurEditor; + if ( node->isType( UI_TYPE_CODEEDITOR ) ) { + codeEditor = node->asType(); + if ( !codeEditor->getDocument().isEmpty() ) { + auto d = createCodeEditorInTabWidget( tabWidgetFromEditor( codeEditor ) ); + codeEditor = d.second; + d.first->getTabWidget()->setTabSelected( d.first ); + } + } + loadFileFromPath( event->file.file, codeEditor ); + } else if ( event->Type == InputEvent::TextDropped ) { + mCurEditor->getDocument().textInput( event->textdrop.text ); + } + } ); + + PixelDensity::setPixelDensity( eemax( mWindow->getScale(), pixelDensity ) ); + + mUISceneNode = UISceneNode::New(); + + mUISceneNode->getUIThemeManager()->setDefaultFont( FontTrueType::New( + "NotoSans-Regular", resPath + "assets/fonts/NotoSans-Regular.ttf" ) ); + + Font* fontMono = + FontTrueType::New( "monospace", resPath + "assets/fonts/DejaVuSansMono.ttf" ); + + SceneManager::instance()->add( mUISceneNode ); + + StyleSheetParser cssParser; + if ( cssParser.loadFromFile( resPath + "assets/ui/breeze.css" ) ) { + mUISceneNode->setStyleSheet( cssParser.getStyleSheet() ); + } + + mUISceneNode->getRoot()->addClass( "appbackground" ); + + mBaseLayout = UILinearLayout::NewVertical(); + mBaseLayout->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); + + createEditorSplitter( mBaseLayout ); + + if ( !file.empty() ) { + loadFileFromPath( file ); + } + + mConsole = eeNew( Console, ( fontMono, true, true, 1024 * 1000, 0, mWindow ) ); + + mWindow->runMainLoop( &appLoop ); } } @@ -141,97 +380,9 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) { return EXIT_FAILURE; } - DisplayManager* displayManager = Engine::instance()->getDisplayManager(); - Display* currentDisplay = displayManager->getDisplayIndex( 0 ); - Float pixelDensity = currentDisplay->getPixelDensity(); - - displayManager->enableScreenSaver(); - displayManager->enableMouseFocusClickThrough(); - - std::string resPath( Sys::getProcessPath() ); - - win = Engine::instance()->createWindow( - WindowSettings( 1280, 720, windowTitle, WindowStyle::Default, WindowBackend::Default, 32, - resPath + "assets/icon/ee.png", pixelDensity ), - ContextSettings( true ) ); - - if ( win->isOpen() ) { - win->setCloseRequestCallback( cb::Make1( onCloseRequestCallback ) ); - - win->getInput()->pushCallback( []( InputEvent* event ) { - if ( NULL == codeEditor ) - return; - - if ( event->Type == InputEvent::FileDropped ) { - loadFileFromPath( event->file.file ); - } else if ( event->Type == InputEvent::TextDropped ) { - codeEditor->getDocument().textInput( event->textdrop.text ); - } - } ); - - PixelDensity::setPixelDensity( eemax( win->getScale(), pixelDensity ) ); - - uiSceneNode = UISceneNode::New(); - - uiSceneNode->getUIThemeManager()->setDefaultFont( FontTrueType::New( - "NotoSans-Regular", resPath + "assets/fonts/NotoSans-Regular.ttf" ) ); - - Font* fontMono = - FontTrueType::New( "monospace", resPath + "assets/fonts/DejaVuSansMono.ttf" ); - - SceneManager::instance()->add( uiSceneNode ); - - StyleSheetParser cssParser; - if ( cssParser.loadFromFile( resPath + "assets/ui/breeze.css" ) ) { - uiSceneNode->setStyleSheet( cssParser.getStyleSheet() ); - } - - std::string layout = R"xml( - - - - )xml"; - uiSceneNode->loadLayoutFromString( layout ); - - uiSceneNode->bind( "code_edit", codeEditor ); - uiSceneNode->getRoot()->addClass( "appbackground" ); - codeEditor->setFontSize( 11 ); - codeEditor->getDocument().setCommand( "find", []() { findTextMessageBox(); } ); - codeEditor->getDocument().setCommand( "repeat-find", []() { findText(); } ); - codeEditor->getDocument().setCommand( "close-app", []() { closeApp(); } ); - codeEditor->getDocument().setCommand( "fullscreen-toggle", - []() { win->toggleFullscreen(); } ); - codeEditor->getDocument().setCommand( "open-file", [] { openFileDialog(); } ); - codeEditor->getDocument().setCommand( "console-toggle", [] { console->toggle(); } ); - codeEditor->addKeyBindingString( "ctrl+s", "save", false ); - codeEditor->addKeyBindingString( "ctrl+f", "find", false ); - codeEditor->addKeyBindingString( "f3", "repeat-find", false ); - codeEditor->addKeyBindingString( "escape", "close-app", true ); - codeEditor->addKeyBindingString( "ctrl+q", "close-app", true ); - codeEditor->addKeyBindingString( "alt+return", "fullscreen-toggle", true ); - codeEditor->addKeyBindingString( "ctrl+o", "open-file", true ); - codeEditor->addKeyBindingString( "f2", "open-file", true ); - codeEditor->addKeyBindingString( "ctrl+l", "lock-toggle", true ); - codeEditor->addKeyBinding( {win->getInput()->getKeyFromScancode( SCANCODE_GRAVE ), 0}, - "console-toggle", true ); - - codeEditor->setFocus(); - - if ( file ) { - loadFileFromPath( file.Get() ); - } - - console = eeNew( Console, ( fontMono, true, true, 1024 * 1000, 0, win ) ); - - win->runMainLoop( &mainLoop ); - } - - eeSAFE_DELETE( console ); + appInstance = eeNew( App, () ); + appInstance->init( file.Get() ); + eeSAFE_DELETE( appInstance ); Engine::destroySingleton(); MemoryManager::showResults(); diff --git a/src/tools/codeeditor/codeeditor.hpp b/src/tools/codeeditor/codeeditor.hpp new file mode 100644 index 000000000..2cef4af71 --- /dev/null +++ b/src/tools/codeeditor/codeeditor.hpp @@ -0,0 +1,52 @@ +#ifndef EE_TOOLS_CODEEDITOR_HPP +#define EE_TOOLS_CODEEDITOR_HPP + +#include + +class App { + public: + ~App(); + + void init( const std::string& file = "" ); + + void loadFileFromPath( const std::string& path, UICodeEditor* codeEditor = NULL ); + + void setAppTitle( const std::string& title ); + + void openFileDialog(); + + void findText( String text = "" ); + + void closeApp(); + + void mainLoop(); + + void findTextMessageBox(); + + bool onCloseRequestCallback( EE::Window::Window* ); + + UICodeEditor* createCodeEditor(); + + UISplitter* createEditorSplitter( Node* parent ); + + UITabWidget* tabWidgetFromEditor( UICodeEditor* editor ); + + std::pair createCodeEditorInTabWidget( UITabWidget* tabWidget ); + + UITabWidget* createEditorWithTabWidget( UISplitter* splitter ); + + void splitEditor( const UIOrientation& orientation ); + + protected: + EE::Window::Window* mWindow = NULL; + UISceneNode* mUISceneNode = NULL; + UICodeEditor* mCurEditor = NULL; + Console* mConsole = NULL; + std::string mWindowTitle = "eepp - Code Editor"; + bool mDocDirtyState = false; + UIMessageBox* mMsgBox = NULL; + String mLastSearch; + UILayout* mBaseLayout; +}; + +#endif // EE_TOOLS_CODEEDITOR_HPP