Merge branch 'develop' into debugger

This commit is contained in:
Martín Lucas Golini
2024-12-29 23:50:46 -03:00
14 changed files with 252 additions and 51 deletions
+1 -1
View File
@@ -574,7 +574,7 @@ class EE_API Node : public Transformable {
void childRemove( Node* node ); void childRemove( Node* node );
Rectf getScreenBounds(); Rectf getScreenBounds() const;
void setInternalPosition( const Vector2f& Pos ); void setInternalPosition( const Vector2f& Pos );
+10
View File
@@ -0,0 +1,10 @@
#ifndef EE_UI_SPLIT_DIRECTION_HPP
#define EE_UI_SPLIT_DIRECTION_HPP
namespace EE { namespace UI {
enum class SplitDirection { Left, Right, Top, Bottom };
}} // namespace EE::UI
#endif // EE_UI_SPLIT_DIRECTION_HPP
+15 -2
View File
@@ -1,6 +1,7 @@
#ifndef EE_UI_TOOLS_UICODEEDITORSPLITTER_HPP #ifndef EE_UI_TOOLS_UICODEEDITORSPLITTER_HPP
#define EE_UI_TOOLS_UICODEEDITORSPLITTER_HPP #define EE_UI_TOOLS_UICODEEDITORSPLITTER_HPP
#include <eepp/ui/splitdirection.hpp>
#include <eepp/ui/uicodeeditor.hpp> #include <eepp/ui/uicodeeditor.hpp>
#include <eepp/ui/uimessagebox.hpp> #include <eepp/ui/uimessagebox.hpp>
#include <eepp/ui/uiscenenode.hpp> #include <eepp/ui/uiscenenode.hpp>
@@ -19,8 +20,6 @@ class EE_API UICodeEditorSplitter {
static const std::map<KeyBindings::Shortcut, std::string> getLocalDefaultKeybindings(); static const std::map<KeyBindings::Shortcut, std::string> getLocalDefaultKeybindings();
enum class SplitDirection { Left, Right, Top, Bottom };
class EE_API Client { class EE_API Client {
public: public:
virtual ~Client() {}; virtual ~Client() {};
@@ -355,6 +354,12 @@ class EE_API UICodeEditorSplitter {
void setOnTabWidgetCreateCb( std::function<void( UITabWidget* )> cb ); void setOnTabWidgetCreateCb( std::function<void( UITabWidget* )> cb );
bool getVisualSplitting() const;
void setVisualSplitting( bool visualSplitting );
Float getVisualSplitEdgePercent() const;
void setVisualSplitEdgePercent( Float visualSplitEdgePercent );
protected: protected:
UISceneNode* mUISceneNode{ nullptr }; UISceneNode* mUISceneNode{ nullptr };
std::shared_ptr<ThreadPool> mThreadPool; std::shared_ptr<ThreadPool> mThreadPool;
@@ -367,6 +372,7 @@ class EE_API UICodeEditorSplitter {
Client* mClient; Client* mClient;
bool mHideTabBarOnSingleTab{ true }; bool mHideTabBarOnSingleTab{ true };
bool mFirstCodeEditor{ true }; bool mFirstCodeEditor{ true };
bool mVisualSplitting{ true };
UICodeEditor* mAboutToAddEditor{ nullptr }; UICodeEditor* mAboutToAddEditor{ nullptr };
UIMessageBox* mTryCloseMsgBox{ nullptr }; UIMessageBox* mTryCloseMsgBox{ nullptr };
Mutex mTabWidgetMutex; Mutex mTabWidgetMutex;
@@ -378,6 +384,7 @@ class EE_API UICodeEditorSplitter {
std::vector<NavigationRecord> mNavigationHistory; std::vector<NavigationRecord> mNavigationHistory;
size_t mNavigationHistoryPos{ std::numeric_limits<size_t>::max() }; size_t mNavigationHistoryPos{ std::numeric_limits<size_t>::max() };
std::function<void( UITabWidget* )> mOnTabWidgetCreateCb; std::function<void( UITabWidget* )> mOnTabWidgetCreateCb;
Float mVisualSplitEdgePercent{ 0.1 };
UICodeEditorSplitter( UICodeEditorSplitter::Client* client, UISceneNode* sceneNode, UICodeEditorSplitter( UICodeEditorSplitter::Client* client, UISceneNode* sceneNode,
std::shared_ptr<ThreadPool> threadPool, std::shared_ptr<ThreadPool> threadPool,
@@ -387,6 +394,12 @@ class EE_API UICodeEditorSplitter {
virtual void onTabClosed( const TabEvent* tabEvent ); virtual void onTabClosed( const TabEvent* tabEvent );
void closeAllTabs( std::vector<UITab*> tabs, UITabWidget::FocusTabBehavior focusTabBehavior ); void closeAllTabs( std::vector<UITab*> tabs, UITabWidget::FocusTabBehavior focusTabBehavior );
UITabWidget* createTabWidget( Node* parent );
UITabWidget* splitTabWidget( SplitDirection, UITabWidget* );
void updateTabWidgetVisualSplitting();
}; };
}}} // namespace EE::UI::Tools }}} // namespace EE::UI::Tools
+2
View File
@@ -428,6 +428,8 @@ class EE_API UINode : public Node {
void smartClipStart( const ClipType& reqClipType ); void smartClipStart( const ClipType& reqClipType );
void smartClipEnd( const ClipType& reqClipType ); void smartClipEnd( const ClipType& reqClipType );
Color getDroppableHoveringColor();
}; };
}} // namespace EE::UI }} // namespace EE::UI
+13 -1
View File
@@ -2,8 +2,10 @@
#define EE_UI_UITABWIDGET_HPP #define EE_UI_UITABWIDGET_HPP
#include <deque> #include <deque>
#include <eepp/ui/splitdirection.hpp>
#include <eepp/ui/uitab.hpp> #include <eepp/ui/uitab.hpp>
#include <eepp/ui/uiwidget.hpp> #include <eepp/ui/uiwidget.hpp>
#include <optional>
namespace EE { namespace UI { namespace EE { namespace UI {
@@ -26,6 +28,8 @@ class EE_API TabEvent : public Event {
class EE_API UITabWidget : public UIWidget { class EE_API UITabWidget : public UIWidget {
public: public:
using SplitFunctionCb = std::function<UITabWidget*( SplitDirection, UITabWidget* )>;
enum class FocusTabBehavior { Closest, FocusOrder, Default }; enum class FocusTabBehavior { Closest, FocusOrder, Default };
class StyleConfig { class StyleConfig {
@@ -157,7 +161,7 @@ class EE_API UITabWidget : public UIWidget {
void setAllowRearrangeTabs( bool allowRearrangeTabs ); void setAllowRearrangeTabs( bool allowRearrangeTabs );
bool getAllowDragAndDropTabs() const; bool allowDragAndDropTabs() const;
void setAllowDragAndDropTabs( bool allowDragAndDropTabs ); void setAllowDragAndDropTabs( bool allowDragAndDropTabs );
@@ -187,6 +191,8 @@ class EE_API UITabWidget : public UIWidget {
void swapTabs( UITab* left, UITab* right ); void swapTabs( UITab* left, UITab* right );
void setSplitFunction( SplitFunctionCb cb, Float splitEdgePercent = 0.1 );
protected: protected:
friend class UITab; friend class UITab;
@@ -209,6 +215,8 @@ class EE_API UITabWidget : public UIWidget {
FocusTabBehavior mFocusTabBehavior{ FocusTabBehavior::Closest }; FocusTabBehavior mFocusTabBehavior{ FocusTabBehavior::Closest };
std::deque<UITab*> mFocusHistory; std::deque<UITab*> mFocusHistory;
UIPopUpMenu* mCurrentMenu{ nullptr }; UIPopUpMenu* mCurrentMenu{ nullptr };
SplitFunctionCb mSplitFn;
Float mSplitEdgePercent{ 0.1 };
void onThemeLoaded(); void onThemeLoaded();
@@ -229,6 +237,8 @@ class EE_API UITabWidget : public UIWidget {
virtual Uint32 onMessage( const NodeMessage* msg ); virtual Uint32 onMessage( const NodeMessage* msg );
virtual void drawDroppableHovering();
void setContainerSize(); void setContainerSize();
void posTabs(); void posTabs();
@@ -254,6 +264,8 @@ class EE_API UITabWidget : public UIWidget {
void insertFocusHistory( UITab* tab ); void insertFocusHistory( UITab* tab );
void eraseFocusHistory( UITab* tab ); void eraseFocusHistory( UITab* tab );
std::optional<SplitDirection> getDropDirection() const;
}; };
}} // namespace EE::UI }} // namespace EE::UI
+1
View File
@@ -360,6 +360,7 @@
../../include/eepp/ui/models/persistentmodelindex.hpp ../../include/eepp/ui/models/persistentmodelindex.hpp
../../include/eepp/ui/models/sortingproxymodel.hpp ../../include/eepp/ui/models/sortingproxymodel.hpp
../../include/eepp/ui/models/widgettreemodel.hpp ../../include/eepp/ui/models/widgettreemodel.hpp
../../include/eepp/ui/splitdirection.hpp
../../include/eepp/ui/tools/textureatlaseditor.hpp ../../include/eepp/ui/tools/textureatlaseditor.hpp
../../include/eepp/ui/tools/uicodeeditorsplitter.hpp ../../include/eepp/ui/tools/uicodeeditorsplitter.hpp
../../include/eepp/ui/tools/uicolorpicker.hpp ../../include/eepp/ui/tools/uicolorpicker.hpp
+1 -1
View File
@@ -510,7 +510,7 @@ void Node::onSizeChange() {
invalidateDraw(); invalidateDraw();
} }
Rectf Node::getScreenBounds() { Rectf Node::getScreenBounds() const {
return Rectf( Vector2f( mScreenPosi.x, mScreenPosi.y ), return Rectf( Vector2f( mScreenPosi.x, mScreenPosi.y ),
Sizef( (Float)(int)mSize.getWidth(), (Float)(int)mSize.getHeight() ) ); Sizef( (Float)(int)mSize.getWidth(), (Float)(int)mSize.getHeight() ) );
} }
+100 -7
View File
@@ -626,11 +626,7 @@ void UICodeEditorSplitter::removeUnusedTab( UITabWidget* tabWidget, bool destroy
} }
} }
UITabWidget* UICodeEditorSplitter::createEditorWithTabWidget( Node* parent, bool openCurEditor ) { UITabWidget* UICodeEditorSplitter::createTabWidget( Node* parent ) {
eeASSERT( curWidgetExists() );
if ( nullptr == mBaseLayout )
mBaseLayout = parent;
UICodeEditor* prevCurEditor = mCurEditor;
UITabWidget* tabWidget = UITabWidget::New(); UITabWidget* tabWidget = UITabWidget::New();
tabWidget->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); tabWidget->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
tabWidget->setParent( parent ); tabWidget->setParent( parent );
@@ -641,6 +637,13 @@ UITabWidget* UICodeEditorSplitter::createEditorWithTabWidget( Node* parent, bool
tabWidget->setAllowSwitchTabsInEmptySpaces( true ); tabWidget->setAllowSwitchTabsInEmptySpaces( true );
tabWidget->setEnabledCreateContextMenu( true ); tabWidget->setEnabledCreateContextMenu( true );
tabWidget->setFocusTabBehavior( UITabWidget::FocusTabBehavior::FocusOrder ); tabWidget->setFocusTabBehavior( UITabWidget::FocusTabBehavior::FocusOrder );
if ( mVisualSplitting ) {
tabWidget->setSplitFunction(
[this]( SplitDirection dir, UITabWidget* widget ) -> UITabWidget* {
return splitTabWidget( dir, widget );
},
mVisualSplitEdgePercent );
}
tabWidget->addEventListener( Event::OnTabSelected, [this]( const Event* event ) { tabWidget->addEventListener( Event::OnTabSelected, [this]( const Event* event ) {
UITabWidget* tabWidget = event->getNode()->asType<UITabWidget>(); UITabWidget* tabWidget = event->getNode()->asType<UITabWidget>();
if ( tabWidget->getTabSelected()->getOwnedWidget()->isType( UI_TYPE_CODEEDITOR ) ) { if ( tabWidget->getTabSelected()->getOwnedWidget()->isType( UI_TYPE_CODEEDITOR ) ) {
@@ -663,6 +666,17 @@ UITabWidget* UICodeEditorSplitter::createEditorWithTabWidget( Node* parent, bool
} ); } );
if ( mOnTabWidgetCreateCb ) if ( mOnTabWidgetCreateCb )
mOnTabWidgetCreateCb( tabWidget ); mOnTabWidgetCreateCb( tabWidget );
Lock l( mTabWidgetMutex );
mTabWidgets.push_back( tabWidget );
return tabWidget;
}
UITabWidget* UICodeEditorSplitter::createEditorWithTabWidget( Node* parent, bool openCurEditor ) {
eeASSERT( curWidgetExists() );
if ( nullptr == mBaseLayout )
mBaseLayout = parent;
UICodeEditor* prevCurEditor = mCurEditor;
UITabWidget* tabWidget = createTabWidget( parent );
auto editorData = createCodeEditorInTabWidget( tabWidget ); auto editorData = createCodeEditorInTabWidget( tabWidget );
if ( editorData.first == nullptr || editorData.second == nullptr ) { if ( editorData.first == nullptr || editorData.second == nullptr ) {
if ( !mTabWidgets.empty() && mTabWidgets[0]->getTabCount() > 0 ) { if ( !mTabWidgets.empty() && mTabWidgets[0]->getTabCount() > 0 ) {
@@ -684,8 +698,6 @@ UITabWidget* UICodeEditorSplitter::createEditorWithTabWidget( Node* parent, bool
editorData.first->setTooltipText( path ); editorData.first->setTooltipText( path );
} }
mAboutToAddEditor = nullptr; mAboutToAddEditor = nullptr;
Lock l( mTabWidgetMutex );
mTabWidgets.push_back( tabWidget );
return tabWidget; return tabWidget;
} }
@@ -1205,6 +1217,51 @@ UISplitter* UICodeEditorSplitter::split( const SplitDirection& direction, UIWidg
return splitter; return splitter;
} }
UITabWidget* UICodeEditorSplitter::splitTabWidget( SplitDirection direction,
UITabWidget* tabWidget ) {
if ( !tabWidget )
return nullptr;
UIOrientation orientation =
direction == SplitDirection::Left || direction == SplitDirection::Right
? UIOrientation::Horizontal
: UIOrientation::Vertical;
Node* parent = tabWidget->getParent();
UISplitter* parentSplitter = nullptr;
bool wasFirst = true;
if ( parent->isType( UI_TYPE_SPLITTER ) ) {
parentSplitter = parent->asType<UISplitter>();
wasFirst = parentSplitter->getFirstWidget() == tabWidget;
if ( !parentSplitter->isFull() ) {
parentSplitter->setOrientation( orientation );
UITabWidget* newTabWidget = createTabWidget( parentSplitter );
if ( direction == SplitDirection::Left || direction == SplitDirection::Top )
parentSplitter->swap();
return newTabWidget;
}
}
UISplitter* splitter = UISplitter::New();
splitter->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
splitter->setOrientation( orientation );
tabWidget->detach();
splitter->setParent( parent );
tabWidget->setParent( splitter );
UITabWidget* newTabWidget = createTabWidget( splitter );
if ( direction == SplitDirection::Left || direction == SplitDirection::Top )
splitter->swap();
if ( parentSplitter ) {
if ( wasFirst && parentSplitter->getFirstWidget() != splitter ) {
parentSplitter->swap();
} else if ( !wasFirst && parentSplitter->getLastWidget() != splitter ) {
parentSplitter->swap();
}
}
return newTabWidget;
}
void UICodeEditorSplitter::switchToTab( Int32 index ) { void UICodeEditorSplitter::switchToTab( Int32 index ) {
UITabWidget* tabWidget = tabWidgetFromWidget( mCurWidget ); UITabWidget* tabWidget = tabWidgetFromWidget( mCurWidget );
if ( tabWidget ) { if ( tabWidget ) {
@@ -1665,4 +1722,40 @@ void UICodeEditorSplitter::setOnTabWidgetCreateCb( std::function<void( UITabWidg
mOnTabWidgetCreateCb = std::move( cb ); mOnTabWidgetCreateCb = std::move( cb );
} }
bool UICodeEditorSplitter::getVisualSplitting() const {
return mVisualSplitting;
}
void UICodeEditorSplitter::setVisualSplitting( bool visualSplitting ) {
if ( mVisualSplitting != visualSplitting ) {
mVisualSplitting = visualSplitting;
updateTabWidgetVisualSplitting();
}
}
Float UICodeEditorSplitter::getVisualSplitEdgePercent() const {
return mVisualSplitEdgePercent;
}
void UICodeEditorSplitter::setVisualSplitEdgePercent( Float visualSplitEdgePercent ) {
if ( mVisualSplitEdgePercent != visualSplitEdgePercent ) {
mVisualSplitEdgePercent = visualSplitEdgePercent;
updateTabWidgetVisualSplitting();
}
}
void UICodeEditorSplitter::updateTabWidgetVisualSplitting() {
for ( UITabWidget* tabWidget : mTabWidgets ) {
if ( mVisualSplitting ) {
tabWidget->setSplitFunction(
[this]( SplitDirection dir, UITabWidget* widget ) -> UITabWidget* {
return splitTabWidget( dir, widget );
},
mVisualSplitEdgePercent );
} else {
tabWidget->setSplitFunction( nullptr, mVisualSplitEdgePercent );
}
}
}
}}} // namespace EE::UI::Tools }}} // namespace EE::UI::Tools
+19 -16
View File
@@ -567,25 +567,10 @@ void UINode::drawOverNode() {
} }
void UINode::drawDroppableHovering() { void UINode::drawDroppableHovering() {
const PropertyDefinition* def =
StyleSheetSpecification::instance()->getProperty( "droppable-hovering-color" );
Color color = Color::fromString( def->getDefaultValue() );
if ( isWidget() ) {
UIWidget* widget = asType<UIWidget>();
std::string colorString = widget->getPropertyString( def );
if ( !colorString.empty() ) {
color = Color::fromString( colorString );
} else {
colorString = mUISceneNode->getRoot()->getPropertyString( def );
if ( !colorString.empty() )
color = Color::fromString( colorString );
}
}
Primitives P; Primitives P;
P.setFillMode( DRAW_FILL ); P.setFillMode( DRAW_FILL );
P.setBlendMode( getBlendMode() ); P.setBlendMode( getBlendMode() );
P.setColor( color ); P.setColor( getDroppableHoveringColor() );
P.setLineWidth( PixelDensity::dpToPxI( 1 ) ); P.setLineWidth( PixelDensity::dpToPxI( 1 ) );
P.drawRectangle( getScreenBounds() ); P.drawRectangle( getScreenBounds() );
} }
@@ -1053,6 +1038,24 @@ void UINode::smartClipEnd( const ClipType& reqClipType ) {
smartClipEnd( reqClipType, isMeOrParentTreeScaledOrRotatedOrFrameBuffer() ); smartClipEnd( reqClipType, isMeOrParentTreeScaledOrRotatedOrFrameBuffer() );
} }
Color UINode::getDroppableHoveringColor() {
const PropertyDefinition* def =
StyleSheetSpecification::instance()->getProperty( "droppable-hovering-color" );
Color color = Color::fromString( def->getDefaultValue() );
if ( isWidget() ) {
UIWidget* widget = asType<UIWidget>();
std::string colorString = widget->getPropertyString( def );
if ( !colorString.empty() ) {
color = Color::fromString( colorString );
} else {
colorString = mUISceneNode->getRoot()->getPropertyString( def );
if ( !colorString.empty() )
color = Color::fromString( colorString );
}
}
return color;
}
void UINode::nodeDraw() { void UINode::nodeDraw() {
if ( mVisible ) { if ( mVisible ) {
if ( mNodeFlags & NODE_FLAG_POSITION_DIRTY ) if ( mNodeFlags & NODE_FLAG_POSITION_DIRTY )
+3 -3
View File
@@ -76,7 +76,7 @@ Uint32 UITab::onDrag( const Vector2f& pos, const Uint32&, const Sizef& dragDiff
tabW->swapTabs( tab, this ); tabW->swapTabs( tab, this );
} }
if ( tabW->getAllowDragAndDropTabs() && !( mFlags & UI_DRAG_VERTICAL ) ) { if ( tabW->allowDragAndDropTabs() && !( mFlags & UI_DRAG_VERTICAL ) ) {
mDragTotalDiff += mDragPoint.y - pos.y; mDragTotalDiff += mDragPoint.y - pos.y;
if ( eeabs( mDragTotalDiff ) >= tabW->getTabVerticalDragResistance() ) { if ( eeabs( mDragTotalDiff ) >= tabW->getTabVerticalDragResistance() ) {
setFlags( UI_DRAG_VERTICAL ); setFlags( UI_DRAG_VERTICAL );
@@ -90,7 +90,7 @@ Uint32 UITab::onDrag( const Vector2f& pos, const Uint32&, const Sizef& dragDiff
} }
} }
if ( tabW->getAllowDragAndDropTabs() ) { if ( tabW->allowDragAndDropTabs() ) {
setEnabled( false ); setEnabled( false );
Node* overFind = getUISceneNode()->overFind( pos ); Node* overFind = getUISceneNode()->overFind( pos );
setEnabled( true ); setEnabled( true );
@@ -435,7 +435,7 @@ void UITab::updateTab() {
} else { } else {
UIPushButton::setText( mText ); UIPushButton::setText( mText );
} }
setDragEnabled( tTabW->getAllowRearrangeTabs() || tTabW->getAllowDragAndDropTabs() ); setDragEnabled( tTabW->getAllowRearrangeTabs() || tTabW->allowDragAndDropTabs() );
onAutoSize(); onAutoSize();
} }
} }
+80 -6
View File
@@ -174,7 +174,7 @@ std::string UITabWidget::getPropertyString( const PropertyDefinition* propertyDe
case PropertyId::TabBarAllowRearrange: case PropertyId::TabBarAllowRearrange:
return getAllowRearrangeTabs() ? "true" : "false"; return getAllowRearrangeTabs() ? "true" : "false";
case PropertyId::TabBarAllowDragAndDrop: case PropertyId::TabBarAllowDragAndDrop:
return getAllowDragAndDropTabs() ? "true" : "false"; return allowDragAndDropTabs() ? "true" : "false";
case PropertyId::TabAllowSwitchTabsInEmptySpaces: case PropertyId::TabAllowSwitchTabsInEmptySpaces:
return getAllowSwitchTabsInEmptySpaces() ? "true" : "false"; return getAllowSwitchTabsInEmptySpaces() ? "true" : "false";
case PropertyId::TabCloseButtonVisible: case PropertyId::TabCloseButtonVisible:
@@ -833,7 +833,7 @@ void UITabWidget::setAllowRearrangeTabs( bool allowRearrangeTabs ) {
} }
} }
bool UITabWidget::getAllowDragAndDropTabs() const { bool UITabWidget::allowDragAndDropTabs() const {
return mAllowDragAndDropTabs; return mAllowDragAndDropTabs;
} }
@@ -859,7 +859,8 @@ void UITabWidget::setAllowSwitchTabsInEmptySpaces( bool allowSwitchTabsInEmptySp
bool UITabWidget::acceptsDropOfWidget( const UIWidget* widget ) { bool UITabWidget::acceptsDropOfWidget( const UIWidget* widget ) {
return mAllowDragAndDropTabs && widget && UI_TYPE_TAB == widget->getType() && return mAllowDragAndDropTabs && widget && UI_TYPE_TAB == widget->getType() &&
!isParentOf( widget ) && widget->asConstType<UITab>()->getTabWidget() != this; !isParentOf( widget ) &&
( mSplitFn || widget->asConstType<UITab>()->getTabWidget() != this );
} }
const Color& UITabWidget::getDroppableHoveringColor() const { const Color& UITabWidget::getDroppableHoveringColor() const {
@@ -933,6 +934,11 @@ void UITabWidget::swapTabs( UITab* left, UITab* right ) {
} }
} }
void UITabWidget::setSplitFunction( SplitFunctionCb cb, Float splitEdgePercent ) {
mSplitFn = std::move( cb );
mSplitEdgePercent = splitEdgePercent;
}
void UITabWidget::selectPreviousTab() { void UITabWidget::selectPreviousTab() {
if ( eeINDEX_NOT_FOUND != mTabSelectedIndex && mTabSelectedIndex > 0 ) { if ( eeINDEX_NOT_FOUND != mTabSelectedIndex && mTabSelectedIndex > 0 ) {
setTabSelected( getTab( mTabSelectedIndex - 1 ) ); setTabSelected( getTab( mTabSelectedIndex - 1 ) );
@@ -1009,10 +1015,19 @@ Uint32 UITabWidget::onMessage( const NodeMessage* msg ) {
const NodeDropMessage* dropMsg = static_cast<const NodeDropMessage*>( msg ); const NodeDropMessage* dropMsg = static_cast<const NodeDropMessage*>( msg );
if ( dropMsg->getDroppedNode()->isType( UI_TYPE_TAB ) ) { if ( dropMsg->getDroppedNode()->isType( UI_TYPE_TAB ) ) {
UITab* tab = dropMsg->getDroppedNode()->asType<UITab>(); UITab* tab = dropMsg->getDroppedNode()->asType<UITab>();
if ( tab->getTabWidget() != this && tab->getTabWidget()->getAllowDragAndDropTabs() ) { auto dir = getDropDirection();
if ( !mSplitFn || !dir ) {
if ( tab->getTabWidget() != this && tab->getTabWidget()->allowDragAndDropTabs() ) {
tab->getTabWidget()->removeTab( tab, false, false, false );
add( tab );
setTabSelected( tab );
return 1;
}
} else if ( dir && tab->getTabWidget()->allowDragAndDropTabs() ) {
tab->getTabWidget()->removeTab( tab, false, false, false ); tab->getTabWidget()->removeTab( tab, false, false, false );
add( tab ); auto tabWidget = mSplitFn( *dir, this );
setTabSelected( tab ); tabWidget->add( tab );
tabWidget->setTabSelected( tab );
return 1; return 1;
} }
} }
@@ -1030,6 +1045,65 @@ Uint32 UITabWidget::onMessage( const NodeMessage* msg ) {
return 0; return 0;
} }
std::optional<SplitDirection> UITabWidget::getDropDirection() const {
Vector2f mousePos( getEventDispatcher()->getMousePosf() );
mousePos = convertToNodeSpace( mousePos );
if ( mTabBar->isVisible() && mousePos.y <= mTabBar->getPixelsSize().y )
return {};
if ( mousePos.y <= mSize.y * mSplitEdgePercent ) {
return SplitDirection::Top;
} else if ( mousePos.y >= mSize.y - mSize.y * mSplitEdgePercent ) {
return SplitDirection::Bottom;
} else if ( mousePos.x <= mSize.x * mSplitEdgePercent ) {
return SplitDirection::Left;
} else if ( mousePos.x >= mSize.x - mSize.x * mSplitEdgePercent ) {
return SplitDirection::Right;
}
return {};
}
void UITabWidget::drawDroppableHovering() {
if ( mSplitFn ) {
auto dir = getDropDirection();
auto rect( getScreenBounds() );
if ( mTabBar->isVisible() )
rect.Top += mTabBar->getPixelsSize().getHeight();
if ( dir ) {
constexpr auto splitSize = 0.5f;
switch ( *dir ) {
case SplitDirection::Top:
rect.Bottom = rect.Top + mSize.y * splitSize;
break;
case SplitDirection::Bottom:
rect.Top = rect.Bottom - mSize.y * splitSize;
break;
case SplitDirection::Left:
rect.Right = rect.Left + mSize.x * splitSize;
break;
case SplitDirection::Right:
rect.Left = rect.Right - mSize.x * splitSize;
break;
}
} else if ( std::any_of( mTabs.begin(), mTabs.end(),
[]( const UITab* tab ) { return tab->isDragging(); } ) ) {
return;
}
Primitives P;
P.setFillMode( DRAW_FILL );
P.setBlendMode( getBlendMode() );
P.setColor( UINode::getDroppableHoveringColor() );
P.setLineWidth( PixelDensity::dpToPxI( 1 ) );
P.drawRectangle( rect );
} else {
UIWidget::drawDroppableHovering();
}
}
void UITabWidget::applyThemeToTabs() { void UITabWidget::applyThemeToTabs() {
if ( mStyleConfig.TabsEdgesDiffSkins ) { if ( mStyleConfig.TabsEdgesDiffSkins ) {
for ( Uint32 i = 0; i < mTabs.size(); i++ ) { for ( Uint32 i = 0; i < mTabs.size(); i++ ) {
+1 -2
View File
@@ -651,8 +651,7 @@ void AppConfig::loadDocuments( UICodeEditorSplitter* editorSplitter, json j,
} }
} else if ( j["type"] == "splitter" ) { } else if ( j["type"] == "splitter" ) {
UISplitter* splitter = editorSplitter->split( UISplitter* splitter = editorSplitter->split(
j["orientation"] == "horizontal" ? UICodeEditorSplitter::SplitDirection::Right j["orientation"] == "horizontal" ? SplitDirection::Right : SplitDirection::Bottom,
: UICodeEditorSplitter::SplitDirection::Bottom,
curTabWidget->getTabSelected()->getOwnedWidget()->asType<UICodeEditor>(), false ); curTabWidget->getTabSelected()->getOwnedWidget()->asType<UICodeEditor>(), false );
if ( nullptr == splitter ) if ( nullptr == splitter )
+4 -8
View File
@@ -201,26 +201,22 @@ class App : public UICodeEditorSplitter::Client {
[this] { mTerminalManager->createTerminalInSplitter(); } ); [this] { mTerminalManager->createTerminalInSplitter(); } );
t.setCommand( "terminal-split-right", [this] { t.setCommand( "terminal-split-right", [this] {
auto cwd = getCurrentWorkingDir(); auto cwd = getCurrentWorkingDir();
mSplitter->split( UICodeEditorSplitter::SplitDirection::Right, mSplitter->split( SplitDirection::Right, mSplitter->getCurWidget(), false );
mSplitter->getCurWidget(), false );
mTerminalManager->createNewTerminal( "", nullptr, cwd ); mTerminalManager->createNewTerminal( "", nullptr, cwd );
} ); } );
t.setCommand( "terminal-split-bottom", [this] { t.setCommand( "terminal-split-bottom", [this] {
auto cwd = getCurrentWorkingDir(); auto cwd = getCurrentWorkingDir();
mSplitter->split( UICodeEditorSplitter::SplitDirection::Bottom, mSplitter->split( SplitDirection::Bottom, mSplitter->getCurWidget(), false );
mSplitter->getCurWidget(), false );
mTerminalManager->createNewTerminal( "", nullptr, cwd ); mTerminalManager->createNewTerminal( "", nullptr, cwd );
} ); } );
t.setCommand( "terminal-split-left", [this] { t.setCommand( "terminal-split-left", [this] {
auto cwd = getCurrentWorkingDir(); auto cwd = getCurrentWorkingDir();
mSplitter->split( UICodeEditorSplitter::SplitDirection::Left, mSplitter->getCurWidget(), mSplitter->split( SplitDirection::Left, mSplitter->getCurWidget(), false );
false );
mTerminalManager->createNewTerminal( "", nullptr, cwd ); mTerminalManager->createNewTerminal( "", nullptr, cwd );
} ); } );
t.setCommand( "terminal-split-top", [this] { t.setCommand( "terminal-split-top", [this] {
auto cwd = getCurrentWorkingDir(); auto cwd = getCurrentWorkingDir();
mSplitter->split( UICodeEditorSplitter::SplitDirection::Top, mSplitter->getCurWidget(), mSplitter->split( SplitDirection::Top, mSplitter->getCurWidget(), false );
false );
mTerminalManager->createNewTerminal( "", nullptr, cwd ); mTerminalManager->createNewTerminal( "", nullptr, cwd );
} ); } );
t.setCommand( "reopen-closed-tab", [this] { reopenClosedTab(); } ); t.setCommand( "reopen-closed-tab", [this] { reopenClosedTab(); } );
+2 -4
View File
@@ -42,15 +42,13 @@ UITerminal* TerminalManager::createTerminalInSplitter( const std::string& workin
switch ( config.term.newTerminalOrientation ) { switch ( config.term.newTerminalOrientation ) {
case NewTerminalOrientation::Vertical: { case NewTerminalOrientation::Vertical: {
auto cwd = workingDir.empty() ? mApp->getCurrentWorkingDir() : workingDir; auto cwd = workingDir.empty() ? mApp->getCurrentWorkingDir() : workingDir;
splitter->split( UICodeEditorSplitter::SplitDirection::Right, splitter->split( SplitDirection::Right, splitter->getCurWidget(), false );
splitter->getCurWidget(), false );
term = createNewTerminal( "", nullptr, cwd, "", {}, fallback ); term = createNewTerminal( "", nullptr, cwd, "", {}, fallback );
break; break;
} }
case NewTerminalOrientation::Horizontal: { case NewTerminalOrientation::Horizontal: {
auto cwd = workingDir.empty() ? mApp->getCurrentWorkingDir() : workingDir; auto cwd = workingDir.empty() ? mApp->getCurrentWorkingDir() : workingDir;
splitter->split( UICodeEditorSplitter::SplitDirection::Bottom, splitter->split( SplitDirection::Bottom, splitter->getCurWidget(), false );
splitter->getCurWidget(), false );
term = createNewTerminal( "", nullptr, cwd, "", {}, fallback ); term = createNewTerminal( "", nullptr, cwd, "", {}, fallback );
break; break;
} }