Added color picking capability in the UICodeEditor.

Some minor improvements to the code editor.
Some minor fixes.
This commit is contained in:
Martín Lucas Golini
2020-06-07 19:52:39 -03:00
parent 3c218237e1
commit bd9170baee
14 changed files with 201 additions and 20 deletions

View File

@@ -86,7 +86,7 @@ string = #f1fa8c
operator = #ff79c6
function = #50fa7b
[gruvbox_dark]
[gruvbox dark]
background = #282828
text = #928374
caret = #fbf1c7

View File

@@ -654,7 +654,7 @@ Menu::Separator {
Menu::SubMenu::Arrow {
width: 16dp;
height: 16dp;
foreground-image: poly(line, var(--icon), "-7dp -5dp, -2dp 0dp"), poly(line, var(--icon), "-7dp 5dp, -2dp 0dp");
foreground-image: poly(line, var(--icon), "5dp 3dp, 10dp 8dp"), poly(line, var(--icon), "5dp 13dp, 10dp 8dp");
}
Menu::Item::icon,

View File

@@ -94,6 +94,9 @@ class EE_API String {
/** @return If the value passed is a letter */
static bool isLetter( const int& value );
/** @return If the string is a representation of a hexa number */
static bool isHexNotation( const std::string& value, const std::string& withPrefix = "" );
/** Split a String and hold it on a vector */
static std::vector<String> split( const String& str, const Uint32& splitchar = '\n',
const bool& pushEmptyString = false );

View File

@@ -160,6 +160,10 @@ class EE_API Color : public tColor<Uint8> {
std::string toHexString( const bool& prependHash = true ) const;
std::string toRgbaString() const;
std::string toRgbString() const;
Color& blendAlpha( const Uint8& alpha );
static Color fromHsl( const Colorf& hsl );

View File

@@ -207,6 +207,10 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
void setSelectionMatchColor( const Color& highlightSelectionMatchColor );
const bool& getEnableColorPickerOnSelection() const;
void setEnableColorPickerOnSelection( const bool& enableColorPickerOnSelection );
protected:
struct LastXOffset {
TextPosition position;
@@ -226,6 +230,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
bool mHighlightCurrentLine;
bool mHighlightMatchingBracket;
bool mHighlightSelectionMatch;
bool mEnableColorPickerOnSelection;
Uint32 mTabWidth;
Int64 mLastColOffset;
Vector2f mScroll;
@@ -362,6 +367,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
void fontSizeReset();
void checkColorPickerAction();
virtual void drawMatchingBrackets( const Vector2f& startScroll, const Float& lineHeight );
virtual void drawSelectionMatch( const std::pair<int, int>& lineRange,

View File

@@ -59,6 +59,14 @@ bool String::isLetter( const int& value ) {
( value != 215 ) && ( value != 247 ) );
}
bool String::isHexNotation( const std::string& value, const std::string& withPrefix ) {
if ( !withPrefix.empty() && !String::startsWith( value, withPrefix ) ) {
return false;
}
return value.find_first_not_of( "0123456789abcdefABCDEF", withPrefix.size() ) ==
std::string::npos;
}
std::vector<String> String::split( const String& str, const Uint32& splitchar,
const bool& pushEmptyString ) {
std::vector<String> tmp;

View File

@@ -229,7 +229,18 @@ std::string Color::toHexString( const bool& prependHashtag ) const {
if ( prependHashtag )
stream << "#";
stream << std::setfill( '0' ) << std::setw( sizeof( Color ) * 2 ) << std::hex << getValue();
return stream.str();
std::string str = stream.str();
if ( this->a == 255 )
return str.substr( 0, 6 );
return str;
}
std::string Color::toRgbaString() const {
return String::format( "rgba(%d, %d, %d, %.2f)", r, g, b, a / 255.f );
}
std::string Color::toRgbString() const {
return String::format( "rgb(%d, %d, %d)", r, g, b );
}
Color& Color::blendAlpha( const Uint8& alpha ) {

View File

@@ -257,7 +257,7 @@ UIColorPicker::UIColorPicker( UIWindow* attachTo, const UIColorPicker::ColorPick
mRoot->getUISceneNode()->getUIThemeManager()->getControlsFadeOutTime() ) );
}
mUIWindow->getModalControl()->addEventListener(
Event::MouseClick, [&]( const Event* event ) {
Event::MouseClick, [&]( const Event* ) {
if ( mModalAlpha != 0.f )
mUIWindow->getModalControl()->runAction( Actions::FadeOut::New(
mRoot->getUISceneNode()->getUIThemeManager()->getControlsFadeOutTime() ) );
@@ -277,9 +277,9 @@ UIColorPicker::UIColorPicker( UIWindow* attachTo, const UIColorPicker::ColorPick
mRoot->bind( "alpha_container", mAlphaContainer );
mRoot->bind( "footer", mFooter );
mRoot->addEventListener( Event::OnSizeChange, [&]( const Event* event ) { updateAll(); } );
mRoot->addEventListener( Event::OnSizeChange, [&]( const Event* ) { updateAll(); } );
mRoot->addEventListener( Event::OnLayoutUpdate, [&]( const Event* event ) {
mRoot->addEventListener( Event::OnLayoutUpdate, [&]( const Event* ) {
if ( mHuePicker->getDrawable() == nullptr ) {
mHuePicker->setDrawable( createHueTexture( mHuePicker->getPixelsSize() ), true );
mCurrentColor->setBackgroundDrawable( createGridTexture(), true );

View File

@@ -4,6 +4,7 @@
#include <eepp/graphics/primitives.hpp>
#include <eepp/graphics/text.hpp>
#include <eepp/ui/doc/syntaxdefinitionmanager.hpp>
#include <eepp/ui/tools/uicolorpicker.hpp>
#include <eepp/ui/uicodeeditor.hpp>
#include <eepp/ui/uieventdispatcher.hpp>
#include <eepp/ui/uiscenenode.hpp>
@@ -13,6 +14,8 @@
#include <eepp/window/input.hpp>
#include <eepp/window/window.hpp>
using namespace EE::UI::Tools;
namespace EE { namespace UI {
UICodeEditor* UICodeEditor::New() {
@@ -31,6 +34,7 @@ UICodeEditor::UICodeEditor() :
mHighlightCurrentLine( true ),
mHighlightMatchingBracket( true ),
mHighlightSelectionMatch( true ),
mEnableColorPickerOnSelection( false ),
mTabWidth( 4 ),
mLastColOffset( 0 ),
mMouseWheelScroll( 50 ),
@@ -541,6 +545,45 @@ Uint32 UICodeEditor::onMouseClick( const Vector2i&, const Uint32& flags ) {
return 1;
}
void UICodeEditor::checkColorPickerAction() {
if ( !mEnableColorPickerOnSelection )
return;
String text( mDoc.getSelectedText() );
TextRange range( mDoc.getSelection( true ) );
if ( range.start().line() != range.end().line() )
return;
const String& line = mDoc.line( range.end().line() ).getText();
bool isHash = range.start().column() > 0 &&
mDoc.line( range.start().line() ).getText()[range.start().column() - 1] == '#' &&
( text.size() == 6 || text.size() == 8 ) && String::isHexNotation( text );
bool isRgba = !isHash && text == "rgba" && range.end().column() < (Int64)line.size() - 1 &&
line[range.end().column()] == '(';
bool isRgb = !isHash && !isRgba && text == "rgb" &&
range.end().column() < (Int64)line.size() - 1 && line[range.end().column()] == '(';
if ( isHash || isRgb || isRgba ) {
UIColorPicker* colorPicker = NULL;
if ( isHash ) {
colorPicker = UIColorPicker::NewModal(
this, [&]( Color color ) { mDoc.replaceSelection( color.toHexString( false ) ); } );
colorPicker->setColor( Color( '#' + text ) );
} else if ( isRgba || isRgb ) {
TextPosition position = mDoc.findCloseBracket(
{range.start().line(), static_cast<Int64>( range.end().column() )}, '(', ')' );
if ( position.isValid() ) {
mDoc.setSelection( {position.line(), position.column() + 1}, range.start() );
colorPicker = UIColorPicker::NewModal( this, [&, isRgba]( Color color ) {
mDoc.replaceSelection( isRgba || color.a != 255 ? color.toRgbaString()
: color.toRgbString() );
} );
colorPicker->setColor( Color::fromString( mDoc.getSelectedText() ) );
}
}
if ( colorPicker )
colorPicker->getUIWindow()->addEventListener( Event::OnWindowClose,
[&]( const Event* ) { setFocus(); } );
}
}
Uint32 UICodeEditor::onMouseDoubleClick( const Vector2i&, const Uint32& flags ) {
if ( mLocked || NULL == mFont )
return 1;
@@ -548,6 +591,7 @@ Uint32 UICodeEditor::onMouseDoubleClick( const Vector2i&, const Uint32& flags )
if ( flags & EE_BUTTON_LMASK ) {
mDoc.selectWord();
mLastDoubleClick.restart();
checkColorPickerAction();
}
return 1;
}
@@ -1004,6 +1048,14 @@ void UICodeEditor::setSelectionMatchColor( const Color& highlightSelectionMatchC
}
}
const bool& UICodeEditor::getEnableColorPickerOnSelection() const {
return mEnableColorPickerOnSelection;
}
void UICodeEditor::setEnableColorPickerOnSelection( const bool& enableColorPickerOnSelection ) {
mEnableColorPickerOnSelection = enableColorPickerOnSelection;
}
void UICodeEditor::checkMatchingBrackets() {
if ( mHighlightMatchingBracket ) {
mMatchingBrackets = TextRange();
@@ -1375,7 +1427,7 @@ void UICodeEditor::registerKeybindings() {
{{KEY_UP, 0}, "move-to-previous-line"},
{{KEY_DOWN, KEYMOD_CTRL | KEYMOD_SHIFT}, "move-lines-down"},
{{KEY_DOWN, KEYMOD_CTRL}, "move-scroll-down"},
{{KEY_DOWN, KEYMOD_SHIFT}, "select-to-next-line"},
{{KEY_DOWN, KEYMOD_SHIFT}, "select-to-next-line"},
{{KEY_DOWN, 0}, "move-to-next-line"},
{{KEY_LEFT, KEYMOD_CTRL | KEYMOD_SHIFT}, "select-to-previous-word"},
{{KEY_LEFT, KEYMOD_CTRL}, "move-to-previous-word"},

View File

@@ -151,7 +151,7 @@ Uint32 UIMenu::add( UIWidget* widget ) {
mItems.push_back( widget );
widget->addEventListener( Event::OnSizeChange, [&]( const Event* event ) {
widget->addEventListener( Event::OnSizeChange, [&]( const Event* ) {
if ( !mResizing ) {
widgetsSetPos();
widgetsResize();
@@ -182,7 +182,7 @@ Uint32 UIMenu::addSeparator() {
resizeMe();
separator->addEventListener( Event::OnSizeChange, [&]( const Event* event ) {
separator->addEventListener( Event::OnSizeChange, [&]( const Event* ) {
if ( !mResizing ) {
widgetsSetPos();
widgetsResize();

View File

@@ -19,12 +19,11 @@ UIMenuSubMenu::UIMenuSubMenu() :
mArrow = UIWidget::NewWithTag( getElementTag() + "::arrow" );
mArrow->setParent( this );
mArrow->setFlags( UI_AUTO_SIZE );
applyDefaultTheme();
mArrow->addEventListener( Event::OnSizeChange, [&]( const Event* ) { onSizeChange(); } );
mArrow->addEventListener( Event::OnMarginChange, [&]( const Event* ) { onSizeChange(); } );
mArrow->setVisible( true );
mArrow->setEnabled( false );
mArrow->addEventListener( Event::OnMarginChange,
[&]( const Event* event ) { onSizeChange(); } );
applyDefaultTheme();
}
UIMenuSubMenu::~UIMenuSubMenu() {}
@@ -41,7 +40,11 @@ void UIMenuSubMenu::setTheme( UITheme* Theme ) {
UIMenuItem::setTheme( Theme );
mArrow->setThemeSkin( "menuarrow" );
mArrow->setSize( mArrow->getSkinSize() );
Sizef skinSize( mArrow->getSkinSize() );
if ( skinSize != Sizef::Zero ) {
mArrow->setSize( skinSize );
}
onStateChange();

View File

@@ -211,6 +211,7 @@ UITextView* UITextView::setFontColor( const Color& color ) {
mFontStyleConfig.FontColor = color;
Color newColor( color.r, color.g, color.b, color.a * mAlpha / 255.f );
mTextCache->setFillColor( newColor );
invalidateDraw();
}
return this;

View File

@@ -183,6 +183,7 @@ void App::applyColorScheme( const SyntaxColorScheme& colorScheme ) {
UICodeEditor* App::createCodeEditor() {
UICodeEditor* codeEditor = UICodeEditor::New();
codeEditor->setFontSize( 11 );
codeEditor->setEnableColorPickerOnSelection( true );
codeEditor->setColorScheme( mColorSchemes[mCurrentColorScheme] );
codeEditor->getDocument().setCommand( "switch-to-previous-colorscheme", [&] {
auto it = mColorSchemes.find( mCurrentColorScheme );
@@ -477,6 +478,7 @@ void App::setAppTitle( const std::string& title ) {
void App::loadFileFromPath( const std::string& path, UICodeEditor* codeEditor ) {
if ( NULL == codeEditor )
codeEditor = mCurEditor;
codeEditor->setColorScheme( mColorSchemes[mCurrentColorScheme] );
codeEditor->loadFromFile( path );
updateEditorTitle( codeEditor );
}
@@ -501,7 +503,7 @@ void App::openFileDialog() {
}
} );
TGDialog->addEventListener( Event::OnWindowClose, [&]( const Event* ) {
if ( mCurEditor )
if ( mCurEditor && !SceneManager::instance()->isShootingDown() )
mCurEditor->setFocus();
} );
TGDialog->center();
@@ -586,6 +588,12 @@ void App::findAndReplace( String find, String replace, const bool& caseSensitive
}
}
void App::runCommand( const std::string& command ) {
if ( mCurEditor ) {
mCurEditor->getDocument().execute( command );
}
}
void App::initSearchBar() {
auto addClickListener = [&]( UIWidget* widget, std::string cmd ) {
widget->addEventListener( Event::MouseClick, [this, cmd]( const Event* event ) {
@@ -731,6 +739,64 @@ App::~App() {
eeSAFE_DELETE( mConsole );
}
void App::createSettingsMenu() {
mSettingsMenu = UIPopUpMenu::New();
mSettingsMenu->add( "New" );
mSettingsMenu->add( "Open..." );
mSettingsMenu->addSeparator();
mSettingsMenu->add( "Save" );
mSettingsMenu->add( "Save as..." );
mSettingsMenu->addSeparator();
mSettingsMenu->addSubMenu( "Color Scheme", NULL, createColorSchemeMenu() );
mSettingsMenu->addSeparator();
mSettingsMenu->add( "Close" );
mSettingsMenu->addSeparator();
mSettingsMenu->add( "Quit" );
mSettingsButton = mUISceneNode->find<UITextView>( "settings" );
mSettingsButton->addEventListener( Event::MouseClick, [&]( const Event* ) {
Vector2f pos( mSettingsButton->getPixelsPosition() );
mSettingsButton->nodeToWorldTranslation( pos );
UIMenu::fixMenuPos( pos, mSettingsMenu );
mSettingsMenu->setPixelsPosition( pos );
mSettingsMenu->show();
} );
mSettingsMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) {
const String& name = event->getNode()->asType<UIMenuItem>()->getText();
if ( name == "New" ) {
runCommand( "create-new" );
} else if ( name == "Open..." ) {
runCommand( "open-file" );
} else if ( name == "Save" ) {
runCommand( "save-doc" );
} else if ( name == "Save as..." ) {
} else if ( name == "Close" ) {
runCommand( "close-doc" );
} else if ( name == "Quit" ) {
runCommand( "close-app" );
}
} );
}
UIMenu* App::createColorSchemeMenu() {
UIPopUpMenu* colorSchemeMenu = UIPopUpMenu::New();
for ( auto& colorScheme : mColorSchemes ) {
colorSchemeMenu->addCheckBox( colorScheme.first, mCurrentColorScheme == colorScheme.first );
}
colorSchemeMenu->addEventListener(
Event::OnItemClicked, [&, colorSchemeMenu]( const Event* event ) {
UIMenuItem* item = event->getNode()->asType<UIMenuItem>();
const String& name = item->getText();
mCurrentColorScheme = name;
applyColorScheme( mColorSchemes[mCurrentColorScheme] );
for ( size_t i = 0; i < colorSchemeMenu->getCount(); i++ ) {
UIMenuCheckBox* menuItem = colorSchemeMenu->getItem( i )->asType<UIMenuCheckBox>();
menuItem->setActive( mCurrentColorScheme == menuItem->getText() );
}
} );
return colorSchemeMenu;
}
void App::init( const std::string& file ) {
DisplayManager* displayManager = Engine::instance()->getDisplayManager();
Display* currentDisplay = displayManager->getDisplayIndex( 0 );
@@ -769,14 +835,18 @@ void App::init( const std::string& file ) {
Font* fontMono =
FontTrueType::New( "monospace", resPath + "assets/fonts/DejaVuSansMono.ttf" );
mUISceneNode->getUIThemeManager()->setDefaultFont( font );
FontTrueType::New( "icon", resPath + "assets/fonts/remixicon.ttf" );
SceneManager::instance()->add( mUISceneNode );
StyleSheetParser cssParser;
if ( cssParser.loadFromFile( resPath + "assets/ui/breeze.css" ) ) {
mUISceneNode->setStyleSheet( cssParser.getStyleSheet() );
}
UITheme* theme =
UITheme::load( "uitheme", "uitheme", "", font, resPath + "assets/ui/breeze.css" );
mUISceneNode->setStyleSheet( theme->getStyleSheet() );
mUISceneNode->getUIThemeManager()
->setDefaultEffectsEnabled( true )
->setDefaultTheme( theme )
->setDefaultFont( font )
->add( theme );
auto colorSchemes =
SyntaxColorScheme::loadFromFile( resPath + "assets/colorschemes/colorschemes.conf" );
@@ -815,7 +885,19 @@ void App::init( const std::string& file ) {
.close_button:hover {
background-color: var(--icon-back-alert);
}
#settings {
color: #eff0f188;
font-family: icon;
font-size: 16dp;
margin-top: 2dp;
margin-right: 22dp;
transition: all 0.15s;
}
#settings:hover {
color: var(--primary);
}
</style>
<RelativeLayout layout_width="match_parent" layout_height="match_parent">
<vbox layout_width="match_parent" layout_height="match_parent">
<vbox id="code_container" layout_width="match_parent" layout_height="0" layout_weight="1">
</vbox>
@@ -845,6 +927,8 @@ void App::init( const std::string& file ) {
</vbox>
</searchbar>
</vbox>
<TextView id="settings" layout_width="wrap_content" layout_height="wrap_content" text="&#xf0e9;" layout_gravity="top|right" />
</RelativeLayout>
)xml";
UIWidgetCreator::registerWidget( "searchbar", [] { return UISearchBar::New(); } );
@@ -854,6 +938,7 @@ void App::init( const std::string& file ) {
mSearchBarLayout->setVisible( false )->setEnabled( false );
initSearchBar();
createSettingsMenu();
createEditorWithTabWidget( mBaseLayout );
if ( !file.empty() ) {

View File

@@ -91,6 +91,7 @@ class App {
void findAndReplace( String find, String replace, const bool& caseSensitive );
void runCommand( const std::string& command );
protected:
EE::Window::Window* mWindow{NULL};
UISceneNode* mUISceneNode{NULL};
@@ -104,6 +105,8 @@ class App {
std::vector<UITabWidget*> mTabWidgets;
std::map<std::string, SyntaxColorScheme> mColorSchemes;
std::string mCurrentColorScheme;
UIPopUpMenu* mSettingsMenu;
UITextView* mSettingsButton;
void onFileDropped( String file );
@@ -128,6 +131,10 @@ class App {
void initSearchBar();
void addRemainingTabWidgets( Node* widget );
void createSettingsMenu();
UIMenu* createColorSchemeMenu();
};
#endif // EE_TOOLS_CODEEDITOR_HPP