#include "Editor.h" #include #include "Parser\ColorParser.h" #include #include #include #include #include using namespace KSGScript; // Inhalt der Editor Klasse // Konstructor Editor::Editor() : ZeichnungHintergrund(), begF( 0 ), cPos( 0 ), tickVal( 0 ), mausKlick( 0 ) { ref = 1; schrift = 0; script = 0; errorDetection = 1; warningDetection = 1; setTextColor( 0xFFFFFFFF, ColorType::NORMAL_TEXT ); setTextColor( 0xFF4040FF, ColorType::KEYWORD ); setTextColor( 0xFFA0A040, ColorType::PARAMETER_VARIABLE ); setTextColor( 0xFFA0A0A0, ColorType::INSTANCE_VARIABLE ); setTextColor( 0xFF40FF70, ColorType::TYPENAME ); setTextColor( 0xFFFFA000, ColorType::STRING ); setTextColor( 0xFFFF4040, ColorType::ERROR_UNDERLINE ); parser = 0; reloadCounter = 10; } // Destructor Editor::~Editor() { if( schrift ) schrift->release(); if( script ) script->release(); if( parser ) parser->release(); } void Editor::updateHScroll( int pos ) { if( pos == -1 ) pos = cPos; if( horizontalScrollBar && script && schrift ) { schrift->lock(); schrift->setSchriftSize( 12 ); int br = gr.x; if( hatStyle( Style::Rahmen ) && rahmen ) br -= rahmen->getRBreite() * 2; if( hatStyle( Style::VScroll ) && vertikalScrollBar ) br -= 15; int maxBr = schrift->getTextBreite( script ) + 12; horizontalScrollBar->update( maxBr, br ); if( hatStyle( Style::Erlaubt ) && maxBr > br && pos > 0 && pos < script->getLength() ) { int p1 = 0; char *tmp = script->getText(); for( int i = 0; i < pos; i++, tmp++ ) { if( *tmp == '\n' ) p1 = i + 1; } Text *t = script->getTeilText( p1, pos ); int cbr = schrift->getTextBreite( t ); t->release(); if( cbr + 12 > horizontalScrollBar->getScroll() + horizontalScrollBar->getScrollData()->anzeige ) horizontalScrollBar->scroll( cbr + 12 - br ); if( cbr - 12 < horizontalScrollBar->getScroll() ) horizontalScrollBar->scroll( cbr - 12 ); } schrift->unlock(); } } void Editor::updateVScroll( int pos ) { if( pos == -1 ) pos = cPos; if( vertikalScrollBar ) { int sPos = 0; int hi = 0; if( script && schrift ) { schrift->setSchriftSize( 12 ); hi = gr.y; if( hatStyle( Style::Rahmen ) && rahmen ) hi -= rahmen->getRBreite() * 2; if( hatStyle( Style::HScroll ) && horizontalScrollBar ) hi -= 15; vertikalScrollBar->update( schrift->getTextHeight( script ) + 12 + schrift->getTextHeight( Text( "a" ).getThis() ), hi ); Text t; int zh = schrift->getTextHeight( &t ) + schrift->getZeilenabstand(); int l = script->getLength(); for( int i = 0; i < l && ( i < pos || hatStyleNicht( Style::Erlaubt ) ); ++i ) { if( script->getText()[ i ] == '\n' ) sPos += zh; } } if( schrift ) { if( sPos - schrift->getZeilenabstand() - schrift->getTextHeight( Text( "a" ).getThis() ) < vertikalScrollBar->getScroll() ) vertikalScrollBar->scroll( sPos - schrift->getZeilenabstand() - schrift->getTextHeight( Text( "a" ).getThis() ) ); if( sPos + schrift->getZeilenabstand() + schrift->getTextHeight( Text( "a" ).getThis() ) > vertikalScrollBar->getScroll() + vertikalScrollBar->getScrollData()->anzeige ) vertikalScrollBar->scroll( sPos + ( schrift->getZeilenabstand() + schrift->getTextHeight( Text( "a" ).getThis() ) ) * 2 - hi ); } rend = 1; } } // Setzt die zu verwendende Schrift // s: Die Schrift void Editor::setSchriftZ( Schrift *s ) { if( schrift ) schrift->release(); schrift = s; } // Setzt den Text (das Script was verändert werden soll) // txt: Der Text void Editor::setText( Text *txt ) { if( script ) script->release(); if( parser ) parser->release(); script = new Text( txt->getText() ); parser = new ColorParser( script ); txt->release(); updateHScroll( -1 ); updateVScroll( -1 ); } // Gibt den aktuellen Text zurück Text *Editor::zText() const { return script; } // Schaltet die Fehlererkennung ein oder aus // on: 1, um die Fehlererkennung einzuschalten, 0 um sie auszuschalten void Editor::setErrorDetection( bool on ) { errorDetection = on; } // Schaltet die Warnungserkennung ein oder aus // on: 1, um die Warnungserkennung einzuschalten, 0 um sie auszuschalten void Editor::setWarningDetection( bool on ) { warningDetection = on; } // gibt 1 zurück, wenn die Fehlererkennung eingeschaltet ist bool Editor::getErrorDetection() const { return errorDetection; } // gibt 1 zurück, wenn die Warnungserkennung eingeschaltet ist bool Editor::getWarningDetection() const { return warningDetection; } // Verarbeitet ein Maus Ereignis. Wird vom Framework automatisch aufgerufen. // me: Das Ereignis void Editor::doMausEreignis( MausEreignis &me ) { bool nmakc = !me.verarbeitet; if( hatStyleNicht( Style::Erlaubt ) || hatStyleNicht( Style::Sichtbar ) ) { if( toolTip ) toolTip->setMausIn( 0 ); me.mx -= pos.x, me.my -= pos.y; int rbr = 0; if( rahmen ) rbr = rahmen->getRBreite(); if( ( ( vertikalScrollBar && hatStyle( Style::VScroll ) ) || ( horizontalScrollBar && hatStyle( Style::HScroll ) ) ) && me.mx > rbr && me.mx < gr.x - rbr && me.my > rbr && me.my < gr.y - rbr ) { vertikalScrollBar->doMausMessage( gr.x - rbr - 15, rbr, 15, gr.y - rbr * 2, me ); horizontalScrollBar->doMausMessage( rbr, gr.y - rbr * 2 - 15, gr.x - rbr * 2 - ( ( vertikalScrollBar && hatStyle( Style::VScroll ) ) ? 15 : 0 ), 15, me ); me.verarbeitet = 1; } me.mx += pos.x, me.my += pos.y; mausKlick = 0; return; } bool removeFokus = 0; if( me.verarbeitet || !( me.mx >= pos.x && me.mx <= pos.x + gr.x && me.my >= pos.y && me.my <= pos.y + gr.y ) ) { if( mausIn ) { mausIn = 0; if( toolTip ) toolTip->setMausIn( 0 ); MausEreignis me2; me2.id = ME_Leaves; me2.mx = me.mx; me2.my = me.my; me2.verarbeitet = 0; doMausEreignis( me2 ); return; } removeFokus = 1; } if( !( me.mx >= pos.x && me.mx <= pos.x + gr.x && me.my >= pos.y && me.my <= pos.y + gr.y ) && me.id != ME_Leaves ) { if( removeFokus && me.id == ME_RLinks ) { me.mx -= pos.x, me.my -= pos.y; if( hatStyle( Style::Fokus ) && mak && ( me.verarbeitet || mak( makParam, this, me ) ) ) removeStyle( Style::Fokus ); if( nmakc && me.verarbeitet && nMak ) me.verarbeitet = nMak( nmakParam, this, me ); me.mx += pos.x, me.my += pos.y; } if( toolTip ) toolTip->setMausIn( 0 ); return; } if( !mausIn && me.id != ME_Leaves ) { mausIn = 1; if( toolTip ) toolTip->setMausIn( 1 ); MausEreignis me2; me2.id = ME_Betritt; me2.mx = me.mx; me2.my = me.my; me2.verarbeitet = 0; doMausEreignis( me2 ); } me.mx -= pos.x, me.my -= pos.y; if( mak && ( me.verarbeitet || mak( makParam, this, me ) ) ) { if( removeFokus && me.id == ME_RLinks ) removeStyle( Style::Fokus ); if( !me.verarbeitet ) { if( hatStyleNicht( Style::Fokus ) ) { mausKlick = 0; if( me.id == Framework::ME_PLinks ) addStyle( Style::Fokus ); } int rbr = 0; if( rahmen ) rbr = rahmen->getRBreite(); if( vertikalScrollBar && hatStyle( Style::VScroll ) ) { if( vertikalScrollBar->doMausMessage( gr.x - rbr - 15, rbr, 15, gr.y - rbr * 2, me ) ) { if( nmakc && me.verarbeitet && nMak ) me.verarbeitet = nMak( nmakParam, this, me ); me.mx += pos.x, me.my += pos.y; return; } } if( horizontalScrollBar && hatStyle( Style::HScroll ) ) { if( horizontalScrollBar->doMausMessage( rbr, gr.y - rbr - 15, gr.x - rbr * 2 - ( ( vertikalScrollBar && hatStyle( Style::VScroll ) ) ? 15 : 0 ), 15, me ) ) { if( nmakc && me.verarbeitet && nMak ) me.verarbeitet = nMak( nmakParam, this, me ); me.mx += pos.x, me.my += pos.y; return; } } if( me.mx < gr.x - rbr - 15 ) { if( schrift ) { schrift->setSchriftSize( 12 ); bool shift = getTastenStand( T_Shift ); if( me.id == Framework::ME_PLinks ) { int tbr = schrift->getTextBreite( script ); int thi = schrift->getTextHeight( script ); int scrollHi = ( vertikalScrollBar && hatStyle( Style::VScroll ) ) ? vertikalScrollBar->getScroll() : 0; int scrollBr = ( horizontalScrollBar && hatStyle( Style::HScroll ) ) ? horizontalScrollBar->getScroll() : 0; int xxx = me.mx - rbr + scrollBr; int yyy = me.my - rbr + scrollHi; int scrollBreite = ( vertikalScrollBar && hatStyle( Style::VScroll ) ) * 15; int pos = schrift->textPos( script, xxx, yyy ); if( pos != -1 ) { if( shift ) begF = pos; else { cPos = pos; begF = pos; } rend = 1; if( vertikalScrollBar && hatStyle( Style::VScroll ) ) updateVScroll( begF ); if( horizontalScrollBar && hatStyle( Style::HScroll ) ) updateHScroll( begF ); } mausKlick = 1; } if( me.id == ME_Bewegung && mausKlick ) { int tbr = schrift->getTextBreite( script ); int thi = schrift->getTextHeight( script ); int scrollHi = ( vertikalScrollBar && hatStyle( Style::VScroll ) ) ? vertikalScrollBar->getScroll() : 0; int scrollBr = ( horizontalScrollBar && hatStyle( Style::HScroll ) ) ? horizontalScrollBar->getScroll() : 0; int xxx = me.mx - rbr + scrollBr; int yyy = me.my - rbr + scrollHi; int scrollBreite = ( vertikalScrollBar && hatStyle( Style::VScroll ) ) * 15; int scrollHeight = ( horizontalScrollBar && hatStyle( Style::HScroll ) ) * 15; int pos = schrift->textPos( script, xxx, yyy ); if( pos != -1 ) { if( begF != pos ) rend = 1; begF = pos; if( vertikalScrollBar && hatStyle( Style::VScroll ) ) updateVScroll( begF ); if( horizontalScrollBar && hatStyle( Style::HScroll ) ) updateHScroll( begF ); } } if( me.id == ME_RLinks ) { if( !shift ) { int tbr = schrift->getTextBreite( script ); int thi = schrift->getTextHeight( script ); int scrollHi = ( vertikalScrollBar && hatStyle( Style::VScroll ) ) ? vertikalScrollBar->getScroll() : 0; int scrollBr = ( horizontalScrollBar && hatStyle( Style::HScroll ) ) ? horizontalScrollBar->getScroll() : 0; int xxx = me.mx - rbr + scrollBr; int yyy = me.my - rbr + scrollHi; int scrollBreite = ( vertikalScrollBar && hatStyle( Style::VScroll ) ) * 15; int scrollHeight = ( horizontalScrollBar && hatStyle( Style::HScroll ) ) * 15; int pos = schrift->textPos( script, xxx, yyy ); if( pos != -1 ) { begF = pos; if( vertikalScrollBar && hatStyle( Style::VScroll ) ) updateVScroll( begF ); if( horizontalScrollBar && hatStyle( Style::HScroll ) ) updateHScroll( begF ); } rend = 1; } mausKlick = 0; } } } } me.verarbeitet = 1; } if( nmakc && me.verarbeitet && nMak ) me.verarbeitet = nMak( nmakParam, this, me ); me.mx += pos.x, me.my += pos.y; } // Verarbeitet ein Tastatur Ereignis. Wird vom Framework automatisch aufgerufen // te: Das Ereignis void Editor::doTastaturEreignis( TastaturEreignis &te ) { bool ntakc = !te.verarbeitet; if( te.verarbeitet || hatStyleNicht( Style::Fokus ) ) return; if( !tak ) return; ++ref; if( tak( takParam, this, te ) ) { if( hatStyleNicht( Style::Erlaubt ) ) { --ref; if( !ref ) delete this; return; } if( te.id == TE_Press ) { bool shift = getTastenStand( T_Shift ); bool strg = getTastenStand( T_Strg ); switch( te.taste ) { case T_Entf: if( cPos != begF ) script->remove( cPos, begF ); else script->remove( cPos, cPos + 1 ); begF = cPos; rend = 1; break; case T_BackSpace: if( cPos != begF ) { script->remove( cPos, begF ); if( cPos > begF ) cPos -= cPos - begF; } else { script->remove( cPos - 1, cPos ); --cPos; } begF = cPos; rend = 1; break; case T_Enter: if( cPos != begF ) { script->remove( begF, cPos ); if( cPos > begF ) cPos -= cPos - begF; } script->insert( cPos, '\n' ); ++cPos; begF = cPos; rend = 1; break; case T_Links: if( shift ) { if( strg ) begF = script->getLKick( begF ); else --begF; } else { if( strg ) cPos = script->getLKick( cPos ); else --cPos; begF = cPos; } rend = 1; break; case T_Oben: if( shift ) { begF = script->getOKick( begF ); } else { cPos = script->getOKick( cPos ); begF = cPos; } rend = 1; break; case T_Rechts: if( shift ) { if( strg ) begF = script->getRKick( begF ); else ++begF; } else { if( strg ) cPos = script->getRKick( cPos ); else ++cPos; begF = cPos; } rend = 1; break; case T_Unten: if( shift ) { begF = script->getUKick( begF ); } else { cPos = script->getUKick( cPos ); begF = cPos; } rend = 1; break; default: if( strg && te.id == TE_Press ) { if( te.taste == 'c' || te.taste == 'C' ) { if( begF != cPos ) { int len = begF - cPos; if( len < 0 ) len = -len; char *txt = new char[ len + 1 ]; txt[ len ] = 0; int beg = begF < cPos ? begF : cPos; for( int i = beg; i < beg + len; ++i ) txt[ i - beg ] = script->getText()[ i ]; TextKopieren( txt ); delete[] txt; } else TextKopieren( script->getText() ); } if( te.taste == 'v' || te.taste == 'V' ) { if( begF != cPos ) { script->remove( begF, cPos ); if( cPos > begF ) cPos = begF; } char *txt = TextInsert(); script->insert( cPos, txt ); cPos += textLength( txt ); begF = cPos; rend = 1; } break; } if( istSchreibbar( te.taste ) ) { if( begF != cPos ) { script->remove( begF, cPos ); if( cPos > begF ) cPos = begF; } script->insert( cPos, (char)te.taste ); ++cPos; begF = cPos; rend = 1; } break; } } if( cPos < 0 ) cPos = 0; if( cPos > script->getLength() ) cPos = script->getLength(); if( begF < 0 ) begF = 0; if( begF > script->getLength() ) begF = script->getLength(); if( hatStyle( Style::VScroll ) ) updateVScroll( begF ); if( hatStyle( Style::HScroll ) ) updateHScroll( begF ); te.verarbeitet = 1; } lockZeichnung(); if( !--reloadCounter ) { reloadCounter = 10; parser->reload(); } unlockZeichnung(); --ref; if( ntakc && te.verarbeitet && nTak ) te.verarbeitet = nTak( ntakParam, this, te ); if( !ref ) delete this; } // Updated den Editor // tickVal: Die vergangene Zeit in Sekunden, die seit dem Letzten Aufruf dieser Funktion verstrichen ist // return: 1, wenn das Bild neu gezeichnet werden muss. 0 sonnst bool Editor::tick( double tickval ) { if( hatStyle( Style::Fokus ) ) { if( tickVal < 0.5 && tickVal + tickval >= 0.5 ) rend = 1; if( tickVal >= 0.5 && tickVal + tickval >= 1 ) rend = 1; tickVal += tickval; if( tickVal >= 1 ) { lockZeichnung(); if( (reloadCounter -= 2 ) <= 0 ) { reloadCounter = 10; parser->reload(); } unlockZeichnung(); tickVal -= 1; } } return __super::tick( tickVal ); } // Zeichnet den Editor nach rObj void Editor::render( Bild &rObj ) { if( hatStyleNicht( Style::Sichtbar ) ) return; __super::render( rObj ); if( !script || !schrift ) return; lockZeichnung(); if( !rObj.setDrawOptions( innenPosition, innenSize ) ) { unlockZeichnung(); return; } schrift->setSchriftSize( 12 ); int tbr = schrift->getTextBreite( script ); int thi = schrift->getTextHeight( script ); int xxx = 0; int yyy = 0; int breite = innenSize.x; int height = innenSize.y; bool hs = horizontalScrollBar && hatStyle( Style::HScroll ); bool vs = vertikalScrollBar && hatStyle( Style::VScroll ); if( vs ) yyy -= vertikalScrollBar->getScroll(); if( hs ) xxx -= horizontalScrollBar->getScroll(); schrift->setDrawPosition( xxx, yyy ); parser->reset(); auto colorF = [ this, &rObj ]( int x, int y ) -> int { if( !parser ) return colors[ KSGScriptEditor::ColorType::NORMAL_TEXT ]; int uC = -1; int tC = colors[ parser->getNextColor( uC ) ]; if( uC >= 0 ) rObj.drawLinieH( x, y + 12, 12, colors[ uC ] ); return tC; }; if( hatStyle( Style::Fokus ) && hatStyle( Style::Erlaubt ) ) { if( tickVal <= 0.5 ) schrift->renderText( script, rObj, cPos, 0xFFFF5555, begF, 0xFF0000FF, colorF ); else schrift->renderText( script, rObj, cPos, 0x00000000, begF, 0xFF0000FF, colorF ); } else { schrift->renderText( script, rObj, colorF ); } rObj.releaseDrawOptions(); unlockZeichnung(); } // Setzt die Farbe eines Bestimmten Codetyps // color: Die Farbe in 0xAARRGGBB Format // cType: Der Codetyp, der die Farbe bekommen soll // Setzt die Farbe eines Bestimmten Codetyps // color: Die Farbe in 0xAARRGGBB Format // cType: Der Codetyp, der die Farbe bekommen soll void Editor::setTextColor( int color, ColorType cType ) { if( cType >= 0 && cType < ColorType::COLOR_ANZAHL ) colors[ cType ] = color; } // Reference Counting KSGScriptEditor *Editor::getThis() { ref++; return this; } KSGScriptEditor *Editor::release() { if( !--ref ) delete this; return 0; }