mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-19 03:53:57 +03:00
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:
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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).
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()};
|
||||
}
|
||||
|
||||
@@ -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() );
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() );
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 ) !=
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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() );
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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 =
|
||||
|
||||
@@ -187,8 +187,6 @@ UIPushButton* UITab::setText( const String& text ) {
|
||||
updateTab();
|
||||
|
||||
tTabW->orderTabs();
|
||||
|
||||
tTabW->setTabSelected( tTabW->getTabSelected() );
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
||||
+368
-768
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user