From c1b03ca7af2f24822be2040d58a1318c48b5a882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sun, 27 Mar 2022 01:35:57 -0300 Subject: [PATCH] FontTrueType: Improved font kerning. Added FontTrueType::getGlyphByIndex. TextDocument: Added hasUndo, hasRedo. UICodeEditor: Improved default context menu. UITextInput: Added context menu. UIFileDialog: Minor improvents, localization and path selection. UIMessageBox: Improved localization. Fixed UITableView::findRowWithText and UITreeView::findRowWithText when doing case insensitive searches. ecode: Fix Sans Serif font selection was breaking the current opened code editors. --- bin/assets/ui/breeze.css | 7 +- bin/assets/ui/uitheme.css | 7 ++ include/eepp/graphics/font.hpp | 13 +-- include/eepp/graphics/fontbmfont.hpp | 2 +- include/eepp/graphics/fontsprite.hpp | 2 +- include/eepp/graphics/fonttruetype.hpp | 16 ++- include/eepp/graphics/text.hpp | 2 +- include/eepp/scene/scenenode.hpp | 6 -- include/eepp/ui/doc/textdocument.hpp | 4 + include/eepp/ui/doc/undostack.hpp | 4 + include/eepp/ui/uicodeeditor.hpp | 6 +- include/eepp/ui/uifiledialog.hpp | 2 +- include/eepp/ui/uitextinput.hpp | 20 ++++ include/eepp/ui/uiwidget.hpp | 4 + projects/linux/ee.creator.user | 2 +- src/eepp/graphics/fontbmfont.cpp | 4 +- src/eepp/graphics/fontsprite.cpp | 4 +- src/eepp/graphics/fonttruetype.cpp | 138 ++++++++++++++++--------- src/eepp/graphics/text.cpp | 22 ++-- src/eepp/ui/doc/textdocument.cpp | 8 ++ src/eepp/ui/doc/undostack.cpp | 8 ++ src/eepp/ui/uicodeeditor.cpp | 23 +++-- src/eepp/ui/uifiledialog.cpp | 54 ++++++---- src/eepp/ui/uilistbox.cpp | 33 +++--- src/eepp/ui/uimenu.cpp | 17 ++- src/eepp/ui/uimenubar.cpp | 4 +- src/eepp/ui/uimessagebox.cpp | 24 ++--- src/eepp/ui/uitableview.cpp | 2 +- src/eepp/ui/uitextinput.cpp | 86 ++++++++++++++- src/eepp/ui/uitextview.cpp | 13 ++- src/eepp/ui/uitreeview.cpp | 6 +- src/eepp/ui/uiwidget.cpp | 19 ++-- src/tools/codeeditor/codeeditor.cpp | 22 ++-- src/tools/codeeditor/codeeditor.hpp | 2 +- 34 files changed, 391 insertions(+), 195 deletions(-) diff --git a/bin/assets/ui/breeze.css b/bin/assets/ui/breeze.css index b42abd01a..e78716416 100644 --- a/bin/assets/ui/breeze.css +++ b/bin/assets/ui/breeze.css @@ -797,12 +797,17 @@ Menu::RadioButton::shortcut { Menu::Item:disabled > Menu::Item::text, Menu::Item:disabled > Menu::Item::shortcut, +Menu::Item:disabled > Menu::Item::icon, Menu::CheckBox:disabled > Menu::CheckBox::text, Menu::CheckBox:disabled > Menu::CheckBox::shortcut, +Menu::CheckBox:disabled > Menu::CheckBox::icon, Menu::RadioButton:disabled > Menu::RadioButton::text, Menu::RadioButton:disabled > Menu::RadioButton::shortcut, -Menu::SubMenu:disabled > Menu::SubMenu::text { +Menu::RadioButton:disabled > Menu::RadioButton::icon, +Menu::SubMenu:disabled > Menu::SubMenu::text, +Menu::SubMenu:disabled > Menu::SubMenu::icon { color: var(--menu-font-disabled); + tint: var(--menu-font-disabled); } Menu::Item:hover > Menu::Item::text, diff --git a/bin/assets/ui/uitheme.css b/bin/assets/ui/uitheme.css index fc75399d3..8df34232a 100644 --- a/bin/assets/ui/uitheme.css +++ b/bin/assets/ui/uitheme.css @@ -109,3 +109,10 @@ Tooltip { padding: 8dp; color: #020203; } + +Menu::Item::shortcut, +Menu::CheckBox::shortcut, +Menu::RadioButton::shortcut { + margin-right: 8dp; +} + diff --git a/include/eepp/graphics/font.hpp b/include/eepp/graphics/font.hpp index 09bf2ef2e..120de66fb 100644 --- a/include/eepp/graphics/font.hpp +++ b/include/eepp/graphics/font.hpp @@ -10,11 +10,11 @@ namespace EE { namespace Graphics { class EE_API Glyph { public: - Glyph() : advance( 0 ) {} - - Float advance; ///< Offset to move horizontally to the next character - Rectf bounds; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline - Rect textureRect; ///< Texture coordinates of the glyph inside the font's texture + Float advance{ 0 }; ///< Offset to move horizontally to the next character + Rectf bounds; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline + Rect textureRect; ///< Texture coordinates of the glyph inside the font's texture + int lsbDelta{ 0 }; //!< Left offset after forced autohint. Internally used by getKerning() + int rsbDelta{ 0 }; //!< Right offset after forced autohint. Internally used by getKerning() }; enum class FontType { TTF, BMF, Sprite }; @@ -86,7 +86,8 @@ class EE_API Font { bool bold = false, Float outlineThickness = 0 ) const = 0; - virtual Float getKerning( Uint32 first, Uint32 second, unsigned int characterSize ) const = 0; + virtual Float getKerning( Uint32 first, Uint32 second, unsigned int characterSize, + bool bold ) const = 0; virtual Float getLineSpacing( unsigned int characterSize ) const = 0; diff --git a/include/eepp/graphics/fontbmfont.hpp b/include/eepp/graphics/fontbmfont.hpp index 77c0dfa91..e8a3cada4 100644 --- a/include/eepp/graphics/fontbmfont.hpp +++ b/include/eepp/graphics/fontbmfont.hpp @@ -38,7 +38,7 @@ class EE_API FontBMFont : public Font { GlyphDrawable* getGlyphDrawable( Uint32 codePoint, unsigned int characterSize, bool bold = false, Float outlineThickness = 0 ) const; - Float getKerning( Uint32 first, Uint32 second, unsigned int characterSize ) const; + Float getKerning( Uint32 first, Uint32 second, unsigned int characterSize, bool bold ) const; Float getLineSpacing( unsigned int characterSize ) const; diff --git a/include/eepp/graphics/fontsprite.hpp b/include/eepp/graphics/fontsprite.hpp index f1e9c29b0..291870019 100644 --- a/include/eepp/graphics/fontsprite.hpp +++ b/include/eepp/graphics/fontsprite.hpp @@ -42,7 +42,7 @@ class EE_API FontSprite : public Font { GlyphDrawable* getGlyphDrawable( Uint32 codePoint, unsigned int characterSize, bool bold = false, Float outlineThickness = 0 ) const; - Float getKerning( Uint32 first, Uint32 second, unsigned int characterSize ) const; + Float getKerning( Uint32 first, Uint32 second, unsigned int characterSize, bool bold ) const; Float getLineSpacing( unsigned int characterSize ) const; diff --git a/include/eepp/graphics/fonttruetype.hpp b/include/eepp/graphics/fonttruetype.hpp index ed98bca72..2cf2b443b 100644 --- a/include/eepp/graphics/fonttruetype.hpp +++ b/include/eepp/graphics/fonttruetype.hpp @@ -33,10 +33,13 @@ class EE_API FontTrueType : public Font { const Glyph& getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold, Float outlineThickness = 0 ) const; + const Glyph& getGlyphByIndex( Uint32 index, unsigned int characterSize, bool bold, + Float outlineThickness = 0 ) const; + GlyphDrawable* getGlyphDrawable( Uint32 codePoint, unsigned int characterSize, bool bold = false, Float outlineThickness = 0 ) const; - Float getKerning( Uint32 first, Uint32 second, unsigned int characterSize ) const; + Float getKerning( Uint32 first, Uint32 second, unsigned int characterSize, bool bold ) const; Float getLineSpacing( unsigned int characterSize ) const; @@ -64,6 +67,8 @@ class EE_API FontTrueType : public Font { bool isEmojiFont() const { return mIsEmojiFont; } + bool hasGlyph( Uint32 codePoint ) const; + protected: explicit FontTrueType( const std::string& FontName ); @@ -94,6 +99,13 @@ class EE_API FontTrueType : public Font { void cleanup(); + const Glyph& getGlyphByIndex( Uint32 index, unsigned int characterSize, bool bold, + Float outlineThickness, Page& page, + const Float& forzeSize ) const; + + const Glyph& getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold, + Float outlineThickness, Page& page, const Float& forzeSize ) const; + Glyph loadGlyph( Uint32 codePoint, unsigned int characterSize, bool bold, Float outlineThickness, Page& page, const Float& forceSize = 0.f ) const; @@ -123,7 +135,7 @@ class EE_API FontTrueType : public Font { bool mIsEmojiFont{ false }; mutable std::map mClosestCharacterSize; - Uint64 getCodePointIndexKey( Uint32 codePoint, bool bold, Float outlineThickness ) const; + Uint64 getIndexKey( Uint32 index, bool bold, Float outlineThickness ) const; }; }} // namespace EE::Graphics diff --git a/include/eepp/graphics/text.hpp b/include/eepp/graphics/text.hpp index 9b5a3ccdc..41af48b40 100644 --- a/include/eepp/graphics/text.hpp +++ b/include/eepp/graphics/text.hpp @@ -125,7 +125,7 @@ class EE_API Text { /** Simulates a selection request and return the initial and end cursor position when the * selection worked. Otherwise both parameters will be -1. */ - void findWordFromCharacterIndex( Int32 characterIndex, Int32& InitCur, Int32& EndCur ) const; + void findWordFromCharacterIndex( Int32 characterIndex, Int32& initCur, Int32& endCur ) const; /** Shrink the String to a max width * @param MaxWidth The maximum possible width diff --git a/include/eepp/scene/scenenode.hpp b/include/eepp/scene/scenenode.hpp index ed3e2c1f7..e875a0cdb 100644 --- a/include/eepp/scene/scenenode.hpp +++ b/include/eepp/scene/scenenode.hpp @@ -25,12 +25,6 @@ class EE_API SceneNode : public Node { ~SceneNode(); - void setTranslator( Translator translator ); - - Translator& getTranslator(); - - String getTranslatorString( const std::string& str ); - void enableFrameBuffer(); void disableFrameBuffer(); diff --git a/include/eepp/ui/doc/textdocument.hpp b/include/eepp/ui/doc/textdocument.hpp index f528740dc..ccde79c5f 100644 --- a/include/eepp/ui/doc/textdocument.hpp +++ b/include/eepp/ui/doc/textdocument.hpp @@ -272,6 +272,10 @@ class EE_API TextDocument { void moveLinesDown(); + bool hasUndo() const; + + bool hasRedo() const; + void undo(); void redo(); diff --git a/include/eepp/ui/doc/undostack.hpp b/include/eepp/ui/doc/undostack.hpp index 1279e8764..b1c0dd951 100644 --- a/include/eepp/ui/doc/undostack.hpp +++ b/include/eepp/ui/doc/undostack.hpp @@ -86,6 +86,10 @@ class EE_API UndoStack { void redo(); + bool hasUndo() const; + + bool hasRedo() const; + const Uint32& getMaxStackSize() const; const Time& getMergeTimeout() const; diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index 20c78b44f..af3500a6b 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -22,6 +22,7 @@ class UIWindow; class UIScrollBar; class UILoader; class UIPopUpMenu; +class UIMenuItem; class UICodeEditorModule { public: @@ -637,8 +638,9 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void createDefaultContextMenuOptions( UIPopUpMenu* menu ); - void menuAdd( UIPopUpMenu* menu, const std::string& translateKey, const String& translateString, - const std::string& icon, const std::string& cmd ); + UIMenuItem* menuAdd( UIPopUpMenu* menu, const std::string& translateKey, + const String& translateString, const std::string& icon, + const std::string& cmd ); }; }} // namespace EE::UI diff --git a/include/eepp/ui/uifiledialog.hpp b/include/eepp/ui/uifiledialog.hpp index 872147347..d608c6b31 100644 --- a/include/eepp/ui/uifiledialog.hpp +++ b/include/eepp/ui/uifiledialog.hpp @@ -83,7 +83,7 @@ class EE_API UIFileDialog : public UIWindow { bool getShowHidden(); - bool getAllowFolderSelect(); + bool allowFolderSelect(); void setSortAlphabetically( const bool& sortAlphabetically ); diff --git a/include/eepp/ui/uitextinput.hpp b/include/eepp/ui/uitextinput.hpp index 6e4904cf9..651c3cef6 100644 --- a/include/eepp/ui/uitextinput.hpp +++ b/include/eepp/ui/uitextinput.hpp @@ -11,6 +11,9 @@ using namespace EE::UI::Doc; namespace EE { namespace UI { +class UIPopUpMenu; +class UIMenuItem; + class EE_API UITextInput : public UITextView, public TextDocument::Client { public: static UITextInput* New(); @@ -99,6 +102,10 @@ class EE_API UITextInput : public UITextView, public TextDocument::Client { KeyBindings& getKeyBindings(); + size_t getMenuIconSize() const; + + void setMenuIconSize( size_t menuIconSize ); + protected: TextDocument mDoc; Float mWaitCursorTime; @@ -111,9 +118,12 @@ class EE_API UITextInput : public UITextView, public TextDocument::Client { bool mOnlyNumbers; bool mAllowFloat; bool mMouseDown; + bool mCreateDefaultContextMenuOptions{ true }; Uint32 mMaxLength{ 0 }; KeyBindings mKeyBindings; Clock mLastDoubleClick; + size_t mMenuIconSize{ 16 }; + UIPopUpMenu* mCurrentMenu{ nullptr }; void resetWaitCursor(); @@ -196,6 +206,16 @@ class EE_API UITextInput : public UITextView, public TextDocument::Client { virtual Uint32 onKeyDown( const KeyEvent& event ); virtual Uint32 onTextInput( const TextInputEvent& event ); + + void createDefaultContextMenuOptions( UIPopUpMenu* menu ); + + virtual bool onCreateContextMenu( const Vector2i& position, const Uint32& flags ); + + UIMenuItem* menuAdd( UIPopUpMenu* menu, const std::string& translateKey, + const String& translateString, const std::string& icon, + const std::string& cmd ); + + Drawable* findIcon( const std::string& name ); }; }} // namespace EE::UI diff --git a/include/eepp/ui/uiwidget.hpp b/include/eepp/ui/uiwidget.hpp index a978bea9a..3f3a4cada 100644 --- a/include/eepp/ui/uiwidget.hpp +++ b/include/eepp/ui/uiwidget.hpp @@ -339,6 +339,10 @@ class EE_API UIWidget : public UINode { void reloadFontFamily(); UIWidget* getNextWidget() const; + + String getTranslatorString( const std::string& str ); + + String getTranslatorString( const std::string& str, const String& defaultValue ); }; }} // namespace EE::UI diff --git a/projects/linux/ee.creator.user b/projects/linux/ee.creator.user index 2c4814b75..1c805ddfc 100644 --- a/projects/linux/ee.creator.user +++ b/projects/linux/ee.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/src/eepp/graphics/fontbmfont.cpp b/src/eepp/graphics/fontbmfont.cpp index 844fc8806..c0701e733 100644 --- a/src/eepp/graphics/fontbmfont.cpp +++ b/src/eepp/graphics/fontbmfont.cpp @@ -223,7 +223,7 @@ Glyph FontBMFont::loadGlyph( Uint32 codePoint, unsigned int characterSize, bool, return glyph; } -Float FontBMFont::getKerning( Uint32, Uint32, unsigned int ) const { +Float FontBMFont::getKerning( Uint32, Uint32, unsigned int, bool bold ) const { return 0; } @@ -232,7 +232,7 @@ Float FontBMFont::getLineSpacing( unsigned int characterSize ) const { } Uint32 FontBMFont::getFontHeight( const Uint32& characterSize ) const { - return ( Uint32 )( (Float)characterSize / mFontSize ) * mFontSize; + return (Uint32)( (Float)characterSize / mFontSize ) * mFontSize; } Float FontBMFont::getUnderlinePosition( unsigned int ) const { diff --git a/src/eepp/graphics/fontsprite.cpp b/src/eepp/graphics/fontsprite.cpp index 0cfdfdad5..f2e3d2e77 100644 --- a/src/eepp/graphics/fontsprite.cpp +++ b/src/eepp/graphics/fontsprite.cpp @@ -214,7 +214,7 @@ Glyph FontSprite::loadGlyph( Uint32 codePoint, unsigned int characterSize ) cons return glyph; } -Float FontSprite::getKerning( Uint32, Uint32, unsigned int ) const { +Float FontSprite::getKerning( Uint32, Uint32, unsigned int, bool ) const { return 0; } @@ -223,7 +223,7 @@ Float FontSprite::getLineSpacing( unsigned int characterSize ) const { } Uint32 FontSprite::getFontHeight( const Uint32& characterSize ) const { - return ( Uint32 )( (Float)characterSize / mFontSize ) * mFontSize; + return (Uint32)( (Float)characterSize / mFontSize ) * mFontSize; } Float FontSprite::getUnderlinePosition( unsigned int ) const { diff --git a/src/eepp/graphics/fonttruetype.cpp b/src/eepp/graphics/fonttruetype.cpp index 27dca2f29..3112dd5a3 100644 --- a/src/eepp/graphics/fonttruetype.cpp +++ b/src/eepp/graphics/fonttruetype.cpp @@ -333,17 +333,70 @@ const FontTrueType::Info& FontTrueType::getInfo() const { return mInfo; } -Uint64 FontTrueType::getCodePointIndexKey( Uint32 codePoint, bool bold, Float outlineThickness ) const { - return combine( outlineThickness, bold, codePoint ); +Uint64 FontTrueType::getIndexKey( Uint32 index, bool bold, Float outlineThickness ) const { + return combine( outlineThickness, bold, index ); +} + +bool FontTrueType::hasGlyph( Uint32 codePoint ) const { + return FT_Get_Char_Index( static_cast( mFace ), codePoint ) != 0; } const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold, Float outlineThickness ) const { + FT_Face face = static_cast( mFace ); + Uint32 index = FT_Get_Char_Index( face, codePoint ); + + if ( Font::isEmojiCodePoint( codePoint ) && !mIsColorEmojiFont && !mIsEmojiFont ) { + if ( !mIsColorEmojiFont && FontManager::instance()->getColorEmojiFont() != nullptr && + FontManager::instance()->getColorEmojiFont()->getType() == FontType::TTF ) { + + Float maxWidth = 0.f; + + if ( isMonospace() ) { + Glyph monospaceGlyph = getGlyph( ' ', characterSize, bold, outlineThickness ); + maxWidth = monospaceGlyph.advance; + } + + FontTrueType* fontEmoji = + static_cast( FontManager::instance()->getColorEmojiFont() ); + return fontEmoji->getGlyph( codePoint, characterSize, bold, outlineThickness, + mPages[characterSize], maxWidth ); + } else if ( !mIsEmojiFont && FontManager::instance()->getEmojiFont() != nullptr && + FontManager::instance()->getEmojiFont()->getType() == FontType::TTF ) { + + Float maxWidth = 0.f; + + if ( isMonospace() ) { + Glyph monospaceGlyph = getGlyph( ' ', characterSize, bold, outlineThickness ); + maxWidth = monospaceGlyph.advance; + } + + FontTrueType* fontEmoji = + static_cast( FontManager::instance()->getEmojiFont() ); + return fontEmoji->getGlyph( codePoint, characterSize, bold, outlineThickness, + mPages[characterSize], maxWidth ); + } + } + + return getGlyphByIndex( index, characterSize, bold, outlineThickness ); +} + +const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold, + Float outlineThickness, Page& page, + const Float& forzeSize ) const { + FT_Face face = static_cast( mFace ); + Uint32 index = FT_Get_Char_Index( face, codePoint ); + return getGlyphByIndex( index, characterSize, bold, outlineThickness, page, forzeSize ); +} + +const Glyph& FontTrueType::getGlyphByIndex( Uint32 index, unsigned int characterSize, bool bold, + Float outlineThickness, Page& page, + const Float& forzeSize ) const { // Get the page corresponding to the character size - GlyphTable& glyphs = mPages[characterSize].glyphs; + GlyphTable& glyphs = page.glyphs; // Build the key by combining the code point, bold flag, and outline thickness - Uint64 key = getCodePointIndexKey( codePoint, bold, outlineThickness ); + Uint64 key = getIndexKey( index, bold, outlineThickness ); // Search the glyph into the cache GlyphTable::const_iterator it = glyphs.find( key ); @@ -352,17 +405,23 @@ const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSiz return it->second; } else { // Not found: we have to load it - Glyph glyph = - loadGlyph( codePoint, characterSize, bold, outlineThickness, mPages[characterSize] ); + Glyph glyph = loadGlyph( index, characterSize, bold, outlineThickness, page, forzeSize ); + return glyphs.insert( std::make_pair( key, glyph ) ).first->second; } } +const Glyph& FontTrueType::getGlyphByIndex( Uint32 index, unsigned int characterSize, bool bold, + Float outlineThickness ) const { + return getGlyphByIndex( index, characterSize, bold, outlineThickness, mPages[characterSize], + 0.f ); +} + GlyphDrawable* FontTrueType::getGlyphDrawable( Uint32 codePoint, unsigned int characterSize, bool bold, Float outlineThickness ) const { GlyphDrawableTable& drawables = mPages[characterSize].drawables; - Uint64 key = getCodePointIndexKey( codePoint, bold, outlineThickness ); + Uint64 key = getIndexKey( codePoint, bold, outlineThickness ); auto it = drawables.find( key ); if ( it != drawables.end() ) { @@ -380,28 +439,38 @@ GlyphDrawable* FontTrueType::getGlyphDrawable( Uint32 codePoint, unsigned int ch } } -Float FontTrueType::getKerning( Uint32 first, Uint32 second, unsigned int characterSize ) const { +Float FontTrueType::getKerning( Uint32 first, Uint32 second, unsigned int characterSize, + bool bold ) const { // Special case where first or second is 0 (null character) if ( first == 0 || second == 0 ) return 0.f; FT_Face face = static_cast( mFace ); - if ( face && FT_HAS_KERNING( face ) && setCurrentSize( characterSize ) ) { + if ( face && setCurrentSize( characterSize ) ) { // Convert the characters to indices FT_UInt index1 = FT_Get_Char_Index( face, first ); FT_UInt index2 = FT_Get_Char_Index( face, second ); + // Retrieve position compensation deltas generated by FT_LOAD_FORCE_AUTOHINT flag + auto firstRsbDelta = static_cast( getGlyph( first, characterSize, bold ).rsbDelta ); + auto secondLsbDelta = + static_cast( getGlyph( second, characterSize, bold ).lsbDelta ); + // Get the kerning vector FT_Vector kerning; - FT_Get_Kerning( face, index1, index2, FT_KERNING_DEFAULT, &kerning ); + kerning.x = kerning.y = 0; + if ( FT_HAS_KERNING( face ) ) + FT_Get_Kerning( face, index1, index2, FT_KERNING_UNFITTED, &kerning ); // X advance is already in pixels for bitmap fonts if ( !FT_IS_SCALABLE( face ) ) return static_cast( kerning.x ); // Return the X advance - return static_cast( kerning.x ) / static_cast( 1 << 6 ); + return std::floor( + ( secondLsbDelta - firstRsbDelta + static_cast( kerning.x ) + 32 ) / + static_cast( 1 << 6 ) ); } else { // Invalid font, or no kerning return 0.f; @@ -543,47 +612,15 @@ void FontTrueType::cleanup() { std::vector().swap( mPixelBuffer ); } -Glyph FontTrueType::loadGlyph( Uint32 codePoint, unsigned int characterSize, bool bold, +Glyph FontTrueType::loadGlyph( Uint32 index, unsigned int characterSize, bool bold, Float outlineThickness, Page& page, const Float& maxWidth ) const { // The glyph to return Glyph glyph; - if ( Font::isEmojiCodePoint( codePoint ) && !mIsColorEmojiFont && !mIsEmojiFont ) { - if ( !mIsColorEmojiFont && FontManager::instance()->getColorEmojiFont() != nullptr && - FontManager::instance()->getColorEmojiFont()->getType() == FontType::TTF ) { - - Float maxWidth = 0.f; - - if ( isMonospace() ) { - Glyph monospaceGlyph = getGlyph( ' ', characterSize, bold, outlineThickness ); - maxWidth = monospaceGlyph.advance; - } - - FontTrueType* fontEmoji = - static_cast( FontManager::instance()->getColorEmojiFont() ); - return fontEmoji->loadGlyph( codePoint, characterSize, bold, outlineThickness, page, - maxWidth ); - } else if ( !mIsEmojiFont && FontManager::instance()->getEmojiFont() != nullptr && - FontManager::instance()->getEmojiFont()->getType() == FontType::TTF ) { - - Float maxWidth = 0.f; - - if ( isMonospace() ) { - Glyph monospaceGlyph = getGlyph( ' ', characterSize, bold, outlineThickness ); - maxWidth = monospaceGlyph.advance; - } - - FontTrueType* fontEmoji = - static_cast( FontManager::instance()->getEmojiFont() ); - return fontEmoji->loadGlyph( codePoint, characterSize, bold, outlineThickness, page, - maxWidth ); - } - } - // First, transform our ugly void* to a FT_Face FT_Face face = static_cast( mFace ); if ( !face ) { - Log::error( "FT_Face failed for: codePoint %d characterSize: %d font %s", codePoint, + Log::error( "FT_Face failed for: codePoint %d characterSize: %d font %s", index, characterSize, mFontName.c_str() ); return glyph; } @@ -592,7 +629,7 @@ Glyph FontTrueType::loadGlyph( Uint32 codePoint, unsigned int characterSize, boo if ( !setCurrentSize( characterSize ) ) { Log::error( "FontTrueType::setCurrentSize failed for: codePoint %d characterSize: %d font %s", - codePoint, characterSize, mFontName.c_str() ); + index, characterSize, mFontName.c_str() ); return glyph; } @@ -602,16 +639,16 @@ Glyph FontTrueType::loadGlyph( Uint32 codePoint, unsigned int characterSize, boo FT_Int32 flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_FORCE_AUTOHINT | FT_LOAD_COLOR; if ( outlineThickness != 0 && !mIsColorEmojiFont ) flags |= FT_LOAD_NO_BITMAP; - if ( ( err = FT_Load_Char( face, codePoint, flags ) ) != 0 ) { + if ( ( err = FT_Load_Glyph( face, index, flags ) ) != 0 ) { Log::error( "FT_Load_Char failed for: codePoint %d characterSize: %d font: %s error: %d", - codePoint, characterSize, mFontName.c_str(), err ); + index, characterSize, mFontName.c_str(), err ); return glyph; } // Retrieve the glyph FT_Glyph glyphDesc; if ( FT_Get_Glyph( face->glyph, &glyphDesc ) != 0 ) { - Log::error( "FT_Get_Glyph failed for: codePoint %d characterSize: %d font: %s", codePoint, + Log::error( "FT_Get_Glyph failed for: codePoint %d characterSize: %d font: %s", index, characterSize, mFontName.c_str() ); return glyph; } @@ -659,6 +696,9 @@ Glyph FontTrueType::loadGlyph( Uint32 codePoint, unsigned int characterSize, boo if ( bold && !mBoldAdvanceSameAsRegular ) glyph.advance += static_cast( weight ) / static_cast( 1 << 6 ); + glyph.lsbDelta = static_cast( face->glyph->lsb_delta ); + glyph.rsbDelta = static_cast( face->glyph->rsb_delta ); + int width = bitmap.width; int height = bitmap.rows; diff --git a/src/eepp/graphics/text.cpp b/src/eepp/graphics/text.cpp index 23f55fa6c..6d9a3c82d 100644 --- a/src/eepp/graphics/text.cpp +++ b/src/eepp/graphics/text.cpp @@ -336,19 +336,19 @@ static bool isStopSelChar( Uint32 c ) { ',' == c || ';' == c || ':' == c || '\n' == c || '"' == c || '\'' == c || '\t' == c; } -void Text::findWordFromCharacterIndex( Int32 characterIndex, Int32& InitCur, Int32& EndCur ) const { - InitCur = 0; - EndCur = mString.size(); +void Text::findWordFromCharacterIndex( Int32 characterIndex, Int32& initCur, Int32& endCur ) const { + initCur = 0; + endCur = mString.size(); for ( std::size_t i = characterIndex; i < mString.size(); i++ ) { if ( isStopSelChar( mString[i] ) ) { - EndCur = i; + endCur = i; break; } } if ( 0 == characterIndex ) { - InitCur = 0; + initCur = 0; } if ( characterIndex >= (Int32)mString.size() ) { @@ -357,13 +357,13 @@ void Text::findWordFromCharacterIndex( Int32 characterIndex, Int32& InitCur, Int for ( Int32 i = characterIndex; i >= 0; i-- ) { if ( isStopSelChar( mString[i] ) ) { - InitCur = i + 1; + initCur = i + 1; break; } } - if ( InitCur == EndCur ) { - InitCur = EndCur = -1; + if ( initCur == endCur ) { + initCur = endCur = -1; } } @@ -391,7 +391,7 @@ void Text::getWidthInfo() { Glyph glyph = mFont->getGlyph( CharID, mRealFontSize, bold, mOutlineThickness ); if ( CharID != '\r' && CharID != '\t' ) { - Width += mFont->getKerning( prevChar, CharID, mRealFontSize ); + Width += mFont->getKerning( prevChar, CharID, mRealFontSize, bold ); prevChar = CharID; Width += glyph.advance; } @@ -455,7 +455,7 @@ void Text::shrinkText( const Uint32& maxWidth ) { tWordWidth += fCharWidth; if ( *tChar != '\r' ) { - tWordWidth += mFont->getKerning( prevChar, *tChar, mRealFontSize ); + tWordWidth += mFont->getKerning( prevChar, *tChar, mRealFontSize, bold ); prevChar = *tChar; } @@ -760,7 +760,7 @@ void Text::ensureGeometryUpdate() { Uint32 curChar = mString[i]; // Apply the kerning offset - x += mFont->getKerning( prevChar, curChar, mRealFontSize ); + x += mFont->getKerning( prevChar, curChar, mRealFontSize, bold ); prevChar = curChar; // If we're using the underlined style and there's a new line, draw a line diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index e1ea2dd92..822f6f788 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -1261,6 +1261,14 @@ void TextDocument::moveLinesDown() { } } +bool TextDocument::hasUndo() const { + return mUndoStack.hasUndo(); +} + +bool TextDocument::hasRedo() const { + return mUndoStack.hasRedo(); +} + void TextDocument::appendLineIfLastLine( Int64 line ) { if ( line >= (Int64)mLines.size() - 1 ) { insert( endOfDoc(), "\n" ); diff --git a/src/eepp/ui/doc/undostack.cpp b/src/eepp/ui/doc/undostack.cpp index ca3c5b2d6..d4b6819a6 100644 --- a/src/eepp/ui/doc/undostack.cpp +++ b/src/eepp/ui/doc/undostack.cpp @@ -153,6 +153,14 @@ void UndoStack::redo() { popUndo( mRedoStack, mUndoStack ); } +bool UndoStack::hasUndo() const { + return !mUndoStack.empty(); +} + +bool UndoStack::hasRedo() const { + return !mRedoStack.empty(); +} + const Uint32& UndoStack::getMaxStackSize() const { return mMaxStackSize; } diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index fb37e9a44..f91a09438 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -817,25 +817,26 @@ Sizef UICodeEditor::getMaxScroll() const { getLineHeight() ); } -void UICodeEditor::menuAdd( UIPopUpMenu* menu, const std::string& translateKey, - const String& translateString, const std::string& icon, - const std::string& cmd ) { - menu->add( menu->getUISceneNode()->getTranslatorString( "uicodeeditor_" + translateKey, - translateString ), - findIcon( icon ), mKeyBindings.getCommandKeybindString( cmd ) ) - ->setId( cmd ); +UIMenuItem* UICodeEditor::menuAdd( UIPopUpMenu* menu, const std::string& translateKey, + const String& translateString, const std::string& icon, + const std::string& cmd ) { + UIMenuItem* menuItem = + menu->add( getTranslatorString( "@string/uicodeeditor_" + translateKey, translateString ), + findIcon( icon ), mKeyBindings.getCommandKeybindString( cmd ) ); + menuItem->setId( cmd ); + return menuItem; } void UICodeEditor::createDefaultContextMenuOptions( UIPopUpMenu* menu ) { if ( !mCreateDefaultContextMenuOptions ) return; - menuAdd( menu, "undo", "Undo", "undo", "undo" ); - menuAdd( menu, "redo", "Redo", "redo", "redo" ); + menuAdd( menu, "undo", "Undo", "undo", "undo" )->setEnabled( mDoc->hasUndo() ); + menuAdd( menu, "redo", "Redo", "redo", "redo" )->setEnabled( mDoc->hasRedo() ); menu->addSeparator(); - menuAdd( menu, "cut", "Cut", "cut", "cut" ); - menuAdd( menu, "copy", "Copy", "copy", "copy" ); + menuAdd( menu, "cut", "Cut", "cut", "cut" )->setEnabled( mDoc->hasSelection() ); + menuAdd( menu, "copy", "Copy", "copy", "copy" )->setEnabled( mDoc->hasSelection() ); menuAdd( menu, "cut", "Paste", "paste", "paste" ); menuAdd( menu, "delete", "Delete", "delete-text", "delete-to-next-char" ); menu->addSeparator(); diff --git a/src/eepp/ui/uifiledialog.cpp b/src/eepp/ui/uifiledialog.cpp index 0d77e4db7..0f095f0db 100644 --- a/src/eepp/ui/uifiledialog.cpp +++ b/src/eepp/ui/uifiledialog.cpp @@ -48,10 +48,10 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa mContainer->setSize( getSize() ); - if ( getAllowFolderSelect() ) { - setTitle( "Select a folder" ); + if ( allowFolderSelect() ) { + setTitle( getTranslatorString( "@string/uifiledialog_select_folder", "Select a folder" ) ); } else { - setTitle( "Select a file" ); + setTitle( getTranslatorString( "@string/uifiledialog_select_file", "Select a file" ) ); } UILinearLayout* linearLayout = UILinearLayout::NewVertical(); @@ -66,7 +66,7 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa ->setId( "lay1" ); UITextView::New() - ->setText( "Look in:" ) + ->setText( getTranslatorString( "@string/uifiledialog_look_in", "Look in:" ) ) ->setLayoutSizePolicy( SizePolicy::WrapContent, SizePolicy::MatchParent ) ->setLayoutMargin( Rectf( 0, 0, 4, 0 ) ) ->setParent( hLayout ) @@ -88,16 +88,20 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa ->setParent( hLayout ); mButtonNewFolder = UIPushButton::New(); - mButtonNewFolder->setText( "New Folder" ) + mButtonNewFolder + ->setText( getTranslatorString( "@string/uifiledialog_new_folder", "New Folder" ) ) ->setLayoutMarginLeft( 4 ) ->setLayoutSizePolicy( SizePolicy::WrapContent, SizePolicy::MatchParent ) ->setParent( hLayout ); mButtonNewFolder->addEventListener( Event::MouseClick, [&]( const Event* event ) { const MouseEvent* mouseEvent = static_cast( event ); if ( mouseEvent->getFlags() & EE_BUTTON_LMASK ) { - UIMessageBox* msgBox = - UIMessageBox::New( UIMessageBox::INPUT, "Enter new folder name:" ); - msgBox->setTitle( "Create new folder" ); + UIMessageBox* msgBox = UIMessageBox::New( + UIMessageBox::INPUT, + getTranslatorString( "@string/uifiledialog_enter_new_folder_name", + "Enter new folder name:" ) ); + msgBox->setTitle( getTranslatorString( "@string/uifiledialog_create_new_folder", + "Create new folder" ) ); msgBox->setCloseShortcut( { KEY_ESCAPE, 0 } ); msgBox->show(); msgBox->addEventListener( Event::MsgBoxConfirmClick, [&, msgBox]( const Event* ) { @@ -150,7 +154,7 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa modelEvent->getModel()->data( modelEvent->getModelIndex(), ModelRole::Custom ) ); if ( vPath.isValid() && vPath.is( Variant::Type::cstr ) ) { bool shouldOpenFolder = false; - if ( getAllowFolderSelect() && modelEvent->getTriggerEvent() && + if ( allowFolderSelect() && modelEvent->getTriggerEvent() && modelEvent->getTriggerEvent()->getType() == Event::EventType::KeyDown ) { const KeyEvent* keyEvent = static_cast( modelEvent->getTriggerEvent() ); @@ -173,7 +177,7 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa return; } if ( !isSaveDialog() ) { - if ( getAllowFolderSelect() || !FileSystem::isDirectory( node->fullPath() ) ) + if ( allowFolderSelect() || !FileSystem::isDirectory( node->fullPath() ) ) setFileName( node->getName() ); } else if ( !FileSystem::isDirectory( node->fullPath() ) ) { setFileName( node->getName() ); @@ -186,7 +190,7 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa ->setParent( linearLayout ); UITextView::New() - ->setText( "File Name:" ) + ->setText( getTranslatorString( "@string/uifiledialog_file_name", "File Name:" ) ) ->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::MatchParent ) ->setSize( 74, 0 ) ->setParent( hLayout ) @@ -201,7 +205,9 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa cb::Make1( this, &UIFileDialog::onPressFileEnter ) ); mButtonOpen = UIPushButton::New(); - mButtonOpen->setText( isSaveDialog() ? "Save" : "Open" ) + mButtonOpen + ->setText( isSaveDialog() ? getTranslatorString( "@string/uifiledialog_save", "Save" ) + : getTranslatorString( "@string/uifiledialog_open", "Open" ) ) ->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::WrapContent ) ->setSize( 80, 0 ) ->setParent( hLayout ); @@ -211,7 +217,7 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa ->setParent( linearLayout ); UITextView::New() - ->setText( "Files of type:" ) + ->setText( getTranslatorString( "@string/uifiledialog_files_of_type", "Files of type:" ) ) ->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::MatchParent ) ->setSize( 74, 0 ) ->setParent( hLayout ) @@ -227,7 +233,7 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa mFiletype->setLayoutMargin( Rectf( 0, 0, 4, 0 ) ); mButtonCancel = UIPushButton::New(); - mButtonCancel->setText( "Cancel" ) + mButtonCancel->setText( getTranslatorString( "@string/uifiledialog_cancel", "Cancel" ) ) ->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::WrapContent ) ->setSize( 80, 0 ) ->setParent( hLayout ); @@ -424,7 +430,7 @@ void UIFileDialog::openFileOrFolder( bool shouldOpenFolder = false ) { void UIFileDialog::goFolderUp() { std::string prevFolderName( FileSystem::fileNameFromPath( mCurPath ) ); setCurPath( FileSystem::removeLastFolderFromPath( mCurPath ) ); - ModelIndex index = mMultiView->getCurrentView()->findRowWithText( prevFolderName ); + ModelIndex index = mMultiView->getCurrentView()->findRowWithText( prevFolderName, true, true ); if ( index.isValid() ) mMultiView->setSelection( index ); } @@ -477,7 +483,7 @@ void UIFileDialog::save() { void UIFileDialog::open() { if ( mMultiView->getSelection().isEmpty() && - !( getAllowFolderSelect() && FileSystem::isDirectory( getFullPath() ) ) && + !( allowFolderSelect() && FileSystem::isDirectory( getFullPath() ) ) && !FileSystem::fileExists( getFullPath() ) ) return; @@ -491,8 +497,8 @@ void UIFileDialog::open() { } } - if ( ( node && "" != node->getName() ) || getAllowFolderSelect() ) { - if ( !getAllowFolderSelect() ) { + if ( ( node && "" != node->getName() ) || allowFolderSelect() ) { + if ( !allowFolderSelect() ) { if ( FileSystem::isDirectory( getFullPath() ) ) return; } else { @@ -512,6 +518,16 @@ void UIFileDialog::open() { void UIFileDialog::onPressEnter( const Event* ) { if ( FileSystem::isDirectory( mPath->getText() ) ) { setCurPath( mPath->getText() ); + } else if ( !allowFolderSelect() && FileSystem::fileExists( mPath->getText() ) ) { + String folderPath( FileSystem::fileRemoveFileName( mPath->getText() ) ); + String fileName( FileSystem::fileNameFromPath( mPath->getText() ) ); + if ( FileSystem::isDirectory( folderPath ) ) { + setCurPath( folderPath ); + setFileName( fileName ); + auto index = mMultiView->getCurrentView()->findRowWithText( fileName, true, true ); + if ( index.isValid() ) + mMultiView->setSelection( index ); + } } } @@ -537,7 +553,7 @@ bool UIFileDialog::getFoldersFirst() { return 0 != ( mDialogFlags & FoldersFirst ); } -bool UIFileDialog::getAllowFolderSelect() { +bool UIFileDialog::allowFolderSelect() { return 0 != ( mDialogFlags & AllowFolderSelect ); } diff --git a/src/eepp/ui/uilistbox.cpp b/src/eepp/ui/uilistbox.cpp index 0c28f3c5a..90f8eb580 100644 --- a/src/eepp/ui/uilistbox.cpp +++ b/src/eepp/ui/uilistbox.cpp @@ -155,7 +155,7 @@ Uint32 UIListBox::addListBoxItem( UIListBoxItem* Item ) { updatePageStep(); - return ( Uint32 )( mItems.size() - 1 ); + return (Uint32)( mItems.size() - 1 ); } Uint32 UIListBox::addListBoxItem( const String& text ) { @@ -165,7 +165,7 @@ Uint32 UIListBox::addListBoxItem( const String& text ) { updatePageStep(); updateScroll(); - return ( Uint32 )( mItems.size() - 1 ); + return (Uint32)( mItems.size() - 1 ); } UIListBoxItem* UIListBox::createListBoxItem( const String& Name ) { @@ -352,7 +352,7 @@ void UIListBox::updatePageStep() { void UIListBox::onTouchDragValueChange( Vector2f diff ) { if ( mVScrollBar->isEnabled() ) mVScrollBar->setValue( mVScrollBar->getValue() + - ( -diff.y / ( Float )( ( mItems.size() - 1 ) * mRowHeight ) ) ); + ( -diff.y / (Float)( ( mItems.size() - 1 ) * mRowHeight ) ) ); if ( mHScrollBar->isEnabled() ) mHScrollBar->setValue( mHScrollBar->getValue() + ( -diff.x / mMaxTextWidth ) ); @@ -497,7 +497,7 @@ void UIListBox::updateScrollBarState() { else ScrollH = PixelDensity::pxToDpI( mMaxTextWidth ) - mContainer->getSize().getWidth(); - Int32 HScrolleable = ( Uint32 )( mHScrollBar->getValue() * ScrollH ); + Int32 HScrolleable = (Uint32)( mHScrollBar->getValue() * ScrollH ); mHScrollInit = -HScrolleable; } else { @@ -538,7 +538,7 @@ void UIListBox::updateScroll( bool fromScrollChange ) { if ( clipped && mSmoothScroll ) { if ( scrolleable >= 0 ) - relPos = ( Uint32 )( mVScrollBar->getValue() * scrolleable ); + relPos = (Uint32)( mVScrollBar->getValue() * scrolleable ); else relPos = 0; @@ -592,7 +592,7 @@ void UIListBox::updateScroll( bool fromScrollChange ) { relPosMax = (Uint32)mItems.size(); if ( mItemsNotVisible > 0 ) { - relPos = ( Uint32 )( mVScrollBar->getValue() * mItemsNotVisible ); + relPos = (Uint32)( mVScrollBar->getValue() * mItemsNotVisible ); relPosMax = relPos + visibleItems; } @@ -850,8 +850,8 @@ void UIListBox::selectPrev() { createItemIndex( SelIndex ); if ( mItems[SelIndex]->getPosition().y < 0 ) { - mVScrollBar->setValue( ( Float )( SelIndex * mRowHeight ) / - ( Float )( ( mItems.size() - 1 ) * mRowHeight ) ); + mVScrollBar->setValue( (Float)( SelIndex * mRowHeight ) / + (Float)( ( mItems.size() - 1 ) * mRowHeight ) ); mItems[SelIndex]->setFocus(); } @@ -874,8 +874,8 @@ void UIListBox::selectNext() { if ( mItems[SelIndex]->getPosition().y + (Int32)getRowHeight() > mContainer->getSize().getHeight() ) { - mVScrollBar->setValue( ( Float )( SelIndex * mRowHeight ) / - ( Float )( ( mItems.size() - 1 ) * mRowHeight ) ); + mVScrollBar->setValue( (Float)( SelIndex * mRowHeight ) / + (Float)( ( mItems.size() - 1 ) * mRowHeight ) ); mItems[SelIndex]->setFocus(); } @@ -936,8 +936,8 @@ Uint32 UIListBox::onKeyDown( const KeyEvent& event ) { Int32 pageSize = eefloor( mDpSize.getHeight() / mRowHeight ); index = eemax( 0, index - pageSize ); setSelected( index ); - mVScrollBar->setValue( ( Float )( index * mRowHeight ) / - ( Float )( ( mItems.size() - 1 ) * mRowHeight ) ); + mVScrollBar->setValue( (Float)( index * mRowHeight ) / + (Float)( ( mItems.size() - 1 ) * mRowHeight ) ); break; } case KEY_PAGEDOWN: { @@ -947,8 +947,8 @@ Uint32 UIListBox::onKeyDown( const KeyEvent& event ) { Int32 pageSize = eefloor( mDpSize.getHeight() / mRowHeight ); index = eemin( getCount() ? (Int32)getCount() - 1 : 0, index + pageSize ); setSelected( index ); - mVScrollBar->setValue( ( Float )( index * mRowHeight ) / - ( Float )( ( mItems.size() - 1 ) * mRowHeight ) ); + mVScrollBar->setValue( (Float)( index * mRowHeight ) / + (Float)( ( mItems.size() - 1 ) * mRowHeight ) ); break; } default: { @@ -1125,9 +1125,8 @@ void UIListBox::loadItemsFromXmlNode( const pugi::xml_node& node ) { for ( pugi::xml_node item = node.child( "item" ); item; item = item.next_sibling( "item" ) ) { std::string data = item.text().as_string(); - if ( NULL != mUISceneNode && !data.empty() ) { - items.push_back( mUISceneNode->getTranslatorString( data ) ); - } + if ( !data.empty() ) + items.push_back( getTranslatorString( data ) ); } if ( !items.empty() ) { diff --git a/src/eepp/ui/uimenu.cpp b/src/eepp/ui/uimenu.cpp index 0e2f6eea9..afc5c8d8d 100644 --- a/src/eepp/ui/uimenu.cpp +++ b/src/eepp/ui/uimenu.cpp @@ -544,22 +544,18 @@ void UIMenu::loadFromXmlNode( const pugi::xml_node& node ) { std::string text( item.attribute( "text" ).as_string() ); std::string icon( item.attribute( "icon" ).as_string() ); if ( nullptr != mSceneNode && mSceneNode->isUISceneNode() ) - add( static_cast( mSceneNode )->getTranslatorString( text ), + add( getTranslatorString( text ), getIconDrawable( icon, getUISceneNode()->getUIIconThemeManager() ) ); } else if ( name == "menuseparator" || name == "separator" ) { addSeparator(); } else if ( name == "menucheckbox" || name == "checkbox" ) { std::string text( item.attribute( "text" ).as_string() ); bool active( item.attribute( "active" ).as_bool() ); - if ( nullptr != mSceneNode && mSceneNode->isUISceneNode() ) - addCheckBox( static_cast( mSceneNode )->getTranslatorString( text ), - active ); + addCheckBox( getTranslatorString( text ), active ); } else if ( name == "menuradiobutton" || name == "radiobutton" ) { std::string text( item.attribute( "text" ).as_string() ); bool active( item.attribute( "active" ).as_bool() ); - if ( nullptr != mSceneNode && mSceneNode->isUISceneNode() ) - addRadioButton( - static_cast( mSceneNode )->getTranslatorString( text ), active ); + addRadioButton( getTranslatorString( text ), active ); } else if ( name == "menusubmenu" || name == "submenu" ) { std::string text( item.attribute( "text" ).as_string() ); std::string icon( item.attribute( "icon" ).as_string() ); @@ -567,10 +563,9 @@ void UIMenu::loadFromXmlNode( const pugi::xml_node& node ) { if ( nullptr != getDrawInvalidator() ) subMenu->setParent( getDrawInvalidator() ); subMenu->loadFromXmlNode( item ); - if ( nullptr != mSceneNode && mSceneNode->isUISceneNode() ) - addSubMenu( static_cast( mSceneNode )->getTranslatorString( text ), - getIconDrawable( icon, getUISceneNode()->getUIIconThemeManager() ), - subMenu ); + addSubMenu( getTranslatorString( text ), + getIconDrawable( icon, getUISceneNode()->getUIIconThemeManager() ), + subMenu ); } } endAttributesTransaction(); diff --git a/src/eepp/ui/uimenubar.cpp b/src/eepp/ui/uimenubar.cpp index 689177fdd..5d9a11ab5 100644 --- a/src/eepp/ui/uimenubar.cpp +++ b/src/eepp/ui/uimenubar.cpp @@ -316,9 +316,7 @@ void UIMenuBar::loadFromXmlNode( const pugi::xml_node& node ) { subMenu->loadFromXmlNode( item ); - if ( nullptr != mSceneNode && mSceneNode->isUISceneNode() ) - addMenuButton( static_cast( mSceneNode )->getTranslatorString( text ), - subMenu ); + addMenuButton( getTranslatorString( text ), subMenu ); } } diff --git a/src/eepp/ui/uimessagebox.cpp b/src/eepp/ui/uimessagebox.cpp index cb6ae9c47..8faead483 100644 --- a/src/eepp/ui/uimessagebox.cpp +++ b/src/eepp/ui/uimessagebox.cpp @@ -58,29 +58,22 @@ UIMessageBox::UIMessageBox( const Type& type, const String& message, const Uint3 switch ( mMsgBoxType ) { case UIMessageBox::INPUT: case UIMessageBox::OK_CANCEL: { - mButtonOK->setText( - getUISceneNode()->getTranslatorString( "@string/msg_box_ok", "Ok" ) ); - mButtonCancel->setText( - getUISceneNode()->getTranslatorString( "@string/msg_box_cancel", "Cancel" ) ); + mButtonOK->setText( getTranslatorString( "@string/msg_box_ok", "Ok" ) ); + mButtonCancel->setText( getTranslatorString( "@string/msg_box_cancel", "Cancel" ) ); break; } case UIMessageBox::YES_NO: { - mButtonOK->setText( - getUISceneNode()->getTranslatorString( "@string/msg_box_yes", "Yes" ) ); - mButtonCancel->setText( - getUISceneNode()->getTranslatorString( "@string/msg_box_no", "No" ) ); + mButtonOK->setText( getTranslatorString( "@string/msg_box_yes", "Yes" ) ); + mButtonCancel->setText( getTranslatorString( "@string/msg_box_no", "No" ) ); break; } case UIMessageBox::RETRY_CANCEL: { - mButtonOK->setText( - getUISceneNode()->getTranslatorString( "@string/msg_box_retry", "Retry" ) ); - mButtonCancel->setText( - getUISceneNode()->getTranslatorString( "@string/msg_box_cancel", "Cancel" ) ); + mButtonOK->setText( getTranslatorString( "@string/msg_box_retry", "Retry" ) ); + mButtonCancel->setText( getTranslatorString( "@string/msg_box_cancel", "Cancel" ) ); break; } case UIMessageBox::OK: { - mButtonOK->setText( - getUISceneNode()->getTranslatorString( "@string/msg_box_ok", "Ok" ) ); + mButtonOK->setText( getTranslatorString( "@string/msg_box_ok", "Ok" ) ); mButtonCancel->setVisible( false ); mButtonCancel->setEnabled( false ); break; @@ -105,8 +98,7 @@ void UIMessageBox::setTheme( UITheme* theme ) { mButtonOK->setTheme( theme ); mButtonCancel->setTheme( theme ); - if ( getUISceneNode()->getTranslatorString( "@string/msg_box_retry", "Retry" ) != - mButtonOK->getText() ) { + if ( getTranslatorString( "@string/msg_box_retry", "Retry" ) != mButtonOK->getText() ) { Drawable* okIcon = getUISceneNode()->findIconDrawable( "ok", PixelDensity::dpToPxI( 16 ) ); Drawable* cancelIcon = getUISceneNode()->findIconDrawable( "cancel", PixelDensity::dpToPxI( 16 ) ); diff --git a/src/eepp/ui/uitableview.cpp b/src/eepp/ui/uitableview.cpp index 08fc20e1b..dd8c6f75d 100644 --- a/src/eepp/ui/uitableview.cpp +++ b/src/eepp/ui/uitableview.cpp @@ -298,7 +298,7 @@ ModelIndex UITableView::findRowWithText( const std::string& text, const bool& ca ( exactMatch ? var.toString() == text : String::startsWith( caseSensitive ? var.toString() : String::toLower( var.toString() ), - text ) ) ) + caseSensitive ? text : String::toLower( text ) ) ) ) return model->index( index.row(), 0 ); } return {}; diff --git a/src/eepp/ui/uitextinput.cpp b/src/eepp/ui/uitextinput.cpp index ce63796a8..44631d0f6 100644 --- a/src/eepp/ui/uitextinput.cpp +++ b/src/eepp/ui/uitextinput.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -326,6 +328,8 @@ Uint32 UITextInput::onMouseUp( const Vector2i& position, const Uint32& flags ) { mMouseDown = false; getUISceneNode()->getWindow()->getInput()->captureMouse( false ); } + } else if ( ( flags & EE_BUTTON_RMASK ) ) { + onCreateContextMenu( position, flags ); } return UITextView::onMouseUp( position, flags ); } @@ -484,8 +488,7 @@ bool UITextInput::applyProperty( const StyleSheetProperty& attribute ) { switch ( attribute.getPropertyDefinition()->getPropertyId() ) { case PropertyId::Text: - if ( NULL != getUISceneNode() ) - setText( getUISceneNode()->getTranslatorString( attribute.asString() ) ); + setText( getTranslatorString( attribute.asString() ) ); break; case PropertyId::AllowEditing: setAllowEditing( attribute.asBool() ); @@ -500,8 +503,7 @@ bool UITextInput::applyProperty( const StyleSheetProperty& attribute ) { setAllowOnlyNumbers( onlyNumbersAllowed(), attribute.asBool() ); break; case PropertyId::Hint: - if ( NULL != getUISceneNode() ) - setHint( getUISceneNode()->getTranslatorString( attribute.asString() ) ); + setHint( getTranslatorString( attribute.asString() ) ); break; case PropertyId::HintColor: setHintColor( attribute.asColor() ); @@ -776,4 +778,80 @@ KeyBindings& UITextInput::getKeyBindings() { return mKeyBindings; } +size_t UITextInput::getMenuIconSize() const { + return mMenuIconSize; +} + +void UITextInput::setMenuIconSize( size_t menuIconSize ) { + mMenuIconSize = menuIconSize; +} + +Drawable* UITextInput::findIcon( const std::string& name ) { + UIIcon* icon = getUISceneNode()->findIcon( name ); + if ( icon ) + return icon->getSize( mMenuIconSize ); + return nullptr; +} + +UIMenuItem* UITextInput::menuAdd( UIPopUpMenu* menu, const std::string& translateKey, + const String& translateString, const std::string& icon, + const std::string& cmd ) { + UIMenuItem* menuItem = + menu->add( getTranslatorString( "@string/uicodeeditor_" + translateKey, translateString ), + findIcon( icon ), mKeyBindings.getCommandKeybindString( cmd ) ); + menuItem->setId( cmd ); + return menuItem; +} + +void UITextInput::createDefaultContextMenuOptions( UIPopUpMenu* menu ) { + if ( !mCreateDefaultContextMenuOptions ) + return; + + menuAdd( menu, "undo", "Undo", "undo", "undo" )->setEnabled( mDoc.hasUndo() ); + menuAdd( menu, "redo", "Redo", "redo", "redo" )->setEnabled( mDoc.hasRedo() ); + menu->addSeparator(); + + menuAdd( menu, "cut", "Cut", "cut", "cut" )->setEnabled( mDoc.hasSelection() ); + menuAdd( menu, "copy", "Copy", "copy", "copy" )->setEnabled( mDoc.hasSelection() ); + menuAdd( menu, "cut", "Paste", "paste", "paste" ); + menuAdd( menu, "delete", "Delete", "delete-text", "delete-to-next-char" ); + menu->addSeparator(); + menuAdd( menu, "select_all", "Select All", "select-all", "select-all" ); +} + +bool UITextInput::onCreateContextMenu( const Vector2i& position, const Uint32& flags ) { + if ( mCurrentMenu ) + return false; + + UIPopUpMenu* menu = UIPopUpMenu::New(); + + ContextMenuEvent event( this, menu, Event::OnCreateContextMenu, position, flags ); + sendEvent( &event ); + + createDefaultContextMenuOptions( menu ); + + if ( menu->getCount() == 0 ) { + menu->close(); + return false; + } + + menu->setCloseOnHide( true ); + menu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { + if ( !event->getNode()->isType( UI_TYPE_MENUITEM ) ) + return; + UIMenuItem* item = event->getNode()->asType(); + std::string txt( item->getId() ); + mDoc.execute( txt ); + } ); + + Vector2f pos( position.asFloat() ); + menu->nodeToWorldTranslation( pos ); + UIMenu::findBestMenuPos( pos, menu ); + menu->setPixelsPosition( pos ); + menu->show(); + menu->addEventListener( Event::OnClose, [&]( const Event* ) { mCurrentMenu = nullptr; } ); + mCurrentMenu = menu; + return true; +} + }} // namespace EE::UI diff --git a/src/eepp/ui/uitextview.cpp b/src/eepp/ui/uitextview.cpp index 3a362d5ca..4802d1d05 100644 --- a/src/eepp/ui/uitextview.cpp +++ b/src/eepp/ui/uitextview.cpp @@ -300,8 +300,8 @@ void UITextView::alignFix() { switch ( Font::getHorizontalAlign( getFlags() ) ) { case UI_HALIGN_CENTER: mRealAlignOffset.x = - ( Float )( ( Int32 )( ( mSize.x - mPaddingPx.Left - mPaddingPx.Right ) / 2 - - mTextCache->getTextWidth() / 2 ) ); + (Float)( (Int32)( ( mSize.x - mPaddingPx.Left - mPaddingPx.Right ) / 2 - + mTextCache->getTextWidth() / 2 ) ); break; case UI_HALIGN_RIGHT: mRealAlignOffset.x = ( (Float)mSize.x - mPaddingPx.Left - mPaddingPx.Right - @@ -315,8 +315,8 @@ void UITextView::alignFix() { switch ( Font::getVerticalAlign( getFlags() ) ) { case UI_VALIGN_CENTER: mRealAlignOffset.y = - ( Float )( ( Int32 )( ( mSize.y - mPaddingPx.Top - mPaddingPx.Bottom ) / 2 - - mTextCache->getTextHeight() / 2 ) ) - + (Float)( (Int32)( ( mSize.y - mPaddingPx.Top - mPaddingPx.Bottom ) / 2 - + mTextCache->getTextHeight() / 2 ) ) - 1; break; case UI_VALIGN_BOTTOM: @@ -591,7 +591,7 @@ const Int32& UITextView::getFontLineCenter() { void UITextView::recalculate() { int fontHeight = mTextCache->getCharacterSizePx(); mFontLineCenter = eefloor( - ( Float )( ( mTextCache->getFont()->getLineSpacing( fontHeight ) - fontHeight ) / 2 ) ); + (Float)( ( mTextCache->getFont()->getLineSpacing( fontHeight ) - fontHeight ) / 2 ) ); autoShrink(); onAutoSize(); @@ -610,8 +610,7 @@ bool UITextView::applyProperty( const StyleSheetProperty& attribute ) { switch ( attribute.getPropertyDefinition()->getPropertyId() ) { case PropertyId::Text: - if ( NULL != mUISceneNode ) - setText( mUISceneNode->getTranslatorString( attribute.asString() ) ); + setText( getTranslatorString( attribute.asString() ) ); break; case PropertyId::Color: setFontColor( attribute.asColor() ); diff --git a/src/eepp/ui/uitreeview.cpp b/src/eepp/ui/uitreeview.cpp index a1bd50a5d..47d46383c 100644 --- a/src/eepp/ui/uitreeview.cpp +++ b/src/eepp/ui/uitreeview.cpp @@ -659,9 +659,9 @@ ModelIndex UITreeView::findRowWithText( const std::string& text, const bool& cas Variant var = model->data( index ); if ( var.isValid() && ( exactMatch ? var.toString() == text - : String::startsWith( caseSensitive ? var.toString() - : String::toLower( var.toString() ), - text ) ) ) { + : String::startsWith( + caseSensitive ? var.toString() : String::toLower( var.toString() ), + caseSensitive ? text : String::toLower( text ) ) ) ) { foundIndex = index; return IterationDecision::Stop; } diff --git a/src/eepp/ui/uiwidget.cpp b/src/eepp/ui/uiwidget.cpp index 240b80b36..adf010ab9 100644 --- a/src/eepp/ui/uiwidget.cpp +++ b/src/eepp/ui/uiwidget.cpp @@ -1550,12 +1550,10 @@ bool UIWidget::applyProperty( const StyleSheetProperty& attribute ) { setLayoutMarginBottom( lengthFromValueAsDp( attribute ) ); break; case PropertyId::Tooltip: { - if ( NULL != mUISceneNode ) { - String text = mUISceneNode->getTranslatorString( attribute.asString() ); - setTooltipText( text ); - if ( NULL != mTooltip ) - mTooltip->setStringBuffer( text ); - } + String text = getTranslatorString( attribute.asString() ); + setTooltipText( text ); + if ( NULL != mTooltip ) + mTooltip->setStringBuffer( text ); break; } case PropertyId::LayoutWeight: @@ -1917,6 +1915,15 @@ UIWidget* UIWidget::getNextWidget() const { return NULL; } +String UIWidget::getTranslatorString( const std::string& str ) { + return getUISceneNode() != nullptr ? getUISceneNode()->getTranslatorString( str ) : String(); +} + +String UIWidget::getTranslatorString( const std::string& str, const String& defaultValue ) { + return getUISceneNode() != nullptr ? getUISceneNode()->getTranslatorString( str, defaultValue ) + : defaultValue; +} + UIWidget* UIWidget::getNextTabWidget() const { UIWidget* widget = getNextWidget(); if ( widget ) { diff --git a/src/tools/codeeditor/codeeditor.cpp b/src/tools/codeeditor/codeeditor.cpp index 813feca84..aeaeb99e4 100644 --- a/src/tools/codeeditor/codeeditor.cpp +++ b/src/tools/codeeditor/codeeditor.cpp @@ -173,7 +173,7 @@ void App::openFolderDialog() { dialog->show(); } -void App::openFontDialog( std::string& fontPath ) { +void App::openFontDialog( std::string& fontPath, bool loadingMonoFont ) { std::string absoluteFontPath( fontPath ); if ( FileSystem::isRelativePath( absoluteFontPath ) ) absoluteFontPath = mResPath + fontPath; @@ -188,12 +188,19 @@ void App::openFontDialog( std::string& fontPath ) { dialog->setWinFlags( UI_WIN_DEFAULT_FLAGS | UI_WIN_MAXIMIZE_BUTTON | UI_WIN_MODAL ); dialog->setTitle( "Select Font File" ); dialog->setCloseShortcut( KEY_ESCAPE ); - dialog->addEventListener( Event::OpenFile, [&]( const Event* event ) { + dialog->addEventListener( Event::OnWindowClose, [&]( const Event* ) { + if ( mEditorSplitter && mEditorSplitter->getCurEditor() && + !SceneManager::instance()->isShootingDown() ) + mEditorSplitter->getCurEditor()->setFocus(); + } ); + dialog->addEventListener( Event::OpenFile, [&, loadingMonoFont]( const Event* event ) { auto newPath = event->getNode()->asType()->getFullPath(); if ( String::startsWith( newPath, mResPath ) ) newPath = newPath.substr( mResPath.size() ); if ( fontPath != newPath ) { fontPath = newPath; + if ( !loadingMonoFont ) + return; auto fontName = FileSystem::fileRemoveExtension( FileSystem::fileNameFromPath( fontPath ) ); FontTrueType* fontMono = loadFont( fontName, fontPath ); @@ -207,11 +214,6 @@ void App::openFontDialog( std::string& fontPath ) { } } } ); - dialog->addEventListener( Event::OnWindowClose, [&]( const Event* ) { - if ( mEditorSplitter && mEditorSplitter->getCurEditor() && - !SceneManager::instance()->isShootingDown() ) - mEditorSplitter->getCurEditor()->setFocus(); - } ); dialog->center(); dialog->show(); } @@ -591,9 +593,9 @@ UIMenu* App::createWindowMenu() { } ); setFocusEditorOnClose( msgBox ); } else if ( item->getText() == "Serif Font..." ) { - openFontDialog( mConfig.ui.serifFont ); + openFontDialog( mConfig.ui.serifFont, false ); } else if ( item->getText() == "Monospace Font..." ) { - openFontDialog( mConfig.ui.monospaceFont ); + openFontDialog( mConfig.ui.monospaceFont, true ); } else if ( "Zoom In" == item->getText() ) { mEditorSplitter->zoomIn(); } else if ( "Zoom Out" == item->getText() ) { @@ -2262,7 +2264,7 @@ void App::init( const std::string& file, const Float& pidelDensity, background-color: #00000066; } #image_close { - color: #eff0f188; + color: var(--floating-icon); font-family: icon; font-size: 22dp; margin-top: 32dp; diff --git a/src/tools/codeeditor/codeeditor.hpp b/src/tools/codeeditor/codeeditor.hpp index 0f6c822b3..e994124f5 100644 --- a/src/tools/codeeditor/codeeditor.hpp +++ b/src/tools/codeeditor/codeeditor.hpp @@ -32,7 +32,7 @@ class App : public UICodeEditorSplitter::Client { void openFolderDialog(); - void openFontDialog( std::string& fontPath ); + void openFontDialog( std::string& fontPath, bool loadingMonoFont ); void downloadFileWeb( const std::string& url );