mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-02 11:10:31 +03:00
Added support for Tab jump modes (SpartanJ/ecode#469). Including a Tab Switcher (I have no better name for the moment).
Added support to hide the Tab Bar (SpartanJ/ecode#477). Updated efsw. Updated JS, TS, C++ grammars.
This commit is contained in:
@@ -209,8 +209,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"max_tokens": 128000,
|
"max_tokens": 128000,
|
||||||
"name": "gpt-4o-mini",
|
"name": "gpt-4o-mini"
|
||||||
"cheapest": true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"max_tokens": 200000,
|
"max_tokens": 200000,
|
||||||
@@ -229,7 +228,8 @@
|
|||||||
"name": "o3-mini"
|
"name": "o3-mini"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gpt-4.1-nano"
|
"name": "gpt-4.1-nano",
|
||||||
|
"cheapest": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gpt-4.1-mini"
|
"name": "gpt-4.1-mini"
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class EE_API KeyBindings {
|
|||||||
|
|
||||||
void removeKeybind( const Shortcut& keys );
|
void removeKeybind( const Shortcut& keys );
|
||||||
|
|
||||||
void removeKeybind(const std::string& kb );
|
void removeKeybind( const std::string& kb );
|
||||||
|
|
||||||
bool existsKeybind( const Shortcut& keys );
|
bool existsKeybind( const Shortcut& keys );
|
||||||
|
|
||||||
@@ -86,6 +86,8 @@ class EE_API KeyBindings {
|
|||||||
|
|
||||||
const std::map<std::string, Uint64> getKeybindings() const;
|
const std::map<std::string, Uint64> getKeybindings() const;
|
||||||
|
|
||||||
|
Shortcut getShortcutFromCommand( const std::string& cmd ) const;
|
||||||
|
|
||||||
std::string getShortcutString( Shortcut shortcut, bool format = false ) const;
|
std::string getShortcutString( Shortcut shortcut, bool format = false ) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ template <typename T> class ItemListOwnerModel final : public Model {
|
|||||||
return std::make_shared<ItemListOwnerModel<T>>( data );
|
return std::make_shared<ItemListOwnerModel<T>>( data );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit ItemListOwnerModel( std::vector<T>&& data ) : mData( std::move( data ) ) {}
|
||||||
|
|
||||||
explicit ItemListOwnerModel( const std::vector<T>& data ) : mData( data ) {}
|
explicit ItemListOwnerModel( const std::vector<T>& data ) : mData( data ) {}
|
||||||
|
|
||||||
virtual ~ItemListOwnerModel() {}
|
virtual ~ItemListOwnerModel() {}
|
||||||
|
|||||||
@@ -230,6 +230,8 @@ class EE_API UICodeEditorSplitter {
|
|||||||
|
|
||||||
void setHideTabBarOnSingleTab( bool hideTabBarOnSingleTab );
|
void setHideTabBarOnSingleTab( bool hideTabBarOnSingleTab );
|
||||||
|
|
||||||
|
void setHideTabBar( bool hideTabBar );
|
||||||
|
|
||||||
const std::vector<UITabWidget*>& getTabWidgets() const;
|
const std::vector<UITabWidget*>& getTabWidgets() const;
|
||||||
|
|
||||||
Node* getBaseLayout() const;
|
Node* getBaseLayout() const;
|
||||||
@@ -280,21 +282,13 @@ class EE_API UICodeEditorSplitter {
|
|||||||
} );
|
} );
|
||||||
t.setCommand( "next-tab", [this] {
|
t.setCommand( "next-tab", [this] {
|
||||||
UITabWidget* tabWidget = tabWidgetFromWidget( mCurWidget );
|
UITabWidget* tabWidget = tabWidgetFromWidget( mCurWidget );
|
||||||
if ( tabWidget && tabWidget->getTabCount() > 1 ) {
|
if ( tabWidget )
|
||||||
UITab* tab = (UITab*)mCurWidget->getData();
|
tabWidget->focusNextTab();
|
||||||
Uint32 tabIndex = tabWidget->getTabIndex( tab );
|
|
||||||
switchToTab( ( tabIndex + 1 ) % tabWidget->getTabCount() );
|
|
||||||
}
|
|
||||||
} );
|
} );
|
||||||
t.setCommand( "previous-tab", [this] {
|
t.setCommand( "previous-tab", [this] {
|
||||||
UITabWidget* tabWidget = tabWidgetFromWidget( mCurWidget );
|
UITabWidget* tabWidget = tabWidgetFromWidget( mCurWidget );
|
||||||
if ( tabWidget && tabWidget->getTabCount() > 1 ) {
|
if ( tabWidget )
|
||||||
UITab* tab = (UITab*)mCurWidget->getData();
|
tabWidget->focusPreviousTab();
|
||||||
Uint32 tabIndex = tabWidget->getTabIndex( tab );
|
|
||||||
Int32 newTabIndex = (Int32)tabIndex - 1;
|
|
||||||
switchToTab( newTabIndex < 0 ? tabWidget->getTabCount() - newTabIndex
|
|
||||||
: newTabIndex );
|
|
||||||
}
|
|
||||||
} );
|
} );
|
||||||
for ( int i = 1; i <= 10; i++ )
|
for ( int i = 1; i <= 10; i++ )
|
||||||
t.setCommand( String::format( "switch-to-tab-%d", i ),
|
t.setCommand( String::format( "switch-to-tab-%d", i ),
|
||||||
@@ -379,6 +373,7 @@ class EE_API UICodeEditorSplitter {
|
|||||||
std::vector<UITabWidget*> mTabWidgets;
|
std::vector<UITabWidget*> mTabWidgets;
|
||||||
Node* mBaseLayout{ nullptr };
|
Node* mBaseLayout{ nullptr };
|
||||||
Client* mClient;
|
Client* mClient;
|
||||||
|
bool mHideTabBar{ false };
|
||||||
bool mHideTabBarOnSingleTab{ true };
|
bool mHideTabBarOnSingleTab{ true };
|
||||||
bool mFirstCodeEditor{ true };
|
bool mFirstCodeEditor{ true };
|
||||||
bool mVisualSplitting{ true };
|
bool mVisualSplitting{ true };
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace EE { namespace UI {
|
|||||||
|
|
||||||
class UIPopUpMenu;
|
class UIPopUpMenu;
|
||||||
class UIScrollBar;
|
class UIScrollBar;
|
||||||
|
class UIListView;
|
||||||
|
|
||||||
class EE_API TabEvent : public Event {
|
class EE_API TabEvent : public Event {
|
||||||
public:
|
public:
|
||||||
@@ -32,6 +33,17 @@ class EE_API UITabWidget : public UIWidget {
|
|||||||
|
|
||||||
enum class FocusTabBehavior { Closest, FocusOrder, Default };
|
enum class FocusTabBehavior { Closest, FocusOrder, Default };
|
||||||
|
|
||||||
|
enum class TabJumpMode { Linear, Chronological };
|
||||||
|
|
||||||
|
static TabJumpMode tabJumpModefromString( std::string_view mode ) {
|
||||||
|
return String::iequals( mode, "chronological" ) ? TabJumpMode::Chronological
|
||||||
|
: TabJumpMode::Linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string tabJumpModeToString( TabJumpMode mode ) {
|
||||||
|
return mode == TabJumpMode::Chronological ? "chronological" : "linear";
|
||||||
|
}
|
||||||
|
|
||||||
class StyleConfig {
|
class StyleConfig {
|
||||||
public:
|
public:
|
||||||
Float TabSeparation = 0;
|
Float TabSeparation = 0;
|
||||||
@@ -151,10 +163,14 @@ class EE_API UITabWidget : public UIWidget {
|
|||||||
|
|
||||||
UITab* setTabSelected( const Uint32& tabIndex );
|
UITab* setTabSelected( const Uint32& tabIndex );
|
||||||
|
|
||||||
|
const bool& getHideTabBar() const;
|
||||||
|
|
||||||
const bool& getHideTabBarOnSingleTab() const;
|
const bool& getHideTabBarOnSingleTab() const;
|
||||||
|
|
||||||
void setHideTabBarOnSingleTab( const bool& hideTabBarOnSingleTab );
|
void setHideTabBarOnSingleTab( const bool& hideTabBarOnSingleTab );
|
||||||
|
|
||||||
|
void setHideTabBar( const bool& hideTabBar );
|
||||||
|
|
||||||
const TabTryCloseCallback& getTabTryCloseCallback() const;
|
const TabTryCloseCallback& getTabTryCloseCallback() const;
|
||||||
|
|
||||||
void setTabTryCloseCallback( const TabTryCloseCallback& tabTryCloseCallback );
|
void setTabTryCloseCallback( const TabTryCloseCallback& tabTryCloseCallback );
|
||||||
@@ -195,6 +211,20 @@ class EE_API UITabWidget : public UIWidget {
|
|||||||
|
|
||||||
void setSplitFunction( SplitFunctionCb cb, Float splitEdgePercent = 0.1 );
|
void setSplitFunction( SplitFunctionCb cb, Float splitEdgePercent = 0.1 );
|
||||||
|
|
||||||
|
const std::deque<UITab*>& getFocusHistory() const { return mFocusHistory; }
|
||||||
|
|
||||||
|
void setEnableTabSwitcher( bool enable ) { mEnableTabSwitcher = enable; }
|
||||||
|
|
||||||
|
bool isTabSwitcherEnabled() const { return mEnableTabSwitcher; }
|
||||||
|
|
||||||
|
void focusNextTab( const std::vector<Keycode>& tabSwitcherMetaTrigger = {} );
|
||||||
|
|
||||||
|
void focusPreviousTab( const std::vector<Keycode>& tabSwitcherMetaTrigger = {} );
|
||||||
|
|
||||||
|
void setTabJumpMode( TabJumpMode mode ) { mTabJumpMode = mode; }
|
||||||
|
|
||||||
|
TabJumpMode getTabJumpMode() const { return mTabJumpMode; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class UITab;
|
friend class UITab;
|
||||||
|
|
||||||
@@ -207,11 +237,13 @@ class EE_API UITabWidget : public UIWidget {
|
|||||||
Uint32 mTabSelectedIndex;
|
Uint32 mTabSelectedIndex;
|
||||||
TabTryCloseCallback mTabTryCloseCallback;
|
TabTryCloseCallback mTabTryCloseCallback;
|
||||||
bool mHideTabBarOnSingleTab{ false };
|
bool mHideTabBarOnSingleTab{ false };
|
||||||
|
bool mHideTabBar{ false };
|
||||||
bool mAllowRearrangeTabs{ false };
|
bool mAllowRearrangeTabs{ false };
|
||||||
bool mAllowDragAndDropTabs{ false };
|
bool mAllowDragAndDropTabs{ false };
|
||||||
bool mAllowSwitchTabsInEmptySpaces{ false };
|
bool mAllowSwitchTabsInEmptySpaces{ false };
|
||||||
bool mDroppableHoveringColorWasSet{ false };
|
bool mDroppableHoveringColorWasSet{ false };
|
||||||
bool mEnabledCreateContextMenu{ false };
|
bool mEnabledCreateContextMenu{ false };
|
||||||
|
bool mEnableTabSwitcher{ false };
|
||||||
Float mTabVerticalDragResistance;
|
Float mTabVerticalDragResistance;
|
||||||
Color mDroppableHoveringColor{ Color::Transparent };
|
Color mDroppableHoveringColor{ Color::Transparent };
|
||||||
FocusTabBehavior mFocusTabBehavior{ FocusTabBehavior::Closest };
|
FocusTabBehavior mFocusTabBehavior{ FocusTabBehavior::Closest };
|
||||||
@@ -219,6 +251,8 @@ class EE_API UITabWidget : public UIWidget {
|
|||||||
UIPopUpMenu* mCurrentMenu{ nullptr };
|
UIPopUpMenu* mCurrentMenu{ nullptr };
|
||||||
SplitFunctionCb mSplitFn;
|
SplitFunctionCb mSplitFn;
|
||||||
Float mSplitEdgePercent{ 0.1 };
|
Float mSplitEdgePercent{ 0.1 };
|
||||||
|
UIListView* mTabSwitcher{ nullptr };
|
||||||
|
TabJumpMode mTabJumpMode{ TabJumpMode::Chronological };
|
||||||
|
|
||||||
void onThemeLoaded();
|
void onThemeLoaded();
|
||||||
|
|
||||||
@@ -268,6 +302,11 @@ class EE_API UITabWidget : public UIWidget {
|
|||||||
void eraseFocusHistory( UITab* tab );
|
void eraseFocusHistory( UITab* tab );
|
||||||
|
|
||||||
std::optional<SplitDirection> getDropDirection() const;
|
std::optional<SplitDirection> getDropDirection() const;
|
||||||
|
|
||||||
|
void createTabSwitcher( const std::vector<Keycode>& tabSwitcherMetaTrigger,
|
||||||
|
bool fromPrev = false );
|
||||||
|
|
||||||
|
Uint32 getTabSelectedFocusHistoryIndex() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace EE::UI
|
}} // namespace EE::UI
|
||||||
|
|||||||
@@ -712,6 +712,8 @@ class EE_API KeyMod {
|
|||||||
|
|
||||||
static const std::map<std::string, Uint32>& getModMap();
|
static const std::map<std::string, Uint32>& getModMap();
|
||||||
|
|
||||||
|
static std::vector<Keycode> getKeyCodesFromModifier( Uint32 mod );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Uint32 defaultModifier;
|
static Uint32 defaultModifier;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ void addCPP() {
|
|||||||
{ "keyword", "keyword", "literal" } },
|
{ "keyword", "keyword", "literal" } },
|
||||||
{ { "cpp_number_parser" }, "number", "", SyntaxPatternMatchType::Parser },
|
{ { "cpp_number_parser" }, "number", "", SyntaxPatternMatchType::Parser },
|
||||||
{ { "[%+%-=/%*%^%%<>!~|&]" }, "operator" },
|
{ { "[%+%-=/%*%^%%<>!~|&]" }, "operator" },
|
||||||
{ { "(if|for|while|switch|catch|sizeof|typeid|defined)\\s*(?=\\()" },
|
{ { "(if|for|while|switch|catch|sizeof|typeid|defined|return|throw|alignof|noexcept|"
|
||||||
|
"new|delete)"
|
||||||
|
"\\s*(?=\\()" },
|
||||||
{ "normal", "keyword", "keyword" },
|
{ "normal", "keyword", "keyword" },
|
||||||
"",
|
"",
|
||||||
SyntaxPatternMatchType::RegEx },
|
SyntaxPatternMatchType::RegEx },
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ void addJavaScript() {
|
|||||||
"string" },
|
"string" },
|
||||||
{ { "js_number_parser" }, "number", "", SyntaxPatternMatchType::Parser },
|
{ { "js_number_parser" }, "number", "", SyntaxPatternMatchType::Parser },
|
||||||
{ { "[%+%-=/%*%^%%<>!~|&]" }, "operator" },
|
{ { "[%+%-=/%*%^%%<>!~|&]" }, "operator" },
|
||||||
{ { "(if|for|while|switch|catch|with)\\s*(?=\\()" },
|
{ { "(if|for|while|switch|catch|with|typeof|delete|void|super|await|function)\\s*(?="
|
||||||
|
"\\()" },
|
||||||
{ "normal", "keyword", "keyword" },
|
{ "normal", "keyword", "keyword" },
|
||||||
"",
|
"",
|
||||||
SyntaxPatternMatchType::RegEx },
|
SyntaxPatternMatchType::RegEx },
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ class TextMateScopeMapper {
|
|||||||
{ "constant.other", "literal" },
|
{ "constant.other", "literal" },
|
||||||
{ "constant.regexp", "string" },
|
{ "constant.regexp", "string" },
|
||||||
|
|
||||||
|
{ "meta.import", "keyword" },
|
||||||
|
{ "meta.package", "keyword" },
|
||||||
|
|
||||||
{ "comment.unused", "normal" }, // unused comments pattern
|
{ "comment.unused", "normal" }, // unused comments pattern
|
||||||
{ "declaration.package", "literal" },
|
{ "declaration.package", "literal" },
|
||||||
{ "declaration.import", "literal" },
|
{ "declaration.import", "literal" },
|
||||||
|
|||||||
@@ -119,6 +119,13 @@ bool KeyBindings::hasCommand( const std::string& command ) {
|
|||||||
return mKeybindingsInvert.find( command ) != mKeybindingsInvert.end();
|
return mKeybindingsInvert.find( command ) != mKeybindingsInvert.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyBindings::Shortcut KeyBindings::getShortcutFromCommand( const std::string& cmd ) const {
|
||||||
|
auto it = mKeybindingsInvert.find( cmd );
|
||||||
|
if ( it != mKeybindingsInvert.end() )
|
||||||
|
return it->second;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void KeyBindings::removeCommandKeybind( const std::string& command ) {
|
void KeyBindings::removeCommandKeybind( const std::string& command ) {
|
||||||
auto kbIt = mKeybindingsInvert.find( command );
|
auto kbIt = mKeybindingsInvert.find( command );
|
||||||
if ( kbIt != mKeybindingsInvert.end() ) {
|
if ( kbIt != mKeybindingsInvert.end() ) {
|
||||||
|
|||||||
@@ -632,6 +632,7 @@ UITabWidget* UICodeEditorSplitter::createTabWidget( Node* parent ) {
|
|||||||
tabWidget->setParent( parent );
|
tabWidget->setParent( parent );
|
||||||
tabWidget->setTabsClosable( true );
|
tabWidget->setTabsClosable( true );
|
||||||
tabWidget->setHideTabBarOnSingleTab( mHideTabBarOnSingleTab );
|
tabWidget->setHideTabBarOnSingleTab( mHideTabBarOnSingleTab );
|
||||||
|
tabWidget->setHideTabBar( mHideTabBar );
|
||||||
tabWidget->setAllowRearrangeTabs( true );
|
tabWidget->setAllowRearrangeTabs( true );
|
||||||
tabWidget->setAllowDragAndDropTabs( true );
|
tabWidget->setAllowDragAndDropTabs( true );
|
||||||
tabWidget->setAllowSwitchTabsInEmptySpaces( true );
|
tabWidget->setAllowSwitchTabsInEmptySpaces( true );
|
||||||
@@ -958,6 +959,15 @@ void UICodeEditorSplitter::setHideTabBarOnSingleTab( bool hideTabBarOnSingleTab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UICodeEditorSplitter::setHideTabBar( bool hideTabBar ) {
|
||||||
|
if ( hideTabBar != mHideTabBar ) {
|
||||||
|
mHideTabBar = hideTabBar;
|
||||||
|
|
||||||
|
for ( auto widget : mTabWidgets )
|
||||||
|
widget->setHideTabBar( hideTabBar );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<UITabWidget*>& UICodeEditorSplitter::getTabWidgets() const {
|
const std::vector<UITabWidget*>& UICodeEditorSplitter::getTabWidgets() const {
|
||||||
return mTabWidgets;
|
return mTabWidgets;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ void UIEventDispatcher::checkTabPress( const Uint32& KeyCode, const Uint32& mod
|
|||||||
if ( mFocusNode->isWidget() && NULL != win && !mJustGainedFocus ) {
|
if ( mFocusNode->isWidget() && NULL != win && !mJustGainedFocus ) {
|
||||||
if ( mod & KEYMOD_SHIFT ) {
|
if ( mod & KEYMOD_SHIFT ) {
|
||||||
mFocusNode->asType<UIWidget>()->onFocusPrevWidget();
|
mFocusNode->asType<UIWidget>()->onFocusPrevWidget();
|
||||||
} else {
|
} else if ( mod == 0 ) {
|
||||||
mFocusNode->asType<UIWidget>()->onFocusNextWidget();
|
mFocusNode->asType<UIWidget>()->onFocusNextWidget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -203,7 +203,9 @@ Rectf UIScrollableWidget::getVisibleRect() const {
|
|||||||
|
|
||||||
bool UIScrollableWidget::shouldVerticalScrollBeVisible() const {
|
bool UIScrollableWidget::shouldVerticalScrollBeVisible() const {
|
||||||
Float totH = getPixelsSize().getHeight() - getPixelsPadding().Top - getPixelsPadding().Bottom -
|
Float totH = getPixelsSize().getHeight() - getPixelsPadding().Top - getPixelsPadding().Bottom -
|
||||||
mHScroll->getPixelsSize().getHeight();
|
( mHScrollMode == ScrollBarMode::AlwaysOff || !mHScroll->isVisible()
|
||||||
|
? 0
|
||||||
|
: mHScroll->getPixelsSize().getHeight() );
|
||||||
return getContentSize().getHeight() > totH;
|
return getContentSize().getHeight() > totH;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,6 +393,17 @@ Uint32 UIScrollableWidget::onMessage( const NodeMessage* Msg ) {
|
|||||||
if ( moved )
|
if ( moved )
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
case NodeMessage::FocusLoss: {
|
||||||
|
if ( NULL != getEventDispatcher() ) {
|
||||||
|
Node* focusNode = getEventDispatcher()->getFocusNode();
|
||||||
|
|
||||||
|
if ( this != focusNode && !isParentOf( focusNode ) ) {
|
||||||
|
onWidgetFocusLoss();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return UIWidget::onMessage( Msg );
|
return UIWidget::onMessage( Msg );
|
||||||
}
|
}
|
||||||
|
|||||||
+213
-5
@@ -1,17 +1,57 @@
|
|||||||
#include "eepp/ui/uiscenenode.hpp"
|
|
||||||
#include <algorithm>
|
|
||||||
#include <eepp/graphics/fontmanager.hpp>
|
#include <eepp/graphics/fontmanager.hpp>
|
||||||
#include <eepp/graphics/primitives.hpp>
|
#include <eepp/graphics/primitives.hpp>
|
||||||
#include <eepp/graphics/renderer/renderer.hpp>
|
#include <eepp/graphics/renderer/renderer.hpp>
|
||||||
#include <eepp/ui/css/propertydefinition.hpp>
|
#include <eepp/ui/css/propertydefinition.hpp>
|
||||||
|
#include <eepp/ui/models/itemlistmodel.hpp>
|
||||||
|
#include <eepp/ui/uilistview.hpp>
|
||||||
#include <eepp/ui/uipopupmenu.hpp>
|
#include <eepp/ui/uipopupmenu.hpp>
|
||||||
|
#include <eepp/ui/uiscenenode.hpp>
|
||||||
#include <eepp/ui/uiscrollbar.hpp>
|
#include <eepp/ui/uiscrollbar.hpp>
|
||||||
#include <eepp/ui/uistyle.hpp>
|
#include <eepp/ui/uistyle.hpp>
|
||||||
#include <eepp/ui/uitabwidget.hpp>
|
#include <eepp/ui/uitabwidget.hpp>
|
||||||
#include <eepp/ui/uithememanager.hpp>
|
#include <eepp/ui/uithememanager.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace EE { namespace UI {
|
namespace EE { namespace UI {
|
||||||
|
|
||||||
|
class TabsModel final : public Model {
|
||||||
|
public:
|
||||||
|
static std::shared_ptr<TabsModel> create( const std::deque<UITab*>& data, bool invertView ) {
|
||||||
|
return std::make_shared<TabsModel>( data, invertView );
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit TabsModel( const std::deque<UITab*>& data, bool invertView ) :
|
||||||
|
mData( data ), mInvertView( invertView ) {}
|
||||||
|
|
||||||
|
virtual ~TabsModel() {}
|
||||||
|
|
||||||
|
virtual size_t rowCount( const ModelIndex& ) const { return mData.size(); }
|
||||||
|
|
||||||
|
virtual size_t columnCount( const ModelIndex& ) const { return 1; }
|
||||||
|
|
||||||
|
virtual std::string columnName( const size_t& ) const { return "Data"; }
|
||||||
|
|
||||||
|
virtual ModelIndex index( int row, int column, const ModelIndex& parent = ModelIndex() ) const {
|
||||||
|
if ( row >= (int)rowCount( parent ) || column >= (int)columnCount( parent ) )
|
||||||
|
return {};
|
||||||
|
return Model::index( row, column, parent );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Variant data( const ModelIndex& index, ModelRole role = ModelRole::Display ) const {
|
||||||
|
if ( role == ModelRole::Display )
|
||||||
|
return mInvertView ? Variant( mData[mData.size() - 1 - index.row()]->getText() )
|
||||||
|
: Variant( mData[index.row()]->getText() );
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool invertedView() const { return mInvertView; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::deque<UITab*>& mData;
|
||||||
|
bool mInvertView{ false };
|
||||||
|
};
|
||||||
|
|
||||||
UITabWidget* UITabWidget::New() {
|
UITabWidget* UITabWidget::New() {
|
||||||
return eeNew( UITabWidget, () );
|
return eeNew( UITabWidget, () );
|
||||||
}
|
}
|
||||||
@@ -23,6 +63,7 @@ UITabWidget::UITabWidget() :
|
|||||||
mTabSelected( NULL ),
|
mTabSelected( NULL ),
|
||||||
mTabSelectedIndex( eeINDEX_NOT_FOUND ),
|
mTabSelectedIndex( eeINDEX_NOT_FOUND ),
|
||||||
mHideTabBarOnSingleTab( false ),
|
mHideTabBarOnSingleTab( false ),
|
||||||
|
mHideTabBar( false ),
|
||||||
mAllowRearrangeTabs( false ),
|
mAllowRearrangeTabs( false ),
|
||||||
mAllowDragAndDropTabs( false ),
|
mAllowDragAndDropTabs( false ),
|
||||||
mAllowSwitchTabsInEmptySpaces( false ),
|
mAllowSwitchTabsInEmptySpaces( false ),
|
||||||
@@ -101,7 +142,7 @@ void UITabWidget::onThemeLoaded() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UITabWidget::setContainerSize() {
|
void UITabWidget::setContainerSize() {
|
||||||
if ( getTabCount() < 2 && mHideTabBarOnSingleTab ) {
|
if ( mHideTabBar || ( getTabCount() < 2 && mHideTabBarOnSingleTab ) ) {
|
||||||
mTabBar->setVisible( false );
|
mTabBar->setVisible( false );
|
||||||
mTabBar->setEnabled( false );
|
mTabBar->setEnabled( false );
|
||||||
mNodeContainer->setPosition( mPadding.Left, mPadding.Top );
|
mNodeContainer->setPosition( mPadding.Left, mPadding.Top );
|
||||||
@@ -222,7 +263,7 @@ void UITabWidget::invalidate( Node* invalidator ) {
|
|||||||
mSceneNode->invalidate( this );
|
mSceneNode->invalidate( this );
|
||||||
}
|
}
|
||||||
} else if ( invalidator == mNodeContainer || invalidator == mTabBar ||
|
} else if ( invalidator == mNodeContainer || invalidator == mTabBar ||
|
||||||
mTabBar->inParentTreeOf( invalidator ) ) {
|
invalidator == mTabSwitcher || mTabBar->inParentTreeOf( invalidator ) ) {
|
||||||
mNodeDrawInvalidator->invalidate( mNodeContainer );
|
mNodeDrawInvalidator->invalidate( mNodeContainer );
|
||||||
} else if ( invalidator->getParent() == mNodeContainer ) {
|
} else if ( invalidator->getParent() == mNodeContainer ) {
|
||||||
if ( invalidator->isVisible() )
|
if ( invalidator->isVisible() )
|
||||||
@@ -815,6 +856,10 @@ UITab* UITabWidget::setTabSelected( const Uint32& tabIndex ) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool& UITabWidget::getHideTabBar() const {
|
||||||
|
return mHideTabBar;
|
||||||
|
}
|
||||||
|
|
||||||
const bool& UITabWidget::getHideTabBarOnSingleTab() const {
|
const bool& UITabWidget::getHideTabBarOnSingleTab() const {
|
||||||
return mHideTabBarOnSingleTab;
|
return mHideTabBarOnSingleTab;
|
||||||
}
|
}
|
||||||
@@ -826,6 +871,13 @@ void UITabWidget::setHideTabBarOnSingleTab( const bool& hideTabBarOnSingleTab )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UITabWidget::setHideTabBar( const bool& hideTabBar ) {
|
||||||
|
if ( mHideTabBar != hideTabBar ) {
|
||||||
|
mHideTabBar = hideTabBar;
|
||||||
|
setContainerSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const UITabWidget::TabTryCloseCallback& UITabWidget::getTabTryCloseCallback() const {
|
const UITabWidget::TabTryCloseCallback& UITabWidget::getTabTryCloseCallback() const {
|
||||||
return mTabTryCloseCallback;
|
return mTabTryCloseCallback;
|
||||||
}
|
}
|
||||||
@@ -986,7 +1038,8 @@ void UITabWidget::onSizeChange() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UITabWidget::onChildCountChange( Node* child, const bool& removed ) {
|
void UITabWidget::onChildCountChange( Node* child, const bool& removed ) {
|
||||||
if ( !removed && child != mTabBar && child != mNodeContainer && child != mTabScroll ) {
|
if ( !removed && child != mTabBar && child != mNodeContainer && child != mTabScroll &&
|
||||||
|
child != mTabSwitcher ) {
|
||||||
if ( child->isType( UI_TYPE_TAB ) ) {
|
if ( child->isType( UI_TYPE_TAB ) ) {
|
||||||
// This must be a tab that was dragging.
|
// This must be a tab that was dragging.
|
||||||
if ( std::find( mTabs.begin(), mTabs.end(), child->asType<UITab>() ) != mTabs.end() )
|
if ( std::find( mTabs.begin(), mTabs.end(), child->asType<UITab>() ) != mTabs.end() )
|
||||||
@@ -1192,4 +1245,159 @@ void UITabWidget::updateScroll( bool updateFocus ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UITabWidget::createTabSwitcher( const std::vector<Keycode>& tabSwitcherMetaTrigger,
|
||||||
|
bool fromPrev ) {
|
||||||
|
bool resetSelection = mTabSwitcher == nullptr || !mTabSwitcher->isVisible();
|
||||||
|
if ( mTabSwitcher == nullptr ) {
|
||||||
|
mTabSwitcher = UIListView::New();
|
||||||
|
mTabSwitcher->setParent( this );
|
||||||
|
mTabSwitcher->setVisible( false );
|
||||||
|
mTabSwitcher->setHorizontalScrollMode( ScrollBarMode::AlwaysOff );
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::deque<UITab*>& history = mTabJumpMode == TabJumpMode::Linear ? mTabs : mFocusHistory;
|
||||||
|
|
||||||
|
if ( mTabSwitcher->getModel() == nullptr ||
|
||||||
|
( mTabJumpMode == TabJumpMode::Linear &&
|
||||||
|
static_cast<TabsModel*>( mTabSwitcher->getModel() )->invertedView() ) ||
|
||||||
|
( mTabJumpMode == TabJumpMode::Chronological &&
|
||||||
|
!static_cast<TabsModel*>( mTabSwitcher->getModel() )->invertedView() ) ) {
|
||||||
|
mTabSwitcher->setModel(
|
||||||
|
TabsModel::create( mTabJumpMode == TabJumpMode::Linear ? mTabs : mFocusHistory,
|
||||||
|
mTabJumpMode == TabJumpMode::Chronological ) );
|
||||||
|
resetSelection = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( resetSelection && !history.empty() ) {
|
||||||
|
switch ( mTabJumpMode ) {
|
||||||
|
case TabJumpMode::Linear: {
|
||||||
|
Uint32 index =
|
||||||
|
fromPrev ? ( (Int32)history.size() - 1 < 0 ? history.size() - 1
|
||||||
|
: ( getTabSelectedIndex() - 1 ) )
|
||||||
|
: ( ( getTabSelectedIndex() + 1 ) % history.size() );
|
||||||
|
mTabSwitcher->setSelection( mTabSwitcher->getModel()->index( index, 0 ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TabJumpMode::Chronological: {
|
||||||
|
mTabSwitcher->setSelection( mTabSwitcher->getModel()->index(
|
||||||
|
fromPrev ? history.size() - 1 : ( history.size() == 1 ? 0 : 1 ), 0 ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mTabSwitcher->setPixelsSize( eeceil( PixelDensity::dpToPx( 300 ) ),
|
||||||
|
eeceil( mTabSwitcher->getContentSize().getHeight() +
|
||||||
|
mTabSwitcher->getPixelsPadding().getHeight() ) );
|
||||||
|
mTabSwitcher->setMaxSizeEq( "80%", "70%" );
|
||||||
|
mTabSwitcher->center();
|
||||||
|
mTabSwitcher->toFront();
|
||||||
|
mTabSwitcher->removeEventsOfType( Event::OnFocusLoss );
|
||||||
|
mTabSwitcher->setVisible( true );
|
||||||
|
mTabSwitcher->setFocus();
|
||||||
|
mTabSwitcher->on( Event::OnWidgetFocusLoss, [this]( const Event* event ) {
|
||||||
|
mTabSwitcher->setVisible( false );
|
||||||
|
mTabSwitcher->removeEventListener( event->getCallbackId() );
|
||||||
|
} );
|
||||||
|
|
||||||
|
if ( !tabSwitcherMetaTrigger.empty() ) {
|
||||||
|
mTabSwitcher->removeEventsOfType( Event::KeyUp );
|
||||||
|
mTabSwitcher->on( Event::KeyUp, [this, tabSwitcherMetaTrigger]( const Event* event ) {
|
||||||
|
bool inverted = mTabJumpMode != TabJumpMode::Linear;
|
||||||
|
const std::deque<UITab*>& history =
|
||||||
|
mTabJumpMode == TabJumpMode::Linear ? mTabs : mFocusHistory;
|
||||||
|
auto keyCode = event->asKeyEvent()->getKeyCode();
|
||||||
|
if ( std::find( tabSwitcherMetaTrigger.begin(), tabSwitcherMetaTrigger.end(),
|
||||||
|
keyCode ) != tabSwitcherMetaTrigger.end() ||
|
||||||
|
keyCode == KEY_RETURN ) {
|
||||||
|
mTabSwitcher->removeEventListener( event->getCallbackId() );
|
||||||
|
mTabSwitcher->setVisible( false );
|
||||||
|
if ( !mTabSwitcher->getSelection().isEmpty() &&
|
||||||
|
mTabSwitcher->getSelection().first().row() < (Int64)history.size() ) {
|
||||||
|
if ( inverted ) {
|
||||||
|
setTabSelected( history[history.size() - 1 -
|
||||||
|
mTabSwitcher->getSelection().first().row()] );
|
||||||
|
} else {
|
||||||
|
setTabSelected( history[mTabSwitcher->getSelection().first().row()] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ( keyCode == KEY_ESCAPE ) {
|
||||||
|
mTabSwitcher->removeEventListener( event->getCallbackId() );
|
||||||
|
mTabSwitcher->setVisible( false );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UITabWidget::focusNextTab( const std::vector<Keycode>& tabSwitcherMetaTrigger ) {
|
||||||
|
if ( mEnableTabSwitcher ) {
|
||||||
|
bool wasVisible = mTabSwitcher && mTabSwitcher->isVisible();
|
||||||
|
|
||||||
|
createTabSwitcher( tabSwitcherMetaTrigger );
|
||||||
|
|
||||||
|
if ( wasVisible && !mTabSwitcher->getSelection().isEmpty() ) {
|
||||||
|
Int32 index = ( mTabSwitcher->getSelection().first().row() + 1 ) %
|
||||||
|
mTabSwitcher->getModel()->rowCount();
|
||||||
|
mTabSwitcher->setSelection( mTabSwitcher->getModel()->index( index, 0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( getTabCount() <= 1 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch ( mTabJumpMode ) {
|
||||||
|
case TabJumpMode::Linear: {
|
||||||
|
Int32 index = ( getTabSelectedIndex() + 1 ) % getTabCount();
|
||||||
|
setTabSelected( eeclamp<Int32>( index, 0, getTabCount() - 1 ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TabJumpMode::Chronological: {
|
||||||
|
Int32 newTabIndex = (Int32)getTabSelectedFocusHistoryIndex() - 1;
|
||||||
|
Int32 index = newTabIndex < 0 ? mFocusHistory.size() - newTabIndex : newTabIndex;
|
||||||
|
setTabSelected( mFocusHistory[index] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UITabWidget::focusPreviousTab( const std::vector<Keycode>& tabSwitcherMetaTrigger ) {
|
||||||
|
if ( mEnableTabSwitcher ) {
|
||||||
|
bool wasVisible = mTabSwitcher && mTabSwitcher->isVisible();
|
||||||
|
|
||||||
|
createTabSwitcher( tabSwitcherMetaTrigger, true );
|
||||||
|
|
||||||
|
if ( wasVisible && !mTabSwitcher->getSelection().isEmpty() ) {
|
||||||
|
Int32 newTabIndex = (Int32)mTabSwitcher->getSelection().first().row() - 1;
|
||||||
|
Int32 index = newTabIndex < 0 ? mTabSwitcher->getModel()->rowCount() - 1 : newTabIndex;
|
||||||
|
mTabSwitcher->setSelection( mTabSwitcher->getModel()->index( index, 0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( getTabCount() <= 1 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch ( mTabJumpMode ) {
|
||||||
|
case TabJumpMode::Linear: {
|
||||||
|
Int32 newTabIndex = (Int32)getTabSelectedIndex() - 1;
|
||||||
|
Int32 index = newTabIndex < 0 ? getTabCount() - newTabIndex : newTabIndex;
|
||||||
|
setTabSelected( eeclamp<Int32>( index, 0, getTabCount() - 1 ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TabJumpMode::Chronological: {
|
||||||
|
Int32 index = ( getTabSelectedFocusHistoryIndex() + 1 ) % mFocusHistory.size();
|
||||||
|
setTabSelected( mFocusHistory[index] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint32 UITabWidget::getTabSelectedFocusHistoryIndex() const {
|
||||||
|
auto it = std::find( mFocusHistory.begin(), mFocusHistory.end(), mTabSelected );
|
||||||
|
return it != mFocusHistory.end() ? std::distance( mFocusHistory.begin(), it ) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
}} // namespace EE::UI
|
}} // namespace EE::UI
|
||||||
|
|||||||
@@ -4,29 +4,29 @@ namespace EE { namespace Window {
|
|||||||
|
|
||||||
Uint32 KeyMod::defaultModifier = KEYMOD_DEFAULT_MODIFIER;
|
Uint32 KeyMod::defaultModifier = KEYMOD_DEFAULT_MODIFIER;
|
||||||
|
|
||||||
std::map<std::string, Uint32> MOD_MAP = { { "lshift", KEYMOD_SHIFT },
|
static std::map<std::string, Uint32> MOD_MAP = { { "lshift", KEYMOD_SHIFT },
|
||||||
{ "rshift", KEYMOD_SHIFT },
|
{ "rshift", KEYMOD_SHIFT },
|
||||||
{ "left shift", KEYMOD_SHIFT },
|
{ "left shift", KEYMOD_SHIFT },
|
||||||
{ "right shift", KEYMOD_SHIFT },
|
{ "right shift", KEYMOD_SHIFT },
|
||||||
{ "shift", KEYMOD_SHIFT },
|
{ "shift", KEYMOD_SHIFT },
|
||||||
{ "lctrl", KEYMOD_CTRL },
|
{ "lctrl", KEYMOD_CTRL },
|
||||||
{ "rctrl", KEYMOD_CTRL },
|
{ "rctrl", KEYMOD_CTRL },
|
||||||
{ "left ctrl", KEYMOD_CTRL },
|
{ "left ctrl", KEYMOD_CTRL },
|
||||||
{ "right ctrl", KEYMOD_CTRL },
|
{ "right ctrl", KEYMOD_CTRL },
|
||||||
{ "ctrl", KEYMOD_CTRL },
|
{ "ctrl", KEYMOD_CTRL },
|
||||||
{ "lalt", KEYMOD_ALT },
|
{ "lalt", KEYMOD_ALT },
|
||||||
{ "ralt", KEYMOD_RALT },
|
{ "ralt", KEYMOD_RALT },
|
||||||
{ "left alt", KEYMOD_LALT },
|
{ "left alt", KEYMOD_LALT },
|
||||||
{ "right alt", KEYMOD_RALT },
|
{ "right alt", KEYMOD_RALT },
|
||||||
{ "altgr", KEYMOD_RALT },
|
{ "altgr", KEYMOD_RALT },
|
||||||
{ "alt", KEYMOD_LALT },
|
{ "alt", KEYMOD_LALT },
|
||||||
{ "lmeta", KEYMOD_META },
|
{ "lmeta", KEYMOD_META },
|
||||||
{ "lmeta", KEYMOD_META },
|
{ "lmeta", KEYMOD_META },
|
||||||
{ "left meta", KEYMOD_META },
|
{ "left meta", KEYMOD_META },
|
||||||
{ "right meta", KEYMOD_META },
|
{ "right meta", KEYMOD_META },
|
||||||
{ "meta", KEYMOD_META },
|
{ "meta", KEYMOD_META },
|
||||||
{ "mod", KeyMod::getDefaultModifier() },
|
{ "mod", KeyMod::getDefaultModifier() },
|
||||||
{ "modifier", KeyMod::getDefaultModifier() } };
|
{ "modifier", KeyMod::getDefaultModifier() } };
|
||||||
|
|
||||||
Uint32 KeyMod::getDefaultModifier() {
|
Uint32 KeyMod::getDefaultModifier() {
|
||||||
return defaultModifier;
|
return defaultModifier;
|
||||||
@@ -66,4 +66,33 @@ const std::map<std::string, Uint32>& KeyMod::getModMap() {
|
|||||||
return MOD_MAP;
|
return MOD_MAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Keycode> KeyMod::getKeyCodesFromModifier( Uint32 mod ) {
|
||||||
|
std::vector<Keycode> codes;
|
||||||
|
if ( mod & KEYMOD_LSHIFT ) {
|
||||||
|
codes.push_back( KEY_LSHIFT );
|
||||||
|
}
|
||||||
|
if ( mod & KEYMOD_RSHIFT ) {
|
||||||
|
codes.push_back( KEY_RSHIFT );
|
||||||
|
}
|
||||||
|
if ( mod & KEYMOD_LCTRL ) {
|
||||||
|
codes.push_back( KEY_LCTRL );
|
||||||
|
}
|
||||||
|
if ( mod & KEYMOD_RCTRL ) {
|
||||||
|
codes.push_back( KEY_RCTRL );
|
||||||
|
}
|
||||||
|
if ( mod & KEYMOD_LALT ) {
|
||||||
|
codes.push_back( KEY_LALT );
|
||||||
|
}
|
||||||
|
if ( mod & KEYMOD_RALT ) {
|
||||||
|
codes.push_back( KEY_RALT );
|
||||||
|
}
|
||||||
|
if ( mod & KEYMOD_LMETA ) {
|
||||||
|
codes.push_back( KEY_LGUI );
|
||||||
|
}
|
||||||
|
if ( mod & KEYMOD_RMETA ) {
|
||||||
|
codes.push_back( KEY_RGUI );
|
||||||
|
}
|
||||||
|
return codes;
|
||||||
|
}
|
||||||
|
|
||||||
}} // namespace EE::Window
|
}} // namespace EE::Window
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ void addTypeScript() {
|
|||||||
{ { "[%+%-=/%*%^%%<>!~|&]" }, "operator" },
|
{ { "[%+%-=/%*%^%%<>!~|&]" }, "operator" },
|
||||||
{ { "(interface%s)([%a_][%w_]*)" }, { "normal", "keyword", "keyword2" } },
|
{ { "(interface%s)([%a_][%w_]*)" }, { "normal", "keyword", "keyword2" } },
|
||||||
{ { "(type%s)([%a_][%w_]*)" }, { "normal", "keyword", "keyword2" } },
|
{ { "(type%s)([%a_][%w_]*)" }, { "normal", "keyword", "keyword2" } },
|
||||||
{ { "(if|for|while|switch|catch|with)\\s*(?=\\()" },
|
{ { "(if|for|while|switch|catch|with|typeof|delete|void|super|await|function)\\s*(?="
|
||||||
|
"\\()" },
|
||||||
{ "normal", "keyword", "keyword" },
|
{ "normal", "keyword", "keyword" },
|
||||||
"",
|
"",
|
||||||
SyntaxPatternMatchType::RegEx },
|
SyntaxPatternMatchType::RegEx },
|
||||||
|
|||||||
Vendored
+1
-1
Submodule src/thirdparty/efsw updated: ad4ac90564...f4ec910175
@@ -160,6 +160,11 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath,
|
|||||||
editor.minimap = ini.getValueB( "editor", "minimap", true );
|
editor.minimap = ini.getValueB( "editor", "minimap", true );
|
||||||
editor.showDocInfo = ini.getValueB( "editor", "show_doc_info", true );
|
editor.showDocInfo = ini.getValueB( "editor", "show_doc_info", true );
|
||||||
editor.hideTabBarOnSingleTab = ini.getValueB( "editor", "hide_tab_bar_on_single_tab", false );
|
editor.hideTabBarOnSingleTab = ini.getValueB( "editor", "hide_tab_bar_on_single_tab", false );
|
||||||
|
editor.hideTabBar = ini.getValueB( "editor", "hide_tab_bar", false );
|
||||||
|
editor.tabSwitcher = ini.getValueB( "editor", "tab_switcher", false );
|
||||||
|
editor.tabJumpMode =
|
||||||
|
UITabWidget::tabJumpModefromString( ini.getValue( "editor", "tab_jump_mode", "linear" ) );
|
||||||
|
|
||||||
editor.singleClickNavigation = ini.getValueB( "editor", "single_click_tree_navigation", false );
|
editor.singleClickNavigation = ini.getValueB( "editor", "single_click_tree_navigation", false );
|
||||||
editor.syncProjectTreeWithEditor =
|
editor.syncProjectTreeWithEditor =
|
||||||
ini.getValueB( "editor", "sync_project_tree_with_editor", true );
|
ini.getValueB( "editor", "sync_project_tree_with_editor", true );
|
||||||
@@ -316,6 +321,10 @@ void AppConfig::save( const std::vector<std::string>& recentFiles,
|
|||||||
ini.setValueB( "editor", "minimap", editor.minimap );
|
ini.setValueB( "editor", "minimap", editor.minimap );
|
||||||
ini.setValueB( "editor", "show_doc_info", editor.showDocInfo );
|
ini.setValueB( "editor", "show_doc_info", editor.showDocInfo );
|
||||||
ini.setValueB( "editor", "hide_tab_bar_on_single_tab", editor.hideTabBarOnSingleTab );
|
ini.setValueB( "editor", "hide_tab_bar_on_single_tab", editor.hideTabBarOnSingleTab );
|
||||||
|
ini.setValueB( "editor", "hide_tab_bar", editor.hideTabBar );
|
||||||
|
ini.setValueB( "editor", "tab_switcher", editor.tabSwitcher );
|
||||||
|
ini.setValue( "editor", "tab_jump_mode",
|
||||||
|
UITabWidget::tabJumpModeToString( editor.tabJumpMode ) );
|
||||||
ini.setValueB( "editor", "single_click_tree_navigation", editor.singleClickNavigation );
|
ini.setValueB( "editor", "single_click_tree_navigation", editor.singleClickNavigation );
|
||||||
ini.setValueB( "editor", "sync_project_tree_with_editor", editor.syncProjectTreeWithEditor );
|
ini.setValueB( "editor", "sync_project_tree_with_editor", editor.syncProjectTreeWithEditor );
|
||||||
ini.setValueB( "editor", "auto_close_xml_tags", editor.autoCloseXMLTags );
|
ini.setValueB( "editor", "auto_close_xml_tags", editor.autoCloseXMLTags );
|
||||||
|
|||||||
@@ -74,6 +74,10 @@ struct CodeEditorConfig {
|
|||||||
bool minimap{ true };
|
bool minimap{ true };
|
||||||
bool showDocInfo{ true };
|
bool showDocInfo{ true };
|
||||||
bool hideTabBarOnSingleTab{ true };
|
bool hideTabBarOnSingleTab{ true };
|
||||||
|
bool hideTabBar{ false };
|
||||||
|
bool tabSwitcher{ false };
|
||||||
|
UITabWidget::TabJumpMode tabJumpMode{ UITabWidget::TabJumpMode::Linear };
|
||||||
|
|
||||||
bool singleClickNavigation{ false };
|
bool singleClickNavigation{ false };
|
||||||
bool syncProjectTreeWithEditor{ true };
|
bool syncProjectTreeWithEditor{ true };
|
||||||
bool autoCloseXMLTags{ true };
|
bool autoCloseXMLTags{ true };
|
||||||
|
|||||||
@@ -3892,6 +3892,7 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe
|
|||||||
mSplitter = UICodeEditorSplitter::New( this, mUISceneNode, mThreadPool, mColorSchemes,
|
mSplitter = UICodeEditorSplitter::New( this, mUISceneNode, mThreadPool, mColorSchemes,
|
||||||
mInitColorScheme );
|
mInitColorScheme );
|
||||||
mSplitter->setHideTabBarOnSingleTab( mConfig.editor.hideTabBarOnSingleTab );
|
mSplitter->setHideTabBarOnSingleTab( mConfig.editor.hideTabBarOnSingleTab );
|
||||||
|
mSplitter->setHideTabBar( mConfig.editor.hideTabBar );
|
||||||
mSplitter->setOnTabWidgetCreateCb( [this]( UITabWidget* tabWidget ) {
|
mSplitter->setOnTabWidgetCreateCb( [this]( UITabWidget* tabWidget ) {
|
||||||
tabWidget->getTabBar()->onDoubleClick(
|
tabWidget->getTabBar()->onDoubleClick(
|
||||||
[this]( const MouseEvent* ) { mSplitter->createEditorInNewTab(); } );
|
[this]( const MouseEvent* ) { mSplitter->createEditorInNewTab(); } );
|
||||||
|
|||||||
@@ -354,7 +354,53 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider {
|
|||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
t.setCommand( "create-new-welcome-tab", [this] { createWelcomeTab(); } );
|
t.setCommand( "create-new-welcome-tab", [this] { createWelcomeTab(); } );
|
||||||
|
|
||||||
mSplitter->registerSplitterCommands( t );
|
mSplitter->registerSplitterCommands( t );
|
||||||
|
|
||||||
|
// Overwrite it
|
||||||
|
t.setCommand( "next-tab", [this] {
|
||||||
|
UITabWidget* tabWidget =
|
||||||
|
getSplitter()->tabWidgetFromWidget( getSplitter()->getCurWidget() );
|
||||||
|
if ( tabWidget ) {
|
||||||
|
tabWidget->setTabJumpMode( mConfig.editor.tabJumpMode );
|
||||||
|
tabWidget->setEnableTabSwitcher( mConfig.editor.tabSwitcher );
|
||||||
|
std::vector<Keycode> triggerCodes;
|
||||||
|
auto kb = getKeybind( "next-tab" );
|
||||||
|
if ( !kb.empty() ) {
|
||||||
|
auto shortcut =
|
||||||
|
KeyBindings::toShortcut( mWindow->getInput(), getKeybind( "next-tab" ) );
|
||||||
|
if ( !shortcut.empty() ) {
|
||||||
|
if ( shortcut.mod & KeyMod::getDefaultModifier() ) {
|
||||||
|
triggerCodes =
|
||||||
|
KeyMod::getKeyCodesFromModifier( KeyMod::getDefaultModifier() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tabWidget->focusNextTab( triggerCodes );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
t.setCommand( "previous-tab", [this] {
|
||||||
|
UITabWidget* tabWidget =
|
||||||
|
getSplitter()->tabWidgetFromWidget( getSplitter()->getCurWidget() );
|
||||||
|
if ( tabWidget ) {
|
||||||
|
tabWidget->setTabJumpMode( mConfig.editor.tabJumpMode );
|
||||||
|
tabWidget->setEnableTabSwitcher( mConfig.editor.tabSwitcher );
|
||||||
|
std::vector<Keycode> triggerCodes;
|
||||||
|
auto kb = getKeybind( "next-tab" );
|
||||||
|
if ( !kb.empty() ) {
|
||||||
|
auto shortcut =
|
||||||
|
KeyBindings::toShortcut( mWindow->getInput(), getKeybind( "next-tab" ) );
|
||||||
|
if ( !shortcut.empty() ) {
|
||||||
|
if ( shortcut.mod & KeyMod::getDefaultModifier() ) {
|
||||||
|
triggerCodes =
|
||||||
|
KeyMod::getKeyCodesFromModifier( KeyMod::getDefaultModifier() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tabWidget->focusPreviousTab( triggerCodes );
|
||||||
|
}
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginManager* getPluginManager() const;
|
PluginManager* getPluginManager() const;
|
||||||
|
|||||||
@@ -1492,6 +1492,116 @@ UIMenu* SettingsMenu::createViewMenu() {
|
|||||||
|
|
||||||
mViewMenu->addSeparator();
|
mViewMenu->addSeparator();
|
||||||
|
|
||||||
|
mTabBarMenu = UIPopUpMenu::New();
|
||||||
|
|
||||||
|
const auto tabBarMenuRefresh = [this] {
|
||||||
|
const auto& cfg = mApp->getConfig();
|
||||||
|
|
||||||
|
mTabBarMenu->getItemId( "hide-tabbar" )
|
||||||
|
->asType<UIMenuCheckBox>()
|
||||||
|
->setActive( cfg.editor.hideTabBar );
|
||||||
|
|
||||||
|
mTabBarMenu->getItemId( "hide-tabbar-on-single-tab" )
|
||||||
|
->asType<UIMenuCheckBox>()
|
||||||
|
->setActive( cfg.editor.hideTabBarOnSingleTab );
|
||||||
|
|
||||||
|
mTabBarMenu->getItemId( "tab-switcher" )
|
||||||
|
->asType<UIMenuCheckBox>()
|
||||||
|
->setActive( cfg.editor.tabSwitcher );
|
||||||
|
|
||||||
|
auto tjmi = mTabBarMenu->getItemId( "tab_jump_mode" );
|
||||||
|
UIPopUpMenu* tabJumpModeMenu =
|
||||||
|
tjmi ? tjmi->asType<UIMenuSubMenu>()->getSubMenu()->asType<UIPopUpMenu>() : nullptr;
|
||||||
|
if ( tabJumpModeMenu ) {
|
||||||
|
tabJumpModeMenu->getItemId( "tab_jump_linear" )
|
||||||
|
->asType<UIMenuRadioButton>()
|
||||||
|
->setActive( cfg.editor.tabJumpMode == UITabWidget::TabJumpMode::Linear );
|
||||||
|
tabJumpModeMenu->getItemId( "tab_jump_chronological" )
|
||||||
|
->asType<UIMenuRadioButton>()
|
||||||
|
->setActive( cfg.editor.tabJumpMode == UITabWidget::TabJumpMode::Chronological );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mViewMenu->addSubMenu( i18n( "tab_bar", "Tab Bar" ), findIcon( "tabbar" ), mTabBarMenu )
|
||||||
|
->on( Event::OnMenuShow, [this, tabBarMenuRefresh]( auto ) {
|
||||||
|
if ( mTabBarMenu->getCount() == 0 ) {
|
||||||
|
mTabBarMenu->addCheckBox( i18n( "hide_tabbar", "Hide Tab Bar" ) )
|
||||||
|
->setActive( mApp->getConfig().editor.hideTabBarOnSingleTab )
|
||||||
|
->setTooltipText( i18n( "hide_tabbar_tooltip", "Always Hide the Tab Bar." ) )
|
||||||
|
->setId( "hide-tabbar" );
|
||||||
|
|
||||||
|
mTabBarMenu
|
||||||
|
->addCheckBox(
|
||||||
|
i18n( "hide_tabbar_on_single_tab", "Hide Tab Bar on single tab" ) )
|
||||||
|
->setActive( mApp->getConfig().editor.hideTabBarOnSingleTab )
|
||||||
|
->setTooltipText(
|
||||||
|
i18n( "hide_tabbar_on_single_tab_tooltip",
|
||||||
|
"Hides the tabbar if there's only one element in the tab widget." ) )
|
||||||
|
->setId( "hide-tabbar-on-single-tab" );
|
||||||
|
|
||||||
|
mTabBarMenu->addCheckBox( i18n( "display_tab_switcher", "Display Tab Switcher" ) )
|
||||||
|
->setActive( mApp->getConfig().editor.tabSwitcher )
|
||||||
|
->setTooltipText(
|
||||||
|
i18n( "display_tab_switcher_tooltip",
|
||||||
|
"Displays a tab switcher at the center of the tab widget." ) )
|
||||||
|
->setId( "tab-switcher" );
|
||||||
|
|
||||||
|
auto tabJumpModeMenu = UIPopUpMenu::New();
|
||||||
|
tabJumpModeMenu->setId( "tab-jump-mode" );
|
||||||
|
tabJumpModeMenu->addRadioButton( i18n( "linear", "Linear" ) )
|
||||||
|
->setTooltipText( i18n(
|
||||||
|
"jump_mode_linear_tooltip",
|
||||||
|
"Linear Jump Mode will switch tabs in the order they are displayed" ) )
|
||||||
|
->setId( "tab_jump_linear" );
|
||||||
|
tabJumpModeMenu->addRadioButton( i18n( "chronological", "Chronological" ) )
|
||||||
|
->setTooltipText( i18n( "jump_mode_chronological_tooltip",
|
||||||
|
"Chronological Jump Mode will switch tabs in the last "
|
||||||
|
"focused / visited order." ) )
|
||||||
|
->setId( "tab_jump_chronological" );
|
||||||
|
|
||||||
|
mTabBarMenu
|
||||||
|
->addSubMenu( i18n( "tab_jump_mode", "Tab Jump Mode" ), nullptr,
|
||||||
|
tabJumpModeMenu )
|
||||||
|
->setId( "tab_jump_mode" );
|
||||||
|
|
||||||
|
tabJumpModeMenu->on( Event::OnItemClicked, [this]( const Event* event ) {
|
||||||
|
if ( !event->getNode()->isType( UI_TYPE_MENUITEM ) )
|
||||||
|
return;
|
||||||
|
UIMenuItem* item = event->getNode()->asType<UIMenuItem>();
|
||||||
|
mApp->getConfig().editor.tabJumpMode =
|
||||||
|
"tab_jump_linear" != item->getId() ? UITabWidget::TabJumpMode::Chronological
|
||||||
|
: UITabWidget::TabJumpMode::Linear;
|
||||||
|
} );
|
||||||
|
|
||||||
|
mTabBarMenu->on(
|
||||||
|
Event::OnItemClicked, [tabBarMenuRefresh, this]( const Event* event ) {
|
||||||
|
if ( !event->getNode()->isType( UI_TYPE_MENUITEM ) )
|
||||||
|
return;
|
||||||
|
UIMenuItem* item = event->getNode()->asType<UIMenuItem>();
|
||||||
|
if ( "hide-tabbar" == item->getId() ) {
|
||||||
|
mApp->getConfig().editor.hideTabBar =
|
||||||
|
item->asType<UIMenuCheckBox>()->isActive();
|
||||||
|
mSplitter->setHideTabBar( mApp->getConfig().editor.hideTabBar );
|
||||||
|
if ( mApp->getConfig().editor.hideTabBar )
|
||||||
|
mApp->getConfig().editor.tabSwitcher = true;
|
||||||
|
tabBarMenuRefresh();
|
||||||
|
} else if ( "hide-tabbar-on-single-tab" == item->getId() ) {
|
||||||
|
mApp->getConfig().editor.hideTabBarOnSingleTab =
|
||||||
|
item->asType<UIMenuCheckBox>()->isActive();
|
||||||
|
mSplitter->setHideTabBarOnSingleTab(
|
||||||
|
mApp->getConfig().editor.hideTabBarOnSingleTab );
|
||||||
|
} else if ( "tab-switcher" == item->getId() ) {
|
||||||
|
mApp->getConfig().editor.tabSwitcher =
|
||||||
|
item->asType<UIMenuCheckBox>()->isActive();
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
tabBarMenuRefresh();
|
||||||
|
} );
|
||||||
|
|
||||||
|
mViewMenu->addSeparator();
|
||||||
|
|
||||||
mViewMenu->addCheckBox( i18n( "show_line_numbers", "Show Line Numbers" ) )
|
mViewMenu->addCheckBox( i18n( "show_line_numbers", "Show Line Numbers" ) )
|
||||||
->setActive( mApp->getConfig().editor.showLineNumbers )
|
->setActive( mApp->getConfig().editor.showLineNumbers )
|
||||||
->setId( "show-line-numbers" );
|
->setId( "show-line-numbers" );
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ class SettingsMenu {
|
|||||||
UIPopUpMenu* mHelpMenu{ nullptr };
|
UIPopUpMenu* mHelpMenu{ nullptr };
|
||||||
UIPopUpMenu* mLineWrapMenu{ nullptr };
|
UIPopUpMenu* mLineWrapMenu{ nullptr };
|
||||||
UIPopUpMenu* mCodeFoldingMenu{ nullptr };
|
UIPopUpMenu* mCodeFoldingMenu{ nullptr };
|
||||||
|
UIPopUpMenu* mTabBarMenu{ nullptr };
|
||||||
UIMenuBar* mMenuBar{ nullptr };
|
UIMenuBar* mMenuBar{ nullptr };
|
||||||
std::vector<UIPopUpMenu*> mFileTypeMenues;
|
std::vector<UIPopUpMenu*> mFileTypeMenues;
|
||||||
Float mFileTypeMenuesCreatedWithHeight{ 0 };
|
Float mFileTypeMenuesCreatedWithHeight{ 0 };
|
||||||
|
|||||||
@@ -73,8 +73,8 @@ UITerminal* StatusTerminalController::createTerminal( const std::string& working
|
|||||||
term->setExclusiveMode( !term->getExclusiveMode() );
|
term->setExclusiveMode( !term->getExclusiveMode() );
|
||||||
mApp->updateTerminalMenu();
|
mApp->updateTerminalMenu();
|
||||||
} );
|
} );
|
||||||
mApp->registerUnlockedCommands( *term );
|
|
||||||
mContext->getSplitter()->registerSplitterCommands( *term );
|
mContext->getSplitter()->registerSplitterCommands( *term );
|
||||||
|
mApp->registerUnlockedCommands( *term );
|
||||||
term->setFocus();
|
term->setFocus();
|
||||||
term->setId( "terminal" );
|
term->setId( "terminal" );
|
||||||
return term;
|
return term;
|
||||||
|
|||||||
@@ -555,7 +555,6 @@ UITerminal* TerminalManager::createNewTerminal( const std::string& title, UITabW
|
|||||||
mApp->updateTerminalMenu();
|
mApp->updateTerminalMenu();
|
||||||
} );
|
} );
|
||||||
mApp->registerUnlockedCommands( *term );
|
mApp->registerUnlockedCommands( *term );
|
||||||
mApp->getSplitter()->registerSplitterCommands( *term );
|
|
||||||
term->setFocus();
|
term->setFocus();
|
||||||
return term;
|
return term;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user