diff --git a/README.md b/README.md index 4605d4e39..4e8ce3d10 100644 --- a/README.md +++ b/README.md @@ -649,7 +649,7 @@ Probably deprecate the Maps module, since I will focus my efforts on the UI syst * Lewis Van Winkle for [PlusCallback](https://github.com/codeplea/pluscallback) -* Dieter Baron and Thomas Klausner for [libbzip](https://libzip.org/) +* Dieter Baron and Thomas Klausner for [libzip](https://libzip.org/) * Jean-loup Gailly and Mark Adler for [zlib](https://zlib.net/) diff --git a/bin/assets/fonts/DroidSansFallbackFull.ttf b/bin/assets/fonts/DroidSansFallbackFull.ttf new file mode 100644 index 000000000..68641aad1 Binary files /dev/null and b/bin/assets/fonts/DroidSansFallbackFull.ttf differ diff --git a/bin/assets/ui/breeze.css b/bin/assets/ui/breeze.css index 8bd08ed36..24cc28084 100644 --- a/bin/assets/ui/breeze.css +++ b/bin/assets/ui/breeze.css @@ -197,6 +197,10 @@ CheckBox::inactive { border-color: var(--button-border); } +CheckBox:hover CheckBox::inactive { + border-color: var(--primary); +} + CheckBox::active { border-color: var(--primary); background-image: rectangle(solid, var(--primary)); @@ -223,6 +227,10 @@ RadioButton::inactive { border-color: var(--button-border); } +RadioButton:hover RadioButton::inactive { + border-color: var(--primary); +} + RadioButton::active { border-color: var(--primary); background-image: circle(solid, var(--primary)); diff --git a/docs/articles/cssspecification.md b/docs/articles/cssspecification.md index a535e211b..2bffbcf93 100644 --- a/docs/articles/cssspecification.md +++ b/docs/articles/cssspecification.md @@ -850,7 +850,7 @@ XML attribute (for those who are familiar with). * `center_vertical`: Place element in the vertical center of its container. * `center`: shorthand of `center_horizontal|center_vertical` * Default value: `left|top` -* Aliases: `layout_gravity` +* Aliases: `layout_gravity`, `lg` --- diff --git a/include/eepp/scene/node.hpp b/include/eepp/scene/node.hpp index c54a41525..406a4cd9f 100644 --- a/include/eepp/scene/node.hpp +++ b/include/eepp/scene/node.hpp @@ -195,6 +195,9 @@ class EE_API Node : public Transformable { return addEventListener( eventType, callback ); } + Uint32 addMouseClickListener( const std::function& callback, + const MouseButton& button ); + void removeEventsOfType( const Uint32& eventType ); void removeEventListener( const Uint32& callbackId ); @@ -229,6 +232,8 @@ class EE_API Node : public Transformable { Node* find( const std::string& id ) const; + Node* hasChild( const std::string& id ) const; + template T* find( const std::string& id ) const { return reinterpret_cast( find( id ) ); } @@ -547,6 +552,8 @@ class EE_API Node : public Transformable { Node* findIdHash( const String::HashType& idHash ) const; + Node* hasChildHash( const String::HashType& idHash ) const; + virtual void updateOriginPoint(); void setDirty(); diff --git a/include/eepp/ui/uicheckbox.hpp b/include/eepp/ui/uicheckbox.hpp index bddf4d09f..6463d72a6 100644 --- a/include/eepp/ui/uicheckbox.hpp +++ b/include/eepp/ui/uicheckbox.hpp @@ -22,7 +22,7 @@ class EE_API UICheckBox : public UITextView { const bool& isChecked() const; - void setChecked( const bool& checked ); + UICheckBox* setChecked( const bool& checked ); UIWidget* getCheckedButton() const; diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index c9c24b3a2..ba41f4afd 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -121,7 +121,6 @@ class EE_API DocSyntaxDefEvent : public DocEvent { const std::string& getNewLang() const { return newLang; } protected: - TextDocument* doc; std::string oldLang; std::string newLang; }; @@ -546,6 +545,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { Clock mBlinkTimer; Time mBlinkTime; bool mDirtyEditor{ false }; + bool mDirtyScroll{ false }; bool mCursorVisible{ false }; bool mMouseDown{ false }; bool mShowLineNumber{ true }; @@ -641,7 +641,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void updateLongestLineWidth(); - void invalidateEditor(); + void invalidateEditor( bool dirtyScroll = true ); void invalidateLongestLineWidth(); diff --git a/projects/linux/ee.creator.user b/projects/linux/ee.creator.user index d457e3e1e..643ea7a65 100644 --- a/projects/linux/ee.creator.user +++ b/projects/linux/ee.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -186,7 +186,7 @@ true - --with-mojoal gmake + --with-mojoal --with-mold-linker gmake premake4 %{buildDir}../../../ ProjectExplorer.ProcessStep diff --git a/src/eepp/graphics/renderer/renderergl3.cpp b/src/eepp/graphics/renderer/renderergl3.cpp index 97b47e768..1c4a4e346 100644 --- a/src/eepp/graphics/renderer/renderergl3.cpp +++ b/src/eepp/graphics/renderer/renderergl3.cpp @@ -7,17 +7,17 @@ namespace EE { namespace Graphics { -const char* EEGL3_STATES_NAME[] = {"dgl_Vertex", "dgl_Normal", "dgl_FrontColor"}; +const char* EEGL3_STATES_NAME[] = { "dgl_Vertex", "dgl_Normal", "dgl_FrontColor" }; -const char* EEGL3_TEXTUREUNIT_NAMES[] = {"dgl_MultiTexCoord0", "dgl_MultiTexCoord1", - "dgl_MultiTexCoord2", "dgl_MultiTexCoord3"}; +const char* EEGL3_TEXTUREUNIT_NAMES[] = { "dgl_MultiTexCoord0", "dgl_MultiTexCoord1", + "dgl_MultiTexCoord2", "dgl_MultiTexCoord3" }; -const char* EEGL3_PLANES_ENABLED_NAME[] = {"dgl_ClipEnabled[0]", "dgl_ClipEnabled[1]", - "dgl_ClipEnabled[2]", "dgl_ClipEnabled[3]", - "dgl_ClipEnabled[4]", "dgl_ClipEnabled[5]"}; +const char* EEGL3_PLANES_ENABLED_NAME[] = { "dgl_ClipEnabled[0]", "dgl_ClipEnabled[1]", + "dgl_ClipEnabled[2]", "dgl_ClipEnabled[3]", + "dgl_ClipEnabled[4]", "dgl_ClipEnabled[5]" }; -const char* EEGL3_PLANES_NAME[] = {"dgl_ClipPlane[0]", "dgl_ClipPlane[1]", "dgl_ClipPlane[2]", - "dgl_ClipPlane[3]", "dgl_ClipPlane[4]", "dgl_ClipPlane[5]"}; +const char* EEGL3_PLANES_NAME[] = { "dgl_ClipPlane[0]", "dgl_ClipPlane[1]", "dgl_ClipPlane[2]", + "dgl_ClipPlane[3]", "dgl_ClipPlane[4]", "dgl_ClipPlane[5]" }; #ifdef EE_GLES2 const GLchar* GL3_SHADER_HEAD = "precision mediump float;\nprecision lowp int;\n"; @@ -88,7 +88,8 @@ void RendererGL3::init() { mShaders[EEGL3_SHADER_BASE] = ShaderProgram::New( vs.c_str(), vs.size(), fs.c_str(), fs.size() ); - mShaders[EEGL3_SHADER_BASE]->setReloadCb( cb::Make1( this, &RendererGL3::reloadShader ) ); + mShaders[EEGL3_SHADER_BASE]->setReloadCb( + [&]( ShaderProgram* sp ) { reloadShader( sp ); } ); Shader::ensure( true ); @@ -323,7 +324,7 @@ void RendererGL3::disableClientState( unsigned int array ) { } void RendererGL3::vertexPointer( int size, unsigned int type, int stride, const void* pointer, - unsigned int allocate ) { + unsigned int /*allocate*/ ) { const int index = mAttribsLoc[EEGL_VERTEX_ARRAY]; if ( -1 != index ) { @@ -338,7 +339,7 @@ void RendererGL3::vertexPointer( int size, unsigned int type, int stride, const } void RendererGL3::colorPointer( int size, unsigned int type, int stride, const void* pointer, - unsigned int allocate ) { + unsigned int /*allocate*/ ) { const int index = mAttribsLoc[EEGL_COLOR_ARRAY]; if ( -1 != index ) { @@ -357,7 +358,7 @@ void RendererGL3::colorPointer( int size, unsigned int type, int stride, const v } void RendererGL3::texCoordPointer( int size, unsigned int type, int stride, const void* pointer, - unsigned int allocate ) { + unsigned int /*allocate*/ ) { const int index = mTextureUnits[mCurActiveTex]; if ( -1 != index ) { diff --git a/src/eepp/scene/node.cpp b/src/eepp/scene/node.cpp index 3477485a0..8684c590f 100644 --- a/src/eepp/scene/node.cpp +++ b/src/eepp/scene/node.cpp @@ -759,6 +759,20 @@ Node* Node::find( const std::string& id ) const { return findIdHash( String::hash( id ) ); } +Node* Node::hasChildHash( const String::HashType& idHash ) const { + Node* child = mChild; + while ( NULL != child ) { + if ( child->getIdHash() == idHash ) + return child; + child = child->mNext; + } + return nullptr; +} + +Node* Node::hasChild( const std::string& id ) const { + return hasChildHash( String::hash( id ) ); +} + Node* Node::findByType( const Uint32& type ) const { if ( !isClosing() && isType( type ) ) { return const_cast( this ); @@ -1104,6 +1118,15 @@ Uint32 Node::addEventListener( const Uint32& eventType, const EventCallback& cal return mNumCallBacks; } +Uint32 Node::addMouseClickListener( const std::function& callback, + const MouseButton& button ) { + return addEventListener( Event::MouseClick, [callback, button]( const Event* event ) { + if ( event->asMouseEvent()->getFlags() & ( EE_BUTTON_MASK( button ) ) ) { + callback( event->asMouseEvent() ); + } + } ); +} + void Node::removeEventsOfType( const Uint32& eventType ) { auto it = mEvents.find( eventType ); if ( it != mEvents.end() ) diff --git a/src/eepp/ui/css/stylesheetspecification.cpp b/src/eepp/ui/css/stylesheetspecification.cpp index f6fa8f9aa..f2dd33045 100644 --- a/src/eepp/ui/css/stylesheetspecification.cpp +++ b/src/eepp/ui/css/stylesheetspecification.cpp @@ -150,7 +150,7 @@ void StyleSheetSpecification::registerDefaultProperties() { .addAlias( "layout_weight" ) .addAlias( "lw8" ) .setType( PropertyType::NumberFloat ); - registerProperty( "layout-gravity", "" ).addAlias( "layout_gravity" ); + registerProperty( "layout-gravity", "" ).addAlias( "layout_gravity" ).addAlias( "lg" ); registerProperty( "layout-width", "" ).addAlias( "layout_width" ).addAlias( "lw" ); registerProperty( "layout-height", "" ).addAlias( "layout_height" ).addAlias( "lh" ); registerProperty( "layout-to-left-of", "" ).addAlias( "layout_to_left_of" ); diff --git a/src/eepp/ui/uicheckbox.cpp b/src/eepp/ui/uicheckbox.cpp index 19e50e262..e1bb6beb6 100644 --- a/src/eepp/ui/uicheckbox.cpp +++ b/src/eepp/ui/uicheckbox.cpp @@ -136,7 +136,7 @@ void UICheckBox::switchState() { setChecked( !mChecked ); } -void UICheckBox::setChecked( const bool& checked ) { +UICheckBox* UICheckBox::setChecked( const bool& checked ) { if ( !checked ) { mActiveButton->setVisible( false ); mInactiveButton->setVisible( true ); @@ -156,6 +156,8 @@ void UICheckBox::setChecked( const bool& checked ) { alignFix(); onValueChange(); + + return this; } const bool& UICheckBox::isChecked() const { @@ -177,13 +179,13 @@ void UICheckBox::alignFix() { switch ( Font::getHorizontalAlign( getFlags() ) ) { case UI_HALIGN_CENTER: - mRealAlignOffset.x = - ( Float )( ( Int32 )( ( mSize.x - mPaddingPx.Left - mPaddingPx.Right - - mTextCache->getTextWidth() - - mActiveButton->getPixelsSize().getWidth() + - PixelDensity::dpToPx( mTextSeparation ) ) / - 2.f ) ) + - mActiveButton->getPixelsSize().getWidth() + PixelDensity::dpToPx( mTextSeparation ); + mRealAlignOffset.x = (Float)( (Int32)( ( mSize.x - mPaddingPx.Left - mPaddingPx.Right - + mTextCache->getTextWidth() - + mActiveButton->getPixelsSize().getWidth() + + PixelDensity::dpToPx( mTextSeparation ) ) / + 2.f ) ) + + mActiveButton->getPixelsSize().getWidth() + + PixelDensity::dpToPx( mTextSeparation ); break; case UI_HALIGN_RIGHT: mRealAlignOffset.x = ( (Float)mSize.x - mPaddingPx.Left - mPaddingPx.Right - diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index 606a4bc6e..e6aa6f9e4 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -776,8 +776,9 @@ bool UICodeEditor::isDirty() const { return mDoc->isDirty(); } -void UICodeEditor::invalidateEditor() { +void UICodeEditor::invalidateEditor( bool dirtyScroll ) { mDirtyEditor = true; + mDirtyScroll = dirtyScroll; } void UICodeEditor::invalidateLongestLineWidth() { @@ -1295,12 +1296,12 @@ void UICodeEditor::drawCursor( const Vector2f& startScroll, const Float& lineHei void UICodeEditor::onSizeChange() { UIWidget::onSizeChange(); - invalidateEditor(); + invalidateEditor( false ); } void UICodeEditor::onPaddingChange() { UIWidget::onPaddingChange(); - invalidateEditor(); + invalidateEditor( false ); } void UICodeEditor::findLongestLine() { @@ -1428,10 +1429,11 @@ void UICodeEditor::scrollToCursor( bool centered ) { void UICodeEditor::updateEditor() { mDoc->setPageSize( getVisibleLinesCount() ); - if ( mDoc->getActiveClient() == this ) + if ( mDirtyScroll && mDoc->getActiveClient() == this ) scrollTo( mDoc->getSelection().start() ); updateScrollBar(); mDirtyEditor = false; + mDirtyScroll = false; } void UICodeEditor::onDocumentTextChanged() { diff --git a/src/eepp/ui/uitabwidget.cpp b/src/eepp/ui/uitabwidget.cpp index 50640b2c4..612bcfc00 100644 --- a/src/eepp/ui/uitabwidget.cpp +++ b/src/eepp/ui/uitabwidget.cpp @@ -249,8 +249,10 @@ bool UITabWidget::applyProperty( const StyleSheetProperty& attribute ) { break; case PropertyId::TabAllowSwitchTabsInEmptySpaces: setAllowSwitchTabsInEmptySpaces( attribute.asBool() ); + break; case PropertyId::DroppableHoveringColor: setDroppableHoveringColor( attribute.asColor() ); + break; default: return UIWidget::applyProperty( attribute ); } diff --git a/src/tools/ecode/appconfig.cpp b/src/tools/ecode/appconfig.cpp index e589ca116..b046e0653 100644 --- a/src/tools/ecode/appconfig.cpp +++ b/src/tools/ecode/appconfig.cpp @@ -78,6 +78,7 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath, ui.monospaceFont = ini.getValue( "ui", "monospace_font", "fonts/DejaVuSansMono.ttf" ); ui.terminalFont = ini.getValue( "ui", "terminal_font", "fonts/DejaVuSansMonoNerdFontComplete.ttf" ); + ui.fallbackFont = ini.getValue( "ui", "fallback_font", "fonts/DroidSansFallbackFull.ttf" ); ui.colorScheme = ini.getValue( "ui", "ui_color_scheme", "dark" ) == "light" ? ColorSchemePreference::Light : ColorSchemePreference::Dark; @@ -179,6 +180,7 @@ void AppConfig::save( const std::vector& recentFiles, ini.setValue( "ui", "serif_font", ui.serifFont ); ini.setValue( "ui", "monospace_font", ui.monospaceFont ); ini.setValue( "ui", "terminal_font", ui.terminalFont ); + ini.setValue( "ui", "fallback_font", ui.fallbackFont ); ini.setValue( "ui", "ui_color_scheme", ui.colorScheme == ColorSchemePreference::Light ? "light" : "dark" ); ini.setValueB( "document", "trim_trailing_whitespaces", doc.trimTrailingWhitespaces ); diff --git a/src/tools/ecode/appconfig.hpp b/src/tools/ecode/appconfig.hpp index fea624601..d595fea05 100644 --- a/src/tools/ecode/appconfig.hpp +++ b/src/tools/ecode/appconfig.hpp @@ -29,6 +29,7 @@ struct UIConfig { std::string serifFont; std::string monospaceFont; std::string terminalFont; + std::string fallbackFont; ColorSchemePreference colorScheme{ ColorSchemePreference::Dark }; }; diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index de4213c56..fd785144d 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -221,15 +221,18 @@ void App::openFontDialog( std::string& fontPath, bool loadingMonoFont ) { if ( String::startsWith( newPath, mResPath ) ) newPath = newPath.substr( mResPath.size() ); if ( fontPath != newPath ) { - fontPath = newPath; - if ( !loadingMonoFont ) + if ( !loadingMonoFont ) { + fontPath = newPath; return; + } auto fontName = - FileSystem::fileRemoveExtension( FileSystem::fileNameFromPath( fontPath ) ); - FontTrueType* fontMono = loadFont( fontName, fontPath ); + FileSystem::fileRemoveExtension( FileSystem::fileNameFromPath( newPath ) ); + FontTrueType* fontMono = loadFont( fontName, newPath ); if ( fontMono ) { - auto loadMonoFont = [&]( FontTrueType* fontMono ) { + auto loadMonoFont = [&, newPath]( FontTrueType* fontMono ) { + fontPath = newPath; mFontMono = fontMono; + mFontMono->setEnableFallbackFont( false ); mFontMono->setBoldAdvanceSameAsRegular( true ); if ( mSplitter ) { mSplitter->forEachEditor( @@ -442,6 +445,13 @@ bool App::trySendUnlockedCmd( const KeyEvent& keyEvent ) { mSplitter->getCurEditor()->getDocument().execute( cmd ); return true; } + } else if ( mSplitter->curWidgetExists() && + mSplitter->getCurWidget()->isType( UI_TYPE_TERMINAL ) ) { + UITerminal* terminal = mSplitter->getCurWidget()->asType(); + std::string cmd = terminal->getKeyBindings().getCommandFromKeyBind( + { keyEvent.getKeyCode(), keyEvent.getMod() } ); + if ( !cmd.empty() ) + terminal->execute( cmd ); } return false; } @@ -536,28 +546,36 @@ App::~App() { eeSAFE_DELETE( mConsole ); } -void App::checkWidgetPick( UITreeView* widgetTree ) { +void App::checkWidgetPick( UITreeView* widgetTree, bool wasHighlightOver ) { Input* input = mWindow->getInput(); if ( input->getClickTrigger() & EE_BUTTON_LMASK ) { Node* node = mUISceneNode->getEventDispatcher()->getMouseOverNode(); WidgetTreeModel* model = static_cast( widgetTree->getModel() ); ModelIndex index( model->getModelIndex( node ) ); widgetTree->setSelection( index ); - mUISceneNode->setHighlightOver( false ); + mUISceneNode->setHighlightOver( wasHighlightOver ); mUISceneNode->getEventDispatcher()->setDisableMousePress( false ); } else { - mUISceneNode->runOnMainThread( [this, widgetTree]() { checkWidgetPick( widgetTree ); } ); + mUISceneNode->runOnMainThread( [this, widgetTree, wasHighlightOver]() { + checkWidgetPick( widgetTree, wasHighlightOver ); + } ); } } -void App::createWidgetTreeView() { +void App::createWidgetInspector() { + if ( mUISceneNode->getRoot()->hasChild( "widget-tree-view" ) ) + return; UIWindow* uiWin = UIWindow::New(); + uiWin->setId( "widget-tree-view" ); uiWin->setMinWindowSize( 600, 400 ); uiWin->setWindowFlags( UI_WIN_DEFAULT_FLAGS | UI_WIN_RESIZEABLE | UI_WIN_MAXIMIZE_BUTTON ); UIWidget* cont = mUISceneNode->loadLayoutFromString( R"xml( - - + + + + + @@ -574,12 +592,31 @@ void App::createWidgetTreeView() { UIPushButton* button = cont->find( "pick_widget" ); button->addEventListener( Event::MouseClick, [&, widgetTree]( const Event* event ) { if ( event->asMouseEvent()->getFlags() & EE_BUTTON_LMASK ) { + bool wasHighlightOver = mUISceneNode->getHighlightOver(); mUISceneNode->setHighlightOver( true ); mUISceneNode->getEventDispatcher()->setDisableMousePress( true ); - mUISceneNode->runOnMainThread( - [this, widgetTree]() { checkWidgetPick( widgetTree ); } ); + mUISceneNode->runOnMainThread( [this, widgetTree, wasHighlightOver]() { + checkWidgetPick( widgetTree, wasHighlightOver ); + } ); } } ); + + cont->find( "debug-draw-highlight" ) + ->setChecked( mUISceneNode->getHighlightOver() ) + ->addEventListener( Event::OnValueChange, [this]( const auto* ) { + runCommand( "debug-draw-highlight-toggle" ); + } ); + + cont->find( "debug-draw-boxes" ) + ->setChecked( mUISceneNode->getDrawBoxes() ) + ->addEventListener( Event::OnValueChange, + [this]( const auto* ) { runCommand( "debug-draw-boxes-toggle" ); } ); + + cont->find( "debug-draw-debug-data" ) + ->setChecked( mUISceneNode->getDrawDebugData() ) + ->addEventListener( Event::OnValueChange, + [this]( const auto* ) { runCommand( "debug-draw-debug-data" ); } ); + uiWin->center(); } @@ -753,6 +790,8 @@ UIMenu* App::createWindowMenu() { ->setId( "monospace-font" ); mWindowMenu->add( i18n( "terminal_font", "Terminal Font..." ), findIcon( "font-size" ) ) ->setId( "terminal-font" ); + mWindowMenu->add( i18n( "fallback_font", "Fallback Font..." ), findIcon( "font-size" ) ) + ->setId( "fallback-font" ); mWindowMenu->addSeparator(); mWindowMenu ->addCheckBox( i18n( "fullscreen_mode", "Full Screen Mode" ), false, @@ -928,6 +967,8 @@ UIMenu* App::createWindowMenu() { openFontDialog( mConfig.ui.monospaceFont, true ); } else if ( item->getId() == "terminal-font" ) { openFontDialog( mConfig.ui.terminalFont, false ); + } else if ( item->getId() == "fallback-font" ) { + openFontDialog( mConfig.ui.fallbackFont, false ); } else if ( "zoom-in" == item->getId() ) { mSplitter->zoomIn(); } else if ( "zoom-out" == item->getId() ) { @@ -1276,13 +1317,20 @@ UIMenu* App::createTerminalMenu() { "avoid keyboard shortcut overlapping between the terminal an the application." ) ) ->setId( "exclusive-mode" ); + mTerminalMenu + ->add( i18n( "rename_session", "Rename Session" ), nullptr, + getKeybind( "terminal-rename" ) ) + ->setId( "terminal-rename" ); + mTerminalMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { const std::string& id( event->getNode()->getId() ); - if ( "exclusive-mode" == id ) { - if ( mSplitter->getCurWidget() && - mSplitter->getCurWidget()->isType( UI_TYPE_TERMINAL ) ) { - mSplitter->getCurWidget()->asType()->setExclusiveMode( + if ( mSplitter->getCurWidget() && mSplitter->getCurWidget()->isType( UI_TYPE_TERMINAL ) ) { + UITerminal* terminal = mSplitter->getCurWidget()->asType(); + if ( "exclusive-mode" == id ) { + terminal->setExclusiveMode( event->getNode()->asType()->isActive() ); + } else { + terminal->execute( id ); } } } ); @@ -1864,6 +1912,19 @@ void App::createPluginManagerUI() { } )->showWhenReady(); } +void App::debugDrawHighlightToggle() { + mUISceneNode->setHighlightFocus( !mUISceneNode->getHighlightFocus() ); + mUISceneNode->setHighlightOver( !mUISceneNode->getHighlightOver() ); +} + +void App::debugDrawBoxesToggle() { + mUISceneNode->setDrawBoxes( !mUISceneNode->getDrawBoxes() ); +} + +void App::debugDrawData() { + mUISceneNode->setDrawDebugData( !mUISceneNode->getDrawDebugData() ); +} + void App::updateDocumentMenu() { if ( !mSplitter->getCurWidget() || !mSplitter->getCurWidget()->isType( UI_TYPE_CODEEDITOR ) ) { mSettingsMenu->getItemId( "doc-menu" )->setEnabled( false ); @@ -2192,9 +2253,6 @@ std::map App::getLocalKeybindings() { { { KEY_O, KeyMod::getDefaultModifier() }, "open-file" }, { { KEY_W, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "download-file-web" }, { { KEY_O, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "open-folder" }, - { { KEY_F6, KEYMOD_NONE }, "debug-draw-highlight-toggle" }, - { { KEY_F7, KEYMOD_NONE }, "debug-draw-boxes-toggle" }, - { { KEY_F8, KEYMOD_NONE }, "debug-draw-debug-data" }, { { KEY_F11, KEYMOD_NONE }, "debug-widget-tree-view" }, { { KEY_K, KeyMod::getDefaultModifier() }, "open-locatebar" }, { { KEY_F, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "open-global-search" }, @@ -2295,14 +2353,14 @@ void App::createDocAlert( UICodeEditor* editor ) { const std::string& msg = R"xml( + tooltip='@string(tooltip_reload_file, "Reload the file from disk. Unsaved changes will be lost.")' /> + tooltip='@string(tooltip_write_local_changes, "Writes the local changes on disk, overwriting the disk changes")' /> + tooltip='@string(tooltip_ignore_file_changes, "Ignores the changes on disk without any action.")' /> )xml"; docAlert = mUISceneNode->loadLayoutFromString( msg, editor )->asType(); @@ -2494,15 +2552,10 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) { } } ); doc.setCommand( "keybindings", [&] { loadFileFromPath( mKeybindingsPath ); } ); - doc.setCommand( "debug-draw-boxes-toggle", - [&] { mUISceneNode->setDrawBoxes( !mUISceneNode->getDrawBoxes() ); } ); - doc.setCommand( "debug-draw-highlight-toggle", [&] { - mUISceneNode->setHighlightFocus( !mUISceneNode->getHighlightFocus() ); - mUISceneNode->setHighlightOver( !mUISceneNode->getHighlightOver() ); - } ); - doc.setCommand( "debug-draw-debug-data", - [&] { mUISceneNode->setDrawDebugData( !mUISceneNode->getDrawDebugData() ); } ); - doc.setCommand( "debug-widget-tree-view", [&] { createWidgetTreeView(); } ); + doc.setCommand( "debug-draw-boxes-toggle", [&] { debugDrawBoxesToggle(); } ); + doc.setCommand( "debug-draw-highlight-toggle", [&] { debugDrawHighlightToggle(); } ); + doc.setCommand( "debug-draw-debug-data", [&] { debugDrawData(); } ); + doc.setCommand( "debug-widget-tree-view", [&] { createWidgetInspector(); } ); doc.setCommand( "go-to-line", [&] { mFileLocator->goToLine(); } ); doc.setCommand( "load-current-dir", [&] { loadCurrentDirectory(); } ); doc.setCommand( "menu-toggle", [&] { toggleSettingsMenu(); } ); @@ -3535,8 +3588,10 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe mFont = loadFont( "sans-serif", mConfig.ui.serifFont, "fonts/NotoSans-Regular.ttf" ); mFontMono = loadFont( "monospace", mConfig.ui.monospaceFont, "fonts/DejaVuSansMono.ttf" ); - if ( mFontMono ) + if ( mFontMono ) { + mFontMono->setEnableFallbackFont( false ); mFontMono->setBoldAdvanceSameAsRegular( true ); + } loadFont( "NotoEmoji-Regular", "fonts/NotoEmoji-Regular.ttf" ); @@ -3553,8 +3608,12 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe return; } - mFontMonoNerdFont = - loadFont( "monospace-nerdfont", "fonts/DejaVuSansMonoNerdFontComplete.ttf" ); + mTerminalFont = loadFont( "monospace-nerdfont", mConfig.ui.terminalFont, + "fonts/DejaVuSansMonoNerdFontComplete.ttf" ); + + mFallbackFont = loadFont( "fallback-font", "fonts/DroidSansFallbackFull.ttf" ); + if ( mFallbackFont ) + FontManager::instance()->setFallbackFont( mFallbackFont ); SceneManager::instance()->add( mUISceneNode ); @@ -3686,9 +3745,9 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe - + - + @@ -3715,25 +3774,25 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe - - + + - - + + - - + + - - - + + + @@ -3743,21 +3802,21 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe - + - - - - + + + + - + - - - + + + @@ -3832,6 +3891,7 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe { "match-case", 0xed8d }, { "palette", 0xefc5 }, { "file-code", 0xecd1 }, + { "cursor-pointer", 0xec09 }, }; for ( const auto& icon : icons ) iconTheme->add( UIGlyphIcon::New( icon.first, iconFont, icon.second ) ); diff --git a/src/tools/ecode/ecode.hpp b/src/tools/ecode/ecode.hpp index 7a4af1a5b..add1fe23a 100644 --- a/src/tools/ecode/ecode.hpp +++ b/src/tools/ecode/ecode.hpp @@ -30,7 +30,7 @@ class App : public UICodeEditorSplitter::Client { ~App(); - void createWidgetTreeView(); + void createWidgetInspector(); void init( const LogLevel& logLevel, std::string file, const Float& pidelDensity, const std::string& colorScheme, bool terminal, bool frameBuffer, @@ -111,10 +111,12 @@ class App : public UICodeEditorSplitter::Client { const std::string& resPath() const { return mResPath; } - Font* getFontMonoNerdFont() const { return mFontMonoNerdFont; } + Font* getTerminalFont() const { return mTerminalFont; } Font* getFontMono() const { return mFontMono; } + Font* getFallbackFont() const { return mFallbackFont; } + const Float& getDisplayDPI() const { return mDisplayDPI; } const std::string& getCurrentProject() const { return mCurrentProject; } @@ -147,6 +149,12 @@ class App : public UICodeEditorSplitter::Client { void createPluginManagerUI(); + void debugDrawHighlightToggle(); + + void debugDrawBoxesToggle(); + + void debugDrawData(); + protected: EE::Window::Window* mWindow{ nullptr }; UISceneNode* mUISceneNode{ nullptr }; @@ -210,7 +218,8 @@ class App : public UICodeEditorSplitter::Client { std::string mCurrentProject; FontTrueType* mFont{ nullptr }; FontTrueType* mFontMono{ nullptr }; - FontTrueType* mFontMonoNerdFont{ nullptr }; + FontTrueType* mTerminalFont{ nullptr }; + FontTrueType* mFallbackFont{ nullptr }; efsw::FileWatcher* mFileWatcher{ nullptr }; FileSystemListener* mFileSystemListener{ nullptr }; Mutex mWatchesLock; @@ -348,7 +357,7 @@ class App : public UICodeEditorSplitter::Client { void initPluginManager(); - void checkWidgetPick( UITreeView* widgetTree ); + void checkWidgetPick( UITreeView* widgetTree, bool wasHighlightOver ); void onPluginEnabled( UICodeEditorPlugin* plugin ); }; diff --git a/src/tools/ecode/globalsearchcontroller.cpp b/src/tools/ecode/globalsearchcontroller.cpp index 18285dc3b..1e5e6d67e 100644 --- a/src/tools/ecode/globalsearchcontroller.cpp +++ b/src/tools/ecode/globalsearchcontroller.cpp @@ -89,7 +89,10 @@ void GlobalSearchController::initGlobalSearchBar( luaPatternChk->setTooltipText( kbind.getCommandKeybindString( "toggle-lua-pattern" ) ); UICheckBox* escapeSequenceChk = mGlobalSearchBarLayout->find( "escape_sequence" ); - escapeSequenceChk->setTooltipText( kbind.getCommandKeybindString( "change-escape-sequence" ) ); + std::string kbindEscape = kbind.getCommandKeybindString( "change-escape-sequence" ); + if ( !kbindEscape.empty() ) + escapeSequenceChk->setTooltipText( escapeSequenceChk->getTooltipText() + " (" + + kbindEscape + ")" ); UIWidget* searchBarClose = mGlobalSearchBarLayout->find( "global_searchbar_close" ); diff --git a/src/tools/ecode/terminalmanager.cpp b/src/tools/ecode/terminalmanager.cpp index 2913affdf..5e6825a46 100644 --- a/src/tools/ecode/terminalmanager.cpp +++ b/src/tools/ecode/terminalmanager.cpp @@ -165,7 +165,7 @@ UITerminal* TerminalManager::createNewTerminal( const std::string& title, UITabW } } UITerminal* term = UITerminal::New( - mApp->getFontMonoNerdFont() ? mApp->getFontMonoNerdFont() : mApp->getFontMono(), + mApp->getTerminalFont() ? mApp->getTerminalFont() : mApp->getFontMono(), mApp->termConfig().fontSize.asPixels( 0, Sizef(), mApp->getDisplayDPI() ), Sizef( 16, 16 ), "", {}, !workingDir.empty() @@ -345,10 +345,10 @@ UITerminal* TerminalManager::createNewTerminal( const std::string& title, UITabW } ); term->setCommand( "reopen-closed-tab", [&] { mApp->reopenClosedTab(); } ); term->setCommand( "plugin-manager", [&] { mApp->createPluginManagerUI(); } ); - // debug-draw-highlight-toggle - // debug-draw-boxes-toggle - // debug-draw-debug-data - // debug-widget-tree-view + term->setCommand( "debug-draw-boxes-toggle", [&] { mApp->debugDrawBoxesToggle(); } ); + term->setCommand( "debug-draw-highlight-toggle", [&] { mApp->debugDrawHighlightToggle(); } ); + term->setCommand( "debug-draw-debug-data", [&] { mApp->debugDrawData(); } ); + term->setCommand( "debug-widget-tree-view", [&] { mApp->createWidgetInspector(); } ); term->setFocus(); return term; #endif diff --git a/src/tools/eterm/eterm.cpp b/src/tools/eterm/eterm.cpp index b37d6dc58..8560e5ef5 100644 --- a/src/tools/eterm/eterm.cpp +++ b/src/tools/eterm/eterm.cpp @@ -214,7 +214,9 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) { ->loadFromFile( resPath + "fonts/NotoEmoji-Regular.ttf" ); } - std::string fallbackFontPath( fallbackFontPathF.Get() ); + std::string fallbackFontPath( fallbackFontPathF + ? fallbackFontPathF.Get() + : resPath + "fonts/DroidSansFallbackFull.ttf" ); if ( FileSystem::fileExists( fallbackFontPath ) ) { FontTrueType* fallbackFont = FontTrueType::New( "fallback-font" ); if ( fallbackFont->loadFromFile( fallbackFontPath ) )