Added Variant "String" support.

Added panel location configuration (left or right).
Added default key modifier (CTRL on Linux and windows, META on macOS, ALT on Haiku).
Optimized GlobalSearchController.
Allow using $FILENAME in linter warning pattern.
Optimized ProjectSearch.
Added TextDocument delete on close option (default for temporal files downloaded from the Internet).
This commit is contained in:
Martín Lucas Golini
2022-03-20 15:04:07 -03:00
parent a0a3674312
commit 375d1e66e8
36 changed files with 374 additions and 198 deletions

View File

@@ -15,8 +15,6 @@ Detect errors and log them.
## TextDocument
* Add multi-line search and replace.
* Add XML tags auto-close.
## ecode - Code Editor

View File

@@ -1,48 +1,48 @@
[
{
"file_patterns": ["%.php$"],
"warning_pattern": "[%a ]+:%s+(.*)%s+in%s.*on%sline%s+(%d+)",
"warning_pattern_order": { "line": 2, "col": 0, "message": 1 },
"command": "php -l $FILENAME"
"file_patterns": ["%.php$"],
"warning_pattern": "[%a ]+:%s+(.*)%s+in%s.*on%sline%s+(%d+)",
"warning_pattern_order": { "line": 2, "col": 0, "message": 1 },
"command": "php -l $FILENAME"
},
{
"file_patterns": ["%.js$", "%.ts$"],
"warning_pattern": "[^:]:(%d+):(%d+): ([^%[]+)%[([^\n]+)",
"warning_pattern_order": { "line": 1, "col": 2, "message": 3, "type": 4 },
"command": "eslint --no-ignore --format unix $FILENAME"
"file_patterns": ["%.js$", "%.ts$"],
"warning_pattern": "[^:]:(%d+):(%d+): ([^%[]+)%[([^\n]+)",
"warning_pattern_order": { "line": 1, "col": 2, "message": 3, "type": 4 },
"command": "eslint --no-ignore --format unix $FILENAME"
},
{
"file_patterns": ["%.lua$"],
"warning_pattern": "[^:]:(%d+):(%d+):[%s]?([^\n]+)",
"command": "luacheck $FILENAME --formatter=plain -g --no-max-line-length"
"file_patterns": ["%.lua$"],
"warning_pattern": "[^:]:(%d+):(%d+):[%s]?([^\n]+)",
"command": "luacheck $FILENAME --formatter=plain -g --no-max-line-length"
},
{
"file_patterns": ["%.py$"],
"warning_pattern": "[^:]:(%d+):(%d+):%s([^\n]+)",
"command": "pycodestyle --ignore=E402 $FILENAME"
"file_patterns": ["%.py$"],
"warning_pattern": "[^:]:(%d+):(%d+):%s([^\n]+)",
"command": "pycodestyle --ignore=E402 $FILENAME"
},
{
"file_patterns": ["%.sh$"],
"warning_pattern": "[^:]:(%d+):(%d+):%s?([^%s]*)([^\n]*)",
"warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 },
"command": "shellcheck -f gcc $FILENAME"
"file_patterns": ["%.sh$"],
"warning_pattern": "[^:]:(%d+):(%d+):%s?([^%s]*)([^\n]*)",
"warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 },
"command": "shellcheck -f gcc $FILENAME"
},
{
"file_patterns": ["%.sol$"],
"warning_pattern": "(%d+):(%d+)%s.(%w*)%s.([^\n]*)",
"warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 },
"command": "solhint $FILENAME"
"file_patterns": ["%.sol$"],
"warning_pattern": "(%d+):(%d+)%s.(%w*)%s.([^\n]*)",
"warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 },
"command": "solhint $FILENAME"
},
{
"file_patterns": ["%.cpp$", "%.hpp$", "%.cxx$", "%.hxx$"],
"warning_pattern": "[^:]:(%d+):(%d+):%s?([^%s]*)([^\n]*)",
"warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 },
"command": "cppcheck --language=c++ --enable=all --template=gcc $FILENAME"
"file_patterns": ["%.cpp$", "%.hpp$", "%.cxx$", "%.hxx$"],
"warning_pattern": "$FILENAME:(%d+):(%d+):%s?([^%s]*)([^\n]*)",
"warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 },
"command": "cppcheck --language=c++ --enable=all --template=gcc $FILENAME"
},
{
"file_patterns": ["%.kt$"],
"warning_pattern": "[^:]:(%d+):(%d+):%s([^\n]+)",
"warning_pattern_order": { "line": 1, "col": 2, "message": 3, "type": 4 },
"command": "ktlint $FILENAME"
"file_patterns": ["%.kt$"],
"warning_pattern": "[^:]:(%d+):(%d+):%s([^\n]+)",
"warning_pattern_order": { "line": 1, "col": 2, "message": 3, "type": 4 },
"command": "ktlint $FILENAME"
}
]

View File

@@ -398,6 +398,10 @@ class EE_API TextDocument {
bool isLoading() const;
bool isDeleteOnClose() const;
void setDeleteOnClose( bool deleteOnClose );
protected:
friend class UndoStack;
UndoStack mUndoStack;
@@ -416,6 +420,7 @@ class EE_API TextDocument {
bool mAutoCloseBrackets{ false };
bool mDirtyOnFileSystem{ false };
bool mSaving{ false };
bool mDeleteOnClose{ false };
std::vector<std::pair<String::StringBaseType, String::StringBaseType>> mAutoCloseBracketsPairs;
Uint32 mIndentWidth{ 4 };
IndentType mIndentType{ IndentType::IndentTabs };

View File

@@ -24,9 +24,9 @@ class EE_API KeyBindings {
Shortcut() {}
Shortcut( Keycode key, Uint32 mod ) : key( key ), mod( mod ) {}
Shortcut( const Uint64& code ) :
key( ( Keycode )( code & 0xFFFFFFFF ) ), mod( ( code >> 32 ) & 0xFFFFFFFF ) {}
Keycode key{KEY_UNKNOWN};
Uint32 mod{0};
key( (Keycode)( code & 0xFFFFFFFF ) ), mod( ( code >> 32 ) & 0xFFFFFFFF ) {}
Keycode key{ KEY_UNKNOWN };
Uint32 mod{ 0 };
Uint64 toUint64() const { return (Uint64)mod << 32 | (Uint64)key; }
operator Uint64() const { return toUint64(); }
bool empty() const { return 0 == mod && 0 == key; }
@@ -66,6 +66,10 @@ class EE_API KeyBindings {
std::string getShortcutString( Shortcut shortcut );
Uint32 getDefaultModifier() const;
void setDefaultModifier( Uint32 newDefaultModifier );
protected:
const Window::Input* mInput;
ShortcutMap mShortcuts;

View File

@@ -19,6 +19,7 @@ class EE_API Variant {
Invalid,
DataPtr,
String,
StdString,
Bool,
Float,
Int,
@@ -32,8 +33,11 @@ class EE_API Variant {
cstr
};
Variant() : mType( Type::Invalid ) {}
explicit Variant( const std::string& string ) : mType( Type::String ) {
mValue.asString = eeNew( std::string, ( string ) );
explicit Variant( const std::string& string ) : mType( Type::StdString ) {
mValue.asStdString = eeNew( std::string, ( string ) );
}
explicit Variant( const String& string ) : mType( Type::String ) {
mValue.asString = eeNew( String, ( string ) );
}
Variant( Drawable* drawable, bool ownDrawable = false ) : mType( Type::Drawable ) {
mValue.asDrawable = drawable;
@@ -53,7 +57,8 @@ class EE_API Variant {
Variant( const Uint64& val ) : mType( Type::Uint64 ) { mValue.asUint64 = val; }
explicit Variant( const char* data ) : mType( Type::cstr ) { mValue.asCStr = data; }
~Variant() { reset(); }
const std::string& asString() const { return *mValue.asString; }
const std::string& asStdString() const { return *mValue.asStdString; }
const String& asString() const { return *mValue.asString; }
Drawable* asDrawable() const { return mValue.asDrawable; }
const bool& asBool() const { return mValue.asBool; }
const Float& asFloat() const { return mValue.asFloat; }
@@ -69,8 +74,11 @@ class EE_API Variant {
bool is( const Type& type ) const { return type == mType; }
void reset() {
switch ( mType ) {
case Type::StdString:
eeSAFE_DELETE( mValue.asStdString );
break;
case Type::String:
eeSAFE_DELETE( mValue.asString );
eeSAFE_DELETE( mValue.asStdString );
break;
case Type::Drawable:
if ( mOwnsObject )
@@ -103,6 +111,8 @@ class EE_API Variant {
return String::toString( asUint64() );
case Type::Float:
return String::toString( asFloat() );
case Type::StdString:
return asStdString();
case Type::String:
return asString();
case Type::Drawable:
@@ -142,6 +152,8 @@ class EE_API Variant {
return asUint64() < other.asUint64();
case Type::Float:
return asFloat() < other.asFloat();
case Type::StdString:
return asStdString() < other.asStdString();
case Type::String:
return asString() < other.asString();
case Type::Drawable:
@@ -178,6 +190,8 @@ class EE_API Variant {
return asUint64() == other.asUint64();
case Type::Float:
return asFloat() == other.asFloat();
case Type::StdString:
return asStdString() == other.asStdString();
case Type::String:
return asString() == other.asString();
case Type::Drawable:
@@ -203,7 +217,8 @@ class EE_API Variant {
void* asDataPtr;
Drawable* asDrawable;
UIIcon* asIcon;
std::string* asString;
std::string* asStdString;
String* asString;
bool asBool;
Float asFloat;
int asInt;
@@ -215,7 +230,7 @@ class EE_API Variant {
const char* asCStr;
} mValue;
Type mType;
bool mOwnsObject{false};
bool mOwnsObject{ false };
};
}}} // namespace EE::UI::Models

View File

@@ -135,7 +135,7 @@ class EE_API UIFileDialog : public UIWindow {
UIDropDownList* mFiletype;
Uint32 mDialogFlags;
KeyBindings::Shortcut mCloseShortcut;
KeyBindings::Shortcut mOpenShortut{ KEY_RETURN, KEYMOD_CTRL };
KeyBindings::Shortcut mOpenShortut{ KEY_RETURN, KEYMOD_DEFAULT_MODIFIER };
std::shared_ptr<FileSystemModel> mModel;
virtual void onWindowReady();

View File

@@ -27,7 +27,7 @@ class EE_API UISplitter : public UILayout {
void setSplitPartition( const StyleSheetLength& divisionSplit );
void swap();
void swap( bool swapSplitPartition = false );
bool isEmpty();

View File

@@ -1,6 +1,8 @@
#ifndef EE_INPUT_KEYKODES_HPP
#define EE_INPUT_KEYKODES_HPP
#include <eepp/config.hpp>
namespace EE { namespace Window {
// This is a exact copy from the SDL_keycode and SDL_scancode.
@@ -685,6 +687,14 @@ enum KeyModTable {
#define KEYMOD_META ( KEYMOD_LMETA | KEYMOD_RMETA )
#define KEYMOD_CTRL_SHIFT_ALT_META ( KEYMOD_CTRL | KEYMOD_SHIFT | KEYMOD_ALT | KEYMOD_META )
#if EE_PLATFORM == EE_PLATFORM_MACOSX
#define KEYMOD_DEFAULT_MODIFIER KEYMOD_META
#elif EE_PLATFORM == EE_PLATFORM_HAIKU
#define KEYMOD_DEFAULT_MODIFIER KEYMOD_ALT
#else
#define KEYMOD_DEFAULT_MODIFIER KEYMOD_CTRL
#endif
/** @enum MouseButton Mouse buttons */
enum MouseButton {
EE_BUTTON_LEFT = 1,

View File

@@ -158,9 +158,10 @@ void MapEditor::createMenuBar() {
PU3->getUISceneNode()->findIconDrawable( "zoom-out", PixelDensity::dpToPxI( 16 ) ) );
PU3->add( "Normal Size", PU3->getUISceneNode()->findIconDrawable(
"zoom-original", PixelDensity::dpToPxI( 16 ) ) );
addShortcut( {KEY_KP_PLUS, KEYMOD_CTRL}, "zoom-in", [&] { zoomIn(); } );
addShortcut( {KEY_KP_MINUS, KEYMOD_CTRL}, "zoom-out", [&] { zoomOut(); } );
addShortcut( {KEY_0, KEYMOD_CTRL}, "zoom-reset", [&] { mUIMap->Map()->setScale( 1 ); } );
addShortcut( { KEY_KP_PLUS, KEYMOD_DEFAULT_MODIFIER }, "zoom-in", [&] { zoomIn(); } );
addShortcut( { KEY_KP_MINUS, KEYMOD_DEFAULT_MODIFIER }, "zoom-out", [&] { zoomOut(); } );
addShortcut( { KEY_0, KEYMOD_DEFAULT_MODIFIER }, "zoom-reset",
[&] { mUIMap->Map()->setScale( 1 ); } );
PU3->addSeparator();

View File

@@ -434,7 +434,9 @@ UIWidget* UIAbstractTableView::updateCell( const int& rowIndex, const ModelIndex
Variant txt( getModel()->data( index, ModelRole::Display ) );
if ( txt.isValid() ) {
if ( txt.is( Variant::Type::String ) )
if ( txt.is( Variant::Type::StdString ) )
cell->setText( txt.asStdString() );
else if ( txt.is( Variant::Type::String ) )
cell->setText( txt.asString() );
else if ( txt.is( Variant::Type::cstr ) )
cell->setText( txt.asCStr() );

View File

@@ -352,10 +352,13 @@ SyntaxDefinitionManager::SyntaxDefinitionManager() {
{ "%.cpp$", "%.cc$", "%.C$", "%.cxx$", "%.c++$", "%.hh$", "%.H$", "%.h$", "%.inl$",
"%.hxx$", "%.hpp$", "%.h++$" },
{
{ { "R%\"xml%(", "%)xml%\"" }, "function", "XML" },
{ { "R%\"css%(", "%)css%\"" }, "function", "CSS" },
{ { "R%\"html%(", "%)html%\"" }, "function", "HTML" },
{ { "R\"[%a-\"]+%(", "%)[%a-\"]+%\"" }, "string" },
{ { "//.-\n" }, "comment" },
{ { "/%*", "%*/" }, "comment" },
{ { "#", "[^\\]\n" }, "keyword2" },
{ { "R\"[%a-\"]+%(", "%)[%a-\"]+%\"" }, "string" },
{ { "\"", "\"", "\\" }, "string" },
{ { "'", "'", "\\" }, "string" },
{ { "-?0x%x+" }, "number" },

View File

@@ -40,6 +40,8 @@ TextDocument::TextDocument( bool verbose ) :
TextDocument::~TextDocument() {
notifyDocumentClosed();
if ( mDeleteOnClose )
FileSystem::fileRemove( mFilePath );
}
bool TextDocument::hasFilepath() {
@@ -322,6 +324,7 @@ bool TextDocument::loadFromURL( const std::string& url, const Http::Request::Fie
FileSystem::fileWrite( path, (const Uint8*)response.getBody().c_str(),
response.getBody().size() );
loadFromFile( path );
setDeleteOnClose( true );
return true;
}
@@ -346,8 +349,11 @@ bool TextDocument::loadAsyncFromURL( const std::string& url,
std::string path( getTempPathFromURI( uri ) );
FileSystem::fileWrite( path, (const Uint8*)response.getBody().c_str(),
response.getBody().size() );
if ( loadFromFile( path ) && onLoaded )
onLoaded( this, true );
if ( loadFromFile( path ) ) {
setDeleteOnClose( true );
if ( onLoaded )
onLoaded( this, true );
}
} else {
onLoaded( this, false );
}
@@ -472,6 +478,14 @@ bool TextDocument::isLoading() const {
return mLoading;
}
bool TextDocument::isDeleteOnClose() const {
return mDeleteOnClose;
}
void TextDocument::setDeleteOnClose( bool deleteOnClose ) {
mDeleteOnClose = deleteOnClose;
}
std::string TextDocument::getFilename() const {
return FileSystem::fileNameFromPath( mFilePath );
}

View File

@@ -5,15 +5,29 @@ using namespace EE::Window;
namespace EE { namespace UI {
std::map<std::string, Uint32> MOD_MAP = {
{"lshift", KEYMOD_SHIFT}, {"rshift", KEYMOD_SHIFT}, {"left shift", KEYMOD_SHIFT},
{"right shift", KEYMOD_SHIFT}, {"shift", KEYMOD_SHIFT}, {"lctrl", KEYMOD_CTRL},
{"rctrl", KEYMOD_CTRL}, {"left ctrl", KEYMOD_CTRL}, {"right ctrl", KEYMOD_CTRL},
{"ctrl", KEYMOD_CTRL}, {"lalt", KEYMOD_ALT}, {"ralt", KEYMOD_RALT},
{"left alt", KEYMOD_LALT}, {"right alt", KEYMOD_RALT}, {"altgr", KEYMOD_RALT},
{"alt", KEYMOD_LALT}, {"lmeta", KEYMOD_META}, {"lmeta", KEYMOD_META},
{"left meta", KEYMOD_META}, {"right meta", KEYMOD_META}, {"meta", KEYMOD_META},
};
std::map<std::string, Uint32> MOD_MAP = { { "lshift", KEYMOD_SHIFT },
{ "rshift", KEYMOD_SHIFT },
{ "left shift", KEYMOD_SHIFT },
{ "right shift", KEYMOD_SHIFT },
{ "shift", KEYMOD_SHIFT },
{ "lctrl", KEYMOD_CTRL },
{ "rctrl", KEYMOD_CTRL },
{ "left ctrl", KEYMOD_CTRL },
{ "right ctrl", KEYMOD_CTRL },
{ "ctrl", KEYMOD_CTRL },
{ "lalt", KEYMOD_ALT },
{ "ralt", KEYMOD_RALT },
{ "left alt", KEYMOD_LALT },
{ "right alt", KEYMOD_RALT },
{ "altgr", KEYMOD_RALT },
{ "alt", KEYMOD_LALT },
{ "lmeta", KEYMOD_META },
{ "lmeta", KEYMOD_META },
{ "left meta", KEYMOD_META },
{ "right meta", KEYMOD_META },
{ "meta", KEYMOD_META },
{ "mod", KEYMOD_DEFAULT_MODIFIER },
{ "modifier", KEYMOD_DEFAULT_MODIFIER } };
Uint32 KeyBindings::getKeyMod( std::string key ) {
String::toLowerInPlace( key );
@@ -142,4 +156,13 @@ std::string KeyBindings::getShortcutString( KeyBindings::Shortcut shortcut ) {
return String::join( mods, '+' ) + "+" + keyname;
}
Uint32 KeyBindings::getDefaultModifier() const {
return MOD_MAP["mod"];
}
void KeyBindings::setDefaultModifier( Uint32 newDefaultModifier ) {
MOD_MAP["mod"] = newDefaultModifier;
MOD_MAP["modifier"] = newDefaultModifier;
}
}} // namespace EE::UI

View File

@@ -213,7 +213,7 @@ bool SortingProxyModel::isColumnSortable( const size_t& columnIndex ) const {
bool SortingProxyModel::lessThan( const ModelIndex& index1, const ModelIndex& index2 ) const {
auto data1 = mSource->data( index1, mSortRole );
auto data2 = mSource->data( index2, mSortRole );
if ( data1.is( Variant::Type::String ) && data2.is( Variant::Type::String ) )
if ( data1.is( Variant::Type::StdString ) && data2.is( Variant::Type::StdString ) )
return String::toLower( data1.asString() ) < String::toLower( data2.asString() );
if ( data1.is( Variant::Type::cstr ) && data2.is( Variant::Type::cstr ) )
return String::toLower( std::string( data1.asCStr() ) ) <

View File

@@ -19,31 +19,31 @@ const std::map<KeyBindings::Shortcut, std::string> UICodeEditorSplitter::getDefa
const std::map<KeyBindings::Shortcut, std::string>
UICodeEditorSplitter::getLocalDefaultKeybindings() {
return {
{ { KEY_S, KEYMOD_CTRL }, "save-doc" },
{ { KEY_L, KEYMOD_CTRL | KEYMOD_SHIFT }, "lock-toggle" },
{ { KEY_T, KEYMOD_CTRL }, "create-new" },
{ { KEY_W, KEYMOD_CTRL }, "close-doc" },
{ { KEY_TAB, KEYMOD_CTRL }, "next-doc" },
{ { KEY_TAB, KEYMOD_CTRL | KEYMOD_SHIFT }, "previous-doc" },
{ { KEY_S, KEYMOD_DEFAULT_MODIFIER }, "save-doc" },
{ { KEY_L, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "lock-toggle" },
{ { KEY_T, KEYMOD_DEFAULT_MODIFIER }, "create-new" },
{ { KEY_W, KEYMOD_DEFAULT_MODIFIER }, "close-doc" },
{ { KEY_TAB, KEYMOD_DEFAULT_MODIFIER }, "next-doc" },
{ { KEY_TAB, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "previous-doc" },
{ { KEY_J, KEYMOD_LALT | KEYMOD_SHIFT }, "split-left" },
{ { KEY_L, KEYMOD_LALT | KEYMOD_SHIFT }, "split-right" },
{ { KEY_I, KEYMOD_LALT | KEYMOD_SHIFT }, "split-top" },
{ { KEY_K, KEYMOD_LALT | KEYMOD_SHIFT }, "split-bottom" },
{ { KEY_S, KEYMOD_LALT | KEYMOD_SHIFT }, "split-swap" },
{ { KEY_J, KEYMOD_CTRL | KEYMOD_LALT }, "switch-to-previous-split" },
{ { KEY_L, KEYMOD_CTRL | KEYMOD_LALT }, "switch-to-next-split" },
{ { KEY_N, KEYMOD_CTRL | KEYMOD_LALT }, "switch-to-previous-colorscheme" },
{ { KEY_M, KEYMOD_CTRL | KEYMOD_LALT }, "switch-to-next-colorscheme" },
{ { KEY_1, KEYMOD_CTRL }, "switch-to-tab-1" },
{ { KEY_2, KEYMOD_CTRL }, "switch-to-tab-2" },
{ { KEY_3, KEYMOD_CTRL }, "switch-to-tab-3" },
{ { KEY_4, KEYMOD_CTRL }, "switch-to-tab-4" },
{ { KEY_5, KEYMOD_CTRL }, "switch-to-tab-5" },
{ { KEY_6, KEYMOD_CTRL }, "switch-to-tab-6" },
{ { KEY_7, KEYMOD_CTRL }, "switch-to-tab-7" },
{ { KEY_8, KEYMOD_CTRL }, "switch-to-tab-8" },
{ { KEY_9, KEYMOD_CTRL }, "switch-to-tab-9" },
{ { KEY_0, KEYMOD_CTRL }, "switch-to-last-tab" },
{ { KEY_J, KEYMOD_DEFAULT_MODIFIER | KEYMOD_LALT }, "switch-to-previous-split" },
{ { KEY_L, KEYMOD_DEFAULT_MODIFIER | KEYMOD_LALT }, "switch-to-next-split" },
{ { KEY_N, KEYMOD_DEFAULT_MODIFIER | KEYMOD_LALT }, "switch-to-previous-colorscheme" },
{ { KEY_M, KEYMOD_DEFAULT_MODIFIER | KEYMOD_LALT }, "switch-to-next-colorscheme" },
{ { KEY_1, KEYMOD_DEFAULT_MODIFIER }, "switch-to-tab-1" },
{ { KEY_2, KEYMOD_DEFAULT_MODIFIER }, "switch-to-tab-2" },
{ { KEY_3, KEYMOD_DEFAULT_MODIFIER }, "switch-to-tab-3" },
{ { KEY_4, KEYMOD_DEFAULT_MODIFIER }, "switch-to-tab-4" },
{ { KEY_5, KEYMOD_DEFAULT_MODIFIER }, "switch-to-tab-5" },
{ { KEY_6, KEYMOD_DEFAULT_MODIFIER }, "switch-to-tab-6" },
{ { KEY_7, KEYMOD_DEFAULT_MODIFIER }, "switch-to-tab-7" },
{ { KEY_8, KEYMOD_DEFAULT_MODIFIER }, "switch-to-tab-8" },
{ { KEY_9, KEYMOD_DEFAULT_MODIFIER }, "switch-to-tab-9" },
{ { KEY_0, KEYMOD_DEFAULT_MODIFIER }, "switch-to-last-tab" },
{ { KEY_1, KEYMOD_LALT }, "switch-to-tab-1" },
{ { KEY_2, KEYMOD_LALT }, "switch-to-tab-2" },
{ { KEY_3, KEYMOD_LALT }, "switch-to-tab-3" },

View File

@@ -17,7 +17,7 @@ namespace EE { namespace UI { namespace Tools {
static CSS::StyleSheetParser sStyleSheetParser;
static UISceneNode* sLastSceneNode = NULL;
const char* COLOR_PICKER_STYLE = R"xml(
const char* COLOR_PICKER_STYLE = R"css(
#color_picker {
margin: 4dp;
window-min-size: 320dp 478dp;
@@ -79,7 +79,7 @@ const char* COLOR_PICKER_STYLE = R"xml(
padding-right: 8dp;
icon: ok;
}
)xml";
)css";
UIColorPicker* UIColorPicker::NewModal( Node* nodeCreator,
const UIColorPicker::ColorPickedCb& colorPickedCb,

View File

@@ -33,66 +33,66 @@ UICodeEditor* UICodeEditor::NewOpt( const bool& autoRegisterBaseCommands,
const std::map<KeyBindings::Shortcut, std::string> UICodeEditor::getDefaultKeybindings() {
return {
{ { KEY_BACKSPACE, KEYMOD_CTRL }, "delete-to-previous-word" },
{ { KEY_BACKSPACE, KEYMOD_DEFAULT_MODIFIER }, "delete-to-previous-word" },
{ { KEY_BACKSPACE, KEYMOD_SHIFT }, "delete-to-previous-char" },
{ { KEY_BACKSPACE, 0 }, "delete-to-previous-char" },
{ { KEY_DELETE, KEYMOD_CTRL }, "delete-to-next-word" },
{ { KEY_DELETE, KEYMOD_DEFAULT_MODIFIER }, "delete-to-next-word" },
{ { KEY_DELETE, KEYMOD_SHIFT }, "delete-current-line" },
{ { KEY_DELETE, 0 }, "delete-to-next-char" },
{ { KEY_KP_ENTER, KEYMOD_CTRL | KEYMOD_SHIFT }, "new-line-above" },
{ { KEY_RETURN, KEYMOD_CTRL | KEYMOD_SHIFT }, "new-line-above" },
{ { KEY_KP_ENTER, KEYMOD_CTRL }, "new-line" },
{ { KEY_RETURN, KEYMOD_CTRL }, "new-line" },
{ { KEY_KP_ENTER, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "new-line-above" },
{ { KEY_RETURN, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "new-line-above" },
{ { KEY_KP_ENTER, KEYMOD_DEFAULT_MODIFIER }, "new-line" },
{ { KEY_RETURN, KEYMOD_DEFAULT_MODIFIER }, "new-line" },
{ { KEY_KP_ENTER, KEYMOD_SHIFT }, "new-line" },
{ { KEY_RETURN, KEYMOD_SHIFT }, "new-line" },
{ { KEY_KP_ENTER, 0 }, "new-line" },
{ { KEY_RETURN, 0 }, "new-line" },
{ { KEY_UP, KEYMOD_CTRL | KEYMOD_SHIFT }, "move-lines-up" },
{ { KEY_UP, KEYMOD_CTRL }, "move-scroll-up" },
{ { KEY_UP, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "move-lines-up" },
{ { KEY_UP, KEYMOD_DEFAULT_MODIFIER }, "move-scroll-up" },
{ { KEY_UP, KEYMOD_SHIFT }, "select-to-previous-line" },
{ { 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_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "move-lines-down" },
{ { KEY_DOWN, KEYMOD_DEFAULT_MODIFIER }, "move-scroll-down" },
{ { 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" },
{ { KEY_LEFT, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "select-to-previous-word" },
{ { KEY_LEFT, KEYMOD_DEFAULT_MODIFIER }, "move-to-previous-word" },
{ { KEY_LEFT, KEYMOD_SHIFT }, "select-to-previous-char" },
{ { KEY_LEFT, 0 }, "move-to-previous-char" },
{ { KEY_RIGHT, KEYMOD_CTRL | KEYMOD_SHIFT }, "select-to-next-word" },
{ { KEY_RIGHT, KEYMOD_CTRL }, "move-to-next-word" },
{ { KEY_RIGHT, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "select-to-next-word" },
{ { KEY_RIGHT, KEYMOD_DEFAULT_MODIFIER }, "move-to-next-word" },
{ { KEY_RIGHT, KEYMOD_SHIFT }, "select-to-next-char" },
{ { KEY_RIGHT, 0 }, "move-to-next-char" },
{ { KEY_Z, KEYMOD_CTRL | KEYMOD_SHIFT }, "redo" },
{ { KEY_HOME, KEYMOD_CTRL | KEYMOD_SHIFT }, "select-to-start-of-doc" },
{ { KEY_Z, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "redo" },
{ { KEY_HOME, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "select-to-start-of-doc" },
{ { KEY_HOME, KEYMOD_SHIFT }, "select-to-start-of-content" },
{ { KEY_HOME, KEYMOD_CTRL }, "move-to-start-of-doc" },
{ { KEY_HOME, KEYMOD_DEFAULT_MODIFIER }, "move-to-start-of-doc" },
{ { KEY_HOME, 0 }, "move-to-start-of-content" },
{ { KEY_END, KEYMOD_CTRL | KEYMOD_SHIFT }, "select-to-end-of-doc" },
{ { KEY_END, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "select-to-end-of-doc" },
{ { KEY_END, KEYMOD_SHIFT }, "select-to-end-of-line" },
{ { KEY_END, KEYMOD_CTRL }, "move-to-end-of-doc" },
{ { KEY_END, KEYMOD_DEFAULT_MODIFIER }, "move-to-end-of-doc" },
{ { KEY_END, 0 }, "move-to-end-of-line" },
{ { KEY_PAGEUP, KEYMOD_CTRL }, "move-to-previous-page" },
{ { KEY_PAGEUP, KEYMOD_DEFAULT_MODIFIER }, "move-to-previous-page" },
{ { KEY_PAGEUP, KEYMOD_SHIFT }, "select-to-previous-page" },
{ { KEY_PAGEUP, 0 }, "move-to-previous-page" },
{ { KEY_PAGEDOWN, KEYMOD_CTRL }, "move-to-next-page" },
{ { KEY_PAGEDOWN, KEYMOD_DEFAULT_MODIFIER }, "move-to-next-page" },
{ { KEY_PAGEDOWN, KEYMOD_SHIFT }, "select-to-next-page" },
{ { KEY_PAGEDOWN, 0 }, "move-to-next-page" },
{ { KEY_Y, KEYMOD_CTRL }, "redo" },
{ { KEY_Z, KEYMOD_CTRL }, "undo" },
{ { KEY_Y, KEYMOD_DEFAULT_MODIFIER }, "redo" },
{ { KEY_Z, KEYMOD_DEFAULT_MODIFIER }, "undo" },
{ { KEY_TAB, KEYMOD_SHIFT }, "unindent" },
{ { KEY_TAB, 0 }, "indent" },
{ { KEY_C, KEYMOD_CTRL }, "copy" },
{ { KEY_X, KEYMOD_CTRL }, "cut" },
{ { KEY_V, KEYMOD_CTRL }, "paste" },
{ { KEY_C, KEYMOD_DEFAULT_MODIFIER }, "copy" },
{ { KEY_X, KEYMOD_DEFAULT_MODIFIER }, "cut" },
{ { KEY_V, KEYMOD_DEFAULT_MODIFIER }, "paste" },
{ { KEY_INSERT, KEYMOD_SHIFT }, "paste" },
{ { KEY_A, KEYMOD_CTRL }, "select-all" },
{ { KEY_PLUS, KEYMOD_CTRL }, "font-size-grow" },
{ { KEY_KP_PLUS, KEYMOD_CTRL }, "font-size-grow" },
{ { KEY_MINUS, KEYMOD_CTRL }, "font-size-shrink" },
{ { KEY_KP_MINUS, KEYMOD_CTRL }, "font-size-shrink" },
{ { KEY_0, KEYMOD_CTRL }, "font-size-reset" },
{ { KEY_KP_DIVIDE, KEYMOD_CTRL }, "toggle-line-comments" },
{ { KEY_A, KEYMOD_DEFAULT_MODIFIER }, "select-all" },
{ { KEY_PLUS, KEYMOD_DEFAULT_MODIFIER }, "font-size-grow" },
{ { KEY_KP_PLUS, KEYMOD_DEFAULT_MODIFIER }, "font-size-grow" },
{ { KEY_MINUS, KEYMOD_DEFAULT_MODIFIER }, "font-size-shrink" },
{ { KEY_KP_MINUS, KEYMOD_DEFAULT_MODIFIER }, "font-size-shrink" },
{ { KEY_0, KEYMOD_DEFAULT_MODIFIER }, "font-size-reset" },
{ { KEY_KP_DIVIDE, KEYMOD_DEFAULT_MODIFIER }, "toggle-line-comments" },
};
}

View File

@@ -154,7 +154,7 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa
modelEvent->getTriggerEvent()->getType() == Event::EventType::KeyDown ) {
const KeyEvent* keyEvent =
static_cast<const KeyEvent*>( modelEvent->getTriggerEvent() );
if ( keyEvent->getMod() & KEYMOD_CTRL ) {
if ( keyEvent->getMod() & KEYMOD_DEFAULT_MODIFIER ) {
shouldOpenFolder = true;
}
}

View File

@@ -87,11 +87,14 @@ void UISplitter::setSplitPartition( const StyleSheetLength& divisionSplit ) {
}
}
void UISplitter::swap() {
void UISplitter::swap( bool swapSplitPartition ) {
if ( isFull() ) {
UIWidget* tmp = mFirstWidget;
mFirstWidget = mLastWidget;
mLastWidget = tmp;
if ( swapSplitPartition )
mSplitPartition.setValue( 100.f - mSplitPartition.getValue(),
StyleSheetLength::Percentage );
setLayoutDirty();
}
}
@@ -183,14 +186,6 @@ void UISplitter::updateFromDrag() {
mDirtyLayout = true;
mSplitter->setVisible( !mAlwaysShowSplitter && !mLastWidget ? false : true );
mSplitter->setEnabled( mSplitter->isVisible() );
Float totalSpace = mOrientation == UIOrientation::Horizontal
? mSize.getWidth() - mPaddingPx.Left - mPaddingPx.Right
: mSize.getHeight() - mPaddingPx.Top - mPaddingPx.Bottom;
if ( mSplitter->isVisible() ) {
totalSpace -= UIOrientation::Horizontal == mOrientation
? mSplitter->getPixelsSize().getWidth()
: mSplitter->getPixelsSize().getHeight();
}
if ( UIOrientation::Horizontal == mOrientation ) {
Float fMinSize = mFirstWidget ? mFirstWidget->getCurrentMinSize().getWidth() : 0.f;

View File

@@ -126,13 +126,16 @@ Float UITableView::getMaxColumnContentWidth( const size_t& colIndex, bool bestGu
};
if ( bestGuess ) {
Variant dataTest( getModel()->data( getModel()->index( 0, colIndex ) ) );
bool isStdString = dataTest.is( Variant::Type::StdString );
bool isString = dataTest.is( Variant::Type::String );
if ( isString || dataTest.is( Variant::Type::cstr ) ) {
if ( isStdString || isString || dataTest.is( Variant::Type::cstr ) ) {
std::map<size_t, ModelIndex> lengths;
for ( size_t i = 0; i < getItemCount(); i++ ) {
ModelIndex index( getModel()->index( i, colIndex ) );
Variant data( getModel()->data( index ) );
size_t length = isString ? data.asString().length() : strlen( data.asCStr() );
size_t length =
isStdString ? data.asStdString().length()
: ( isString ? data.asString().length() : strlen( data.asCStr() ) );
if ( lengths.empty() || length > lengths.rbegin()->first )
lengths[length] = index;
}
@@ -153,8 +156,10 @@ Float UITableView::getMaxColumnContentWidth( const size_t& colIndex, bool bestGu
}
void UITableView::createOrUpdateColumns() {
if ( !getModel() )
if ( !getModel() ) {
updateContentSize();
return;
}
UIAbstractTableView::createOrUpdateColumns();
updateContentSize();
}

View File

@@ -684,36 +684,36 @@ void UITextInput::registerCommands() {
void UITextInput::registerKeybindings() {
mKeyBindings.addKeybinds( {
{ { KEY_BACKSPACE, KEYMOD_CTRL }, "delete-to-previous-word" },
{ { KEY_BACKSPACE, KEYMOD_DEFAULT_MODIFIER }, "delete-to-previous-word" },
{ { KEY_BACKSPACE, KEYMOD_SHIFT }, "delete-to-previous-char" },
{ { KEY_BACKSPACE, 0 }, "delete-to-previous-char" },
{ { KEY_DELETE, KEYMOD_CTRL }, "delete-to-next-word" },
{ { KEY_DELETE, KEYMOD_DEFAULT_MODIFIER }, "delete-to-next-word" },
{ { KEY_DELETE, 0 }, "delete-to-next-char" },
{ { KEY_KP_ENTER, 0 }, "press-enter" },
{ { KEY_RETURN, 0 }, "press-enter" },
{ { KEY_LEFT, KEYMOD_CTRL | KEYMOD_SHIFT }, "select-to-previous-word" },
{ { KEY_LEFT, KEYMOD_CTRL }, "move-to-previous-word" },
{ { KEY_LEFT, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "select-to-previous-word" },
{ { KEY_LEFT, KEYMOD_DEFAULT_MODIFIER }, "move-to-previous-word" },
{ { KEY_LEFT, KEYMOD_SHIFT }, "select-to-previous-char" },
{ { KEY_LEFT, 0 }, "move-to-previous-char" },
{ { KEY_RIGHT, KEYMOD_CTRL | KEYMOD_SHIFT }, "select-to-next-word" },
{ { KEY_RIGHT, KEYMOD_CTRL }, "move-to-next-word" },
{ { KEY_RIGHT, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "select-to-next-word" },
{ { KEY_RIGHT, KEYMOD_DEFAULT_MODIFIER }, "move-to-next-word" },
{ { KEY_RIGHT, KEYMOD_SHIFT }, "select-to-next-char" },
{ { KEY_RIGHT, 0 }, "move-to-next-char" },
{ { KEY_Z, KEYMOD_CTRL | KEYMOD_SHIFT }, "redo" },
{ { KEY_HOME, KEYMOD_CTRL | KEYMOD_SHIFT }, "select-to-start-of-doc" },
{ { KEY_Z, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "redo" },
{ { KEY_HOME, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "select-to-start-of-doc" },
{ { KEY_HOME, KEYMOD_SHIFT }, "select-to-start-of-content" },
{ { KEY_HOME, KEYMOD_CTRL }, "move-to-start-of-doc" },
{ { KEY_HOME, KEYMOD_DEFAULT_MODIFIER }, "move-to-start-of-doc" },
{ { KEY_HOME, 0 }, "move-to-start-of-content" },
{ { KEY_END, KEYMOD_CTRL | KEYMOD_SHIFT }, "select-to-end-of-doc" },
{ { KEY_END, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "select-to-end-of-doc" },
{ { KEY_END, KEYMOD_SHIFT }, "select-to-end-of-line" },
{ { KEY_END, KEYMOD_CTRL }, "move-to-end-of-doc" },
{ { KEY_END, KEYMOD_DEFAULT_MODIFIER }, "move-to-end-of-doc" },
{ { KEY_END, 0 }, "move-to-end-of-line" },
{ { KEY_Y, KEYMOD_CTRL }, "redo" },
{ { KEY_Z, KEYMOD_CTRL }, "undo" },
{ { KEY_C, KEYMOD_CTRL }, "copy" },
{ { KEY_X, KEYMOD_CTRL }, "cut" },
{ { KEY_V, KEYMOD_CTRL }, "paste" },
{ { KEY_A, KEYMOD_CTRL }, "select-all" },
{ { KEY_Y, KEYMOD_DEFAULT_MODIFIER }, "redo" },
{ { KEY_Z, KEYMOD_DEFAULT_MODIFIER }, "undo" },
{ { KEY_C, KEYMOD_DEFAULT_MODIFIER }, "copy" },
{ { KEY_X, KEYMOD_DEFAULT_MODIFIER }, "cut" },
{ { KEY_V, KEYMOD_DEFAULT_MODIFIER }, "paste" },
{ { KEY_A, KEYMOD_DEFAULT_MODIFIER }, "select-all" },
} );
}

View File

@@ -84,9 +84,9 @@ void UITreeView::traverseTree( TreeViewCallback callback ) const {
}
void UITreeView::createOrUpdateColumns() {
updateContentSize();
if ( !getModel() )
return;
updateContentSize();
UIAbstractTableView::createOrUpdateColumns();
}
@@ -201,7 +201,9 @@ UIWidget* UITreeView::updateCell( const int& rowIndex, const ModelIndex& index,
Variant txt( getModel()->data( index, ModelRole::Display ) );
if ( txt.isValid() ) {
if ( txt.is( Variant::Type::String ) )
if ( txt.is( Variant::Type::StdString ) )
cell->setText( txt.asStdString() );
else if ( txt.is( Variant::Type::String ) )
cell->setText( txt.asString() );
else if ( txt.is( Variant::Type::cstr ) )
cell->setText( txt.asCStr() );

View File

@@ -6,6 +6,18 @@
using namespace EE::Network;
static PanelPosition panelPositionFromString( const std::string& str ) {
if ( String::toLower( str ) == "right" )
return PanelPosition::Right;
return PanelPosition::Left;
}
static std::string panelPositionToString( const PanelPosition& pos ) {
if ( pos == PanelPosition::Right )
return "right";
return "left";
}
static std::vector<std::string> urlEncode( const std::vector<std::string>& vec ) {
std::vector<std::string> encoded;
for ( const auto& item : vec )
@@ -55,6 +67,7 @@ void AppConfig::load( std::string& confPath, std::string& keybindingsPath,
editor.horizontalScrollbar = ini.getValueB( "editor", "horizontal_scrollbar", false );
ui.fontSize = ini.getValue( "ui", "font_size", "11dp" );
ui.showSidePanel = ini.getValueB( "ui", "show_side_panel", true );
ui.panelPosition = panelPositionFromString( ini.getValue( "ui", "panel_position", "left" ) );
ui.serifFont = ini.getValue( "ui", "serif_font", "assets/fonts/NotoSans-Regular.ttf" );
ui.monospaceFont = ini.getValue( "ui", "monospace_font", "assets/fonts/DejaVuSansMono.ttf" );
editor.trimTrailingWhitespaces = ini.getValueB( "editor", "trim_trailing_whitespaces", false );
@@ -119,6 +132,7 @@ void AppConfig::save( const std::vector<std::string>& recentFiles,
ini.setValue( "editor", "font_size", editor.fontSize.toString() );
ini.setValue( "ui", "font_size", ui.fontSize.toString() );
ini.setValueB( "ui", "show_side_panel", ui.showSidePanel );
ini.setValue( "ui", "panel_position", panelPositionToString( ui.panelPosition ) );
ini.setValue( "ui", "serif_font", ui.serifFont );
ini.setValue( "ui", "monospace_font", ui.monospaceFont );
ini.setValueB( "editor", "trim_trailing_whitespaces", editor.trimTrailingWhitespaces );
@@ -179,7 +193,7 @@ void AppConfig::loadProject( std::string projectFolder, UICodeEditorSplitter* ed
do {
std::string val( ini.getValue( "files", String::format( "file_name_%lu", i ) ) );
found = !val.empty();
if ( found )
if ( found && FileSystem::fileExists( val ) )
editorSplitter->loadFileFromPathInNewTab( val );
i++;
} while ( found );

View File

@@ -16,9 +16,12 @@ using namespace EE::UI::Tools;
using namespace EE::System;
using namespace EE::Window;
enum class PanelPosition { Left, Right };
struct UIConfig {
StyleSheetLength fontSize{ 12, StyleSheetLength::Dp };
bool showSidePanel{ true };
PanelPosition panelPosition{ PanelPosition::Left };
std::string serifFont;
std::string monospaceFont;
};

View File

@@ -161,7 +161,7 @@ bool AutoCompleteModule::onKeyDown( UICodeEditor* editor, const KeyEvent& event
pickSuggestion( editor );
return true;
}
} else if ( event.getKeyCode() == KEY_SPACE && ( event.getMod() & KEYMOD_CTRL ) ) {
} else if ( event.getKeyCode() == KEY_SPACE && ( event.getMod() & KEYMOD_DEFAULT_MODIFIER ) ) {
std::string partialSymbol( getPartialSymbol( &editor->getDocument() ) );
if ( partialSymbol.size() >= 3 ) {
updateSuggestions( partialSymbol, editor );

View File

@@ -480,12 +480,26 @@ void App::showSidePanel( bool show ) {
void App::switchSidePanel() {
mConfig.ui.showSidePanel = !mConfig.ui.showSidePanel;
mWindowMenu->getItem( "Show Left Sidebar" )
mWindowMenu->getItem( "Show Side Panel" )
->asType<UIMenuCheckBox>()
->setActive( mConfig.ui.showSidePanel );
showSidePanel( mConfig.ui.showSidePanel );
}
void App::panelPosition( const PanelPosition& panelPosition ) {
mConfig.ui.panelPosition = panelPosition;
if ( !mSidePanel->isVisible() )
return;
if ( ( panelPosition == PanelPosition::Right &&
mProjectSplitter->getFirstWidget() == mSidePanel ) ||
( panelPosition == PanelPosition::Left &&
mProjectSplitter->getFirstWidget() != mSidePanel ) ) {
mProjectSplitter->swap( true );
}
}
UIMenu* App::createWindowMenu() {
mWindowMenu = UIPopUpMenu::New();
mWindowMenu->add( "UI Scale Factor (Pixel Density)", findIcon( "pixel-density" ) );
@@ -496,8 +510,12 @@ UIMenu* App::createWindowMenu() {
mWindowMenu->addSeparator();
mWindowMenu->addCheckBox( "Full Screen Mode", false, getKeybind( "fullscreen-toggle" ) )
->setId( "fullscreen-mode" );
mWindowMenu->addCheckBox( "Show Left Sidebar", mConfig.ui.showSidePanel,
mWindowMenu->addCheckBox( "Show Side Panel", mConfig.ui.showSidePanel,
getKeybind( "switch-side-panel" ) );
mWindowMenu->add( "Move panel to left...", findIcon( "layout-left" ),
getKeybind( "layout-left" ) );
mWindowMenu->add( "Move panel to right...", findIcon( "layout-right" ),
getKeybind( "layout-rigth" ) );
mWindowMenu->addSeparator();
mWindowMenu->add( "Split Left", findIcon( "split-horizontal" ), getKeybind( "split-left" ) );
mWindowMenu->add( "Split Right", findIcon( "split-horizontal" ), getKeybind( "split-right" ) );
@@ -511,7 +529,7 @@ UIMenu* App::createWindowMenu() {
if ( !event->getNode()->isType( UI_TYPE_MENUITEM ) )
return;
UIMenuItem* item = event->getNode()->asType<UIMenuItem>();
if ( item->getText() == "Show Left Sidebar" ) {
if ( item->getText() == "Show Side Panel" ) {
mConfig.ui.showSidePanel = item->asType<UIMenuCheckBox>()->isActive();
showSidePanel( mConfig.ui.showSidePanel );
} else if ( item->getText() == "UI Scale Factor (Pixel Density)" ) {
@@ -596,6 +614,10 @@ UIMenu* App::createWindowMenu() {
mEditorSplitter->zoomReset();
} else if ( "Full Screen Mode" == item->getText() ) {
runCommand( "fullscreen-toggle" );
} else if ( "Move panel to left..." == item->getText() ) {
runCommand( "move-panel-left" );
} else if ( "Move panel to right..." == item->getText() ) {
runCommand( "move-panel-right" );
} else {
String text = String( event->getNode()->asType<UIMenuItem>()->getText() ).toLower();
String::replaceAll( text, " ", "-" );
@@ -1140,19 +1162,19 @@ std::map<KeyBindings::Shortcut, std::string> App::getLocalKeybindings() {
{ { KEY_F3, KEYMOD_NONE }, "repeat-find" },
{ { KEY_F3, KEYMOD_SHIFT }, "find-prev" },
{ { KEY_F12, KEYMOD_NONE }, "console-toggle" },
{ { KEY_F, KEYMOD_CTRL }, "find-replace" },
{ { KEY_Q, KEYMOD_CTRL }, "close-app" },
{ { KEY_O, KEYMOD_CTRL }, "open-file" },
{ { KEY_W, KEYMOD_CTRL | KEYMOD_SHIFT }, "download-file-web" },
{ { KEY_O, KEYMOD_CTRL | KEYMOD_SHIFT }, "open-folder" },
{ { KEY_F, KEYMOD_DEFAULT_MODIFIER }, "find-replace" },
{ { KEY_Q, KEYMOD_DEFAULT_MODIFIER }, "close-app" },
{ { KEY_O, KEYMOD_DEFAULT_MODIFIER }, "open-file" },
{ { KEY_W, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "download-file-web" },
{ { KEY_O, KEYMOD_DEFAULT_MODIFIER | 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_K, KEYMOD_CTRL }, "open-locatebar" },
{ { KEY_F, KEYMOD_CTRL | KEYMOD_SHIFT }, "open-global-search" },
{ { KEY_L, KEYMOD_CTRL }, "go-to-line" },
{ { KEY_M, KEYMOD_CTRL }, "menu-toggle" },
{ { KEY_S, KEYMOD_CTRL | KEYMOD_SHIFT }, "save-all" },
{ { KEY_K, KEYMOD_DEFAULT_MODIFIER }, "open-locatebar" },
{ { KEY_F, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "open-global-search" },
{ { KEY_L, KEYMOD_DEFAULT_MODIFIER }, "go-to-line" },
{ { KEY_M, KEYMOD_DEFAULT_MODIFIER }, "menu-toggle" },
{ { KEY_S, KEYMOD_DEFAULT_MODIFIER | KEYMOD_SHIFT }, "save-all" },
{ { KEY_F9, KEYMOD_LALT }, "switch-side-panel" },
{ { KEY_F, KEYMOD_LALT }, "format-doc" } };
}
@@ -1417,6 +1439,8 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) {
msgBox->closeWindow();
} );
} );
doc.setCommand( "move-panel-left", [&] { panelPosition( PanelPosition::Left ); } );
doc.setCommand( "move-panel-right", [&] { panelPosition( PanelPosition::Right ); } );
editor->addEventListener( Event::OnDocumentSave, [&]( const Event* event ) {
UICodeEditor* editor = event->getNode()->asType<UICodeEditor>();
@@ -1807,8 +1831,12 @@ void App::createProjectTreeMenu( const FileInfo& file ) {
if ( file.isDirectory() ) {
mProjectTreeMenu->add( "New File...", findIcon( "file-add" ) )->setId( "new_file" );
mProjectTreeMenu->add( "New Folder...", findIcon( "folder-add" ) )->setId( "new_folder" );
mProjectTreeMenu->add( "Open Folder...", findIcon( "folder-open" ) )
->setId( "open_folder" );
} else {
mProjectTreeMenu->add( "Open File", findIcon( "document-open" ) )->setId( "open_file" );
mProjectTreeMenu->add( "Open Containing Folder...", findIcon( "folder-open" ) )
->setId( "open_containing_folder" );
mProjectTreeMenu->add( "New File in directory...", findIcon( "file-add" ) )
->setId( "new_file_in_place" );
mProjectTreeMenu->add( "Duplicate File...", findIcon( "file-copy" ) )
@@ -1882,6 +1910,10 @@ void App::createProjectTreeMenu( const FileInfo& file ) {
} );
} else if ( "rename" == txt ) {
renameFile( file );
} else if ( "open_containing_folder" == txt ) {
Engine::instance()->openURL( file.getDirectoryPath() );
} else if ( "open_folder" == txt ) {
Engine::instance()->openURL( file.getFilepath() );
}
} );
@@ -2135,7 +2167,7 @@ void App::init( const std::string& file, const Float& pidelDensity ) {
mUISceneNode->getRoot()->addClass( "appbackground" );
const std::string baseUI = R"xml(
const std::string baseUI = R"html(
<style>
TextInput#search_find,
TextInput#search_replace,
@@ -2314,6 +2346,7 @@ void App::init( const std::string& file, const Float& pidelDensity ) {
<Widget layout_width="0" layout_weight="1" layout_height="match_parent" />
<TextView layout_width="wrap_content" layout_height="wrap_content" text="History:" margin-right="4dp" layout_height="18dp" />
<DropDownList id="global_search_history" layout_width="300dp" layout_height="18dp" margin-right="4dp" />
<PushButton id="global_search_clear_history" layout_width="wrap_content" layout_height="18dp" text="Clear History" margin-right="4dp" />
<PushButton id="global_search" layout_width="wrap_content" layout_height="18dp" text="Search" margin-right="4dp" />
<PushButton id="global_search_replace" layout_width="wrap_content" layout_height="18dp" text="Search & Replace" />
</hbox>
@@ -2325,7 +2358,7 @@ void App::init( const std::string& file, const Float& pidelDensity ) {
</Splitter>
<TextView id="settings" layout_width="wrap_content" layout_height="wrap_content" text="&#xf0e9;" layout_gravity="top|right" />
</RelativeLayout>
)xml";
)html";
UIIconTheme* iconTheme = UIIconTheme::New( "remixicon" );
mMenuIconSize = mConfig.ui.fontSize.asPixels( 0, Sizef(), mDisplayDPI );
@@ -2374,6 +2407,8 @@ void App::init( const std::string& file, const Float& pidelDensity ) {
{ "menu-unfold", 0xef40 },
{ "menu-fold", 0xef3d },
{ "download-cloud", 0xec58 },
{ "layout-left", 0xee94 },
{ "layout-right", 0xee9b },
};
for ( const auto& icon : icons )
iconTheme->add( UIGlyphIcon::New( icon.first, iconFont, icon.second ) );
@@ -2397,6 +2432,8 @@ void App::init( const std::string& file, const Float& pidelDensity ) {
mDocInfo->setVisible( mConfig.editor.showDocInfo );
mProjectSplitter->setSplitPartition( StyleSheetLength( mConfig.window.panelPartition ) );
if ( mConfig.ui.panelPosition == PanelPosition::Right )
mProjectSplitter->swap();
if ( !mConfig.ui.showSidePanel )
showSidePanel( mConfig.ui.showSidePanel );

View File

@@ -238,6 +238,8 @@ class App : public UICodeEditorSplitter::Client {
void switchSidePanel();
void panelPosition( const PanelPosition& panelPosition );
void removeFolderWatches();
void createDocAlert( UICodeEditor* editor );

View File

@@ -103,13 +103,13 @@ void DocSearchController::initSearchBar( UISearchBar* searchBar ) {
mSearchBarLayout->getKeyBindings().addKeybindsString(
{ { mApp->getKeybind( "repeat-find" ), "repeat-find" },
{ mApp->getKeybind( "find-prev" ), "find-prev" },
{ "ctrl+g", "repeat-find" },
{ "mod+g", "repeat-find" },
{ "escape", "close-searchbar" },
{ "ctrl+r", "replace-all" },
{ "ctrl+s", "change-case" },
{ "ctrl+w", "change-whole-word" },
{ "ctrl+l", "toggle-lua-pattern" },
{ "ctrl+e", "change-escape-sequence" } } );
{ "mod+r", "replace-all" },
{ "mod+s", "change-case" },
{ "mod+w", "change-whole-word" },
{ "mod+l", "toggle-lua-pattern" },
{ "mod+e", "change-escape-sequence" } } );
addReturnListener( findInput, "repeat-find" );
addReturnListener( replaceInput, "find-and-replace" );
addClickListener( mSearchBarLayout->find<UIPushButton>( "find_prev" ), "find-prev" );

View File

@@ -38,6 +38,11 @@ void FormatterModule::onRegister( UICodeEditor* editor ) {
return;
doc.setCommand( "format-doc", [&, editor]() { formatDoc( editor ); } );
editor->addEventListener( Event::OnDocumentSave, [&]( const Event* event ) {
if ( mAutoFormatOnSave && event->getNode()->isType( UI_TYPE_CODEEDITOR ) )
formatDoc( event->getNode()->asType<UICodeEditor>() );
} );
}
void FormatterModule::onUnregister( UICodeEditor* editor ) {
@@ -46,6 +51,14 @@ void FormatterModule::onUnregister( UICodeEditor* editor ) {
mEditors.erase( editor );
}
bool FormatterModule::getAutoFormatOnSave() const {
return mAutoFormatOnSave;
}
void FormatterModule::setAutoFormatOnSave( bool autoFormatOnSave ) {
mAutoFormatOnSave = autoFormatOnSave;
}
void FormatterModule::load( const std::string& formatterPath ) {
if ( !FileSystem::fileExists( formatterPath ) )
return;

View File

@@ -24,6 +24,10 @@ class FormatterModule : public UICodeEditorModule {
void onUnregister( UICodeEditor* );
bool getAutoFormatOnSave() const;
void setAutoFormatOnSave( bool autoFormatOnSave );
protected:
enum class FormatterType { Inplace, Output };
@@ -36,8 +40,9 @@ class FormatterModule : public UICodeEditorModule {
std::shared_ptr<ThreadPool> mPool;
std::vector<Formatter> mFormatters;
std::set<UICodeEditor*> mEditors;
bool mClosing{ false };
bool mAutoFormatOnSave{ false };
bool mClosing{ false };
bool mReady{ false };
void load( const std::string& formatterPath );

View File

@@ -59,6 +59,8 @@ void GlobalSearchController::initGlobalSearchBar( UIGlobalSearchBar* globalSearc
UIPushButton* searchButton = mGlobalSearchBarLayout->find<UIPushButton>( "global_search" );
UIPushButton* searchReplaceButton =
mGlobalSearchBarLayout->find<UIPushButton>( "global_search_replace" );
UIPushButton* searchClearHistory =
mGlobalSearchBarLayout->find<UIPushButton>( "global_search_clear_history" );
UICheckBox* caseSensitiveChk = mGlobalSearchBarLayout->find<UICheckBox>( "case_sensitive" );
UICheckBox* wholeWordChk = mGlobalSearchBarLayout->find<UICheckBox>( "whole_word" );
UICheckBox* luaPatternChk = mGlobalSearchBarLayout->find<UICheckBox>( "lua_pattern" );
@@ -68,6 +70,7 @@ void GlobalSearchController::initGlobalSearchBar( UIGlobalSearchBar* globalSearc
mGlobalSearchHistoryList =
mGlobalSearchBarLayout->find<UIDropDownList>( "global_search_history" );
mGlobalSearchBarLayout->addCommand( "global-search-clear-history", [&] { clearHistory(); } );
mGlobalSearchBarLayout->addCommand(
"search-in-files", [&, caseSensitiveChk, wholeWordChk, luaPatternChk, escapeSequenceChk] {
doGlobalSearch( mGlobalSearchInput->getText(), caseSensitiveChk->isChecked(),
@@ -108,14 +111,15 @@ void GlobalSearchController::initGlobalSearchBar( UIGlobalSearchBar* globalSearc
} );
mGlobalSearchBarLayout->getKeyBindings().addKeybindsString( {
{ "escape", "close-global-searchbar" },
{ "ctrl+s", "change-case" },
{ "ctrl+w", "change-whole-word" },
{ "ctrl+l", "toggle-lua-pattern" },
{ "ctrl+r", "search-replace-in-files" },
{ "ctrl+g", "search-again" },
{ "ctrl+a", "expand-all" },
{ "ctrl+shift+e", "collapse-all" },
{ "ctrl+e", "change-escape-sequence" },
{ "mod+s", "change-case" },
{ "mod+w", "change-whole-word" },
{ "mod+l", "toggle-lua-pattern" },
{ "mod+r", "search-replace-in-files" },
{ "mod+g", "search-again" },
{ "mod+a", "expand-all" },
{ "mod+shift+e", "collapse-all" },
{ "mod+e", "change-escape-sequence" },
{ "mod+h", "global-search-clear-history" },
} );
mGlobalSearchBarLayout->addCommand( "change-case", [&, caseSensitiveChk] {
caseSensitiveChk->setChecked( !caseSensitiveChk->isChecked() );
@@ -153,6 +157,7 @@ void GlobalSearchController::initGlobalSearchBar( UIGlobalSearchBar* globalSearc
addClickListener( searchButton, "search-in-files" );
addClickListener( searchReplaceButton, "search-replace-in-files" );
addClickListener( searchBarClose, "close-global-searchbar" );
addClickListener( searchClearHistory, "global-search-clear-history" );
mGlobalSearchLayout = mUISceneNode
->loadLayoutFromString( R"xml(
<vbox id="global_search_layout" layout_width="wrap_content" layout_height="wrap_content" visible="false">
@@ -267,6 +272,19 @@ bool GlobalSearchController::isUsingSearchReplaceTree() {
return mGlobalSearchTreeReplace == mGlobalSearchTree;
}
void GlobalSearchController::clearHistory() {
auto listBox = mGlobalSearchHistoryList->getListBox();
listBox->clear();
mGlobalSearchHistory.clear();
mGlobalSearchHistoryOnItemSelectedCb = 0;
mGlobalSearchTree->setSearchStr( "" );
mGlobalSearchTree->setModel( nullptr );
mGlobalSearchInput->setText( "" );
mGlobalSearchLayout->findByClass( "status_box" )->setVisible( false );
mGlobalSearchLayout->findByClass<UITextView>( "search_str" )->setText( "" );
updateGlobalSearchBar();
}
void GlobalSearchController::updateGlobalSearchBar() {
mGlobalSearchBarLayout->runOnMainThread( [&] {
Float width = eeceil( mGlobalSearchInput->getPixelsSize().getWidth() );

View File

@@ -36,6 +36,7 @@ class GlobalSearchController {
bool isUsingSearchReplaceTree();
void clearHistory();
protected:
UICodeEditorSplitter* mEditorSplitter{ nullptr };
UISceneNode* mUISceneNode{ nullptr };

View File

@@ -234,7 +234,8 @@ void LinterModule::runLinter( std::shared_ptr<TextDocument> doc, const Linter& l
std::map<Int64, std::vector<LinterMatch>> matches;
for ( auto& warningPatterm : linter.warningPattern ) {
for ( auto warningPatterm : linter.warningPattern ) {
String::replaceAll( warningPatterm, "$FILENAME", path );
LuaPattern pattern( warningPatterm );
for ( auto& match : pattern.gmatch( data ) ) {
LinterMatch linterMatch;

View File

@@ -34,7 +34,9 @@ static String textLine( const std::string& fileText, const size_t& fromPos, size
}
end = ptr - stringStartPtr;
relCol = String( fileText.substr( start, startPtr - nlStartPtr ) ).size();
return fileText.substr( start, end - start );
// if the line to substract is massive we only get the fist kilobyte of that line, since the
// line is only shared for visual aid.
return fileText.substr( start, end - start > EE_1KB ? EE_1KB : end - start );
}
static std::vector<ProjectSearch::ResultData::Result>

View File

@@ -124,16 +124,13 @@ class ProjectSearch {
} else {
switch ( index.column() ) {
case FileOrPosition:
return Variant( String::format( "%6lld %s",
mResult[index.internalId()]
.results[index.row()]
.position.start()
.line() +
1,
mResult[index.internalId()]
.results[index.row()]
.line.toUtf8()
.c_str() ) );
return Variant(
String( String::format( "%6lld ", mResult[index.internalId()]
.results[index.row()]
.position.start()
.line() +
1 ) ) +
mResult[index.internalId()].results[index.row()].line );
}
}
} else if ( role == ModelRole::Custom ) {

View File

@@ -101,18 +101,21 @@ ProjectSearch::ResultData* UITreeViewCellGlobalSearch::getResultDataPtr() {
return nullptr;
}
#define CELL_GLOBAL_SEARCH_PADDING ( 12 )
UITreeViewCellGlobalSearch::UITreeViewCellGlobalSearch( bool selectionEnabled ) :
UITreeViewCell( selectionEnabled ? getCheckBoxFn() : nullptr ) {}
UIPushButton* UITreeViewCellGlobalSearch::setText( const String& text ) {
auto* result = getResultPtr();
if ( text != mTextBox->getText() ||
( result && std::make_pair<size_t, size_t>( result->position.start().column() + 12,
result->position.end().column() + 12 ) !=
mSearchStrPos ) ) {
( result &&
std::make_pair<size_t, size_t>(
result->position.start().column() + CELL_GLOBAL_SEARCH_PADDING,
result->position.end().column() + CELL_GLOBAL_SEARCH_PADDING ) != mSearchStrPos ) ) {
mTextBox->setVisible( !text.empty() );
mTextBox->setText( text );
updateText( text + '\n' );
updateText( text + "\n" );
updateLayout();
}
return this;
@@ -122,7 +125,8 @@ UIPushButton* UITreeViewCellGlobalSearch::updateText( const std::string& text )
if ( getCurIndex().internalId() != -1 ) {
UITreeViewGlobalSearch* pp = getParent()->getParent()->asType<UITreeViewGlobalSearch>();
ProjectSearch::ResultData* res = (ProjectSearch::ResultData*)getCurIndex().parent().internalData();
ProjectSearch::ResultData* res =
(ProjectSearch::ResultData*)getCurIndex().parent().internalData();
auto styleDef = SyntaxDefinitionManager::instance()->getStyleByExtension( res->file );
@@ -134,8 +138,8 @@ UIPushButton* UITreeViewCellGlobalSearch::updateText( const std::string& text )
}
auto* result = getResultPtr();
mSearchStrPos = { result->position.start().column() + 12,
result->position.end().column() + 12 };
mSearchStrPos = { result->position.start().column() + CELL_GLOBAL_SEARCH_PADDING,
result->position.end().column() + CELL_GLOBAL_SEARCH_PADDING };
const String& txt = mTextBox->getText();
@@ -193,6 +197,8 @@ void UITreeViewCellGlobalSearch::draw() {
UICheckBox* chk = mTextBox->asType<UICheckBox>();
screenPos.x += chk->getRealAlignOffset().x;
}
if ( mSearchStrPos.second >= mTextBox->getText().length() )
return;
p.drawRectangle( Rectf(
{ screenPos.x + mTextBox->getPixelsPosition().x +
getXOffsetCol( hspace, mTextBox->getTextCache()->getTabWidth(),