More WIP on the code editor.

This commit is contained in:
Martín Lucas Golini
2020-05-20 19:37:21 -03:00
parent 098c882a8d
commit 18847a5974
14 changed files with 316 additions and 62 deletions

View File

@@ -12,6 +12,7 @@ class EE_API Event {
enum EventType {
KeyDown = 0,
KeyUp,
TextInput,
MouseMove,
MouseDown,
MouseClick,

View File

@@ -46,9 +46,11 @@ class EE_API EventDispatcher {
void sendMsg( Node* Ctrl, const Uint32& Msg, const Uint32& Flags = 0 );
void sendKeyUp( const Uint32& KeyCode, const Uint16& Char, const Uint32& Mod );
void sendTextInput( const Uint32& textChar, const Uint32& timestamp );
void sendKeyDown( const Uint32& KeyCode, const Uint16& Char, const Uint32& Mod );
void sendKeyUp( const Uint32& KeyCode, const Uint32& Char, const Uint32& Mod );
void sendKeyDown( const Uint32& KeyCode, const Uint32& Char, const Uint32& Mod );
void sendMouseClick( Node* ToCtrl, const Vector2i& Pos, const Uint32 Flags );
@@ -98,7 +100,7 @@ class EE_API EventDispatcher {
Node* mNodeDragging;
Time mElapsed;
virtual void inputCallback( InputEvent* Event );
virtual void inputCallback( InputEvent* event );
};
}} // namespace EE::Scene

View File

@@ -1,29 +1,46 @@
#ifndef EE_SCENEEVENTKEY_HPP
#define EE_SCENEEVENTKEY_HPP
#include <eepp/core/string.hpp>
#include <eepp/scene/event.hpp>
namespace EE { namespace Scene {
class EE_API KeyEvent : public Event {
public:
KeyEvent( Node* node, const Uint32& EventNum, const Uint32& getKeyCode, const Uint16& getChar,
const Uint32& getMod );
KeyEvent( Node* node, const Uint32& eventNum, const Uint32& keyCode, const Uint32& chr,
const Uint32& mod );
~KeyEvent();
const Uint32& getKeyCode() const;
const Uint16& getChar() const;
const Uint32& getChar() const;
const Uint32& getMod() const;
protected:
Uint32 mKeyCode;
Uint16 mChar;
Uint32 mChar;
Uint32 mMod;
};
class EE_API TextInputEvent : public Event {
public:
TextInputEvent( Node* node, const Uint32& eventNum, const Uint32& chr,
const Uint32& timestamp );
const Uint32& getChar() const;
const Uint32& getTimestamp() const;
String getText() const;
protected:
Uint32 mChar;
Uint32 mTimestamp;
};
}} // namespace EE::Scene
#endif

View File

@@ -405,6 +405,8 @@ class EE_API Node : public Transformable {
virtual Uint32 onMessage( const NodeMessage* Msg );
virtual Uint32 onTextInput( const TextInputEvent& Event );
virtual Uint32 onKeyDown( const KeyEvent& Event );
virtual Uint32 onKeyUp( const KeyEvent& Event );

View File

@@ -19,6 +19,8 @@ class EE_API TextDocument {
virtual void onDocumentSelectionChange( const TextRange& ) = 0;
};
enum IndentType { IndentSpaces, IndentTabs };
static bool isNonWord( String::StringBaseType ch );
TextDocument();
@@ -102,6 +104,8 @@ class EE_API TextDocument {
void moveTo( TextPosition offset );
void moveTo( int columnOffset );
void textInput( const String& text );
void registerClient( Client& client );
@@ -120,12 +124,28 @@ class EE_API TextDocument {
void moveToNextPage( Int64 pageSize );
void deleteToPreviousChar();
void deleteToNextChar();
void newLine();
void indent();
void unindent();
String getIndentString();
const Uint32& getTabWidth() const;
void setTabWidth( const Uint32& tabWidth );
TextPosition sanitizePosition( const TextPosition& position ) const;
const IndentType& getIndentType() const;
void setIndentType( const IndentType& indentType );
protected:
std::string mFilename;
std::vector<String> mLines;
@@ -133,12 +153,17 @@ class EE_API TextDocument {
std::unordered_set<Client*> mClients;
bool mIsCLRF;
Uint32 mTabWidth{4};
IndentType mIndentType{IndentTabs};
void notifyTextChanged();
void notifyCursorChanged();
void notifySelectionChanged();
void insertAtStartOfSelectedLines( String text, bool skipEmpty );
void removeFromStartOfSelectedLines( String text, bool skipEmpty );
};
}}} // namespace EE::UI::Doc

View File

@@ -43,6 +43,10 @@ class EE_API UICodeEdit : public UIWidget, public TextDocument::Client {
const Uint32& getTabWidth() const;
void setTabWidth( const Uint32& tabWidth );
const Float& getMouseWheelScroll() const;
void setMouseWheelScroll( const Float& mouseWheelScroll );
protected:
Font* mFont;
UIFontStyleConfig mFontStyleConfig;
@@ -54,13 +58,18 @@ class EE_API UICodeEdit : public UIWidget, public TextDocument::Client {
Uint32 mTabWidth;
Int64 mLastColOffset;
Vector2f mScroll;
Float mMouseWheelScroll;
void invalidateEditor();
virtual Uint32 onTextInput( const TextInputEvent& event );
virtual Uint32 onKeyDown( const KeyEvent& Event );
virtual Uint32 onMouseDown( const Vector2i& position, const Uint32& flags );
virtual Uint32 onMouseUp( const Vector2i& position, const Uint32& flags );
virtual void onSizeChange();
virtual void onPaddingChange();
@@ -90,6 +99,10 @@ class EE_API UICodeEdit : public UIWidget, public TextDocument::Client {
void updateLastColumnOffset();
TextPosition resolveScreenPosition( const Vector2f& position ) const;
Vector2f getViewPortLineCount() const;
Sizef getMaxScroll() const;
};
}} // namespace EE::UI

View File

@@ -41,7 +41,7 @@ class InputEvent {
struct KeySym {
Uint32 sym; /** virtual keysym */
Uint32 mod; /** current key modifiers */
Uint16 unicode; /** translated character */
Uint32 unicode; /** translated character */
};
/** Application visibility event structure */
@@ -93,7 +93,7 @@ class InputEvent {
Uint32 timestamp;
Uint32 text;
String Text() { return String( text ); }
String getText() { return String( text ); }
};
/** Joystick axis motion event structure */

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.12.0, 2020-05-20T05:57:57. -->
<!-- Written by QtCreator 4.12.0, 2020-05-20T19:32:27. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>

View File

@@ -33,21 +33,23 @@ EventDispatcher::~EventDispatcher() {
}
}
void EventDispatcher::inputCallback( InputEvent* Event ) {
switch ( Event->Type ) {
void EventDispatcher::inputCallback( InputEvent* event ) {
switch ( event->Type ) {
case InputEvent::Window: {
if ( Event->window.type == InputEvent::WindowKeyboardFocusGain ) {
if ( event->window.type == InputEvent::WindowKeyboardFocusGain ) {
mMousePosi = mInput->queryMousePos();
mMousePos = mMousePosi.asFloat();
}
break;
}
case InputEvent::KeyUp:
sendKeyUp( Event->key.keysym.sym, Event->key.keysym.unicode, Event->key.keysym.mod );
sendKeyUp( event->key.keysym.sym, event->key.keysym.unicode, event->key.keysym.mod );
break;
case InputEvent::KeyDown:
sendKeyDown( Event->key.keysym.sym, Event->key.keysym.unicode, Event->key.keysym.mod );
sendKeyDown( event->key.keysym.sym, event->key.keysym.unicode, event->key.keysym.mod );
break;
case InputEvent::TextInput:
sendTextInput( event->text.text, event->text.timestamp );
case InputEvent::SysWM:
case InputEvent::VideoResize:
case InputEvent::VideoExpose: {
@@ -151,7 +153,20 @@ Input* EventDispatcher::getInput() const {
return mInput;
}
void EventDispatcher::sendKeyUp( const Uint32& KeyCode, const Uint16& Char, const Uint32& Mod ) {
void EventDispatcher::sendTextInput( const Uint32& textChar, const Uint32& timestamp ) {
TextInputEvent textInputEvent =
TextInputEvent( mFocusControl, Event::TextInput, textChar, timestamp );
Node* CtrlLoop = mFocusControl;
while ( NULL != CtrlLoop ) {
if ( CtrlLoop->isEnabled() && CtrlLoop->onTextInput( textInputEvent ) )
break;
CtrlLoop = CtrlLoop->getParent();
}
}
void EventDispatcher::sendKeyUp( const Uint32& KeyCode, const Uint32& Char, const Uint32& Mod ) {
KeyEvent keyEvent = KeyEvent( mFocusControl, Event::KeyUp, KeyCode, Char, Mod );
Node* CtrlLoop = mFocusControl;
@@ -163,7 +178,7 @@ void EventDispatcher::sendKeyUp( const Uint32& KeyCode, const Uint16& Char, cons
}
}
void EventDispatcher::sendKeyDown( const Uint32& KeyCode, const Uint16& Char, const Uint32& Mod ) {
void EventDispatcher::sendKeyDown( const Uint32& KeyCode, const Uint32& Char, const Uint32& Mod ) {
KeyEvent keyEvent = KeyEvent( mFocusControl, Event::KeyDown, KeyCode, Char, Mod );
Node* CtrlLoop = mFocusControl;

View File

@@ -3,9 +3,9 @@
namespace EE { namespace Scene {
KeyEvent::KeyEvent( Node* node, const Uint32& EventNum, const Uint32& KeyCode, const Uint16& Char,
const Uint32& Mod ) :
Event( node, EventNum ), mKeyCode( KeyCode ), mChar( Char ), mMod( Mod ) {}
KeyEvent::KeyEvent( Node* node, const Uint32& eventNum, const Uint32& keyCode, const Uint32& chr,
const Uint32& mod ) :
Event( node, eventNum ), mKeyCode( keyCode ), mChar( chr ), mMod( mod ) {}
KeyEvent::~KeyEvent() {}
@@ -13,7 +13,7 @@ const Uint32& KeyEvent::getKeyCode() const {
return mKeyCode;
}
const Uint16& KeyEvent::getChar() const {
const Uint32& KeyEvent::getChar() const {
return mChar;
}
@@ -21,4 +21,20 @@ const Uint32& KeyEvent::getMod() const {
return mMod;
}
TextInputEvent::TextInputEvent( Node* node, const Uint32& eventNum, const Uint32& chr,
const Uint32& timestamp ) :
Event( node, eventNum ), mChar( chr ), mTimestamp( timestamp ) {}
const Uint32& TextInputEvent::getChar() const {
return mChar;
}
const Uint32& TextInputEvent::getTimestamp() const {
return mTimestamp;
}
String TextInputEvent::getText() const {
return String( mChar );
}
}} // namespace EE::Scene

View File

@@ -307,6 +307,11 @@ void Node::sendCommonEvent( const Uint32& event ) {
sendEvent( &CommonEvent );
}
Uint32 Node::onTextInput( const TextInputEvent& event ) {
sendEvent( &event );
return 0;
}
Uint32 Node::onKeyDown( const KeyEvent& Event ) {
sendEvent( &Event );
return 0;

View File

@@ -145,39 +145,40 @@ TextPosition TextDocument::insert( const TextPosition& position, const String& t
TextPosition TextDocument::insert( TextPosition position, const String::StringBaseType& ch ) {
position = sanitizePosition( position );
size_t tabWidth = mTabWidth;
bool atHead = position.column() == 0;
bool atTail = position.column() == (Int64)line( position.line() ).length();
bool atTail = position.column() == (Int64)line( position.line() ).length() - 1;
if ( ch == '\n' ) {
if ( atTail || atHead ) {
String new_line_contents;
String newLineContents( "\n" );
size_t row = position.line();
String line_content;
for ( size_t i = position.column(); i < line( row ).length(); i++ )
line_content.append( line( row )[i] );
mLines.insert( mLines.begin() + position.line() + ( atTail ? 1 : 0 ),
new_line_contents );
return {position.line() + 1, (Int64)line( position.line() + 1 ).length()};
mLines.insert( mLines.begin() + position.line() + ( atTail ? 1 : 0 ), newLineContents );
notifyTextChanged();
if ( atTail )
return {position.line() + 1, (Int64)line( position.line() + 1 ).length()};
return {position.line() + 1, 0};
}
String newLine;
newLine +=
String newLine =
line( position.line() )
.substr( position.column(), line( position.line() ).length() - position.column() );
String lineContent( newLine );
line( position.line() ).substr( 0, position.column() );
line( position.line() ) = line( position.line() ).substr( 0, position.column() );
mLines.insert( mLines.begin() + position.line() + 1, std::move( newLine ) );
notifyTextChanged();
return {position.line() + 1, 0};
} else if ( ch == '\t' ) {
Int64 nextSoftTabStop = ( ( position.column() + tabWidth ) / tabWidth ) * tabWidth;
size_t spaces_to_insert = nextSoftTabStop - position.column();
for ( size_t i = 0; i < spaces_to_insert; ++i ) {
line( position.line() )
.insert( line( position.line() ).begin() + position.column(), ' ' );
}
return {position.line(), nextSoftTabStop};
}
} /* else if ( ch == '\t' ) {
Int64 nextSoftTabStop =
( ( position.column() + tabWidth ) / getTabWidth() ) * getTabWidth();
size_t spacesToInsert = nextSoftTabStop - position.column();
for ( size_t i = 0; i < spacesToInsert; ++i ) {
line( position.line() )
.insert( line( position.line() ).begin() + position.column(), ' ' );
}
return {position.line(), nextSoftTabStop};
}*/
line( position.line() ).insert( line( position.line() ).begin() + position.column(), ch );
notifyTextChanged();
return {position.line(), position.column() + 1};
}
@@ -202,32 +203,33 @@ void TextDocument::remove( TextRange range ) {
if ( range.start().line() == range.end().line() ) {
// Delete within same line.
auto& line = this->line( range.start().line() );
bool whole_line_is_selected =
bool wholeLineIsSelected =
range.start().column() == 0 && range.end().column() == (Int64)line.length();
if ( whole_line_is_selected ) {
if ( wholeLineIsSelected ) {
line.clear();
} else {
auto before_selection = line.substr( 0, range.start().column() );
auto after_selection =
auto beforeSelection = line.substr( 0, range.start().column() );
auto afterSelection =
line.substr( range.end().column(), line.length() - range.end().column() );
line.assign( before_selection + after_selection );
line.assign( beforeSelection + afterSelection );
}
} else {
// Delete across a newline, merging lines.
eeASSERT( range.start().line() == range.end().line() - 1 );
auto& first_line = line( range.start().line() );
auto& second_line = line( range.end().line() );
auto before_selection = first_line.substr( 0, range.start().column() );
auto after_selection =
second_line.substr( range.end().column(), second_line.length() - range.end().column() );
first_line.assign( before_selection + after_selection );
auto& firstLine = line( range.start().line() );
auto& secondLine = line( range.end().line() );
auto beforeSelection = firstLine.substr( 0, range.start().column() );
auto afterSelection =
secondLine.substr( range.end().column(), secondLine.length() - range.end().column() );
firstLine.assign( beforeSelection + afterSelection );
mLines.erase( mLines.begin() + range.end().line() );
}
if ( lines().empty() ) {
mLines.emplace_back( String() );
}
notifyTextChanged();
}
TextPosition TextDocument::positionOffset( TextPosition position, int columnOffset ) const {
@@ -235,11 +237,11 @@ TextPosition TextDocument::positionOffset( TextPosition position, int columnOffs
position.setColumn( position.column() + columnOffset );
while ( position.line() > 0 && position.column() < 0 ) {
position.setLine( position.line() - 1 );
position.setColumn( position.column() + mLines[position.line()].size() );
position.setColumn( eemax<Int64>( 0, position.column() + mLines[position.line()].size() ) );
}
while ( position.line() < (Int64)mLines.size() &&
position.column() > (Int64)mLines[position.line()].size() - 1 ) {
position.setColumn( position.column() - mLines[position.line()].size() );
position.column() > (Int64)eemax<Int64>( 0, mLines[position.line()].size() - 1 ) ) {
position.setColumn( position.column() - mLines[position.line()].size() - 1 );
position.setLine( position.line() + 1 );
}
return sanitizePosition( position );
@@ -377,13 +379,15 @@ void TextDocument::moveTo( TextPosition offset ) {
setSelection( getSelection().start() + offset );
}
void TextDocument::moveTo( int columnOffset ) {
setSelection( positionOffset( getSelection().start(), columnOffset ) );
}
void TextDocument::textInput( const String& text ) {
if ( hasSelection() ) {
deleteTo( 0 );
}
TextPosition start = getSelection().start();
insert( start, text );
moveTo( TextPosition( 0, text.size() ) );
setSelection( insert( getSelection().start(), text ) );
}
void TextDocument::registerClient( TextDocument::Client& client ) {
@@ -444,6 +448,84 @@ void TextDocument::moveToNextPage( Int64 pageSize ) {
setSelection( pos );
}
void TextDocument::deleteToPreviousChar() {
deleteTo( -1 );
}
void TextDocument::deleteToNextChar() {
deleteTo( 1 );
}
void TextDocument::newLine() {
String input( "\n" );
TextPosition start = getSelection().start();
if ( start.line() >= 0 && start.line() < (Int64)mLines.size() ) {
String& ln = line( start.line() );
size_t to = eemin<size_t>( ln.size(), start.column() );
int indent = 0;
for ( size_t i = 0; i < to; i++ ) {
if ( '\t' == ln[i] || ' ' == ln[i] ) {
indent++;
} else {
break;
}
}
if ( indent ) {
input.append( ln.substr( 0, indent ) );
}
}
textInput( input );
}
void TextDocument::insertAtStartOfSelectedLines( String text, bool skipEmpty ) {
TextPosition prevStart = getSelection().start();
TextRange range = getSelection( true );
bool swap = prevStart != range.start();
for ( auto i = range.start().line(); i <= range.end().line(); i++ ) {
const String& line = this->line( i );
if ( !skipEmpty || line.length() != 1 ) {
insert( {i, 0}, text );
}
}
setSelection( TextPosition( range.start().line(), range.start().column() + text.size() ),
TextPosition( range.end().line(), range.end().column() + text.size() ), swap );
}
void TextDocument::removeFromStartOfSelectedLines( String text, bool skipEmpty ) {
TextPosition prevStart = getSelection().start();
TextRange range = getSelection( true );
bool swap = prevStart != range.start();
for ( auto i = range.start().line(); i <= range.end().line(); i++ ) {
const String& line = this->line( i );
if ( !skipEmpty || line.length() != 1 ) {
if ( line.substr( 0, text.length() ) == text ) {
remove( {{i, 0}, {i, static_cast<Int64>( text.length() )}} );
}
}
}
setSelection( TextPosition( range.start().line(), range.start().column() - text.size() ),
TextPosition( range.end().line(), range.end().column() - text.size() ), swap );
}
void TextDocument::indent() {
if ( hasSelection() ) {
insertAtStartOfSelectedLines( getIndentString(), false );
} else {
textInput( getIndentString() );
}
}
void TextDocument::unindent() {
removeFromStartOfSelectedLines( getIndentString(), false );
}
String TextDocument::getIndentString() {
if ( IndentSpaces == mIndentType ) {
return String( std::string( mTabWidth, ' ' ) );
}
return String( "\t" );
}
const Uint32& TextDocument::getTabWidth() const {
return mTabWidth;
}
@@ -473,10 +555,19 @@ void TextDocument::print() const {
TextPosition TextDocument::sanitizePosition( const TextPosition& position ) const {
Int64 line = eeclamp<Int64>( position.line(), 0UL, mLines.size() - 1 );
Int64 col = eeclamp<Int64>( position.column(), 0UL, mLines[line].size() - 1 );
Int64 col =
eeclamp<Int64>( position.column(), 0UL, eemax<Int64>( 0, mLines[line].size() - 1 ) );
return {line, col};
}
const TextDocument::IndentType& TextDocument::getIndentType() const {
return mIndentType;
}
void TextDocument::setIndentType( const IndentType& indentType ) {
mIndentType = indentType;
}
void TextDocument::notifyTextChanged() {
for ( auto& client : mClients ) {
client->onDocumentTextChanged();

View File

@@ -19,7 +19,8 @@ UICodeEdit::UICodeEdit() :
mDirtyEditor( false ),
mCursorVisible( false ),
mTabWidth( 4 ),
mLastColOffset( 0 ) {
mLastColOffset( 0 ),
mMouseWheelScroll( 50 ) {
clipEnable();
if ( NULL == mFont ) {
mFont = FontTrueType::New( "monospace", "assets/fonts/DejaVuSansMono.ttf" );
@@ -124,12 +125,40 @@ void UICodeEdit::setTabWidth( const Uint32& tabWidth ) {
}
}
const Float& UICodeEdit::getMouseWheelScroll() const {
return mMouseWheelScroll;
}
void UICodeEdit::setMouseWheelScroll( const Float& mouseWheelScroll ) {
mMouseWheelScroll = mouseWheelScroll;
}
void UICodeEdit::invalidateEditor() {
mDirtyEditor = true;
}
Uint32 UICodeEdit::onTextInput( const TextInputEvent& event ) {
mDoc.textInput( event.getText() );
return 1;
}
Uint32 UICodeEdit::onKeyDown( const KeyEvent& event ) {
switch ( event.getKeyCode() ) {
case KEY_BACKSPACE: {
mDoc.deleteToPreviousChar();
updateLastColumnOffset();
break;
}
case KEY_DELETE: {
mDoc.deleteToNextChar();
break;
}
case KEY_KP_ENTER:
case KEY_RETURN: {
mDoc.newLine();
updateLastColumnOffset();
break;
}
case KEY_UP: {
mDoc.moveToPreviousLine( mLastColOffset );
break;
@@ -168,6 +197,16 @@ Uint32 UICodeEdit::onKeyDown( const KeyEvent& event ) {
updateLastColumnOffset();
break;
}
case KEY_TAB: {
if ( event.getMod() & KEYMOD_LSHIFT ) {
mDoc.unindent();
updateLastColumnOffset();
} else if ( !event.getMod() ) {
mDoc.indent();
updateLastColumnOffset();
}
break;
}
default:
break;
}
@@ -187,6 +226,19 @@ TextPosition UICodeEdit::resolveScreenPosition( const Vector2f& position ) const
return TextPosition( line, getColFromXOffset( line, localPos.x ) );
}
Vector2f UICodeEdit::getViewPortLineCount() const {
return Vector2f( eefloor( mSize.getWidth() / getGlyphWidth() ),
eefloor( mSize.getHeight() / getLineHeight() ) );
}
Sizef UICodeEdit::getMaxScroll() const {
Vector2f vplc( getViewPortLineCount() );
return Sizef( 0 /*TODO: Implement*/,
vplc.y > mDoc.lineCount() - 1
? 0.f
: ( mDoc.lineCount() - getViewPortLineCount().y ) * getLineHeight() );
}
Uint32 UICodeEdit::onMouseDown( const Vector2i& position, const Uint32& flags ) {
if ( flags & EE_BUTTON_LMASK ) {
mDoc.setSelection( resolveScreenPosition( position.asFloat() ) );
@@ -194,8 +246,22 @@ Uint32 UICodeEdit::onMouseDown( const Vector2i& position, const Uint32& flags )
return UIWidget::onMouseDown( position, flags );
}
Uint32 UICodeEdit::onMouseUp( const Vector2i& position, const Uint32& flags ) {
if ( flags & EE_BUTTON_WDMASK ) {
mScroll.y += PixelDensity::dpToPx( mMouseWheelScroll );
mScroll.y = eemin( mScroll.y, getMaxScroll().y );
invalidateDraw();
} else if ( flags & EE_BUTTON_WUMASK ) {
mScroll.y -= PixelDensity::dpToPx( mMouseWheelScroll );
mScroll.y = eemax( mScroll.y, 0.f );
invalidateDraw();
}
return UIWidget::onMouseUp( position, flags );
}
void UICodeEdit::onSizeChange() {
UIWidget::onSizeChange();
mScroll = {0, 0};
invalidateEditor();
}
@@ -206,6 +272,7 @@ void UICodeEdit::onPaddingChange() {
void UICodeEdit::updateEditor() {
scrollToMakeVisible( mDoc.getSelection().start() );
mDirtyEditor = false;
}
void UICodeEdit::onDocumentTextChanged() {

View File

@@ -28,14 +28,14 @@ void mainLoop() {
}
EE_MAIN_FUNC int main( int, char** ) {
Doc::TextDocument doc;
/*Doc::TextDocument doc;
doc.loadFromPath( "/home/downloads/textposition.hpp" );
doc.remove( TextRange( TextPosition( 0, 0 ), TextPosition( 1, 40 ) ) );
doc.insert( TextPosition( 0, 0 ),
String( "#ifndef EE_UI_DOC_TEXPOS\n#define EE_UI_DOC_TEXPOS" ) );
doc.remove( TextRange( TextPosition( 31, 2 ), TextPosition( 33, 15 ) ) );
doc.insert( TextPosition( 31, 2 ), String( "hexNumber" ) );
doc.print();
doc.print();*/
// return EXIT_SUCCESS;
win = Engine::instance()->createWindow( WindowSettings( 640, 480, "eepp - UI Hello World" ),
ContextSettings( true ) );