Added support for range based searches in the TextDocument and Code Editor.

Total refactor of the Code Editor.
Many many minor changes and fixes, still needs more testing.
This commit is contained in:
Martín Lucas Golini
2020-06-26 06:32:33 -03:00
parent 71f974b7e8
commit 60a7a28b28
26 changed files with 1644 additions and 1100 deletions
+169 -167
View File
@@ -10,7 +10,8 @@ line_number_background = #2e2e32
whitespace = #54575b
line_break_column = #54575b99
matching_bracket = #FFFFFF33
matching_selection = #FFFFFF33
matching_selection = #FFFFFF66
matching_search = #181b1e
normal = #e1e1e6
symbol = #e1e1e6
@@ -28,7 +29,7 @@ link = #93DDFA,underline
background = #282a36
text = #e1e1e6
caret = #93DDFA
selection = #4c5163
selection = #394484
line_highlight = #2d303d
line_number = #525259
line_number2 = #83838f
@@ -36,7 +37,8 @@ line_number_background = #282a36
whitespace = #54575b
line_break_column = #54575b99
matching_bracket = #FFFFFF33
matching_selection = #FFFFFF33
matching_selection = #3e596e
matching_search = #181b1e
normal = #e1e1e6
symbol = #e1e1e6
@@ -51,132 +53,132 @@ function = #00dc7f,shadow
link = #6ae0f9,shadow,underline,#FFFFFF11
[fall]
background = #343233
text = #c4b398
caret = #61efce
accent = #ffd152
selection = #454244
line_number = #454244
line_number2 = #615d5f
line_highlight = #383637
background = #343233
text = #c4b398
caret = #61efce
accent = #ffd152
selection = #454244
line_number = #454244
line_number2 = #615d5f
line_highlight = #383637
normal = #efdab9
symbol = #efdab9
comment = #615d5f
keyword = #d36e2d
keyword2 = #ef6179
number = #ffd152
literal = #ffd152
string = #ffd152
operator = #efdab9
function = #61efce
normal = #efdab9
symbol = #efdab9
comment = #615d5f
keyword = #d36e2d
keyword2 = #ef6179
number = #ffd152
literal = #ffd152
string = #ffd152
operator = #efdab9
function = #61efce
[summer]
background = #fbfbfb
text = #404040
caret = #fc1785
accent = #fc1785
selection = #b7dce8
line_number = #d0d0d0
line_number2 = #808080
line_highlight = #f2f2f2
background = #fbfbfb
text = #404040
caret = #fc1785
accent = #fc1785
selection = #b7dce8
line_number = #d0d0d0
line_number2 = #808080
line_highlight = #f2f2f2
normal = #181818
symbol = #181818
comment = #22a21f
keyword = #fb6620
keyword2 = #fc1785
number = #1586d2
literal = #1586d2
string = #1586d2
operator = #fb6620
function = #fc1785
normal = #181818
symbol = #181818
comment = #22a21f
keyword = #fb6620
keyword2 = #fc1785
number = #1586d2
literal = #1586d2
string = #1586d2
operator = #fb6620
function = #fc1785
[dracula]
background = #282a36
text = #7b81a6
caret = #f8f8f0
accent = #8be9fd
selection = #44475a
line_number = #53576e
line_number2 = #f8f8f0
line_highlight = #313442
background = #282a36
text = #7b81a6
caret = #f8f8f0
accent = #8be9fd
selection = #44475a
line_number = #53576e
line_number2 = #f8f8f0
line_highlight = #313442
normal = #f8f8f2
symbol = #f8f8f2
comment = #6272a4
keyword = #ff79c6
keyword2 = #ff79c6
number = #bd93f9
literal = #f1fa8c
string = #f1fa8c
operator = #ff79c6
function = #50fa7b
normal = #f8f8f2
symbol = #f8f8f2
comment = #6272a4
keyword = #ff79c6
keyword2 = #ff79c6
number = #bd93f9
literal = #f1fa8c
string = #f1fa8c
operator = #ff79c6
function = #50fa7b
[gruvbox dark]
background = #282828
text = #928374
caret = #fbf1c7
accent = #ebdbb2
selection = #3c3836
line_number = #928374
line_number2 = #ebdbb2
line_highlight = #32302f
background = #282828
text = #928374
caret = #fbf1c7
accent = #ebdbb2
selection = #3c3836
line_number = #928374
line_number2 = #ebdbb2
line_highlight = #32302f
normal = #ebdbb2
symbol = #ebdbb2
comment = #928374
keyword = #fb4934
keyword2 = #83a598
number = #d3869b
literal = #d3869b
string = #b8bb26
operator = #ebdbb2
function = #8ec07c
normal = #ebdbb2
symbol = #ebdbb2
comment = #928374
keyword = #fb4934
keyword2 = #83a598
number = #d3869b
literal = #d3869b
string = #b8bb26
operator = #ebdbb2
function = #8ec07c
[liqube]
background = #13171e
text = #abb2bf
caret = #abb2bf
accent = #ffffff
selection = #3e4451
line_number = #323641
line_number2 = #596275
line_highlight = #1c1f25
whitespace = #1c1f25
background = #13171e
text = #abb2bf
caret = #abb2bf
accent = #ffffff
selection = #3e4451
line_number = #323641
line_number2 = #596275
line_highlight = #1c1f25
whitespace = #1c1f25
normal = #abb2bf
symbol = #71a9d7
comment = #5c6370
keyword = #98c875
keyword2 = #ffffff
number = #ffffff
literal = #ea5964
string = #ea5964
operator = #657085
function = #ffffff
preprocessor = #98c875
normal = #abb2bf
symbol = #71a9d7
comment = #5c6370
keyword = #98c875
keyword2 = #ffffff
number = #ffffff
literal = #ea5964
string = #ea5964
operator = #657085
function = #ffffff
preprocessor = #98c875
[monodark]
background = #080808
text = #707070
caret = #ffffff
accent = #d0d0d0
selection = #242424
line_number = #202020
line_number2 = #707070
line_highlight = #101010
background = #080808
text = #707070
caret = #ffffff
accent = #d0d0d0
selection = #242424
line_number = #202020
line_number2 = #707070
line_highlight = #101010
normal = #a0a0a0
symbol = #a0a0a0
comment = #404040
keyword = #f0f0f0
keyword2 = #f0f0f0
number = #f0f0f0
literal = #f0f0f0
string = #f0f0f0
operator = #f0f0f0
function = #a0a0a0
normal = #a0a0a0
symbol = #a0a0a0
comment = #404040
keyword = #f0f0f0
keyword2 = #f0f0f0
number = #f0f0f0
literal = #f0f0f0
string = #f0f0f0
operator = #f0f0f0
function = #a0a0a0
[monokai]
background = #272822
@@ -200,64 +202,64 @@ operator = #F8F8F2
function = #A6E22E
[winter]
background = #282a36
text = #aab3e6
caret = #f5faff
accent = #ffb86c
selection = #4c5163
line_number = #44475a
line_number2 = #717796
line_highlight = #2d303d
background = #282a36
text = #aab3e6
caret = #f5faff
accent = #ffb86c
selection = #4c5163
line_number = #44475a
line_number2 = #717796
line_highlight = #2d303d
normal = #f5faff
symbol = #f5faff
comment = #6272a4
keyword = #ff79c6
keyword2 = #8be9fd
number = #bd93f9
literal = #bd93f9
string = #f1fa8c
operator = #ff79c6
function = #8be9fd
normal = #f5faff
symbol = #f5faff
comment = #6272a4
keyword = #ff79c6
keyword2 = #8be9fd
number = #bd93f9
literal = #bd93f9
string = #f1fa8c
operator = #ff79c6
function = #8be9fd
[github]
background = #fbfbfb
text = #404040
caret = #181818
accent = #0366d6
selection = #b7dce8
line_number = #d0d0d0
line_number2 = #808080
line_highlight = #f2f2f2
background = #fbfbfb
text = #404040
caret = #181818
accent = #0366d6
selection = #b7dce8
line_number = #d0d0d0
line_number2 = #808080
line_highlight = #f2f2f2
normal = #24292e
symbol = #24292e
comment = #6a737d
keyword = #d73a49
keyword2 = #d73a49
number = #005cc5
literal = #005cc5
string = #032f62
operator = #d73a49
function = #005cc5
normal = #24292e
symbol = #24292e
comment = #6a737d
keyword = #d73a49
keyword2 = #d73a49
number = #005cc5
literal = #005cc5
string = #032f62
operator = #d73a49
function = #005cc5
[solarized light]
background = #fdf6e3
text = #657b83
caret = #657b83
accent = #002b36
selection = #eee8d5
line_number = #93a1a1
line_number2 = #002b36
line_highlight = #eee8d5
background = #fdf6e3
text = #657b83
caret = #657b83
accent = #002b36
selection = #eee8d5
line_number = #93a1a1
line_number2 = #002b36
line_highlight = #eee8d5
normal = #657b83
symbol = #657b83
comment = #93a1a1
keyword = #859900
keyword2 = #268bd2
number = #d33682
literal = #2aa198
string = #2aa198
operator = #859900
function = #268bd2
normal = #657b83
symbol = #657b83
comment = #93a1a1
keyword = #859900
keyword2 = #268bd2
number = #d33682
literal = #2aa198
string = #2aa198
operator = #859900
function = #268bd2
+2
View File
@@ -759,6 +759,8 @@ class EE_API String {
String& toUpper();
StringBaseType lastChar() const;
private:
friend EE_API bool operator==( const String& left, const String& right );
friend EE_API bool operator<( const String& left, const String& right );
+5
View File
@@ -17,6 +17,7 @@
#define CINIFILE_H
#include <eepp/system/iostream.hpp>
#include <map>
#include <vector>
#define MAX_KEYNAME 128
@@ -210,6 +211,10 @@ class EE_API IniFile {
/** Delete all header comments. */
void deleteHeaderComments() { mComments.clear(); }
std::map<std::string, std::string> getKeyMap( const unsigned & keyID ) const;
std::map<std::string, std::string> getKeyMap( const std::string& keyname ) const;
/** Key comment functions.
** Key comments are those comments within a key. Any comments
** defined within value Names will be added to this list. Therefore,
+5 -4
View File
@@ -1,8 +1,6 @@
#ifndef EEPP_UI_HPP
#define EEPP_UI_HPP
#include <eepp/ui/tools/textureatlaseditor.hpp>
#include <eepp/ui/tools/uicolorpicker.hpp>
#include <eepp/ui/uicheckbox.hpp>
#include <eepp/ui/uicodeeditor.hpp>
#include <eepp/ui/uicombobox.hpp>
@@ -51,9 +49,8 @@
#include <eepp/ui/uitouchdraggablewidget.hpp>
#include <eepp/ui/uiviewpager.hpp>
#include <eepp/ui/uiwidget.hpp>
#include <eepp/ui/uiwindow.hpp>
#include <eepp/ui/uiwidgetcreator.hpp>
#include <eepp/ui/uiwindow.hpp>
#include <eepp/ui/css/stylesheet.hpp>
#include <eepp/ui/css/stylesheetparser.hpp>
@@ -66,4 +63,8 @@
#include <eepp/ui/doc/syntaxdefinitionmanager.hpp>
#include <eepp/ui/doc/textdocument.hpp>
#include <eepp/ui/tools/textureatlaseditor.hpp>
#include <eepp/ui/tools/uicodeeditorsplitter.hpp>
#include <eepp/ui/tools/uicolorpicker.hpp>
#endif
+5 -2
View File
@@ -14,12 +14,15 @@ namespace EE { namespace UI { namespace Doc {
/**
* Syntax colors types accepted/used are:
* "normal", "symbol", "comment", "keyword", "keyword2",
* "number", "literal", "string", "operator", "function"
* "number", "literal", "string", "operator", "function",
* "link"
*
* Editor colors types accepted/used are:
* "background", "text", "caret"
* "selection", "line_number_background",
* "line_number", "line_number2", "line_highlight"
* "line_number", "line_number2", "line_highlight",
* "line_number_background", "whitespace", "line_break_column",
* "matching_bracket", "matching_selection"
*
* Following the lite editor syntax colors (https://github.com/rxi/lite).
*/
+9 -3
View File
@@ -126,6 +126,8 @@ class EE_API TextDocument {
TextPosition endOfDoc() const;
TextRange getDocRange() const;
void deleteTo( TextPosition position );
void deleteTo( int offset );
@@ -232,15 +234,17 @@ class EE_API TextDocument {
void setCommand( const std::string& command, DocumentCommand func );
TextPosition find( String text, TextPosition from = {0, 0}, const bool& caseSensitive = true );
TextPosition find( String text, TextPosition from = {0, 0}, const bool& caseSensitive = true,
TextRange restrictRange = TextRange() );
TextPosition findLast( String text, TextPosition from = {0, 0},
const bool& caseSensitive = true );
const bool& caseSensitive = true,
TextRange restrictRange = TextRange() );
TextPosition replaceSelection( const String& replace );
TextPosition replace( String search, const String& replace, TextPosition from = {0, 0},
const bool& caseSensitive = true );
const bool& caseSensitive = true, TextRange restrictRange = TextRange() );
String getIndentString();
@@ -312,6 +316,8 @@ class EE_API TextDocument {
bool getBOM() const;
TextRange sanitizeRange( const TextRange& range );
protected:
friend class UndoStack;
UndoStack mUndoStack;
+4
View File
@@ -35,6 +35,10 @@ class EE_API TextPosition {
return mLine < other.mLine || ( mLine == other.mLine && mColumn < other.mColumn );
}
bool operator>( const TextPosition& other ) const {
return mLine > other.mLine || ( mLine == other.mLine && mColumn > other.mColumn );
}
TextPosition operator+( const TextPosition& other ) const {
return {mLine + other.line(), mColumn + other.column()};
}
+8
View File
@@ -54,6 +54,14 @@ class EE_API TextRange {
return true;
}
bool hasSelection() const {
return isValid() && mStart != mEnd;
}
bool inSameLine() const {
return isValid() && mStart.line() == mEnd.line();
}
std::string toString() {
return String::format( "%s - %s", mStart.toString().c_str(), mEnd.toString().c_str() );
}
+8 -2
View File
@@ -16,6 +16,8 @@ namespace EE { namespace UI {
class UIWidget;
typedef std::map<Uint64, std::string> ShortcutMap;
class EE_API KeyBindings {
public:
struct Shortcut {
@@ -58,10 +60,14 @@ class EE_API KeyBindings {
std::string getCommandFromKeyBind( const Shortcut& keys );
void reset();
const ShortcutMap& getShortcutMap() const;
std::string getShortcutString( Shortcut shortcut );
protected:
const Window::Input* mInput;
/** Map first keys, then Mods (Shortcut) to get the command */
typedef std::map<Uint64, std::string> ShortcutMap;
ShortcutMap mShortcuts;
};
@@ -0,0 +1,143 @@
#ifndef EE_UI_TOOLS_UICODEEDITORSPLITTER_HPP
#define EE_UI_TOOLS_UICODEEDITORSPLITTER_HPP
#include <eepp/ui/uicodeeditor.hpp>
#include <eepp/ui/uiscenenode.hpp>
#include <eepp/ui/uisplitter.hpp>
#include <eepp/ui/uitabwidget.hpp>
using namespace EE::UI::Doc;
namespace EE { namespace UI { namespace Tools {
class EE_API UICodeEditorSplitter {
public:
struct CodeEditorConfig {
std::string colorScheme{"lite"};
Float fontSize{11};
bool showLineNumbers{true};
bool showWhiteSpaces{true};
bool highlightMatchingBracket{true};
bool horizontalScrollbar{false};
bool highlightCurrentLine{true};
bool trimTrailingWhitespaces{false};
bool forceNewLineAtEndOfFile{false};
bool autoDetectIndentType{true};
bool writeUnicodeBOM{false};
bool indentSpaces{false};
bool windowsLineEndings{false};
bool highlightSelectionMatch{true};
int indentWidth{4};
int tabWidth{4};
int lineBreakingColumn{100};
};
enum class SplitDirection { Left, Right, Top, Bottom };
class EE_API Client {
public:
virtual ~Client(){};
virtual void onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) = 0;
virtual void onCodeEditorFocusChange( UICodeEditor* editor ) = 0;
virtual void onDocumentStateChanged( UICodeEditor* editor, TextDocument& doc ) = 0;
virtual void onDocumentModified( UICodeEditor* editor, TextDocument& doc ) = 0;
virtual void onDocumentSelectionChange( UICodeEditor* editor, TextDocument& doc ) = 0;
virtual void onColorSchemeChanged( const std::string& currentColorScheme ) = 0;
virtual void onDocumentLoaded( UICodeEditor* codeEditor, const std::string& path ) = 0;
virtual const CodeEditorConfig& getCodeEditorConfig() const = 0;
};
static UICodeEditorSplitter* New( UICodeEditorSplitter::Client* client, UISceneNode* sceneNode,
const std::vector<SyntaxColorScheme>& colorSchemes = {},
const std::string& initColorScheme = "" );
virtual ~UICodeEditorSplitter();
virtual bool tryTabClose( UICodeEditor* editor );
void closeEditorTab( UICodeEditor* editor );
void splitEditor( const SplitDirection& direction, UICodeEditor* editor );
void switchToTab( Int32 index );
UITabWidget* findPreviousSplit( UICodeEditor* editor );
void switchPreviousSplit( UICodeEditor* editor );
UITabWidget* findNextSplit( UICodeEditor* editor );
void switchNextSplit( UICodeEditor* editor );
void setCurrentEditor( UICodeEditor* editor );
UITabWidget* tabWidgetFromEditor( UICodeEditor* editor );
UISplitter* splitterFromEditor( UICodeEditor* editor );
std::pair<UITab*, UICodeEditor*> createCodeEditorInTabWidget( UITabWidget* tabWidget );
UICodeEditor* createCodeEditor();
void focusSomeEditor( Node* searchFrom = nullptr );
bool loadFileFromPath( const std::string& path, UICodeEditor* codeEditor = nullptr );
void loadFileFromPathInNewTab( const std::string& path );
void removeUnusedTab( UITabWidget* tabWidget );
UITabWidget* createEditorWithTabWidget( Node* parent );
void applyColorScheme( const SyntaxColorScheme& colorScheme );
void forEachEditor( std::function<void( UICodeEditor* )> run );
void zoomIn();
void zoomOut();
void zoomReset();
void closeSplitter( UISplitter* splitter );
void addRemainingTabWidgets( Node* widget );
void closeTabWidgets( UISplitter* splitter );
UICodeEditor* getCurEditor() const;
const std::string& getCurrentColorScheme() const;
void setColorScheme( const std::string& name );
const std::map<std::string, SyntaxColorScheme>& getColorSchemes() const;
bool editorExists( UICodeEditor* editor ) const;
protected:
UISceneNode* mUISceneNode{nullptr};
UICodeEditor* mCurEditor{nullptr};
std::map<std::string, SyntaxColorScheme> mColorSchemes;
std::string mCurrentColorScheme;
std::vector<UITabWidget*> mTabWidgets;
Client* mClient;
UICodeEditorSplitter( UICodeEditorSplitter::Client* client, UISceneNode* sceneNode,
const std::vector<SyntaxColorScheme>& colorSchemes,
const std::string& initColorScheme );
virtual void onTabClosed( const TabEvent* tabEvent );
};
}}} // namespace EE::UI::Tools
#endif // EE_UI_TOOLS_UICODEEDITORSPLITTER_HPP
+16 -2
View File
@@ -275,6 +275,14 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
void setShowWhitespaces( const bool& showWhitespaces );
const String& getHighlightWord() const;
void setHighlightWord( const String& highlightWord );
const TextRange& getHighlightTextRange() const;
void setHighlightTextRange( const TextRange& highlightSelection );
protected:
struct LastXOffset {
TextPosition position;
@@ -325,6 +333,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
Float mLongestLineWidth{0};
Time mFindLongestLineWidthUpdateFrequency;
Clock mLongestLineWidthLastUpdate;
String mHighlightWord;
TextRange mHighlightTextRange;
UICodeEditor( const std::string& elementTag, const bool& autoRegisterBaseCommands = true,
const bool& autoRegisterBaseKeybindings = true );
@@ -425,14 +435,18 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
virtual void drawSelectionMatch( const std::pair<int, int>& lineRange,
const Vector2f& startScroll, const Float& lineHeight );
virtual void drawWordMatch( const String& text, const std::pair<int, int>& lineRange,
const Vector2f& startScroll, const Float& lineHeight );
virtual void drawLineText( const Int64& index, Vector2f position, const Float& fontSize,
const Float& lineHeight );
virtual void drawWhitespaces( const std::pair<int, int>& lineRange, const Vector2f& startScroll,
const Float& lineHeight );
virtual void drawSelection( const std::pair<int, int>& lineRange, const Vector2f& startScroll,
const Float& lineHeight );
virtual void drawTextRange( const TextRange& range, const std::pair<int, int>& lineRange,
const Vector2f& startScroll, const Float& lineHeight,
const Color& backgrundColor );
virtual void drawLineNumbers( const std::pair<int, int>& lineRange, const Vector2f& startScroll,
const Vector2f& screenStart, const Float& lineHeight,
+4
View File
@@ -332,6 +332,7 @@
../../include/eepp/ui/keyboardshortcut.hpp
../../include/eepp/ui/marginmove/scale.hpp
../../include/eepp/ui/tools/textureatlaseditor.hpp
../../include/eepp/ui/tools/uicodeeditorsplitter.hpp
../../include/eepp/ui/tools/uicolorpicker.hpp
../../include/eepp/ui/uibackgrounddrawable.hpp
../../include/eepp/ui/uiborderdrawable.hpp
@@ -788,6 +789,7 @@
../../src/eepp/ui/tools/textureatlasnew.hpp
../../src/eepp/ui/tools/textureatlastextureregioneditor.cpp
../../src/eepp/ui/tools/textureatlastextureregioneditor.hpp
../../src/eepp/ui/tools/uicodeeditorsplitter.cpp
../../src/eepp/ui/tools/uicolorpicker.cpp
../../src/eepp/ui/uibackgrounddrawable.cpp
../../src/eepp/ui/uiborderdrawable.cpp
@@ -972,6 +974,8 @@
../../src/thirdparty/SOIL2/src/SOIL2/stbi_pvr.h
../../src/tools/codeeditor/codeeditor.cpp
../../src/tools/codeeditor/codeeditor.hpp
../../src/tools/codeeditor/uicodeeditorsplitter.cpp
../../src/tools/codeeditor/uicodeeditorsplitter.hpp
../../src/tools/mapeditor/mapeditor.cpp
../../src/tools/textureatlaseditor/textureatlaseditor.cpp
../../src/tools/texturepacker/texturepacker.cpp
-5
View File
@@ -6,8 +6,3 @@
../../src/thirdparty/libvorbis/include
/usr/include/freetype2/
../../src/thirdparty/mbedtls/include
../../docs/articles
../../include/eepp/ui/doc
../../src/eepp/ui/doc
../../include/eepp/ui
../../src/eepp/ui
+5
View File
@@ -259,6 +259,11 @@ String& String::toUpper() {
return *this;
}
String::StringBaseType String::lastChar() const {
return mString.empty() ? std::numeric_limits<StringBaseType>::max()
: mString[mString.size() - 1];
}
std::vector<Uint8> String::stringToUint8( const std::string& str ) {
return std::vector<Uint8>( str.begin(), str.end() );
}
+18
View File
@@ -445,6 +445,24 @@ bool IniFile::deleteHeaderComment( unsigned commentID ) {
return false;
}
std::map<std::string, std::string> IniFile::getKeyMap( const unsigned& keyID ) const {
std::map<std::string, std::string> map;
if ( keyID < mKeys.size() ) {
for ( size_t i = 0; i < mKeys[keyID].names.size(); i++ ) {
map[mKeys[keyID].names[i]] = mKeys[keyID].values[i];
}
return map;
}
return {};
}
std::map<std::string, std::string> IniFile::getKeyMap( const std::string& keyname ) const {
long keyID = findKey( keyname );
if ( keyID != noID )
return getKeyMap( keyID );
return {};
}
unsigned IniFile::getNumKeyComments( unsigned const keyID ) const {
if ( keyID < mKeys.size() )
return (unsigned int)mKeys[keyID].comments.size();
+11 -7
View File
@@ -8,6 +8,8 @@
#include <eepp/system/packmanager.hpp>
#include <eepp/ui/doc/syntaxcolorscheme.hpp>
using namespace EE::Graphics;
namespace EE { namespace UI { namespace Doc {
// Color schemes are compatible with the lite (https://github.com/rxi/lite) color schemes.
@@ -17,9 +19,10 @@ namespace EE { namespace UI { namespace Doc {
// "line_break_column" (the right margin line column color)
// "matching_bracket" (the background color drawn in the matching brackets)
// "matching_selection" (the background color drawn in the text matching the current selected text)
// "matching_search" (the background color drawn in the text matching the current searched text)
SyntaxColorScheme SyntaxColorScheme::getDefault() {
return {"lite-theme",
return {"lite",
{
{"normal", Color( "#e1e1e6" )},
{"symbol", Color( "#e1e1e6" )},
@@ -31,7 +34,7 @@ SyntaxColorScheme SyntaxColorScheme::getDefault() {
{"string", Color( "#f7c95c" )},
{"operator", Color( "#93DDFA" )},
{"function", Color( "#93DDFA" )},
{"link", {Color( "#93DDFA" ), Color::Transparent, Graphics::Text::Underlined}},
{"link", {Color( "#93DDFA" ), Color::Transparent, Text::Underlined}},
},
{
{"background", Color( "#2e2e32" )},
@@ -47,6 +50,7 @@ SyntaxColorScheme SyntaxColorScheme::getDefault() {
{"line_break_column", Color( "#54575b99" )},
{"matching_bracket", Color( "#FFFFFF33" )},
{"matching_selection", Color( "#FFFFFF33" )},
{"matching_search", Color( "#181b1e" )},
}};
}
@@ -79,15 +83,15 @@ std::vector<SyntaxColorScheme> SyntaxColorScheme::loadFromStream( IOStream& stre
}
} else {
if ( "bold" == val )
style.style |= Graphics::Text::Bold;
style.style |= Text::Bold;
else if ( "italic" == val )
style.style |= Graphics::Text::Italic;
style.style |= Text::Italic;
else if ( "underline" == val || "underlined" == val )
style.style |= Graphics::Text::Underlined;
style.style |= Text::Underlined;
else if ( "strikethrough" == val )
style.style |= Graphics::Text::StrikeThrough;
style.style |= Text::StrikeThrough;
else if ( "shadow" == val )
style.style |= Graphics::Text::Shadow;
style.style |= Text::Shadow;
}
if ( refColorScheme.mSyntaxColors.find( valueName ) !=
+9 -5
View File
@@ -880,15 +880,19 @@ SyntaxDefinitionManager::SyntaxDefinitionManager() {
add( {"Config File",
{"%.ini$", "%.conf$", "%.desktop$", "%.service$", "%.cfg$", "Doxyfile"},
{
{{"#[%da-fA-F]+"}, "literal"},
{{"#.-\n"}, "comment"},
{{"%s?#%x+"}, "string"},
{{"[%a_][%w-+_%s%p]*%f[=]"}, "keyword"},
{{"^#.-\n"}, "comment"},
{{"%s#.-\n"}, "comment"},
{{"\"", "\"", "\\"}, "string"},
{{"'", "'", "\\"}, "string"},
{{"%[", "%]"}, "keyword2"},
{{"[%a][%w_-]*%s*%f[=]"}, "keyword"},
{{"^%[.-%]"}, "keyword2"},
{{"%s%[.-%]"}, "keyword2"},
{{"="}, "operator"},
{{"https?://%S+"}, "link"},
}} );
},
{},
"#"} );
// Makefile
add( {"Makefile",
+2 -1
View File
@@ -95,7 +95,8 @@ std::pair<std::vector<SyntaxToken>, int> SyntaxTokenizer::tokenize( const Syntax
pattern.patterns[0][0] == '^' ? pattern.patterns[0] : "^" + pattern.patterns[0] );
LuaPatternMatcher words( patternStr );
int start, end = 0;
if ( words.find( text, start, end, i ) ) {
if ( words.find( text, start, end, i ) && start != end ) {
eeASSERT( start != end );
std::string patternText( text.substr( start, end - start ) );
std::string type = syntax.getSymbol( patternText );
pushToken( tokens, type.empty() ? pattern.type : type, patternText );
+60 -14
View File
@@ -309,13 +309,15 @@ bool TextDocument::save( IOStream& stream ) {
notifyTextChanged();
}
if ( i == lastLine ) {
if ( !text.empty() && text[text.size() - 1] == '\n' && !mForceNewLineAtEndOfFile ) {
if ( !text.empty() && text[text.size() - 1] == '\n' ) {
// Last \n is added by the document but it's not part of the document.
text.pop_back();
if ( text.empty() )
continue;
} else if ( !text.empty() && text[text.size()] != '\n' && mForceNewLineAtEndOfFile ) {
text += mLineEnding == LineEnding::CRLF ? "\n\r" : "\n";
}
if ( mForceNewLineAtEndOfFile && !text.empty() && text[text.size() - 1] != '\n' ) {
text += "\n";
textInput( "\n" );
}
}
if ( mLineEnding == LineEnding::CRLF ) {
@@ -678,6 +680,10 @@ TextPosition TextDocument::endOfDoc() const {
return TextPosition( mLines.size() - 1, mLines[mLines.size() - 1].size() - 1 );
}
TextRange TextDocument::getDocRange() const {
return {startOfDoc(), endOfDoc()};
}
void TextDocument::deleteTo( int offset ) {
TextPosition cursorPos = getSelection( true ).start();
if ( hasSelection() ) {
@@ -725,12 +731,14 @@ void TextDocument::textInput( const String& text ) {
void TextDocument::registerClient( Client* client ) {
mClients.insert( client );
if ( mActiveClient == nullptr )
setActiveClient( client );
}
void TextDocument::unregisterClient( Client* client ) {
mClients.erase( client );
if ( mActiveClient == client )
mActiveClient = nullptr;
setActiveClient( nullptr );
}
void TextDocument::moveToPreviousChar() {
@@ -1043,6 +1051,10 @@ void TextDocument::print() const {
printf( "%s", mLines[i].toUtf8().c_str() );
}
TextRange TextDocument::sanitizeRange( const TextRange& range ) {
return {sanitizePosition( range.start() ), sanitizePosition( range.end() )};
}
TextPosition TextDocument::sanitizePosition( const TextPosition& position ) const {
Int64 line = eeclamp<Int64>( position.line(), 0UL, mLines.size() - 1 );
Int64 col =
@@ -1105,18 +1117,36 @@ void TextDocument::setCommand( const std::string& command, TextDocument::Documen
mCommands[command] = func;
}
TextPosition TextDocument::find( String text, TextPosition from, const bool& caseSensitive ) {
TextPosition TextDocument::find( String text, TextPosition from, const bool& caseSensitive,
TextRange restrictRange ) {
if ( text.empty() )
return TextPosition();
from = sanitizePosition( from );
TextPosition to = endOfDoc();
if ( restrictRange.isValid() ) {
restrictRange = sanitizeRange( restrictRange.normalized() );
to = restrictRange.end();
if ( from < restrictRange.start() || from > restrictRange.end() )
return TextPosition();
}
if ( !caseSensitive )
text.toLower();
for ( size_t i = from.line(); i < linesCount(); i++ ) {
for ( Int64 i = from.line(); i <= to.line(); i++ ) {
size_t col;
if ( (Int64)i == from.line() ) {
if ( i == from.line() ) {
col = caseSensitive
? line( i ).getText().substr( from.column() ).find( text )
: String::toLower( line( i ).getText() ).substr( from.column() ).find( text );
if ( String::StringType::npos != col )
col += from.column();
} else if ( i == to.line() && to != endOfDoc() ) {
col =
caseSensitive
? line( i ).getText().substr( 0, to.column() ).find( text )
: String::toLower( line( i ).getText() ).substr( 0, to.column() ).find( text );
} else {
col = caseSensitive ? line( i ).getText().find( text )
: String::toLower( line( i ).getText() ).find( text );
@@ -1128,17 +1158,35 @@ TextPosition TextDocument::find( String text, TextPosition from, const bool& cas
return TextPosition();
}
TextPosition TextDocument::findLast( String text, TextPosition from, const bool& caseSensitive ) {
TextPosition TextDocument::findLast( String text, TextPosition from, const bool& caseSensitive,
TextRange restrictRange ) {
if ( text.empty() )
return TextPosition();
from = sanitizePosition( from );
TextPosition to = startOfDoc();
if ( restrictRange.isValid() ) {
restrictRange = sanitizeRange( restrictRange.normalized() );
to = restrictRange.start();
if ( from < restrictRange.start() || from > restrictRange.end() )
return TextPosition();
}
if ( !caseSensitive )
text.toLower();
for ( Int64 i = from.line(); i >= 0; i-- ) {
for ( Int64 i = from.line(); i >= to.line(); i-- ) {
size_t col;
if ( (Int64)i == from.line() ) {
if ( i == from.line() ) {
col = caseSensitive ? line( i ).getText().substr( 0, from.column() ).rfind( text )
: String::toLower( line( i ).getText() )
.substr( 0, from.column() )
.rfind( text );
} else if ( i == to.line() ) {
col = caseSensitive
? line( i ).getText().substr( to.column() ).rfind( text )
: String::toLower( line( i ).getText() ).substr( to.column() ).rfind( text );
if ( String::StringType::npos != col )
col += to.column();
} else {
col = caseSensitive ? line( i ).getText().rfind( text )
: String::toLower( line( i ).getText() ).rfind( text );
@@ -1159,8 +1207,8 @@ TextPosition TextDocument::replaceSelection( const String& replace ) {
}
TextPosition TextDocument::replace( String search, const String& replace, TextPosition from,
const bool& caseSensitive ) {
TextPosition start( find( search, from, caseSensitive ) );
const bool& caseSensitive, TextRange restrictRange ) {
TextPosition start( find( search, from, caseSensitive, restrictRange ) );
if ( start.isValid() ) {
TextPosition end = positionOffset( start, search.size() );
if ( end.isValid() ) {
@@ -1344,5 +1392,3 @@ void TextDocument::initializeCommands() {
TextDocument::Client::~Client() {}
}}} // namespace EE::UI::Doc
+33
View File
@@ -83,6 +83,13 @@ KeyBindings::Shortcut KeyBindings::getShortcutFromString( const std::string& key
Shortcut shortcut;
Uint32 mod = 0;
auto keysSplit = String::split( keys, '+' );
if ( keys.find( "keypad +" ) != std::string::npos )
mod = 0;
if ( keysSplit.size() == 1 && getKeyMod( keysSplit[0] ) && keys.find( "++" ) )
keysSplit.emplace_back( "+" );
if ( keysSplit.size() == 2 && getKeyMod( keysSplit[0] ) &&
keys.find( " +" ) != std::string::npos )
keysSplit[1] += "+";
for ( auto& part : keysSplit ) {
if ( ( mod = getKeyMod( part ) ) ) {
shortcut.mod |= mod;
@@ -112,4 +119,30 @@ std::string KeyBindings::getCommandFromKeyBind( const KeyBindings::Shortcut& key
return "";
}
void KeyBindings::reset() {
mShortcuts.clear();
}
const ShortcutMap& KeyBindings::getShortcutMap() const {
return mShortcuts;
}
std::string KeyBindings::getShortcutString( KeyBindings::Shortcut shortcut ) {
std::vector<std::string> mods;
std::string keyname( String::toLower( mInput->getKeyName( shortcut.key ) ) );
if ( shortcut.mod & KEYMOD_CTRL )
mods.emplace_back( "ctrl" );
if ( shortcut.mod & KEYMOD_SHIFT )
mods.emplace_back( "shift" );
if ( shortcut.mod & KEYMOD_LALT )
mods.emplace_back( "alt" );
if ( shortcut.mod & KEYMOD_RALT )
mods.emplace_back( "altgr" );
if ( shortcut.mod & KEYMOD_META )
mods.emplace_back( "meta" );
if ( mods.empty() )
return keyname;
return String::join( mods, '+' ) + "+" + keyname;
}
}} // namespace EE::UI
@@ -28,7 +28,7 @@ TextureAtlasTextureRegionEditor::TextureAtlasTextureRegionEditor( TextureAtlasEd
mDrag->center();
mDragPos = mDrag->getPixelsPosition();
mDrag->addEventListener( Event::OnPositionChange, [this]( const Event* event ) {
mDrag->addEventListener( Event::OnPositionChange, [this]( const Event* ) {
if ( NULL != mGfx->getTextureRegion() ) {
Vector2f Diff = -( mDragPos - mDrag->getPixelsPosition() );
+640
View File
@@ -0,0 +1,640 @@
#include <algorithm>
#include <eepp/system/filesystem.hpp>
#include <eepp/ui/tools/uicodeeditorsplitter.hpp>
#include <eepp/ui/uimessagebox.hpp>
using namespace EE::System;
namespace EE { namespace UI { namespace Tools {
UICodeEditorSplitter* UICodeEditorSplitter::New( UICodeEditorSplitter::Client* client,
UISceneNode* sceneNode,
const std::vector<SyntaxColorScheme>& colorSchemes,
const std::string& initColorScheme ) {
return eeNew( UICodeEditorSplitter, ( client, sceneNode, colorSchemes, initColorScheme ) );
}
UICodeEditorSplitter::UICodeEditorSplitter( UICodeEditorSplitter::Client* client,
UISceneNode* sceneNode,
const std::vector<SyntaxColorScheme>& colorSchemes,
const std::string& initColorScheme ) :
mUISceneNode( sceneNode ), mClient( client ) {
if ( !colorSchemes.empty() ) {
for ( auto& colorScheme : colorSchemes )
mColorSchemes.insert( std::make_pair( colorScheme.getName(), colorScheme ) );
mCurrentColorScheme = mColorSchemes.find( initColorScheme ) != mColorSchemes.end()
? initColorScheme
: colorSchemes[0].getName();
} else {
mColorSchemes["default"] = SyntaxColorScheme::getDefault();
mCurrentColorScheme = "default";
}
}
UICodeEditorSplitter::~UICodeEditorSplitter() {}
UITabWidget* UICodeEditorSplitter::tabWidgetFromEditor( UICodeEditor* editor ) {
if ( editor )
return ( (UITab*)editor->getData() )->getTabWidget();
return nullptr;
}
UISplitter* UICodeEditorSplitter::splitterFromEditor( UICodeEditor* editor ) {
if ( editor && editor->getParent()->getParent()->getParent()->isType( UI_TYPE_SPLITTER ) )
return editor->getParent()->getParent()->getParent()->asType<UISplitter>();
return nullptr;
}
UICodeEditor* UICodeEditorSplitter::createCodeEditor() {
UICodeEditor* codeEditor = UICodeEditor::NewOpt( false, true );
TextDocument& doc = codeEditor->getDocument();
const CodeEditorConfig& editorConfig = mClient->getCodeEditorConfig();
codeEditor->setFontSize( editorConfig.fontSize );
codeEditor->setEnableColorPickerOnSelection( true );
codeEditor->setColorScheme( mColorSchemes[mCurrentColorScheme] );
codeEditor->setShowLineNumber( editorConfig.showLineNumbers );
codeEditor->setShowWhitespaces( editorConfig.showWhiteSpaces );
codeEditor->setHighlightMatchingBracket( editorConfig.highlightMatchingBracket );
codeEditor->setHorizontalScrollBarEnabled( editorConfig.horizontalScrollbar );
codeEditor->setHighlightCurrentLine( editorConfig.highlightCurrentLine );
codeEditor->setTabWidth( editorConfig.tabWidth );
codeEditor->setLineBreakingColumn( editorConfig.lineBreakingColumn );
codeEditor->setHighlightSelectionMatch( editorConfig.highlightSelectionMatch );
doc.setAutoDetectIndentType( editorConfig.autoDetectIndentType );
doc.setLineEnding( editorConfig.windowsLineEndings ? TextDocument::LineEnding::CRLF
: TextDocument::LineEnding::LF );
doc.setTrimTrailingWhitespaces( editorConfig.trimTrailingWhitespaces );
doc.setIndentType( editorConfig.indentSpaces ? TextDocument::IndentType::IndentSpaces
: TextDocument::IndentType::IndentTabs );
doc.setForceNewLineAtEndOfFile( editorConfig.forceNewLineAtEndOfFile );
doc.setIndentWidth( editorConfig.indentWidth );
doc.setBOM( editorConfig.writeUnicodeBOM );
/* global commands */
doc.setCommand( "move-to-previous-line", [&] {
if ( mCurEditor )
mCurEditor->moveToPreviousLine();
} );
doc.setCommand( "move-to-next-line", [&] {
if ( mCurEditor )
mCurEditor->moveToNextLine();
} );
doc.setCommand( "select-to-previous-line", [&] {
if ( mCurEditor )
mCurEditor->selectToPreviousLine();
} );
doc.setCommand( "select-to-next-line", [&] {
if ( mCurEditor )
mCurEditor->selectToNextLine();
} );
doc.setCommand( "move-scroll-up", [&] {
if ( mCurEditor )
mCurEditor->moveScrollUp();
} );
doc.setCommand( "move-scroll-down", [&] {
if ( mCurEditor )
mCurEditor->moveScrollDown();
} );
doc.setCommand( "indent", [&] {
if ( mCurEditor )
mCurEditor->indent();
} );
doc.setCommand( "unindent", [&] {
if ( mCurEditor )
mCurEditor->unindent();
} );
doc.setCommand( "copy", [&] {
if ( mCurEditor )
mCurEditor->copy();
} );
doc.setCommand( "cut", [&] {
if ( mCurEditor )
mCurEditor->cut();
} );
doc.setCommand( "paste", [&] {
if ( mCurEditor )
mCurEditor->paste();
} );
doc.setCommand( "font-size-grow", [&] { zoomIn(); } );
doc.setCommand( "font-size-shrink", [&] { zoomOut(); } );
doc.setCommand( "font-size-reset", [&] { zoomReset(); } );
doc.setCommand( "lock", [&] {
if ( mCurEditor ) {
mCurEditor->setLocked( true );
mClient->onDocumentStateChanged( mCurEditor, mCurEditor->getDocument() );
}
} );
doc.setCommand( "unlock", [&] {
if ( mCurEditor ) {
mCurEditor->setLocked( false );
mClient->onDocumentStateChanged( mCurEditor, mCurEditor->getDocument() );
}
} );
doc.setCommand( "lock-toggle", [&] {
if ( mCurEditor ) {
mCurEditor->setLocked( !mCurEditor->isLocked() );
mClient->onDocumentStateChanged( mCurEditor, mCurEditor->getDocument() );
}
} );
codeEditor->addUnlockedCommand( "copy" );
codeEditor->addUnlockedCommand( "select-all" );
/* global commands */
doc.setCommand( "switch-to-previous-colorscheme", [&] {
auto it = mColorSchemes.find( mCurrentColorScheme );
auto prev = std::prev( it, 1 );
if ( prev != mColorSchemes.end() ) {
setColorScheme( prev->first );
} else {
setColorScheme( mColorSchemes.rbegin()->first );
}
} );
doc.setCommand( "switch-to-next-colorscheme", [&] {
auto it = mColorSchemes.find( mCurrentColorScheme );
if ( ++it != mColorSchemes.end() )
mCurrentColorScheme = it->first;
else
mCurrentColorScheme = mColorSchemes.begin()->first;
applyColorScheme( mColorSchemes[mCurrentColorScheme] );
} );
doc.setCommand( "switch-to-previous-split", [&] { switchPreviousSplit( mCurEditor ); } );
doc.setCommand( "switch-to-next-split", [&] { switchNextSplit( mCurEditor ); } );
doc.setCommand( "close-doc", [&] { tryTabClose( mCurEditor ); } );
doc.setCommand( "create-new", [&] {
auto d = createCodeEditorInTabWidget( tabWidgetFromEditor( mCurEditor ) );
d.first->getTabWidget()->setTabSelected( d.first );
} );
doc.setCommand( "next-doc", [&] {
UITabWidget* tabWidget = tabWidgetFromEditor( mCurEditor );
if ( tabWidget && tabWidget->getTabCount() > 1 ) {
UITab* tab = (UITab*)mCurEditor->getData();
Uint32 tabIndex = tabWidget->getTabIndex( tab );
switchToTab( ( tabIndex + 1 ) % tabWidget->getTabCount() );
}
} );
doc.setCommand( "previous-doc", [&] {
UITabWidget* tabWidget = tabWidgetFromEditor( mCurEditor );
if ( tabWidget && tabWidget->getTabCount() > 1 ) {
UITab* tab = (UITab*)mCurEditor->getData();
Uint32 tabIndex = tabWidget->getTabIndex( tab );
Int32 newTabIndex = (Int32)tabIndex - 1;
switchToTab( newTabIndex < 0 ? tabWidget->getTabCount() - newTabIndex : newTabIndex );
}
} );
for ( int i = 1; i <= 10; i++ )
doc.setCommand( String::format( "switch-to-tab-%d", i ), [&, i] { switchToTab( i - 1 ); } );
doc.setCommand( "switch-to-first-tab", [&] {
UITabWidget* tabWidget = tabWidgetFromEditor( mCurEditor );
if ( tabWidget && tabWidget->getTabCount() ) {
switchToTab( 0 );
}
} );
doc.setCommand( "switch-to-last-tab", [&] {
UITabWidget* tabWidget = tabWidgetFromEditor( mCurEditor );
if ( tabWidget && tabWidget->getTabCount() ) {
switchToTab( tabWidget->getTabCount() - 1 );
}
} );
doc.setCommand( "split-right", [&] { splitEditor( SplitDirection::Right, mCurEditor ); } );
doc.setCommand( "split-bottom", [&] { splitEditor( SplitDirection::Bottom, mCurEditor ); } );
doc.setCommand( "split-left", [&] { splitEditor( SplitDirection::Left, mCurEditor ); } );
doc.setCommand( "split-top", [&] { splitEditor( SplitDirection::Top, mCurEditor ); } );
doc.setCommand( "split-swap", [&] {
if ( UISplitter* splitter = splitterFromEditor( mCurEditor ) )
splitter->swap();
} );
codeEditor->addEventListener( Event::OnFocus, [&]( const Event* event ) {
setCurrentEditor( event->getNode()->asType<UICodeEditor>() );
} );
codeEditor->addEventListener( Event::OnTextChanged, [&]( const Event* event ) {
mClient->onDocumentModified( event->getNode()->asType<UICodeEditor>(),
event->getNode()->asType<UICodeEditor>()->getDocument() );
} );
codeEditor->addEventListener( Event::OnSelectionChanged, [&]( const Event* event ) {
mClient->onDocumentSelectionChange(
event->getNode()->asType<UICodeEditor>(),
event->getNode()->asType<UICodeEditor>()->getDocument() );
} );
codeEditor->addKeyBindingString( "ctrl+s", "save-doc", false );
codeEditor->addKeyBindingString( "ctrl+l", "lock-toggle", true );
codeEditor->addKeyBindingString( "ctrl+t", "create-new", true );
codeEditor->addKeyBindingString( "ctrl+w", "close-doc", true );
codeEditor->addKeyBindingString( "ctrl+tab", "next-doc", true );
codeEditor->addKeyBindingString( "ctrl+shift+tab", "previous-doc", true );
codeEditor->addKeyBindingString( "alt+shift+j", "split-left", true );
codeEditor->addKeyBindingString( "alt+shift+l", "split-right", true );
codeEditor->addKeyBindingString( "alt+shift+i", "split-top", true );
codeEditor->addKeyBindingString( "alt+shift+k", "split-bottom", true );
codeEditor->addKeyBindingString( "alt+shift+s", "split-swap", true );
codeEditor->addKeyBindingString( "ctrl+alt+j", "switch-to-previous-split", true );
codeEditor->addKeyBindingString( "ctrl+alt+l", "switch-to-next-split", true );
codeEditor->addKeyBindingString( "ctrl+alt+n", "switch-to-previous-colorscheme", true );
codeEditor->addKeyBindingString( "ctrl+alt+m", "switch-to-next-colorscheme", true );
for ( int i = 1; i <= 10; i++ ) {
codeEditor->addKeyBindingString( String::format( "ctrl+%d", i ),
String::format( "switch-to-tab-%d", i ), true );
codeEditor->addKeyBindingString( String::format( "alt+%d", i ),
String::format( "switch-to-tab-%d", i ), true );
}
if ( nullptr == mCurEditor )
setCurrentEditor( codeEditor );
mClient->onCodeEditorCreated( codeEditor, doc );
return codeEditor;
}
const std::string& UICodeEditorSplitter::getCurrentColorScheme() const {
return mCurrentColorScheme;
}
void UICodeEditorSplitter::setColorScheme( const std::string& name ) {
if ( name != mCurrentColorScheme ) {
mCurrentColorScheme = name;
applyColorScheme( mColorSchemes[mCurrentColorScheme] );
}
}
const std::map<std::string, SyntaxColorScheme>& UICodeEditorSplitter::getColorSchemes() const {
return mColorSchemes;
}
bool UICodeEditorSplitter::editorExists( UICodeEditor* editor ) const {
for ( auto tabWidget : mTabWidgets ) {
for ( size_t i = 0; i < tabWidget->getTabCount(); i++ ) {
if ( editor == tabWidget->getTab( i )->getOwnedWidget() ) {
return true;
}
}
}
return false;
}
bool UICodeEditorSplitter::loadFileFromPath( const std::string& path, UICodeEditor* codeEditor ) {
if ( FileSystem::isDirectory( path ) )
return false;
if ( nullptr == codeEditor )
codeEditor = mCurEditor;
codeEditor->setColorScheme( mColorSchemes[mCurrentColorScheme] );
bool ret = codeEditor->loadFromFile( path );
mClient->onDocumentLoaded( codeEditor, path );
return ret;
}
void UICodeEditorSplitter::loadFileFromPathInNewTab( const std::string& path ) {
auto d = createCodeEditorInTabWidget( tabWidgetFromEditor( mCurEditor ) );
UITabWidget* tabWidget = d.first->getTabWidget();
UITab* addedTab = d.first;
loadFileFromPath( path, d.second );
tabWidget->setTabSelected( addedTab );
}
void UICodeEditorSplitter::setCurrentEditor( UICodeEditor* editor ) {
bool isNew = mCurEditor != editor;
mCurEditor = editor;
if ( isNew )
mClient->onCodeEditorFocusChange( editor );
if ( editor )
mClient->onDocumentStateChanged( editor, editor->getDocument() );
}
std::pair<UITab*, UICodeEditor*>
UICodeEditorSplitter::createCodeEditorInTabWidget( UITabWidget* tabWidget ) {
if ( nullptr == tabWidget )
return std::make_pair( (UITab*)nullptr, (UICodeEditor*)nullptr );
UICodeEditor* editor = createCodeEditor();
editor->addEventListener( Event::OnDocumentChanged, [&]( const Event* event ) {
mClient->onDocumentStateChanged( event->getNode()->asType<UICodeEditor>(),
event->getNode()->asType<UICodeEditor>()->getDocument() );
} );
UITab* tab = tabWidget->add( editor->getDocument().getFilename(), editor );
editor->setData( (UintPtr)tab );
return std::make_pair( tab, editor );
}
void UICodeEditorSplitter::removeUnusedTab( UITabWidget* tabWidget ) {
if ( tabWidget && tabWidget->getTabCount() == 2 &&
tabWidget->getTab( 0 )
->getOwnedWidget()
->asType<UICodeEditor>()
->getDocument()
.isEmpty() ) {
tabWidget->removeTab( (Uint32)0 );
}
}
UITabWidget* UICodeEditorSplitter::createEditorWithTabWidget( Node* parent ) {
UICodeEditor* prevCurEditor = mCurEditor;
UITabWidget* tabWidget = UITabWidget::New();
tabWidget->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
tabWidget->setParent( parent );
tabWidget->setTabsClosable( true );
tabWidget->setHideTabBarOnSingleTab( true );
tabWidget->setAllowRearrangeTabs( true );
tabWidget->setAllowDragAndDropTabs( true );
tabWidget->addEventListener( Event::OnTabSelected, [&]( const Event* event ) {
UITabWidget* tabWidget = event->getNode()->asType<UITabWidget>();
setCurrentEditor( tabWidget->getTabSelected()->getOwnedWidget()->asType<UICodeEditor>() );
} );
tabWidget->setTabTryCloseCallback( [&]( UITab* tab ) -> bool {
tryTabClose( tab->getOwnedWidget()->asType<UICodeEditor>() );
return false;
} );
tabWidget->addEventListener( Event::OnTabClosed, [&]( const Event* event ) {
onTabClosed( static_cast<const TabEvent*>( event ) );
} );
auto editorData = createCodeEditorInTabWidget( tabWidget );
// Open same document in the new split
if ( prevCurEditor && prevCurEditor != editorData.second &&
!prevCurEditor->getDocument().isEmpty() )
editorData.second->setDocument( prevCurEditor->getDocumentRef() );
mTabWidgets.push_back( tabWidget );
return tabWidget;
}
void UICodeEditorSplitter::applyColorScheme( const SyntaxColorScheme& colorScheme ) {
forEachEditor(
[colorScheme]( UICodeEditor* editor ) { editor->setColorScheme( colorScheme ); } );
mClient->onColorSchemeChanged( mCurrentColorScheme );
}
void UICodeEditorSplitter::forEachEditor( std::function<void( UICodeEditor* )> run ) {
for ( auto tabWidget : mTabWidgets )
for ( size_t i = 0; i < tabWidget->getTabCount(); i++ )
run( tabWidget->getTab( i )->getOwnedWidget()->asType<UICodeEditor>() );
}
void UICodeEditorSplitter::zoomIn() {
forEachEditor( []( UICodeEditor* editor ) { editor->fontSizeGrow(); } );
}
void UICodeEditorSplitter::zoomOut() {
forEachEditor( []( UICodeEditor* editor ) { editor->fontSizeShrink(); } );
}
void UICodeEditorSplitter::zoomReset() {
forEachEditor( []( UICodeEditor* editor ) { editor->fontSizeReset(); } );
}
bool UICodeEditorSplitter::tryTabClose( UICodeEditor* editor ) {
if ( nullptr != editor && editor->isDirty() ) {
UIMessageBox* msgBox =
UIMessageBox::New( UIMessageBox::OK_CANCEL,
"Do you really want to close this tab?\nAll changes will be lost." );
msgBox->addEventListener( Event::MsgBoxConfirmClick,
[&, editor]( const Event* ) { closeEditorTab( editor ); } );
msgBox->addEventListener( Event::OnClose, [&]( const Event* ) {
msgBox = nullptr;
if ( mCurEditor )
mCurEditor->setFocus();
} );
msgBox->setTitle( "Close Tab?" );
msgBox->center();
msgBox->show();
return false;
} else {
closeEditorTab( editor );
return true;
}
}
void UICodeEditorSplitter::closeEditorTab( UICodeEditor* editor ) {
if ( editor ) {
UITabWidget* tabWidget = tabWidgetFromEditor( editor );
if ( tabWidget ) {
if ( !( editor->getDocument().isEmpty() &&
!tabWidget->getParent()->isType( UI_TYPE_SPLITTER ) &&
tabWidget->getTabCount() == 1 ) ) {
tabWidget->removeTab( (UITab*)editor->getData() );
}
}
}
}
void UICodeEditorSplitter::splitEditor( const SplitDirection& direction, UICodeEditor* editor ) {
if ( !editor )
return;
UIOrientation orientation =
direction == SplitDirection::Left || direction == SplitDirection::Right
? UIOrientation::Horizontal
: UIOrientation::Vertical;
UITabWidget* tabWidget = tabWidgetFromEditor( editor );
if ( !tabWidget )
return;
Node* parent = tabWidget->getParent();
UISplitter* parentSplitter = nullptr;
bool wasFirst = true;
if ( parent->isType( UI_TYPE_SPLITTER ) ) {
parentSplitter = parent->asType<UISplitter>();
wasFirst = parentSplitter->getFirstWidget() == tabWidget;
if ( !parentSplitter->isFull() ) {
parentSplitter->setOrientation( orientation );
createEditorWithTabWidget( parentSplitter );
if ( direction == SplitDirection::Left || direction == SplitDirection::Top )
parentSplitter->swap();
return;
}
}
UISplitter* splitter = UISplitter::New();
splitter->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
splitter->setOrientation( orientation );
tabWidget->detach();
splitter->setParent( parent );
tabWidget->setParent( splitter );
createEditorWithTabWidget( splitter );
if ( direction == SplitDirection::Left || direction == SplitDirection::Top )
splitter->swap();
if ( parentSplitter ) {
if ( wasFirst && parentSplitter->getFirstWidget() != splitter ) {
parentSplitter->swap();
} else if ( !wasFirst && parentSplitter->getLastWidget() != splitter ) {
parentSplitter->swap();
}
}
}
void UICodeEditorSplitter::switchToTab( Int32 index ) {
UITabWidget* tabWidget = tabWidgetFromEditor( mCurEditor );
if ( tabWidget ) {
tabWidget->setTabSelected( eeclamp<Int32>( index, 0, tabWidget->getTabCount() - 1 ) );
}
}
UITabWidget* UICodeEditorSplitter::findPreviousSplit( UICodeEditor* editor ) {
if ( !editor )
return nullptr;
UISplitter* splitter = splitterFromEditor( editor );
if ( !splitter )
return nullptr;
UITabWidget* tabWidget = tabWidgetFromEditor( editor );
if ( tabWidget ) {
auto it = std::find( mTabWidgets.rbegin(), mTabWidgets.rend(), tabWidget );
if ( it != mTabWidgets.rend() && ++it != mTabWidgets.rend() ) {
return *it;
}
}
return nullptr;
}
void UICodeEditorSplitter::switchPreviousSplit( UICodeEditor* editor ) {
UITabWidget* tabWidget = findPreviousSplit( editor );
if ( tabWidget && tabWidget->getTabSelected() &&
tabWidget->getTabSelected()->getOwnedWidget() ) {
tabWidget->getTabSelected()->getOwnedWidget()->setFocus();
} else {
tabWidget = findNextSplit( editor );
if ( tabWidget && tabWidget->getTabSelected() &&
tabWidget->getTabSelected()->getOwnedWidget() ) {
tabWidget->getTabSelected()->getOwnedWidget()->setFocus();
}
}
}
UITabWidget* UICodeEditorSplitter::findNextSplit( UICodeEditor* editor ) {
if ( !editor )
return nullptr;
UISplitter* splitter = splitterFromEditor( editor );
if ( !splitter )
return nullptr;
UITabWidget* tabWidget = tabWidgetFromEditor( editor );
if ( tabWidget ) {
auto it = std::find( mTabWidgets.begin(), mTabWidgets.end(), tabWidget );
if ( it != mTabWidgets.end() && ++it != mTabWidgets.end() ) {
return *it;
}
}
return nullptr;
}
void UICodeEditorSplitter::switchNextSplit( UICodeEditor* editor ) {
UITabWidget* tabWidget = findNextSplit( editor );
if ( tabWidget && tabWidget->getTabSelected() &&
tabWidget->getTabSelected()->getOwnedWidget() ) {
tabWidget->getTabSelected()->getOwnedWidget()->setFocus();
} else {
tabWidget = findPreviousSplit( editor );
if ( tabWidget && tabWidget->getTabSelected() &&
tabWidget->getTabSelected()->getOwnedWidget() ) {
tabWidget->getTabSelected()->getOwnedWidget()->setFocus();
}
}
}
void UICodeEditorSplitter::focusSomeEditor( Node* searchFrom ) {
UICodeEditor* editor =
searchFrom ? searchFrom->findByType<UICodeEditor>( UI_TYPE_CODEEDITOR )
: mUISceneNode->getRoot()->findByType<UICodeEditor>( UI_TYPE_CODEEDITOR );
if ( searchFrom && !editor )
editor = mUISceneNode->getRoot()->findByType<UICodeEditor>( UI_TYPE_CODEEDITOR );
if ( editor && tabWidgetFromEditor( editor ) && !tabWidgetFromEditor( editor )->isClosing() ) {
UITabWidget* tabW = tabWidgetFromEditor( editor );
if ( tabW && tabW->getTabCount() > 0 ) {
tabW->setTabSelected( tabW->getTabSelected() );
}
} else {
UITabWidget* tabW = mUISceneNode->getRoot()->findByType<UITabWidget>( UI_TYPE_TABWIDGET );
if ( tabW && tabW->getTabCount() > 0 ) {
tabW->setTabSelected( tabW->getTabSelected() );
}
}
}
void UICodeEditorSplitter::closeTabWidgets( UISplitter* splitter ) {
Node* node = splitter->getFirstChild();
while ( node ) {
if ( node->isType( UI_TYPE_TABWIDGET ) ) {
auto it =
std::find( mTabWidgets.begin(), mTabWidgets.end(), node->asType<UITabWidget>() );
if ( it != mTabWidgets.end() ) {
mTabWidgets.erase( it );
}
} else if ( node->isType( UI_TYPE_SPLITTER ) ) {
closeTabWidgets( node->asType<UISplitter>() );
}
node = node->getNextNode();
}
}
UICodeEditor* UICodeEditorSplitter::getCurEditor() const {
return mCurEditor;
}
void UICodeEditorSplitter::addRemainingTabWidgets( Node* widget ) {
if ( widget->isType( UI_TYPE_TABWIDGET ) ) {
if ( std::find( mTabWidgets.begin(), mTabWidgets.end(), widget->asType<UITabWidget>() ) ==
mTabWidgets.end() ) {
mTabWidgets.push_back( widget->asType<UITabWidget>() );
}
} else if ( widget->isType( UI_TYPE_SPLITTER ) ) {
UISplitter* splitter = widget->asType<UISplitter>();
addRemainingTabWidgets( splitter->getFirstWidget() );
addRemainingTabWidgets( splitter->getLastWidget() );
}
}
void UICodeEditorSplitter::closeSplitter( UISplitter* splitter ) {
splitter->setParent( mUISceneNode->getRoot() );
splitter->setVisible( false );
splitter->setEnabled( false );
splitter->close();
closeTabWidgets( splitter );
}
void UICodeEditorSplitter::onTabClosed( const TabEvent* tabEvent ) {
UICodeEditor* editor = mCurEditor;
UITabWidget* tabWidget = tabEvent->getTab()->getTabWidget();
if ( tabWidget->getTabCount() == 0 ) {
UISplitter* splitter = splitterFromEditor( editor );
if ( splitter ) {
if ( splitter->isFull() ) {
tabWidget->close();
auto itWidget = std::find( mTabWidgets.begin(), mTabWidgets.end(), tabWidget );
if ( itWidget != mTabWidgets.end() ) {
mTabWidgets.erase( itWidget );
}
// Remove splitter if it's redundant
Node* parent = splitter->getParent();
if ( parent->isType( UI_TYPE_SPLITTER ) ) {
UISplitter* parentSplitter = parent->asType<UISplitter>();
Node* remainingNode = tabWidget == splitter->getFirstWidget()
? splitter->getLastWidget()
: splitter->getFirstWidget();
bool wasFirst = parentSplitter->getFirstWidget() == splitter;
remainingNode->detach();
closeSplitter( splitter );
remainingNode->setParent( parentSplitter );
addRemainingTabWidgets( remainingNode );
if ( wasFirst )
parentSplitter->swap();
focusSomeEditor( parentSplitter );
} else {
// Then this is the main splitter
Node* remainingNode = tabWidget == splitter->getFirstWidget()
? splitter->getLastWidget()
: splitter->getFirstWidget();
closeSplitter( splitter );
eeASSERT( parent->getChildCount() == 0 );
remainingNode->setParent( parent );
addRemainingTabWidgets( remainingNode );
focusSomeEditor( nullptr );
}
if ( tabEvent->getTab()->getOwnedWidget() == mCurEditor )
setCurrentEditor( nullptr );
return;
}
}
auto d = createCodeEditorInTabWidget( tabWidget );
d.first->getTabWidget()->setTabSelected( d.first );
} else {
tabWidget->setTabSelected( eemin( tabWidget->getTabCount() - 1, tabEvent->getTabIndex() ) );
}
if ( tabEvent->getTab()->getOwnedWidget() == mCurEditor )
setCurrentEditor( nullptr );
}
}}} // namespace EE::UI::Tools
+66 -28
View File
@@ -152,13 +152,22 @@ void UICodeEditor::draw() {
drawMatchingBrackets( startScroll, lineHeight );
}
if ( mHighlightSelectionMatch && mDoc->hasSelection() &&
mDoc->getSelection().start().line() == mDoc->getSelection().end().line() ) {
if ( mDoc->hasSelection() ) {
drawTextRange( mDoc->getSelection( true ), lineRange, startScroll, lineHeight,
mFontStyleConfig.getFontSelectionBackColor() );
}
if ( mHighlightTextRange.isValid() && mHighlightTextRange.hasSelection() ) {
drawTextRange( mHighlightTextRange, lineRange, startScroll, lineHeight,
mFontStyleConfig.getFontSelectionBackColor() );
}
if ( mHighlightSelectionMatch && mDoc->hasSelection() && mDoc->getSelection().inSameLine() ) {
drawSelectionMatch( lineRange, startScroll, lineHeight );
}
if ( mDoc->hasSelection() ) {
drawSelection( lineRange, startScroll, lineHeight );
if ( !mHighlightWord.empty() ) {
drawWordMatch( mHighlightWord, lineRange, startScroll, lineHeight );
}
// Draw tab marker
@@ -590,11 +599,13 @@ Sizef UICodeEditor::getMaxScroll() const {
}
Uint32 UICodeEditor::onMouseDown( const Vector2i& position, const Uint32& flags ) {
if ( isTextSelectionEnabled() && !getUISceneNode()->getEventDispatcher()->isNodeDragging() &&
NULL != mFont && !mMouseDown && ( flags & EE_BUTTON_LMASK ) ) {
if ( isTextSelectionEnabled() && !getEventDispatcher()->isNodeDragging() && NULL != mFont &&
!mMouseDown && getEventDispatcher()->getMouseDownNode() == this &&
( flags & EE_BUTTON_LMASK ) ) {
mMouseDown = true;
Input* input = getUISceneNode()->getWindow()->getInput();
input->captureMouse( true );
setFocus();
if ( input->isShiftPressed() ) {
mDoc->selectTo( resolveScreenPosition( position.asFloat() ) );
} else {
@@ -793,6 +804,7 @@ void UICodeEditor::updateEditor() {
void UICodeEditor::onDocumentTextChanged() {
invalidateDraw();
checkMatchingBrackets();
sendCommonEvent( Event::OnTextChanged );
invalidateLongestLineWidth();
}
@@ -1237,9 +1249,9 @@ const SyntaxDefinition& UICodeEditor::getSyntaxDefinition() const {
void UICodeEditor::checkMatchingBrackets() {
if ( mHighlightMatchingBracket ) {
const std::vector<String::StringBaseType> open{'{', '(', '['};
const std::vector<String::StringBaseType> close{'}', ')', ']'};
mMatchingBrackets = TextRange();
std::vector<String::StringBaseType> open{'{', '(', '['};
std::vector<String::StringBaseType> close{'}', ')', ']'};
TextPosition pos = mDoc->getSelection().start();
TextDocumentLine& line = mDoc->line( pos.line() );
auto isOpenIt = std::find( open.begin(), open.end(), line[pos.column()] );
@@ -1406,7 +1418,32 @@ const bool& UICodeEditor::getShowWhitespaces() const {
}
void UICodeEditor::setShowWhitespaces( const bool& showWhitespaces ) {
mShowWhitespaces = showWhitespaces;
if ( mShowWhitespaces != showWhitespaces ) {
mShowWhitespaces = showWhitespaces;
invalidateDraw();
}
}
const String& UICodeEditor::getHighlightWord() const {
return mHighlightWord;
}
void UICodeEditor::setHighlightWord( const String& highlightWord ) {
if ( mHighlightWord != highlightWord ) {
mHighlightWord = highlightWord;
invalidateDraw();
}
}
const TextRange& UICodeEditor::getHighlightTextRange() const {
return mHighlightTextRange;
}
void UICodeEditor::setHighlightTextRange( const TextRange& highlightSelection ) {
if ( highlightSelection != mHighlightTextRange ) {
mHighlightTextRange = highlightSelection;
invalidateDraw();
}
}
const Time& UICodeEditor::getFindLongestLineWidthUpdateFrequency() const {
@@ -1449,15 +1486,18 @@ void UICodeEditor::drawSelectionMatch( const std::pair<int, int>& lineRange,
const Vector2f& startScroll, const Float& lineHeight ) {
if ( !mDoc->hasSelection() )
return;
Primitives primitives;
primitives.setForceDraw( false );
primitives.setColor( Color( mSelectionMatchColor ).blendAlpha( mAlpha ) );
TextRange selection = mDoc->getSelection( true );
const String& selectionLine = mDoc->line( selection.start().line() ).getText();
String text( selectionLine.substr( selection.start().column(),
selection.end().column() - selection.start().column() ) );
drawWordMatch( text, lineRange, startScroll, lineHeight );
}
void UICodeEditor::drawWordMatch( const String& text, const std::pair<int, int>& lineRange,
const Vector2f& startScroll, const Float& lineHeight ) {
Primitives primitives;
primitives.setForceDraw( false );
primitives.setColor( Color( mSelectionMatchColor ).blendAlpha( mAlpha ) );
for ( auto ln = lineRange.first; ln <= lineRange.second; ln++ ) {
const String& line = mDoc->line( ln ).getText();
@@ -1512,34 +1552,32 @@ void UICodeEditor::drawLineText( const Int64& index, Vector2f position, const Fl
}
}
void UICodeEditor::drawSelection( const std::pair<int, int>& lineRange, const Vector2f& startScroll,
const Float& lineHeight ) {
void UICodeEditor::drawTextRange( const TextRange& range, const std::pair<int, int>& lineRange,
const Vector2f& startScroll, const Float& lineHeight,
const Color& backgrundColor ) {
Primitives primitives;
primitives.setForceDraw( false );
primitives.setColor(
Color( mFontStyleConfig.getFontSelectionBackColor() ).blendAlpha( mAlpha ) );
primitives.setColor( Color( backgrundColor ).blendAlpha( mAlpha ) );
TextRange selection = mDoc->getSelection( true );
int startLine = eemax<int>( lineRange.first, selection.start().line() );
int endLine = eemin<int>( lineRange.second, selection.end().line() );
int startLine = eemax<int>( lineRange.first, range.start().line() );
int endLine = eemin<int>( lineRange.second, range.end().line() );
for ( auto ln = startLine; ln <= endLine; ln++ ) {
const String& line = mDoc->line( ln ).getText();
Rectf selRect;
selRect.Top = startScroll.y + ln * lineHeight;
selRect.Bottom = selRect.Top + lineHeight;
if ( selection.start().line() == ln ) {
selRect.Left = startScroll.x + getXOffsetCol( {ln, selection.start().column()} );
if ( selection.end().line() == ln ) {
selRect.Right = startScroll.x + getXOffsetCol( {ln, selection.end().column()} );
if ( range.start().line() == ln ) {
selRect.Left = startScroll.x + getXOffsetCol( {ln, range.start().column()} );
if ( range.end().line() == ln ) {
selRect.Right = startScroll.x + getXOffsetCol( {ln, range.end().column()} );
} else {
selRect.Right =
startScroll.x + getXOffsetCol( {ln, static_cast<Int64>( line.length() )} );
}
} else if ( selection.end().line() == ln ) {
} else if ( range.end().line() == ln ) {
selRect.Left = startScroll.x + getXOffsetCol( {ln, 0} );
selRect.Right = startScroll.x + getXOffsetCol( {ln, selection.end().column()} );
selRect.Right = startScroll.x + getXOffsetCol( {ln, range.end().column()} );
} else {
selRect.Left = startScroll.x + getXOffsetCol( {ln, 0} );
selRect.Right =
-2
View File
@@ -187,8 +187,6 @@ UIPushButton* UITab::setText( const String& text ) {
updateTab();
tTabW->orderTabs();
tTabW->setTabSelected( tTabW->getTabSelected() );
}
}
return this;
File diff suppressed because it is too large Load Diff
+53 -89
View File
@@ -35,39 +35,36 @@ class UISearchBar : public UILinearLayout {
}
};
class App {
struct UIConfig {
Float fontSize{11};
};
struct WindowConfig {
Float pixelDensity{0};
Sizei size{1280, 720};
bool maximized{false};
};
struct AppConfig {
WindowConfig window;
UICodeEditorSplitter::CodeEditorConfig editor;
UIConfig ui;
};
struct SearchState {
UICodeEditor* editor{nullptr};
String text;
TextRange range = TextRange();
bool caseSensitive{false};
void reset() {
editor = nullptr;
range = TextRange();
text = "";
}
};
class App : public UICodeEditorSplitter::Client {
public:
struct Config {
struct {
Float pixelDensity{0};
Sizei size{1280, 720};
bool maximized{false};
} window;
struct {
std::string colorScheme{"lite"};
Float fontSize{11};
bool showLineNumbers{true};
bool showWhiteSpaces{true};
bool highlightMatchingBracket{true};
bool horizontalScrollbar{false};
bool highlightCurrentLine{true};
bool trimTrailingWhitespaces{false};
bool forceNewLineAtEndOfFile{false};
bool autoDetectIndentType{true};
bool writeUnicodeBOM{false};
bool indentSpaces{false};
bool windowsLineEndings{false};
int indentWidth{4};
int tabWidth{4};
int lineBreakingColumn{100};
} editor;
struct {
Float fontSize{11};
} ui;
};
enum class SplitDirection { Left, Right, Top, Bottom };
~App();
void init( const std::string& file, const Float& pidelDensity );
@@ -80,9 +77,9 @@ class App {
void saveFileDialog();
void findPrevText( String text = "", const bool& caseSensitive = true );
void findPrevText( SearchState& search );
void findNextText( String text = "", const bool& caseSensitive = true );
void findNextText( SearchState& search );
void closeApp();
@@ -90,37 +87,11 @@ class App {
void showFindView();
UICodeEditor* createCodeEditor();
void replaceSelection( SearchState& search, const String& replacement );
UITabWidget* tabWidgetFromEditor( UICodeEditor* editor );
void replaceAll( SearchState& search, const String& replace );
UISplitter* splitterFromEditor( UICodeEditor* editor );
std::pair<UITab*, UICodeEditor*> createCodeEditorInTabWidget( UITabWidget* tabWidget );
UITabWidget* createEditorWithTabWidget( Node* parent );
void splitEditor( const SplitDirection& direction, UICodeEditor* editor );
void focusSomeEditor( Node* searchFrom = nullptr );
void switchToTab( Int32 index );
UITabWidget* findPreviousSplit( UICodeEditor* editor );
void switchPreviousSplit( UICodeEditor* editor );
UITabWidget* findNextSplit( UICodeEditor* editor );
void switchNextSplit( UICodeEditor* editor );
void applyColorScheme( const SyntaxColorScheme& colorScheme );
void replaceSelection( const String& replacement );
void replaceAll( String find, const String& replace, const bool& caseSensitive );
void findAndReplace( String find, String replace, const bool& caseSensitive );
void findAndReplace( SearchState& search, const String& replace );
void runCommand( const std::string& command );
@@ -128,22 +99,14 @@ class App {
void saveConfig();
void loadFileFromPathInNewTab( const std::string& path );
void setCurrentEditor( UICodeEditor* editor );
protected:
EE::Window::Window* mWindow{nullptr};
UISceneNode* mUISceneNode{nullptr};
UICodeEditor* mCurEditor{nullptr};
Console* mConsole{nullptr};
std::string mWindowTitle{"ecode"};
String mLastSearch;
UILayout* mBaseLayout{nullptr};
UISearchBar* mSearchBarLayout{nullptr};
std::vector<UITabWidget*> mTabWidgets;
std::map<std::string, SyntaxColorScheme> mColorSchemes;
std::string mCurrentColorScheme;
UIPopUpMenu* mSettingsMenu{nullptr};
UITextView* mSettingsButton{nullptr};
UIPopUpMenu* mColorSchemeMenu{nullptr};
@@ -151,9 +114,14 @@ class App {
IniFile mIni;
IniFile mIniState;
std::vector<std::string> mRecentFiles;
Config mConfig;
AppConfig mConfig;
UIPopUpMenu* mDocMenu{nullptr};
UIPopUpMenu* mViewMenu{nullptr};
UICodeEditorSplitter* mEditorSplitter{nullptr};
std::string mInitColorScheme;
std::map<std::string, std::string> mDefKeybindings;
std::string mConfigPath;
SearchState mSearchState;
void onFileDropped( String file );
@@ -167,14 +135,6 @@ class App {
bool onCloseRequestCallback( EE::Window::Window* );
void closeEditorTab( UICodeEditor* editor );
void onTabClosed( const TabEvent* tabEvent );
void closeSplitter( UISplitter* splitter );
void closeTabWidgets( UISplitter* splitter );
void initSearchBar();
void addRemainingTabWidgets( Node* widget );
@@ -185,8 +145,6 @@ class App {
void updateColorSchemeMenu();
void setColorScheme( const std::string& name );
UIMenu* createFiletypeMenu();
void updateCurrentFiletype();
@@ -195,12 +153,8 @@ class App {
void saveDoc();
void removeUnusedTab( UITabWidget* tabWidget );
void updateRecentFiles();
void forEachEditor( std::function<void( UICodeEditor* )> run );
UIMenu* createViewMenu();
UIMenu* createEditMenu();
@@ -211,11 +165,21 @@ class App {
void updateDocumentMenu();
void zoomIn();
void onDocumentStateChanged( UICodeEditor*, TextDocument& );
void zoomOut();
void onDocumentModified( UICodeEditor* editor, TextDocument& );
void zoomReset();
void onColorSchemeChanged( const std::string& );
void onDocumentLoaded( UICodeEditor* codeEditor, const std::string& path );
const UICodeEditorSplitter::CodeEditorConfig& getCodeEditorConfig() const;
void onCodeEditorCreated( UICodeEditor*, TextDocument& doc );
void onDocumentSelectionChange( UICodeEditor* editor, TextDocument& );
void onCodeEditorFocusChange( UICodeEditor* editor );
};
#endif // EE_TOOLS_CODEEDITOR_HPP