#include "Editor.h" #include #include "Parser/ColorParser.h" #include #include #include #include #include using namespace KSGScript; // Inhalt der Editor Klasse // Konstructor Editor::Editor() : ZeichnungHintergrund(), tickVal(0), cPos(0), begF(0), mausKlick(0) { textRd = 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(0xFF20FFFF, ColorType::KOMMENTAR); setTextColor(0xFFFF4040, ColorType::ERROR_UNDERLINE); parser = 0; reloadCounter = 10; } // Destructor Editor::~Editor() { if (textRd) textRd->release(); if (script) script->release(); if (parser) parser->release(); } // Verarbeitet ein Maus Ereignis. Wird vom Framework automatisch aufgerufen. // me: Das Ereignis void Editor::doMausEreignis(MausEreignis& me, bool userRet) { if (hatStyleNicht(Style::Erlaubt) || !userRet) { 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) { me.verarbeitet |= vertikalScrollBar->doMausMessage(gr.x - rbr - 15, rbr, 15, gr.y - rbr * 2, me); me.verarbeitet |= horizontalScrollBar->doMausMessage(rbr, gr.y - rbr * 2 - 15, gr.x - rbr * 2 - ((vertikalScrollBar && hatStyle(Style::VScroll)) ? 15 : 0), 15, me); } mausKlick = 0; return; } if (!me.verarbeitet) { if (me.id == ME_Betritt) mausKlick = 0; 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)) { me.verarbeitet = 1; 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)) { me.verarbeitet = 1; return; } } if (me.mx < gr.x - rbr - 15) { if (textRd) { textRd->setSchriftSize(12); bool shift = getTastenStand(T_Shift); if (me.id == Framework::ME_PLinks) { 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 pos = textRd->textPos(script->getText(), 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 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 pos = textRd->textPos(script->getText(), 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 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 pos = textRd->textPos(script->getText(), 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; } void Editor::updateHScroll(int pos) { if (pos == -1) pos = cPos; if (horizontalScrollBar && script && textRd) { textRd->setSchriftSize(12); int br = gr.x; if (hatStyle(Style::Rahmen) && rahmen) br -= rahmen->getRBreite() * 2; if (hatStyle(Style::VScroll) && vertikalScrollBar) br -= 15; int maxBr = textRd->getTextBreite(script->getText()) + 12; horizontalScrollBar->update(maxBr, br); if (hatStyle(Style::Erlaubt) && maxBr > br && pos > 0 && pos < script->getLength()) { int p1 = 0; const 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 = textRd->getTextBreite(t->getText()); t->release(); if (cbr + 12 > horizontalScrollBar->getScroll() + horizontalScrollBar->getScrollData()->anzeige) horizontalScrollBar->scroll(cbr + 12 - br); if (cbr - 12 < horizontalScrollBar->getScroll()) horizontalScrollBar->scroll(cbr - 12); } } } void Editor::updateVScroll(int pos) { if (pos == -1) pos = cPos; if (vertikalScrollBar) { int sPos = 0; int hi = 0; if (script && textRd) { textRd->setSchriftSize(12); hi = gr.y; if (hatStyle(Style::Rahmen) && rahmen) hi -= rahmen->getRBreite() * 2; if (hatStyle(Style::HScroll) && horizontalScrollBar) hi -= 15; vertikalScrollBar->update(textRd->getTextHeight(script->getText()) + 12 + textRd->getTextHeight("a"), hi); Text t; int zh = textRd->getTextHeight(t) + textRd->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 (textRd) { if (sPos - textRd->getZeilenabstand() - textRd->getTextHeight(Text("a")) < vertikalScrollBar->getScroll()) vertikalScrollBar->scroll(sPos - textRd->getZeilenabstand() - textRd->getTextHeight(Text("a"))); if (sPos + textRd->getZeilenabstand() + textRd->getTextHeight(Text("a")) > vertikalScrollBar->getScroll() + vertikalScrollBar->getScrollData()->anzeige) vertikalScrollBar->scroll(sPos + (textRd->getZeilenabstand() + textRd->getTextHeight(Text("a"))) * 2 - hi); } rend = 1; } } // Setzt die zu verwendende Schrift // s: Die Schrift void Editor::setSchriftZ(Schrift* s) { if (!textRd) textRd = new TextRenderer(s); else textRd->setSchriftZ(s); } // Setzt den zu verwendenden Text Renderer // t: Der Text Renderer void Editor::setTextRendererZ(TextRenderer* t) { if (textRd) textRd->release(); textRd = t; } // Setzt den Text (das Script was verändert werden soll) // txt: Der Text void Editor::setText(Text* txt) { lockZeichnung(); if (script) script->release(); if (parser) parser->release(); script = new Text(txt->getText()); parser = new ColorParser(script); txt->release(); updateHScroll(-1); updateVScroll(-1); unlockZeichnung(); } // 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 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; getThis(); if (tak(takParam, this, te)) { if (hatStyleNicht(Style::Erlaubt)) { release(); 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) { zm.messungStart(); parser->reload(); zm.messungEnde(); reloadCounter = (int)(zm.getSekunden() * 100); } unlockZeichnung(); if (ntakc && te.verarbeitet && nTak) te.verarbeitet = nTak(ntakParam, this, te); release(); } // 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) { zm.messungStart(); parser->reload(); zm.messungEnde(); reloadCounter = (int)(zm.getSekunden() * 100); } unlockZeichnung(); tickVal -= 1; } } return ZeichnungHintergrund::tick(tickVal); } // Zeichnet den Editor nach rObj void Editor::render(Bild& rObj) { if (hatStyleNicht(Style::Sichtbar)) return; ZeichnungHintergrund::render(rObj); if (!script || !textRd) return; lockZeichnung(); if (!rObj.setDrawOptions(innenPosition, innenSize)) { unlockZeichnung(); return; } textRd->setSchriftSize(12); int xxx = 0; int yyy = 0; bool hs = horizontalScrollBar && hatStyle(Style::HScroll); bool vs = vertikalScrollBar && hatStyle(Style::VScroll); if (vs) yyy -= vertikalScrollBar->getScroll(); if (hs) xxx -= horizontalScrollBar->getScroll(); parser->reset(); auto colorF = [this, &rObj](int x, int y, int pos) -> int { if (!parser) return colors[(int)KSGScriptEditor::ColorType::NORMAL_TEXT]; int uC = -1; int tC = colors[(int)parser->getNextColor(pos, 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) textRd->renderText(xxx, yyy, script->getText(), rObj, colorF, cPos, 0xFFFF5555, begF, 0xFF0000FF); else textRd->renderText(xxx, yyy, script->getText(), rObj, colorF, cPos, 0x00000000, begF, 0xFF0000FF); } else { textRd->renderText(xxx, yyy, script->getText(), 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 ((int)cType >= 0 && cType < ColorType::COLOR_ANZAHL) colors[(int)cType] = color; }