diff --git a/include/eepp/ui/css/propertydefinition.hpp b/include/eepp/ui/css/propertydefinition.hpp index 4525ef866..8205dee39 100644 --- a/include/eepp/ui/css/propertydefinition.hpp +++ b/include/eepp/ui/css/propertydefinition.hpp @@ -247,6 +247,7 @@ enum class PropertyId : Uint32 { Bottom = String::hash( "bottom" ), Left = String::hash( "left" ), ZIndex = String::hash( "z-index" ), + DataLanguage = String::hash( "data-language" ), // Minor hack }; enum class PropertyType : Uint32 { diff --git a/include/eepp/ui/uihtmlwidget.hpp b/include/eepp/ui/uihtmlwidget.hpp index 1e9e2e04a..9bdf461f3 100644 --- a/include/eepp/ui/uihtmlwidget.hpp +++ b/include/eepp/ui/uihtmlwidget.hpp @@ -56,6 +56,7 @@ class EE_API UIHTMLWidget : public UILayout { Rectf mOffsets{ 0, 0, 0, 0 }; int mZIndex{ 0 }; UILayouter* mLayouter{ nullptr }; + UnorderedMap mDataProperties; }; }} // namespace EE::UI diff --git a/include/eepp/version.hpp b/include/eepp/version.hpp index 6fe91c64e..cb5f61ff3 100644 --- a/include/eepp/version.hpp +++ b/include/eepp/version.hpp @@ -4,10 +4,10 @@ #include #include -#define EEPP_MAJOR_VERSION 2 -#define EEPP_MINOR_VERSION 9 -#define EEPP_PATCH_LEVEL 2 -#define EEPP_CODENAME "Sādhanā" +#define EEPP_MAJOR_VERSION 3 +#define EEPP_MINOR_VERSION 0 +#define EEPP_PATCH_LEVEL 0 +#define EEPP_CODENAME "Khaya" /** The compiled version of the library */ #define EEPP_VERSION( x ) \ diff --git a/src/eepp/ui/blocklayouter.cpp b/src/eepp/ui/blocklayouter.cpp index 75945eeea..28baa9e46 100644 --- a/src/eepp/ui/blocklayouter.cpp +++ b/src/eepp/ui/blocklayouter.cpp @@ -54,6 +54,8 @@ void BlockLayouter::updateLayout() { mResizedCount = 0; mPacking = true; + mContainer->beginAttributesTransaction(); + setMatchParentIfNeededVerticalGrowth(); const StyleSheetProperty* prop = nullptr; @@ -94,6 +96,8 @@ void BlockLayouter::updateLayout() { mContainer->getLayoutHeightPolicy() == SizePolicy::WrapContent ) mContainer->setInternalPixelsHeight( totH ); + mContainer->endAttributesTransaction(); + if ( mResizedCount > 0 ) positionRichTextChildren( rt ); diff --git a/src/eepp/ui/css/stylesheetspecification.cpp b/src/eepp/ui/css/stylesheetspecification.cpp index 378b01d54..e0b6f043c 100644 --- a/src/eepp/ui/css/stylesheetspecification.cpp +++ b/src/eepp/ui/css/stylesheetspecification.cpp @@ -456,6 +456,8 @@ void StyleSheetSpecification::registerDefaultProperties() { registerProperty( "display-options", "" ).setType( PropertyType::String ); registerProperty( "menu-width-mode", "" ).setType( PropertyType::String ); + registerProperty( "data-language", "" ).setType( PropertyType::String ); + // Shorthands registerShorthand( "margin", { "margin-top", "margin-right", "margin-bottom", "margin-left" }, "box" ); diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index 8755f2c04..f6673687f 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -3055,6 +3055,10 @@ bool UICodeEditor::applyProperty( const StyleSheetProperty& attribute ) { case PropertyId::Text: mDoc->textInput( attribute.asString() ); break; + case PropertyId::DataLanguage: + setSyntaxDefinition( + SyntaxDefinitionManager::instance()->findFromString( attribute.asString() ) ); + break; default: return UIWidget::applyProperty( attribute ); } @@ -5697,13 +5701,46 @@ void UICodeEditor::loadFromXmlNode( const pugi::xml_node& node ) { UIWidget::loadFromXmlNode( node ); - if ( !node.text().empty() ) { - std::string_view str{ node.text().as_string() }; - if ( '\n' == str.back() ) - str = str.substr( 0, str.size() - 1 ); - mDoc->textInput( str ); + std::string text; + bool hasElementChildren = false; + for ( pugi::xml_node child : node.children() ) { + if ( child.type() == pugi::node_element ) { + hasElementChildren = true; + break; + } } + auto collectText = []( const pugi::xml_node& n, std::string& out, auto& self ) -> void { + for ( pugi::xml_node c : n.children() ) { + if ( c.type() == pugi::node_pcdata || c.type() == pugi::node_cdata ) { + out += c.value(); + } else if ( c.type() == pugi::node_element ) { + self( c, out, self ); + } + } + }; + + if ( hasElementChildren ) { + for ( pugi::xml_node child : node.children() ) { + if ( child.type() == pugi::node_element ) { + if ( !text.empty() ) + text += "\n"; + collectText( child, text, collectText ); + } + } + } else { + for ( pugi::xml_node child : node.children() ) { + if ( child.type() == pugi::node_pcdata || child.type() == pugi::node_cdata ) { + text += child.value(); + } + } + if ( !text.empty() && text.back() == '\n' ) + text.pop_back(); + } + + if ( !text.empty() ) + mDoc->textInput( text ); + endAttributesTransaction(); } diff --git a/src/eepp/ui/uirichtext.cpp b/src/eepp/ui/uirichtext.cpp index 08108ef1b..b0d424401 100644 --- a/src/eepp/ui/uirichtext.cpp +++ b/src/eepp/ui/uirichtext.cpp @@ -50,7 +50,9 @@ UIHTMLBody* UIHTMLBody::New( const std::string& tag ) { return eeNew( UIHTMLBody, ( tag ) ); } -UIHTMLBody::UIHTMLBody( const std::string& tag ) : UIRichText( tag ) {} +UIHTMLBody::UIHTMLBody( const std::string& tag ) : UIRichText( tag ) { + enableReportSizeChangeToChildren(); +} Uint32 UIHTMLBody::getType() const { return UI_TYPE_HTML_BODY; @@ -228,6 +230,13 @@ bool UIRichText::applyProperty( const StyleSheetProperty& attribute ) { setTextAlign( TEXT_ALIGN_RIGHT ); break; } + case PropertyId::DataLanguage: { + if ( mTag == "pre" && mChild && mChild->isType( UI_TYPE_CODEEDITOR ) ) { + mChild->asType()->applyProperty( attribute ); + } else + mDataProperties["data-language"] = attribute; + break; + } default: return UILayout::applyProperty( attribute ); } @@ -479,6 +488,11 @@ void UIRichText::loadFromXmlNode( const pugi::xml_node& node ) { editor->setShowLineNumber( false ); editor->setShowFoldingRegion( false ); editor->setLocked( true ); + + auto langIt = mDataProperties.find( "data-language" ); + if ( langIt != mDataProperties.end() ) { + editor->applyProperty( langIt->second ); + } } } else { // Let parent logic load standard child widget diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 8b0761408..21028d268 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -3236,7 +3236,7 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) { auto splitter = getSplitter(); auto editor = static_cast( client ); auto doc = editor->getDocumentRef(); - auto scrollView = UIScrollView::New(); + auto scrollView = UIScrollViewCommandExecuter::New(); auto mdView = UIMarkdownView::New(); mdView->setParent( scrollView ); @@ -3274,11 +3274,14 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) { mdView->loadFromString( doc->toUtf8String() ); auto title = - i18n( "markdown_live_preview_ellipsis", "Markdown Live Preview:" ) + " " + + i18n( "markdown_live_preview_colon", "Markdown Live Preview:" ) + " " + doc->getFilename(); auto [tab, _] = getSplitter()->createWidgetInTabWidget( tabWidget, scrollView, title ); tab->setIcon( findIcon( "filetype-md" ) ); + tab->setTooltipText( title ); + + registerUnlockedCommands( *scrollView ); if ( removeUnusedEditor ) splitter->removeUnusedTab( tabWidget ); diff --git a/src/tools/ecode/version.hpp b/src/tools/ecode/version.hpp index 500ca8d33..f318c30f0 100644 --- a/src/tools/ecode/version.hpp +++ b/src/tools/ecode/version.hpp @@ -7,13 +7,13 @@ using namespace EE; #define ECODE_MAJOR_VERSION 0 -#define ECODE_MINOR_VERSION 7 -#define ECODE_PATCH_LEVEL 5 +#define ECODE_MINOR_VERSION 8 +#define ECODE_PATCH_LEVEL 0 /* ECODE_COMMIT_NUMBER 9999 is used for official releases, nightly builds (pre-releases) will * contain the number of commits after the last official release */ #define ECODE_COMMIT_NUMBER 9999 -#define ECODE_CODENAME "Vastiva" +#define ECODE_CODENAME "Kappa" /** The compiled version of the library */ #define ECODE_VERSION( x ) \ diff --git a/src/tools/ecode/widgetcommandexecuter.hpp b/src/tools/ecode/widgetcommandexecuter.hpp index 9d2fbe60c..ac1c7d0f8 100644 --- a/src/tools/ecode/widgetcommandexecuter.hpp +++ b/src/tools/ecode/widgetcommandexecuter.hpp @@ -97,6 +97,17 @@ class UIVLinearLayoutCommandExecuter : public UILinearLayout, public WidgetComma } }; +class UIScrollViewCommandExecuter : public UIScrollView, public WidgetCommandExecuter { + public: + static UIScrollViewCommandExecuter* New() { return eeNew( UIScrollViewCommandExecuter, () ); } + + UIScrollViewCommandExecuter() : UIScrollView(), WidgetCommandExecuter( getInput() ) {} + + virtual Uint32 onKeyDown( const KeyEvent& event ) { + return WidgetCommandExecuter::onKeyDown( event ) || UIScrollView::onKeyDown( event ); + } +}; + } // namespace ecode #endif // ECODE_WIDGETCOMMANDEXECUTER_HPP