| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304 |
- #include "JsonEditor.h"
- #include "Font.h"
- #include "Globals.h"
- #include "Image.h"
- #include "KeyboardEvent.h"
- #include "MouseEvent.h"
- #include "Regex.h"
- #include "TextField.h"
- using namespace Framework;
- using namespace JSON;
- const char* errors[] = {"Unexpected start of object",
- "Unexpected start of array",
- "Unexpected value",
- "Unexpected ','",
- "Unexpected ':'",
- "Unexpected end of object",
- "Unexpected end of array",
- "Unexpected start of string",
- "Invalid json value",
- ""};
- class EditableJsonElementReference : public virtual AbstractElement,
- public virtual ReferenceCounter,
- public virtual AbstractBool,
- public virtual AbstractNumber,
- public virtual AbstractString,
- public virtual AbstractArray,
- public virtual AbstractObject
- {
- private:
- EditableJsonElement* root;
- RCArray<EditableJsonElementReference>* children;
- EditableJsonElementReference(EditableJsonElement* root,
- RCArray<EditableJsonElementReference>* children)
- : root(root),
- children(children)
- {}
- public:
- EditableJsonElementReference(EditableJsonElement* root)
- : root(root),
- children(new RCArray<EditableJsonElementReference>())
- {}
- ~EditableJsonElementReference()
- {
- children->release();
- }
- AbstractType getType() const override
- {
- if (root->hasError() || root->getValue().isEqual("null"))
- {
- return AbstractType::NULL_;
- }
- else if (root->getOpeningControllChar() == '{')
- {
- return AbstractType::OBJECT;
- }
- else if (root->getOpeningControllChar() == '[')
- {
- return AbstractType::ARRAY;
- }
- else if (root->getValue().isEqual("true")
- || root->getValue().isEqual("false"))
- {
- return AbstractType::BOOLEAN;
- }
- else if (root->getValue().hasAt(0, "\""))
- {
- return AbstractType::STRING;
- }
- else
- {
- return AbstractType::NUMBER;
- }
- }
- const AbstractBool* asAbstractBool() const override
- {
- return this;
- }
- const AbstractNumber* asAbstractNumber() const override
- {
- return this;
- }
- const AbstractString* asAbstractString() const override
- {
- return this;
- }
- const AbstractArray* asAbstractArray() const override
- {
- return this;
- }
- const AbstractObject* asAbstractObject() const override
- {
- return this;
- }
- Text toString() const override
- {
- return root->getRecursiveContent();
- }
- bool getBool() const override
- {
- return (bool)root->getValue();
- }
- double getNumber() const override
- {
- return (double)root->getValue();
- }
- Text getString() const override
- {
- Text txt = root->getValue().getText() + 1;
- txt.remove(txt.getLength() - 1, 1);
- return (double)root->getValue();
- }
- AbstractElement* zAbstractValue(int i) const override
- {
- EditableJsonElement* e = root->zFirstChildren();
- while (e && i > 0)
- {
- e = e->zMextSibling();
- i--;
- }
- if (e)
- {
- EditableJsonElementReference* result
- = new EditableJsonElementReference(e, children);
- children->add(result);
- return result;
- }
- return 0;
- }
- int getLength() const override
- {
- EditableJsonElement* e = root->zFirstChildren();
- int i = 0;
- while (e)
- {
- e = e->zMextSibling();
- i++;
- }
- return i;
- }
- AbstractElement* zAbstractValue(Text field) const override
- {
- EditableJsonElement* e = root->zFirstChildren();
- while (e)
- {
- if (e->getKey().isEqual(field))
- {
- EditableJsonElementReference* result
- = new EditableJsonElementReference(e, children);
- children->add(result);
- return result;
- }
- e = e->zMextSibling();
- }
- return 0;
- }
- int getFieldCount() const override
- {
- return getLength();
- }
- Text getFieldKey(int i) const override
- {
- EditableJsonElement* e = root->zFirstChildren();
- while (e && i > 0)
- {
- e = e->zMextSibling();
- i--;
- }
- if (e)
- {
- return e->getKey();
- }
- return 0;
- }
- bool hasValue(Text field) const override
- {
- EditableJsonElement* e = root->zFirstChildren();
- while (e)
- {
- if (e->getKey().isEqual(field))
- {
- return 1;
- }
- e = e->zMextSibling();
- }
- return 0;
- }
- };
- SyntaxError::SyntaxError(int start, int end, SyntaxErrorType errorType)
- : start(start),
- end(end),
- errorType(errorType)
- {}
- SyntaxError::SyntaxError()
- : start(-1),
- end(-1),
- errorType(SyntaxErrorType::OTHER)
- {}
- int SyntaxError::getStart() const
- {
- return start;
- }
- int SyntaxError::getEnd() const
- {
- return end;
- }
- SyntaxErrorType SyntaxError::getErrorType() const
- {
- return errorType;
- }
- Framework::JSON::ParserState::ParserState(
- JsonStructure parent, bool valueExpected)
- : index(0),
- keyStart(-1),
- keyEnd(0),
- valueStart(-1),
- valueEnd(0),
- errorStart(0),
- parent(parent),
- inString(0),
- escaped(0),
- colon(parent != JsonStructure::OBJECT),
- key(parent != JsonStructure::OBJECT),
- value(0),
- inValue(0),
- valueValidationNeeded(0),
- openingControllChar(0),
- closingControllChar(0),
- valueExpected(valueExpected)
- {}
- bool Framework::JSON::ParserState::next(
- const char* current, const char* next, SyntaxError& error)
- {
- if (current[0] == 0) return next == 0;
- bool stop = 0;
- if (current[0] == '{' && !inString)
- {
- stop = 1;
- if (!colon || value)
- {
- error.start = index;
- error.end = index + 1;
- error.errorType = SyntaxErrorType::UNEXPECTED_OBJECT_START;
- }
- value = 1;
- openingControllChar = current[0];
- }
- else if (current[0] == '[' && !inString)
- {
- stop = 1;
- if (!colon || value)
- {
- error.start = index;
- error.end = index + 1;
- error.errorType = SyntaxErrorType::UNEXPECTED_ARRAY_START;
- }
- value = 1;
- openingControllChar = current[0];
- }
- else if (current[0] == '}' && !inString)
- {
- stop = current[1] == ']' || current[1] == '}';
- if (!stop)
- {
- const char* n = current + 1;
- while (*n && (*n == ' ' || *n == '\t' || *n == '\r' || *n == '\n'))
- {
- n++;
- }
- stop = *n == ']' || *n == '}';
- if (!stop && next)
- {
- n = next;
- while (
- *n && (*n == ' ' || *n == '\t' || *n == '\r' || *n == '\n'))
- {
- n++;
- }
- stop = *n == ']' || *n == '}';
- }
- }
- if (parent != JsonStructure::OBJECT || (!value && valueExpected))
- {
- error.start = index;
- error.end = index + 1;
- error.errorType = SyntaxErrorType::UNEXPECTED_END_OF_OBJECT;
- }
- value = 1;
- closingControllChar = current[0];
- }
- else if (current[0] == ']' && !inString)
- {
- stop = current[1] == ']' || current[1] == '}';
- if (!stop)
- {
- const char* n = current + 1;
- while (*n && (*n == ' ' || *n == '\t' || *n == '\r' || *n == '\n'))
- {
- n++;
- }
- stop = *n == ']' || *n == '}';
- if (!stop && next)
- {
- n = next;
- while (
- *n && (*n == ' ' || *n == '\t' || *n == '\r' || *n == '\n'))
- {
- n++;
- }
- stop = *n == ']' || *n == '}';
- }
- }
- if (parent != JsonStructure::ARRAY || (!value && valueExpected))
- {
- error.start = index;
- error.end = index + 1;
- error.errorType = SyntaxErrorType::UNEXPECTED_END_OF_ARRAY;
- }
- value = 1;
- closingControllChar = current[0];
- }
- else if (current[0] == '"' && !escaped)
- {
- inString = !inString;
- if (inString)
- {
- if (!key)
- {
- keyStart = index + 1;
- }
- else if (colon && !value)
- {
- valueStart = index;
- }
- else
- {
- error.start = index;
- error.end = index + 1;
- error.errorType = SyntaxErrorType::UNEXPECTED_START_OF_STRING;
- }
- }
- else
- {
- if (!key)
- {
- keyEnd = index;
- key = 1;
- }
- else if (colon && !value)
- {
- valueEnd = index + 1;
- value = 1;
- }
- }
- }
- else if (current[0] == '\\' && inString)
- {
- escaped = !escaped;
- }
- else if (current[0] == ':' && !inString)
- {
- if (key && !colon)
- {
- colon = 1;
- }
- else
- {
- error.start = index;
- error.end = index + 1;
- error.errorType = SyntaxErrorType::UNEXPECTED_COLON;
- }
- }
- else if (current[0] == ',' && !inString)
- {
- stop = 1;
- if (!value)
- {
- error.start = index;
- error.end = index + 1;
- error.errorType = SyntaxErrorType::UNEXPECTED_COMMA;
- }
- }
- else
- {
- escaped = 0;
- if (!inString && current[0] != ' ' && current[0] != '\t'
- && current[0] != '\n' && current[0] != '\r')
- {
- if (colon && !value)
- {
- if (!inValue)
- {
- valueStart = index;
- inValue = 1;
- }
- }
- else
- {
- if (!inValue)
- {
- errorStart = index;
- inValue = 1;
- }
- }
- if (inValue
- && (current[1] == ':' || current[1] == '"' || current[1] == '{'
- || current[1] == '[' || current[1] == ']'
- || current[1] == '}' || current[1] == ','))
- {
- inValue = 0;
- if (colon && !value)
- {
- value = 1;
- valueEnd = index + 1;
- valueValidationNeeded = 1;
- }
- else
- {
- error.start = errorStart;
- error.end = index;
- error.errorType = SyntaxErrorType::UNEXPECTED_VALUE;
- }
- }
- }
- else if (inValue)
- {
- inValue = 0;
- if (colon && !value)
- {
- valueEnd = index;
- value = 1;
- valueValidationNeeded = 1;
- }
- else
- {
- error.start = errorStart;
- error.end = index;
- error.errorType = SyntaxErrorType::UNEXPECTED_VALUE;
- }
- }
- }
- index++;
- return stop;
- }
- EditableJsonElement::EditableJsonElement(Regex::Automata<char>* valueValidator)
- : ReferenceCounter(),
- content(),
- valueStart(-1),
- keyStart(-1),
- valueValidator(valueValidator),
- newLineCount(0)
- {
- children = 0;
- siblings = 0;
- lastChild = 0;
- parent = 0;
- hidden = false;
- parentStructure = JsonStructure::VALUE;
- }
- Framework::JSON::EditableJsonElement::EditableJsonElement(
- Regex::Automata<char>* valueValidator, const char* content)
- : EditableJsonElement(valueValidator)
- {
- setContent(content);
- valueValidator->release();
- }
- EditableJsonElement::~EditableJsonElement()
- {
- if (children)
- {
- children->release();
- }
- if (siblings)
- {
- siblings->release();
- }
- }
- void Framework::JSON::EditableJsonElement::setContentOnly(const char** content,
- int& startPos,
- Array<EditableJsonElement*>& afterList,
- Array<EditableJsonElement*>& deleteList)
- {
- errors.clear();
- int start = startPos;
- EditableJsonElement* before = zBefore(0, false, 0);
- ParserState p(parentStructure,
- before
- ? before->getContent()[before->getContent().getLength() - 1] == ','
- : 0);
- SyntaxError error;
- key = "";
- value = "";
- this->content = "";
- while (true)
- {
- const char* current = (*content) + startPos++;
- const char* next = 0;
- if (afterList.getEntryCount())
- {
- next = afterList.get(0)->getContent();
- }
- if (p.next(current, next, error))
- {
- break;
- }
- if (error.getErrorType() != SyntaxErrorType::OTHER)
- {
- errors.add(error);
- error = SyntaxError();
- }
- if (!*current)
- {
- startPos--;
- }
- if (!(*content)[startPos])
- {
- if (!afterList.getEntryCount())
- {
- break;
- }
- else
- {
- if (p.keyStart >= 0
- && (p.keyEnd < p.keyStart || p.keyEnd + start >= 0)
- && parentStructure == JsonStructure::OBJECT)
- {
- int s = p.keyStart + start < 0 ? 0 : p.keyStart + start;
- int e = p.keyEnd < p.keyStart ? p.index : p.keyEnd + start;
- key += Text(*content, s, e - s);
- }
- if (p.valueStart >= 0
- && (p.valueEnd < p.valueStart || p.valueEnd + start >= 0)
- && parentStructure == JsonStructure::OBJECT)
- {
- int s = p.valueStart + start < 0 ? 0 : p.valueStart + start;
- int e = p.valueEnd < p.valueStart ? p.index + start
- : p.valueEnd + start;
- value += Text(*content, s, e - s);
- }
- this->content += Text(*content,
- start < 0 ? 0 : start,
- start < 0 ? startPos : startPos - start);
- EditableJsonElement* next = afterList.get(0);
- int i = 0;
- afterList.remove(i);
- if (next->children)
- {
- afterList.add(next->children, i);
- i++;
- }
- if (next->siblings)
- {
- afterList.add(next->siblings, i);
- }
- next->disconnect();
- deleteList.add(next);
- *content = next->getContent();
- startPos = 0;
- start = -p.index;
- }
- }
- }
- if (error.getErrorType() != SyntaxErrorType::OTHER)
- {
- errors.add(error);
- error = SyntaxError();
- }
- if (p.keyStart >= 0 && (p.keyEnd < p.keyStart || p.keyEnd + start >= 0)
- && parentStructure == JsonStructure::OBJECT)
- {
- int s = p.keyStart + start < 0 ? 0 : p.keyStart + start;
- int e = p.keyEnd < p.keyStart ? p.index : p.keyEnd + start;
- key += Text(*content, s, e - s);
- }
- if (p.valueStart >= 0
- && (p.valueEnd < p.valueStart || p.valueEnd + start >= 0))
- {
- int s = p.valueStart + start < 0 ? 0 : p.valueStart + start;
- int e
- = p.valueEnd < p.valueStart ? p.index + start : p.valueEnd + start;
- value += Text(*content, s, e - s);
- }
- if (p.valueValidationNeeded)
- {
- if (!isValueValid(value, 0, value.getLength()))
- {
- errors.add(SyntaxError(
- p.valueStart, p.valueEnd, SyntaxErrorType::INVALID_VALUE));
- }
- }
- this->content += Text(*content,
- start < 0 ? 0 : start,
- start < 0 ? startPos : startPos - start);
- newLineCount = this->content.countOf('\n');
- openingControllChar = p.openingControllChar;
- closingControllChar = p.closingControllChar;
- valueStart = p.valueStart;
- keyStart = p.keyStart;
- if ((*content)[startPos]
- && ((*content)[startPos - 1] == '[' || (*content)[startPos - 1] == '{'))
- {
- EditableJsonElement* next = new EditableJsonElement(valueValidator);
- addChildren(next);
- next->setContentRecursive(content, startPos, afterList, deleteList);
- }
- // TODO: set parent structure of children
- // TODO: update tree
- }
- void Framework::JSON::EditableJsonElement::setContentRecursive(
- const char** content,
- int& startPos,
- Array<EditableJsonElement*>& afterList,
- Array<EditableJsonElement*>& deleteList)
- {
- setContentOnly(content, startPos, afterList, deleteList);
- char lastControl = closingControllChar;
- while ((*content)[startPos]
- && !((lastControl == ']' && parentStructure == JsonStructure::ARRAY)
- || (lastControl == '}'
- && parentStructure == JsonStructure::OBJECT)))
- {
- if (closingControllChar == ']'
- && parentStructure == JsonStructure::ARRAY)
- {
- break;
- }
- EditableJsonElement* next = new EditableJsonElement(valueValidator);
- addSibling(next);
- next->setContentOnly(content, startPos, afterList, deleteList);
- lastControl = next->getClosingControllChar();
- }
- }
- void Framework::JSON::EditableJsonElement::format(
- int indent, bool insertNewLine)
- {
- Text content = this->content;
- content.removeWhitespaceAfter(0);
- int index = 0;
- if (insertNewLine)
- {
- content.insert(0, "\n");
- for (int i = 0; i < indent; i++)
- {
- content.insert(1, " ");
- }
- index = indent * 4 + 1;
- }
- bool keyStart = false;
- bool keyEnd = false;
- bool colonFound = false;
- bool valueStart = false;
- bool valueEnd = false;
- bool escaped = false;
- for (int i = index; i < content.getLength(); i++)
- {
- if ((content[i] == '{' || content[i] == '[' || content[i] == ',')
- && !(keyStart && !keyEnd) && !(valueStart && !valueEnd))
- {
- if (content[i] == ',')
- {
- i -= content.removeWhitespaceBefore(i);
- }
- content.removeWhitespaceAfter(i + 1);
- }
- else if ((content[i] == '}' || content[i] == ']')
- && !(keyStart && !keyEnd) && !(valueStart && !valueEnd))
- {
- content.removeWhitespaceAfter(i + 1);
- if (!parent || parent->children != this)
- {
- i -= content.removeWhitespaceBefore(i);
- content.insert(i, '\n');
- for (int j = 0; j < indent - 1; j++)
- {
- content.insert(i + 1, " ");
- }
- i += 1 + (indent > 0 ? (indent - 1) * 4 : 0);
- }
- else
- {
- i -= content.removeWhitespaceBefore(i);
- }
- }
- else if (content[i] == '"' && !escaped)
- { // format whitespaces arround values and keys
- if (!keyStart)
- {
- keyStart = true;
- }
- else
- {
- if (!keyEnd)
- {
- keyEnd = true;
- content.removeWhitespaceAfter(i + 1);
- }
- else
- {
- if (colonFound)
- {
- if (!valueStart)
- {
- valueStart = true;
- }
- else if (!valueEnd)
- {
- valueEnd = true;
- content.removeWhitespaceAfter(i + 1);
- }
- }
- }
- }
- }
- else if (content[i] == ':' && !(keyStart && !keyEnd)
- && !(valueStart && !valueEnd))
- {
- if (!colonFound && keyEnd)
- {
- colonFound = true;
- content.removeWhitespaceAfter(i + 1);
- content.insert(i + 1, " ");
- }
- }
- else if (content[i] == '\t' && !(keyStart && !keyEnd)
- && !(valueStart && !valueEnd))
- {
- content.remove(i, 1);
- i--;
- }
- else if (content[i] == '\\')
- {
- if ((keyStart && !keyEnd) || (valueStart && !valueEnd))
- {
- escaped = !escaped;
- }
- }
- else
- {
- escaped = false;
- }
- }
- int count = 0;
- Array<EditableJsonElement*> empty;
- const char* tmp = content.getText();
- setContentOnly(&tmp, count, empty, empty);
- if (count < content.getLength())
- {
- throw "Illegal State Exception: tree changed after formatting";
- }
- if (children)
- {
- children->formatRecursive(indent + 1, true);
- }
- }
- void Framework::JSON::EditableJsonElement::formatRecursive(
- int indent, bool insertNewLine)
- {
- format(indent, insertNewLine);
- EditableJsonElement* tmp = siblings;
- while (tmp)
- {
- tmp->format(indent, true);
- tmp = tmp->siblings;
- }
- }
- bool Framework::JSON::EditableJsonElement::isValueValid(
- const char* content, int start, int end)
- {
- Text value(content, start, end - start);
- if (value.isEqual("null") || value.isEqual("true")
- || value.isEqual("false"))
- {
- return true;
- }
- RCArray<Regex::Result>* results
- = valueValidator->match(value, value.getLength());
- bool ok = results->getEntryCount() == 1;
- results->release();
- return ok;
- }
- void Framework::JSON::EditableJsonElement::setContent(
- const char* content, int& startPos, Array<EditableJsonElement*>& afterList)
- {
- if (children)
- {
- afterList.add(children);
- }
- if (siblings)
- {
- afterList.add(siblings);
- }
- EditableJsonElement* p = parent;
- EditableJsonElement* last = this;
- while (p)
- {
- if (p->siblings)
- {
- afterList.add(p->siblings);
- p->siblings = 0;
- }
- p->lastChild = last;
- last = p;
- p = p->parent;
- }
- lastChild = 0;
- children = 0;
- siblings = 0;
- if (parent)
- {
- parent->lastChild = this;
- }
- Array<EditableJsonElement*> deleteList;
- setContentRecursive(&content, startPos, afterList, deleteList);
- if (content[startPos])
- {
- EditableJsonElement* next = new EditableJsonElement(valueValidator);
- if (parent)
- {
- parent->addSibling(next);
- }
- else
- {
- addSibling(next);
- }
- next->setContent(content, startPos, afterList);
- }
- else if (afterList.getEntryCount())
- {
- if (openingControllChar)
- {
- while (afterList.getEntryCount()
- && (!lastChild
- || !((openingControllChar == '['
- && lastChild->closingControllChar == ']')
- || (openingControllChar == '{'
- && lastChild->closingControllChar == '}'))))
- {
- EditableJsonElement* next = afterList.get(0);
- afterList.remove(0);
- EditableJsonElement* end = next;
- while (end)
- {
- if ((end->closingControllChar == ']'
- && this->openingControllChar == '[')
- || (end->closingControllChar == '}'
- && this->openingControllChar == '{'))
- {
- if (end->siblings)
- {
- afterList.add(end->siblings, 0);
- end->siblings = 0;
- }
- break;
- }
- end = end->siblings;
- }
- addChildren(next);
- next->checkSyntax();
- while (next->siblings)
- {
- next = next->siblings;
- next->checkSyntax();
- }
- }
- }
- EditableJsonElement* p = parent;
- EditableJsonElement* c = this;
- while (afterList.getEntryCount())
- {
- if (p)
- {
- if (p->siblings)
- {
- afterList.add(p->siblings);
- p->siblings = 0;
- if (p->parent)
- {
- p->parent->lastChild = p;
- }
- }
- while (
- afterList.getEntryCount()
- && (!p->lastChild
- || !((p->openingControllChar == '['
- && p->lastChild->closingControllChar == ']')
- || (p->openingControllChar == '{'
- && p->lastChild->closingControllChar == '}'))))
- {
- EditableJsonElement* next = afterList.get(0);
- afterList.remove(0);
- EditableJsonElement* end = next;
- while (end)
- {
- if ((end->closingControllChar == ']'
- && p->openingControllChar == '[')
- || (end->closingControllChar == '}'
- && p->openingControllChar == '{'))
- {
- if (end->siblings)
- {
- afterList.add(end->siblings, 0);
- end->siblings = 0;
- }
- break;
- }
- end = end->siblings;
- }
- p->addChildren(next);
- next->checkSyntax();
- while (next->siblings)
- {
- next = next->siblings;
- next->checkSyntax();
- }
- }
- c = p;
- p = p->parent;
- }
- else
- {
- while (afterList.getEntryCount())
- {
- EditableJsonElement* next = afterList.get(0);
- afterList.remove(0);
- c->addSibling(next);
- next->checkSyntax();
- while (next->siblings)
- {
- next = next->siblings;
- next->checkSyntax();
- }
- }
- }
- }
- }
- for (EditableJsonElement* e : deleteList)
- {
- e->release();
- }
- }
- void Framework::JSON::EditableJsonElement::checkSyntax()
- {
- errors.clear();
- EditableJsonElement* before = zBefore(0, false, 0);
- ParserState p(parentStructure,
- before
- ? before->getContent()[before->getContent().getLength() - 1] == ','
- : 0);
- SyntaxError error;
- key = "";
- value = "";
- int pos = 0;
- while (pos < content.getLength())
- {
- const char* current = content.getText() + pos++;
- p.next(current, 0, error);
- if (error.getErrorType() != SyntaxErrorType::OTHER)
- {
- errors.add(error);
- error = SyntaxError();
- }
- }
- if (error.getErrorType() != SyntaxErrorType::OTHER)
- {
- errors.add(error);
- error = SyntaxError();
- }
- if (p.keyStart >= 0 && p.keyEnd >= p.keyStart
- && parentStructure == JsonStructure::OBJECT)
- {
- key += Text(content, p.keyStart, p.keyEnd - p.keyStart);
- }
- if (p.valueStart >= 0 && p.valueEnd >= p.valueStart)
- {
- value += Text(content, p.valueStart, p.valueEnd - p.valueStart);
- }
- if (p.valueValidationNeeded)
- {
- if (!isValueValid(value, 0, value.getLength()))
- {
- errors.add(SyntaxError(
- p.valueStart, p.valueEnd, SyntaxErrorType::INVALID_VALUE));
- }
- }
- openingControllChar = p.openingControllChar;
- closingControllChar = p.closingControllChar;
- valueStart = p.valueStart;
- keyStart = p.keyStart;
- }
- void EditableJsonElement::setContent(const char* content)
- {
- Array<EditableJsonElement*> afterList;
- int p = 0;
- setContent(content, p, afterList);
- }
- void EditableJsonElement::addChildren(EditableJsonElement* content)
- {
- JsonStructure currentStructure
- = openingControllChar == '['
- ? JsonStructure::ARRAY
- : (openingControllChar == '{' ? JsonStructure::OBJECT
- : JsonStructure::VALUE);
- if (this->children)
- {
- this->lastChild->siblings = content;
- }
- else
- {
- this->children = content;
- this->lastChild = content;
- }
- if (content->parent != this)
- {
- content->parent = this;
- content->parentStructure = currentStructure;
- for (; lastChild->siblings; lastChild = lastChild->siblings)
- {
- lastChild->siblings->parent = this;
- lastChild->siblings->parentStructure = currentStructure;
- }
- }
- while (lastChild->siblings)
- {
- lastChild = lastChild->siblings;
- }
- }
- void Framework::JSON::EditableJsonElement::setNextSibling(
- EditableJsonElement* content)
- {
- this->siblings = content;
- EditableJsonElement* current = this;
- if (content->parent != parent)
- {
- for (; current->siblings; current = current->siblings)
- {
- current->siblings->parent = parent;
- current->siblings->parentStructure = parentStructure;
- }
- }
- if (parent)
- {
- parent->lastChild = current;
- while (parent->lastChild->siblings)
- {
- parent->lastChild = parent->lastChild->siblings;
- }
- }
- }
- void EditableJsonElement::addSibling(EditableJsonElement* content)
- {
- EditableJsonElement* current = parent ? parent->lastChild : this;
- while (current->siblings)
- {
- current = current->siblings;
- }
- current->siblings = content;
- if (content->parent != parent)
- {
- for (; current->siblings; current = current->siblings)
- {
- current->siblings->parent = parent;
- current->siblings->parentStructure = parentStructure;
- }
- }
- if (parent)
- {
- parent->lastChild = current;
- while (parent->lastChild->siblings)
- {
- parent->lastChild = parent->lastChild->siblings;
- }
- }
- }
- void Framework::JSON::EditableJsonElement::format()
- {
- int indent = getIndent();
- formatRecursive(indent, false);
- }
- const Text& Framework::JSON::EditableJsonElement::getContent()
- {
- return content;
- }
- Text Framework::JSON::EditableJsonElement::getRecursiveContent()
- {
- Text result
- = content + (children ? children->getRecursiveContent() : Text(""));
- EditableJsonElement* s = siblings;
- while (s)
- {
- result += s->content
- + (s->children ? s->children->getRecursiveContent() : Text(""));
- s = s->siblings;
- }
- return result;
- }
- int Framework::JSON::EditableJsonElement::lineCount()
- {
- return newLineCount;
- }
- bool Framework::JSON::EditableJsonElement::lineCount(bool includeChildren,
- bool includeSiblings,
- EditableJsonElement* stop,
- int& count)
- {
- count += newLineCount;
- if (this == stop)
- {
- return false;
- }
- if (includeChildren && children)
- {
- if (!children->lineCount(true, true, stop, count))
- {
- return false;
- }
- }
- if (includeSiblings && siblings)
- {
- return siblings->lineCount(true, true, stop, count);
- };
- return true;
- }
- bool Framework::JSON::EditableJsonElement::isHidden()
- {
- return hidden;
- }
- void Framework::JSON::EditableJsonElement::setHidden(bool hidden)
- {
- this->hidden = hidden;
- }
- EditableJsonElement* Framework::JSON::EditableJsonElement::zParent()
- {
- return parent;
- }
- EditableJsonElement* Framework::JSON::EditableJsonElement::zMextSibling()
- {
- return siblings;
- }
- EditableJsonElement* Framework::JSON::EditableJsonElement::zFirstChildren()
- {
- return children;
- }
- EditableJsonElement* Framework::JSON::EditableJsonElement::zLastChildren()
- {
- return lastChild;
- }
- char Framework::JSON::EditableJsonElement::getOpeningControllChar()
- {
- return openingControllChar;
- }
- char Framework::JSON::EditableJsonElement::getClosingControllChar()
- {
- return closingControllChar;
- }
- Text& Framework::JSON::EditableJsonElement::getKey()
- {
- return key;
- }
- Text& Framework::JSON::EditableJsonElement::getValue()
- {
- return value;
- }
- void Framework::JSON::EditableJsonElement::disconnect()
- {
- children = 0;
- lastChild = 0;
- siblings = 0;
- parent = 0;
- }
- void Framework::JSON::EditableJsonElement::removeChild(
- EditableJsonElement* zElement)
- {
- // TODO: needed?
- if (children == zElement)
- {
- children = 0;
- lastChild = 0;
- }
- else
- {
- EditableJsonElement* current = children;
- while (current)
- {
- if (current->siblings == zElement)
- {
- current->siblings = 0;
- if (current->parent)
- {
- current->parent->lastChild = current;
- }
- break;
- }
- current = current->siblings;
- }
- }
- }
- void Framework::JSON::EditableJsonElement::getWordBounds(
- int pos, int* left, int* right)
- {
- bool escaped = false;
- int lastStartStr = -1;
- int lastBlank = 0;
- bool found = false;
- int len = content.getLength();
- for (int i = 0; i < len; i++)
- {
- if ((content[i] == ' ' || content[i] == ',' || content[i] == '\n')
- && lastStartStr == -1)
- {
- if (i >= pos)
- {
- if (left)
- {
- *left = lastBlank;
- }
- if (right)
- {
- *right = i;
- }
- found = true;
- break;
- }
- lastBlank = i + 1;
- }
- else if (content[i] == '"')
- {
- if (lastStartStr == -1)
- {
- lastStartStr = i + 1;
- if (i >= pos)
- {
- if (left)
- {
- *left = i;
- }
- if (right)
- {
- *right = i + 1;
- }
- found = true;
- break;
- }
- }
- else if (!escaped)
- {
- if (i >= pos)
- {
- if (left)
- {
- *left = lastStartStr;
- }
- if (right)
- {
- *right = i;
- }
- found = true;
- break;
- }
- lastStartStr = -1;
- }
- }
- else if (content[i] == '\\' && lastStartStr >= 0)
- {
- escaped = !escaped;
- }
- else
- {
- escaped = false;
- }
- }
- if (!found && lastBlank >= 0)
- {
- if (left)
- {
- *left = lastBlank;
- }
- if (right)
- {
- *right = len;
- }
- }
- }
- bool Framework::JSON::EditableJsonElement::hasError(int column) const
- {
- for (const SyntaxError& error : errors)
- {
- if (error.getStart() <= column && error.getEnd() >= column)
- {
- return true;
- }
- }
- return false;
- }
- SyntaxError Framework::JSON::EditableJsonElement::getError(int column) const
- {
- for (const SyntaxError& error : errors)
- {
- if (error.getStart() <= column && error.getEnd() >= column)
- {
- return error;
- }
- }
- return SyntaxError();
- }
- bool Framework::JSON::EditableJsonElement::hasError() const
- {
- return errors.getEntryCount() > 0;
- }
- void Framework::JSON::EditableJsonElement::makeVisible()
- {
- EditableJsonElement* current = parent;
- while (current)
- {
- current->setHidden(false);
- current = current->zParent();
- }
- }
- bool Framework::JSON::EditableJsonElement::isVisible() const
- {
- EditableJsonElement* current = parent;
- while (current)
- {
- if (current->isHidden())
- {
- return false;
- }
- current = current->zParent();
- }
- return true;
- }
- int Framework::JSON::EditableJsonElement::getIndent() const
- {
- int indent = 0;
- EditableJsonElement* tmp = parent;
- while (tmp)
- {
- indent++;
- tmp = tmp->parent;
- }
- return indent;
- }
- int Framework::JSON::EditableJsonElement::getColor(int index)
- {
- int color = 0xFFA0A0A0;
- if (hasError(index))
- {
- color = 0xFFFF3030;
- }
- else if (keyStart >= 0 && index >= keyStart - 1
- && index < keyStart + key.getLength() + 1)
- {
- color = 0xFF7070C0;
- }
- else if (valueStart >= 0 && index >= valueStart
- && index < valueStart + value.getLength())
- {
- if (value[0] == '"')
- {
- color = 0xFF70C070;
- }
- else if (value.isEqual("null"))
- {
- color = 0xFFC0A070;
- }
- else if (value.isEqual("true") || value.isEqual("false"))
- {
- color = 0xFFC070C0;
- }
- else
- {
- color = 0xFF70C0C0;
- }
- }
- return color;
- }
- void Framework::JSON::EditableJsonElement::removeUntil(
- int startIndex, EditableJsonElement* end, int endIndex)
- {
- Text* result = content.getTeilText(0, startIndex);
- if (end == this)
- {
- Text* tmp = content.getTeilText(endIndex);
- result->append(*tmp);
- tmp->release();
- setContent(*result);
- result->release();
- return;
- }
- else
- {
- Array<EditableJsonElement*> toDelete;
- Stack<EditableJsonElement*> stack;
- if (siblings)
- {
- stack.push(siblings);
- }
- if (children)
- {
- stack.push(children);
- }
- if (!stack.getSize())
- {
- EditableJsonElement* p = parent;
- while (p)
- {
- if (p->siblings)
- {
- stack.push(p->siblings);
- break;
- }
- p = p->parent;
- }
- }
- if (stack.getSize())
- {
- EditableJsonElement* next = stack.pop();
- while (true)
- {
- if (next->siblings)
- {
- stack.push(siblings);
- }
- if (next->children)
- {
- stack.push(children);
- }
- if (!stack.getSize() && next != end)
- {
- EditableJsonElement* p = next->parent;
- while (p)
- {
- if (p->siblings)
- {
- stack.push(p->siblings);
- break;
- }
- p = p->parent;
- }
- }
- if (next->parent)
- {
- next->parent->removeChild(next);
- }
- else
- {
- EditableJsonElement* p = this;
- while (p->parent)
- {
- p = p->parent;
- }
- while (p->siblings != next)
- {
- p = p->siblings;
- }
- p->siblings = 0;
- }
- toDelete.add(next);
- if (!stack.getSize())
- {
- next = 0;
- break;
- }
- if (next == end)
- {
- break;
- }
- next = stack.pop();
- }
- if (next == end)
- {
- Text* tmp = next->content.getTeilText(endIndex);
- result->append(*tmp);
- }
- for (EditableJsonElement* del : toDelete)
- {
- del->disconnect();
- del->release();
- }
- Array<EditableJsonElement*> afterList;
- while (stack.getSize())
- {
- afterList.add(stack.pop());
- }
- int p = 0;
- setContent(*result, p, afterList);
- }
- else
- {
- setContent(*result);
- result->release();
- return;
- }
- }
- }
- EditableJsonElement* Framework::JSON::EditableJsonElement::zBefore(
- EditableJsonElement* zRoot, bool onlyVisible, int* lineCount)
- {
- if (this == zRoot)
- {
- return 0;
- }
- EditableJsonElement* parent = this->parent;
- EditableJsonElement* current = parent ? parent->children : zRoot;
- EditableJsonElement* last = parent;
- while (current)
- {
- if (current == this)
- {
- break;
- }
- last = current;
- current = current->siblings;
- }
- if (last && last->children != this && (!last->hidden || !onlyVisible))
- {
- current = last->lastChild;
- while (current)
- {
- last = current;
- if (current->children)
- {
- if ((!current->hidden || !onlyVisible))
- {
- current = current->lastChild;
- }
- else if (*lineCount)
- {
- EditableJsonElement* e = current->children;
- while (e)
- {
- int lc = 0;
- e->lineCount(true, false, 0, lc);
- *lineCount -= lc;
- e = e->siblings;
- }
- break;
- }
- }
- else
- {
- break;
- }
- }
- }
- else if (last && last->hidden && onlyVisible && lineCount)
- {
- EditableJsonElement* e = last->children;
- while (e)
- {
- int lc = 0;
- e->lineCount(true, false, 0, lc);
- *lineCount -= lc;
- e = e->siblings;
- }
- }
- return last;
- }
- EditableJsonElement* Framework::JSON::EditableJsonElement::zAfter(
- bool onlyVisible, int* lineCount)
- {
- EditableJsonElement* zElement = this;
- if (zElement->children)
- {
- if (!zElement->hidden || !onlyVisible)
- {
- return zElement->children;
- }
- else if (lineCount)
- {
- EditableJsonElement* e = zElement->children;
- while (e)
- {
- int lc = 0;
- e->lineCount(true, false, 0, lc);
- *lineCount += lc;
- e = e->siblings;
- }
- }
- }
- if (zElement->siblings)
- {
- return zElement->siblings;
- }
- while (zElement->parent)
- {
- zElement = zElement->parent;
- if (zElement->siblings)
- {
- return zElement->siblings;
- }
- }
- return 0;
- }
- JsonEditor::JsonEditor(UIInit uiInit)
- : DrawableBackground(),
- uiInit(uiInit)
- {
- valueValidator = Regex::parse("^-?[0-9]+(\\.[0-9]+)?([eE][+-]?[0-9]+)?$");
- validator = 0;
- content = 0;
- renderStart = {0, 0};
- renderStartLine = 0;
- lineCount = 0;
- cursorPos.x = -1;
- cursorPos.y = -1;
- textCursor = {0, 0};
- selectionStart = {0, 0};
- renderStartOffset = 0;
- selectionEnd = {0, 0};
- textRenderer = new TextRenderer();
- textRenderer->setFontSize(12);
- textRenderer->setLineSpacing(2);
- textRenderer->setCharSpacing(1);
- pressed = 0;
- time = 0;
- drag = 0;
- drawCursor = 0;
- dragSart = {-1, -1};
- pressedPos = {-1, -1};
- dragStartPos = {0, -1};
- timeSicePress = 0.0;
- lastClickCursorPos = {0, 0};
- tps = 0;
- renderings = 0;
- renderedLines = 0;
- renderStopLine = 0;
- errorDescription = uiInit.createTextField(uiInit.initParam);
- errorDescription->setStyle(TextField::Style::Text | TextField::Style::Center
- | TextField::Style::Border
- | TextField::Style::Background
- | TextField::Style::BAlpha);
- errorDescription->removeStyle(TextField::Style::Visible);
- errorDescription->setFontColor(0xFFFFFFFF);
- errorDescription->setBorderColor(0xFFA0A0A0);
- errorDescription->setBackgroundColor(0xA0000000);
- hasSyntaxError = false;
- }
- JsonEditor::~JsonEditor()
- {
- if (content) content->release();
- if (validator) validator->release();
- textRenderer->release();
- errorDescription->release();
- }
- void Framework::JSON::JsonEditor::doMouseEvent(MouseEvent& me, bool userRet)
- {
- LOCK({&cs});
- rend |= cursorPos.x != me.mx || cursorPos.y != me.my;
- cursorPos.x = me.mx;
- cursorPos.y = me.my;
- if (me.id == ME_RLeft)
- {
- pressedPos = cursorPos;
- if (timeSicePress < 0.5)
- {
- if (lastClickCursorPos.line == textCursor.line
- && lastClickCursorPos.column == textCursor.column
- && lastClickCursorPos.line && lastClickCursorPos.column > 0)
- {
- EditableJsonElement* current = textCursor.line;
- int start = 0;
- int end = 0;
- current->getWordBounds(textCursor.column, &start, &end);
- selectionStart = {current, start};
- selectionEnd = {current, end};
- unifyPosition(selectionEnd);
- textCursor = selectionEnd;
- }
- }
- lastClickCursorPos = textCursor;
- pressed = true;
- drag = false;
- rend = 1;
- time = 0;
- timeSicePress = 0.0;
- }
- if (me.id == ME_PLeft || (me.id == ME_Enter && getMouseState(M_Left)))
- {
- if (me.mx >= getInnerWidth() - 15)
- {
- int line = (int)(me.my / ((double)getInnerHeight() / lineCount));
- if (line >= lineCount)
- {
- line = lineCount - 1;
- }
- scrollToLine(line + 1, Center);
- }
- if (!drag)
- {
- drag = true;
- textCursor = getScreenPosition(cursorPos.x, cursorPos.y);
- selectionStart = textCursor;
- selectionEnd = textCursor;
- dragSart = cursorPos;
- dragStartPos = textCursor;
- rend = 1;
- time = 0;
- }
- }
- if (me.id == ME_Move)
- {
- if (drag)
- {
- if (dragSart.x >= getInnerWidth() - 15)
- {
- int line
- = (int)(me.my / ((double)getInnerHeight() / lineCount));
- if (line >= lineCount)
- {
- line = lineCount - 1;
- }
- scrollToLine(line + 1, Center);
- }
- else
- {
- EditorPosition pos
- = getScreenPosition(cursorPos.x, cursorPos.y);
- if (pos.line == dragStartPos.line)
- {
- if (pos.column < dragStartPos.column)
- {
- selectionStart = pos;
- selectionEnd = dragStartPos;
- }
- else if (pos.column > dragStartPos.column)
- {
- selectionStart = dragStartPos;
- selectionEnd = pos;
- }
- }
- else
- {
- if (cursorPos.y < dragSart.y)
- {
- selectionStart = pos;
- selectionEnd = dragStartPos;
- }
- else if (cursorPos.y > dragSart.y)
- {
- selectionStart = dragStartPos;
- selectionEnd = pos;
- }
- }
- textCursor = pos;
- }
- }
- }
- if (me.id == ME_UScroll)
- {
- if (renderStart.column > 0)
- {
- const char* content = renderStart.line->getContent();
- int index = renderStart.column - 2;
- while (index > 0 && content[index] != '\n')
- {
- index--;
- }
- if (content[index] == '\n')
- {
- renderStart.column = index + 1;
- rend = 1;
- renderStartLine--;
- unifyPosition(renderStart);
- return;
- }
- }
- while (true)
- {
- EditableJsonElement* next
- = renderStart.line->zBefore(content, true, &renderStartLine);
- if (next)
- {
- renderStart.line = next;
- const char* content = next->getContent();
- int index = next->getContent().getLength() - 1;
- while (index > 0 && content[index] != '\n')
- {
- index--;
- }
- if (content[index] == '\n')
- {
- renderStart.column = index + 1;
- rend = 1;
- renderStartLine--;
- unifyPosition(renderStart);
- return;
- }
- }
- else
- {
- renderStart.column = 0;
- rend = 1;
- renderStartLine = 1;
- return;
- }
- }
- }
- if (me.id == ME_DScroll)
- {
- const char* content = renderStart.line->getContent();
- int length = renderStart.line->getContent().getLength();
- int index = renderStart.column;
- while (index < length && content[index] != '\n')
- {
- index++;
- }
- if (content[index] == '\n')
- {
- renderStart.column = index + 1;
- rend = 1;
- renderStartLine++;
- unifyPosition(renderStart);
- return;
- }
- while (true)
- {
- EditableJsonElement* next
- = renderStart.line->zAfter(true, &renderStartLine);
- if (next)
- {
- renderStart.line = next;
- const char* content = next->getContent();
- int length = next->getContent().getLength();
- int index = 0;
- while (index < length && content[index] != '\n')
- {
- index++;
- }
- if (content[index] == '\n')
- {
- renderStart.column = index + 1;
- rend = 1;
- renderStartLine++;
- unifyPosition(renderStart);
- return;
- }
- }
- else
- {
- return;
- }
- }
- }
- }
- EditorPosition Framework::JSON::JsonEditor::getScreenPosition(
- int localX, int localY)
- {
- if (!renderStart.line) return {0, 0};
- int y = 0;
- int lineNumberWidth = 0;
- for (int i = lineCount; i > 0; i /= 10)
- {
- lineNumberWidth++;
- }
- lineNumberWidth = lineNumberWidth * textRenderer->getMaxCharWidth()
- + textRenderer->getCharSpacing() * (lineNumberWidth - 1);
- int x = lineNumberWidth + 26;
- EditableJsonElement* current = renderStart.line;
- int index = renderStart.column;
- EditableJsonElement* last = current;
- while (y < gr.y && current)
- {
- int length = current->getContent().getLength();
- const char* content = current->getContent();
- for (int i = index; i < length; i++)
- {
- if (y >= localY - textRenderer->getRowHeight()
- - textRenderer->getLineSpacing()
- && x >= localX - textRenderer->getCharWidth(content[i]) / 2
- - textRenderer->getCharSpacing())
- {
- EditorPosition result = {current, i};
- unifyPosition(result);
- return result;
- }
- if (content[i] == '\n')
- {
- if (y >= localY - textRenderer->getRowHeight()
- - textRenderer->getLineSpacing())
- {
- EditorPosition result = {current, i};
- unifyPosition(result);
- return result;
- }
- y += textRenderer->getRowHeight()
- + textRenderer->getLineSpacing();
- x = lineNumberWidth + 26;
- }
- else
- {
- x += textRenderer->getCharWidth(content[i])
- + textRenderer->getCharSpacing();
- }
- }
- last = current;
- current = current->zAfter(true, 0);
- index = 0;
- }
- return {last, last->getContent().getLength()};
- }
- void Framework::JSON::JsonEditor::deleteSelection()
- {
- if (selectionStart.line && selectionEnd.line)
- {
- selectionStart.line->removeUntil(
- selectionStart.column, selectionEnd.line, selectionEnd.column);
- selectionEnd = selectionStart;
- textCursor = selectionStart;
- fixTree(selectionStart.line);
- if (dragStartPos.line)
- {
- dragStartPos = selectionStart;
- }
- if (lastClickCursorPos.line)
- {
- lastClickCursorPos = selectionStart;
- }
- }
- }
- void Framework::JSON::JsonEditor::unifyPosition(EditorPosition& pos)
- {
- while (pos.line && pos.column >= pos.line->getContent().getLength())
- {
- if (pos.line->zFirstChildren() && pos.line->isVisible())
- {
- pos = {pos.line->zFirstChildren(),
- pos.column - pos.line->getContent().getLength()};
- }
- else if (pos.line->zMextSibling())
- {
- pos = {pos.line->zMextSibling(),
- pos.column - pos.line->getContent().getLength()};
- }
- else
- {
- EditableJsonElement* p = pos.line->zParent();
- while (p)
- {
- if (p->zMextSibling())
- {
- pos = {p->zMextSibling(), 0};
- break;
- }
- p = p->zParent();
- }
- if (!p)
- {
- pos.column = pos.line->getContent().getLength();
- break;
- }
- }
- }
- }
- void Framework::JSON::JsonEditor::fixTree(EditableJsonElement* zElement)
- {
- EditableJsonElement* before = zElement->zBefore(content, false, 0);
- int beforeLength = before ? before->getContent().getLength() : 0;
- if (zElement->hasError() && before)
- {
- Text content = before->getContent();
- before->setContent(content);
- if (before->getContent().getLength() != beforeLength)
- {
- before->makeVisible();
- }
- }
- if (textCursor.line == zElement)
- {
- textCursor.column += beforeLength;
- textCursor.line = before ? before : zElement;
- unifyPosition(textCursor);
- }
- if (renderStart.line == zElement)
- {
- renderStart.column += beforeLength;
- renderStart.line = before ? before : zElement;
- unifyPosition(renderStart);
- }
- }
- void Framework::JSON::JsonEditor::setFont(Font* font)
- {
- textRenderer->setFontZ(font);
- }
- void Framework::JSON::JsonEditor::setFontSize(int size)
- {
- textRenderer->setFontSize(size);
- textRenderer->setLineSpacing(size / 6);
- textRenderer->setCharSpacing(size / 8);
- }
- void JsonEditor::setContent(Text content)
- {
- if (this->content)
- {
- this->content->release();
- this->content = 0;
- this->renderStart = {0, 0};
- }
- this->content = new EditableJsonElement(
- dynamic_cast<Regex::Automata<char>*>(valueValidator->getThis()));
- content.replace("\r", "");
- content.replace("\t", " ");
- this->content->setContent(content);
- textCursor = {this->content, 0};
- selectionStart = {this->content, 0};
- selectionEnd = {this->content, 0};
- format();
- }
- void Framework::JSON::JsonEditor::setContent(JSONValue* content)
- {
- setContent(content->toString());
- content->release();
- }
- void Framework::JSON::JsonEditor::format()
- {
- if (content)
- {
- content->format();
- lineCount = 0;
- content->lineCount(true, true, 0, lineCount);
- }
- }
- void Framework::JSON::JsonEditor::setValidator(
- Validator::DataValidator* validator)
- {
- if (this->validator) this->validator->release();
- this->validator = validator;
- // if (content) validate(); TODO: validate attributes
- }
- void Framework::JSON::JsonEditor::doKeyboardEvent(KeyboardEvent& te)
- {
- LOCK({&cs});
- if (!textCursor.line)
- {
- return;
- }
- bool shift = getKeyState(T_Shift);
- bool strg = getKeyState(T_Strg);
- if (te.id == TE_Press)
- {
- switch (te.virtualKey)
- {
- case T_Tab:
- {
- Text illegalStarts = "[]{},\": ";
- if (shift)
- {
- bool lastStr
- = textCursor.line->getContent().getLength()
- > textCursor.column
- ? textCursor.line->getContent()[textCursor.column]
- == '"'
- : false;
- int nextColumn = textCursor.column - 1;
- EditableJsonElement* nextLine = textCursor.line;
- while (nextLine)
- {
- if (nextColumn < 0)
- {
- nextLine = nextLine->zBefore(content, true, 0);
- if (!nextLine)
- {
- return;
- }
- nextColumn = nextLine->getContent().getLength();
- }
- int start = 0;
- int end = 0;
- nextLine->getWordBounds(nextColumn, &start, &end);
- if ((start != end
- && !illegalStarts.has(
- nextLine->getContent()[start]))
- || (lastStr
- && nextLine->getContent()[nextColumn] == '"'))
- {
- if (lastStr
- && nextLine->getContent()[nextColumn] == '"')
- {
- start = end;
- }
- if (selectionStart.column != start
- || selectionStart.line != nextLine
- || selectionEnd.column != end
- || selectionEnd.line != nextLine)
- {
- selectionStart = {nextLine, start};
- selectionEnd = {nextLine, end};
- unifyPosition(selectionEnd);
- textCursor = selectionEnd;
- scrollToLine(textCursor, Top);
- te.processed = true;
- time = 0;
- rend = 1;
- return;
- }
- }
- lastStr = nextLine->getContent()[nextColumn] == '"';
- nextColumn--;
- }
- }
- else
- {
- bool lastStr
- = textCursor.line->getContent().getLength()
- > textCursor.column
- ? textCursor.line->getContent()[textCursor.column]
- == '"'
- : false;
- int nextColumn = textCursor.column + 1;
- EditableJsonElement* nextLine = textCursor.line;
- while (nextLine)
- {
- if (nextColumn > nextLine->getContent().getLength())
- {
- nextLine = nextLine->zAfter(true, 0);
- if (!nextLine)
- {
- return;
- }
- nextColumn = 0;
- }
- int start = 0;
- int end = 0;
- nextLine->getWordBounds(nextColumn, &start, &end);
- if (((start != end
- && !illegalStarts.has(
- nextLine->getContent()[start]))
- || (lastStr
- && nextLine->getContent()[nextColumn]
- == '"'))
- && (selectionStart.column != start
- || selectionStart.line != nextLine
- || selectionEnd.column != end
- || selectionEnd.line != nextLine))
- {
- selectionStart = {nextLine, start};
- selectionEnd = {nextLine, end};
- unifyPosition(selectionEnd);
- textCursor = selectionEnd;
- scrollToLine(textCursor, Bottom);
- te.processed = true;
- time = 0;
- rend = 1;
- return;
- }
- lastStr = nextLine->getContent()[nextColumn] == '"';
- nextColumn++;
- }
- }
- }
- return;
- case T_Entf:
- if (selectionStart.line == selectionEnd.line
- && selectionStart.column == selectionEnd.column)
- {
- if (textCursor.column
- < textCursor.line->getContent().getLength())
- {
- Text content = textCursor.line->getContent();
- content.remove(textCursor.column, textCursor.column + 1);
- textCursor.line->setContent(content);
- fixTree(textCursor.line);
- }
- }
- else
- {
- deleteSelection();
- }
- break;
- case T_BackSpace:
- if (selectionStart.line == selectionEnd.line
- && selectionStart.column == selectionEnd.column)
- {
- if (textCursor.column > 0)
- {
- Text content = textCursor.line->getContent();
- content.remove(textCursor.column - 1, textCursor.column);
- textCursor.line->setContent(content);
- textCursor.column--;
- fixTree(textCursor.line);
- }
- else
- {
- EditableJsonElement* before
- = textCursor.line->zBefore(content, false, 0);
- if (before)
- {
- before->makeVisible();
- Text content = before->getContent();
- content.remove(
- content.getLength() - 1, content.getLength());
- before->setContent(content);
- textCursor = {before, content.getLength()};
- fixTree(before);
- scrollToLine(textCursor, Top);
- }
- }
- }
- else
- {
- deleteSelection();
- }
- break;
- case T_Enter:
- {
- deleteSelection();
- Text content = textCursor.line->getContent();
- content.insert(textCursor.column, "\n");
- textCursor.column += 1;
- textCursor.line->setContent(content);
- fixTree(textCursor.line);
- scrollToLine(textCursor, Bottom);
- }
- break;
- case T_Links:
- {
- int nextColumn = textCursor.column - 1;
- EditableJsonElement* nextLine = textCursor.line;
- while (nextColumn < 0)
- {
- nextLine = textCursor.line->zBefore(content, true, 0);
- if (!nextLine)
- {
- return;
- }
- nextColumn = nextLine->getContent().getLength() - 1;
- }
- if (strg)
- {
- int start = 0;
- nextLine->getWordBounds(nextColumn, &start, 0);
- nextColumn = start;
- }
- if (shift)
- {
- if (textCursor.line == selectionStart.line
- && textCursor.column == selectionStart.column)
- {
- selectionStart = {nextLine, nextColumn};
- unifyPosition(selectionStart);
- textCursor = selectionStart;
- }
- else
- {
- selectionEnd = {nextLine, nextColumn};
- unifyPosition(selectionEnd);
- textCursor = selectionEnd;
- }
- }
- else
- {
- textCursor = {nextLine, nextColumn};
- unifyPosition(textCursor);
- selectionStart = textCursor;
- selectionEnd = textCursor;
- }
- scrollToLine(textCursor, Top);
- te.processed = true;
- time = 0;
- rend = 1;
- return;
- }
- case T_Oben:
- {
- EditableJsonElement* current = textCursor.line;
- int count = 0;
- bool found = 0;
- int index = textCursor.column - 1;
- const char* content = current->getContent();
- while (current)
- {
- while (index < 0)
- {
- current = current->zBefore(this->content, true, 0);
- if (!current)
- {
- break;
- }
- content = current->getContent();
- index = current->getContent().getLength() - 1;
- }
- if (!current)
- {
- break;
- }
- if (content[index] == '\n')
- {
- if (found)
- {
- break;
- }
- found = 1;
- }
- if (!found)
- {
- count++;
- }
- index--;
- }
- if (!current)
- {
- break;
- }
- index++;
- while (current && count > 0)
- {
- while (index >= current->getContent().getLength())
- {
- current = current->zAfter(true, 0);
- if (!current)
- {
- break;
- }
- content = current->getContent();
- index = 0;
- }
- if (!current)
- {
- break;
- }
- if (content[index] == '\n')
- {
- break;
- }
- count--;
- index++;
- }
- if (!current)
- {
- break;
- }
- if (shift)
- {
- if (textCursor.line == selectionStart.line
- && textCursor.column == selectionStart.column)
- {
- selectionStart = {current, index};
- unifyPosition(selectionStart);
- textCursor = selectionStart;
- }
- else
- {
- selectionEnd = {current, index};
- unifyPosition(selectionEnd);
- textCursor = selectionEnd;
- }
- }
- else
- {
- textCursor = {current, index};
- unifyPosition(textCursor);
- selectionStart = textCursor;
- selectionEnd = textCursor;
- }
- scrollToLine(textCursor, Top);
- te.processed = true;
- time = 0;
- rend = 1;
- return;
- }
- case T_Rechts:
- {
- int nextColumn = textCursor.column + 1;
- EditableJsonElement* nextLine = textCursor.line;
- if (nextColumn > nextLine->getContent().getLength())
- {
- nextLine = textCursor.line->zAfter(true, 0);
- if (!nextLine)
- {
- return;
- }
- nextColumn = 0;
- }
- if (strg)
- {
- int end = 0;
- nextLine->getWordBounds(nextColumn, 0, &end);
- nextColumn = end;
- }
- if (shift)
- {
- if (textCursor.line == selectionEnd.line
- && textCursor.column == selectionEnd.column)
- {
- selectionEnd = {nextLine, nextColumn};
- unifyPosition(selectionEnd);
- textCursor = selectionEnd;
- }
- else
- {
- selectionStart = {nextLine, nextColumn};
- unifyPosition(selectionStart);
- textCursor = selectionStart;
- }
- }
- else
- {
- textCursor = {nextLine, nextColumn};
- unifyPosition(textCursor);
- selectionStart = textCursor;
- selectionEnd = textCursor;
- }
- scrollToLine(textCursor, Bottom);
- te.processed = true;
- time = 0;
- rend = 1;
- return;
- }
- case T_Unten:
- {
- EditableJsonElement* current = textCursor.line;
- int count = 0;
- int index = textCursor.column - 1;
- const char* content = current->getContent();
- while (current)
- {
- while (index < 0)
- {
- current = current->zBefore(this->content, true, 0);
- if (!current)
- {
- break;
- }
- content = current->getContent();
- index = current->getContent().getLength() - 1;
- }
- if (!current)
- {
- break;
- }
- if (content[index] == '\n')
- {
- break;
- }
- count++;
- index--;
- }
- bool found = 0;
- current = textCursor.line;
- index = textCursor.column;
- content = current->getContent();
- while (current && (count > 0 || !found))
- {
- while (index >= current->getContent().getLength())
- {
- current = current->zAfter(true, 0);
- if (!current)
- {
- break;
- }
- content = current->getContent();
- index = 0;
- }
- if (found)
- {
- count--;
- }
- if (content[index] == '\n')
- {
- if (found)
- {
- break;
- }
- found = 1;
- }
- index++;
- }
- if (shift)
- {
- if (textCursor.line == selectionEnd.line
- && textCursor.column == selectionEnd.column)
- {
- selectionEnd = {current, index};
- unifyPosition(selectionEnd);
- textCursor = selectionEnd;
- }
- else
- {
- selectionStart = {current, index};
- unifyPosition(selectionStart);
- textCursor = selectionStart;
- }
- }
- else
- {
- textCursor = {current, index};
- unifyPosition(textCursor);
- selectionStart = textCursor;
- selectionEnd = textCursor;
- }
- scrollToLine(textCursor, Bottom);
- te.processed = true;
- time = 0;
- rend = 1;
- return;
- }
- default:
- if (strg)
- {
- if (te.virtualKey == 'c' || te.virtualKey == 'C')
- {
- Text content = getSelectedContent();
- TextKopieren(content);
- return;
- }
- else if (te.virtualKey == 'x' || te.virtualKey == 'X')
- {
- Text content = getSelectedContent();
- TextKopieren(content);
- deleteSelection();
- scrollToLine(textCursor, Top);
- return;
- }
- else if (te.virtualKey == 'v' || te.virtualKey == 'V')
- {
- deleteSelection();
- EditableJsonElement* changed = textCursor.line;
- Text content = changed->getContent();
- const char* inserted = TextInsert();
- content.insert(textCursor.column, inserted);
- textCursor.column += textLength(inserted);
- unifyPosition(textCursor);
- scrollToLine(textCursor, Bottom);
- break;
- }
- else if (te.virtualKey == 'a' || te.virtualKey == 'A')
- {
- selectionStart = {content, 0};
- EditableJsonElement* element = content;
- while (element->zMextSibling())
- {
- element = element->zMextSibling();
- }
- while (element->zLastChildren())
- {
- element = element->zLastChildren();
- }
- selectionEnd = {element, element->getContent().getLength()};
- textCursor = selectionEnd;
- te.processed = true;
- time = 0;
- rend = 1;
- scrollToLine(textCursor, Bottom);
- return;
- }
- else if (te.virtualKey == 'f' || te.virtualKey == 'F')
- {
- format();
- return;
- }
- }
- if (isWritable(te.key[0]))
- {
- deleteSelection();
- Text content = textCursor.line->getContent();
- content.insert(textCursor.column, te.key);
- textCursor.column += textLength(te.key);
- textCursor.line->setContent(content);
- fixTree(textCursor.line);
- }
- else
- {
- return;
- }
- }
- selectionStart = textCursor;
- selectionEnd = textCursor;
- te.processed = true;
- lineCount = 0;
- content->lineCount(true, true, 0, lineCount);
- }
- time = 0;
- rend = 1;
- }
- bool Framework::JSON::JsonEditor::tick(double tickVal)
- {
- LOCK({&cs});
- time += tickVal;
- timeSicePress += tickVal;
- if (time > 1.0)
- {
- tps = renderings / time;
- time = 0.0;
- renderings = 0;
- }
- rend |= drawCursor != (time < 0.5);
- drawCursor = time < 0.5;
- errorDescription->tick(tickVal);
- return DrawableBackground::tick(tickVal);
- }
- void Framework::JSON::JsonEditor::render(Image& rObj)
- {
- LOCK({&cs});
- renderings++;
- renderedLines = 0;
- errorDescription->removeStyle(TextField::Style::Visible);
- DrawableBackground::render(rObj);
- if (textRenderer->zFont() && content
- && rObj.setDrawOptions(pos + Point(getBorderWidth(), getBorderWidth()),
- Point(getInnerWidth(), getInnerHeight())))
- {
- if (!renderStart.line)
- {
- renderStart = {content, 0};
- renderStartLine = 1;
- }
- int y = 0;
- int lineNumberWidth = 0;
- for (int i = lineCount; i > 0; i /= 10)
- {
- lineNumberWidth++;
- }
- lineNumberWidth
- = lineNumberWidth * textRenderer->getMaxCharWidth()
- + textRenderer->getCharSpacing() * (lineNumberWidth - 1);
- bool selected = false;
- EditableJsonElement* element = content;
- while (element)
- {
- if (element == selectionStart.line)
- {
- if (element != renderStart.line)
- {
- selected = true;
- }
- else
- {
- if (selectionStart.column < renderStart.column)
- {
- selected = true;
- }
- }
- }
- if (element == selectionEnd.line)
- {
- if (element != renderStart.line)
- {
- selected = false;
- break;
- }
- else
- {
- if (selectionEnd.column < renderStart.column)
- {
- selected = false;
- }
- }
- }
- if (element == renderStart.line)
- {
- break;
- }
- element = element->zAfter(false, 0);
- }
- int line = renderStartLine;
- int x = lineNumberWidth + 26;
- EditableJsonElement* current = renderStart.line;
- EditableJsonElement* highlightStop = 0;
- int index = renderStart.column;
- bool treeBranchRendered = false;
- bool highlighted = false;
- int numberWidth = textRenderer->getTextWidth(Text(line));
- textRenderer->renderText(
- 5 + lineNumberWidth - numberWidth, y, Text(line), rObj, 0xFF707070);
- bool whiteSpaceOnly = true;
- while (y < gr.y && current)
- {
- const Text& content = current->getContent();
- int column = index;
- for (int i = index; i < content.getLength() && y < gr.y;
- i++, column++)
- {
- if (selectionStart.line == current
- && selectionStart.column == i)
- {
- selected = true;
- }
- if (selectionEnd.line == current && selectionEnd.column == i)
- {
- selected = false;
- }
- int color = current->getColor(i);
- int cursorX = x - 1;
- if (textCursor.line == current && textCursor.column == i
- && drawCursor)
- {
- rObj.drawLineV(
- cursorX, y, textRenderer->getFontSize(), 0xFFC0C0C0);
- }
- if (content[i] == '\n')
- {
- column = -1;
- highlighted = false;
- if (!treeBranchRendered)
- {
- // | in tree view
- rObj.drawLineV(lineNumberWidth + 13,
- y
- - (line > 1 ? textRenderer->getFontSize() / 6
- : 0),
- textRenderer->getFontSize()
- + (line > 1 ? textRenderer->getFontSize() / 6
- : 0),
- 0xFF808080);
- if (highlightStop)
- {
- // hover effect in tree view
- rObj.fillRegion(lineNumberWidth + 10,
- y - textRenderer->getFontSize() / 6,
- 7,
- textRenderer->getFontSize()
- + textRenderer->getFontSize() / 6,
- 0xFF505050);
- }
- }
- if (selected)
- {
- rObj.fillRegion(x,
- y,
- textRenderer->getTextWidth(" "),
- textRenderer->getRowHeight()
- + textRenderer->getLineSpacing(),
- 0xFF502020);
- }
- x = lineNumberWidth + 26;
- y += textRenderer->getRowHeight()
- + textRenderer->getLineSpacing();
- whiteSpaceOnly = true;
- line++;
- renderedLines++;
- treeBranchRendered = false;
- int numberWidth = textRenderer->getTextWidth(Text(line));
- textRenderer->renderText(5 + lineNumberWidth - numberWidth,
- y,
- Text(line),
- rObj,
- 0xFF707070);
- }
- else
- {
- textRenderer->renderChar(x,
- y,
- content[i],
- rObj,
- color,
- false,
- selected,
- 0xFF502020);
- }
- if (cursorPos.x > cursorX && cursorPos.x <= x
- && cursorPos.y >= y
- && cursorPos.y <= y + textRenderer->getRowHeight())
- {
- if (current->hasError(i))
- {
- const SyntaxError& error = current->getError(i);
- errorDescription->setText(errors[error.getErrorType()]);
- errorDescription->setSize(
- errorDescription->getNeededWidth() + 6,
- errorDescription->getNeededHeight() + 6);
- errorDescription->setPosition(
- cursorPos.x, cursorPos.y + 20);
- if (errorDescription->getX()
- + errorDescription->getWidth()
- > getInnerWidth())
- {
- errorDescription->setX(
- getInnerWidth() - errorDescription->getWidth()
- - 5);
- }
- if (errorDescription->getY()
- + errorDescription->getHeight()
- > getInnerHeight())
- {
- errorDescription->setY(
- getInnerHeight() - errorDescription->getHeight()
- - 5);
- }
- errorDescription->addStyle(TextField::Style::Visible);
- }
- }
- if (column % 4 == 0 && content[i] == ' ' && whiteSpaceOnly)
- {
- rObj.drawLineV(
- cursorX + 1 + textRenderer->getTextWidth(" ") / 2,
- y + 2,
- textRenderer->getFontSize() - 4,
- 0xFF353535);
- }
- whiteSpaceOnly &= content[i] == ' ' || content[i] == '\n';
- }
- if (selectionStart.line == current
- && selectionStart.column == content.getLength())
- {
- selected = true;
- }
- if (selectionEnd.line == current
- && selectionEnd.column == content.getLength())
- {
- selected = false;
- }
- if (textCursor.line == current
- && textCursor.column == content.getLength() && drawCursor)
- {
- rObj.drawLineV(
- x - 1, y, textRenderer->getFontSize(), 0xFFC0C0C0);
- }
- if (current->zFirstChildren())
- {
- if (pressed && pressedPos.x >= lineNumberWidth + 10
- && pressedPos.x <= lineNumberWidth + 16
- && pressedPos.y >= y + textRenderer->getFontSize() / 2 - 4
- && pressedPos.y <= y + textRenderer->getFontSize() / 2 + 2)
- {
- pressed = false;
- current->setHidden(!current->isHidden());
- }
- if (cursorPos.x >= lineNumberWidth + 10
- && cursorPos.x <= lineNumberWidth + 16
- && cursorPos.y >= y + textRenderer->getFontSize() / 2 - 4
- && cursorPos.y <= y + textRenderer->getFontSize() / 2 + 2
- && !current->isHidden())
- {
- highlightStop = current->zLastChildren();
- }
- if (current->isHidden())
- {
- if (!treeBranchRendered)
- {
- rObj.fillRegion(lineNumberWidth + 10,
- y + textRenderer->getFontSize() / 2 - 4,
- 6,
- 6,
- 0xFF000000);
- rObj.drawLine(
- Point(lineNumberWidth + 10,
- y + textRenderer->getFontSize() / 2 - 4),
- Point(lineNumberWidth + 16,
- y + textRenderer->getFontSize() / 2 - 1),
- 0xFF808080);
- rObj.drawLine(
- Point(lineNumberWidth + 10,
- y + textRenderer->getFontSize() / 2 + 2),
- Point(lineNumberWidth + 16,
- y + textRenderer->getFontSize() / 2 - 1),
- 0xFF808080);
- }
- for (char c : " ... ")
- {
- textRenderer->renderChar(x,
- y,
- c,
- rObj,
- 0xFF505050,
- false,
- selected,
- 0xFF502020);
- }
- if (current->getOpeningControllChar() == '{')
- {
- textRenderer->renderChar(x,
- y,
- '}',
- rObj,
- 0xFF505050,
- false,
- selected,
- 0xFF502020);
- }
- else if (current->getOpeningControllChar() == '[')
- {
- textRenderer->renderChar(x,
- y,
- ']',
- rObj,
- 0xFF505050,
- false,
- selected,
- 0xFF502020);
- }
- }
- else
- {
- if (!treeBranchRendered)
- {
- rObj.fillRegion(lineNumberWidth + 10,
- y + textRenderer->getFontSize() / 2 - 4,
- 6,
- 6,
- 0xFF000000);
- rObj.drawLine(
- Point(lineNumberWidth + 10,
- y + textRenderer->getFontSize() / 2 - 4),
- Point(lineNumberWidth + 13,
- y + textRenderer->getFontSize() / 2 + 2),
- 0xFF808080);
- rObj.drawLine(
- Point(lineNumberWidth + 16,
- y + textRenderer->getFontSize() / 2 - 4),
- Point(lineNumberWidth + 13,
- y + textRenderer->getFontSize() / 2 + 2),
- 0xFF808080);
- }
- }
- treeBranchRendered = true;
- }
- if (!current->zMextSibling() && current->zParent())
- {
- // |_ in tree view
- rObj.drawLineH(lineNumberWidth + 14,
- y + textRenderer->getFontSize() - 1,
- 3,
- 0xFF808080);
- }
- rObj.drawLineV(x,
- y,
- textRenderer->getFontSize(),
- 0xFF30C030); // TODO: debug tree seperator
- if (current == highlightStop)
- {
- highlightStop = 0;
- if (!treeBranchRendered)
- {
- // hover effect in tree view
- rObj.fillRegion(lineNumberWidth + 10,
- y - textRenderer->getFontSize() / 6,
- 7,
- textRenderer->getFontSize()
- + textRenderer->getFontSize() / 6,
- 0xFF505050);
- highlighted = true;
- }
- }
- current = current->zAfter(true, &line);
- index = 0;
- }
- if (!treeBranchRendered && !highlighted)
- {
- // | in tree view
- rObj.drawLineV(lineNumberWidth + 13,
- y - (line > 1 ? textRenderer->getFontSize() / 6 : 0),
- textRenderer->getFontSize()
- + (line > 1 ? textRenderer->getFontSize() / 6 : 0),
- 0xFF808080);
- }
- EditableJsonElement* resnderStopElement = current;
- renderStopLine = line;
- textRenderer->renderText(5,
- y + textRenderer->getRowHeight() + textRenderer->getLineSpacing(),
- Text("FPS: ") + Text(tps),
- rObj,
- 0xFFFFFFFF);
- bool visible = false;
- double sy = 0.0;
- double yOffset = (double)getInnerHeight() / lineCount;
- current = content;
- EditableJsonElement* hiddenStop = 0;
- while (current)
- {
- if (hiddenStop == current)
- {
- hiddenStop = 0;
- }
- if (current == renderStart.line)
- {
- visible = true;
- }
- if (current == resnderStopElement)
- {
- visible = false;
- }
- int f = 0xFF303030;
- if (visible)
- {
- f = 0xFFA0A0A0;
- }
- if (hiddenStop)
- {
- f = 0xFF505050;
- }
- if (current->hasError())
- {
- f = 0xFFFF0000;
- }
- double size = current->lineCount() * yOffset;
- if ((int)(sy + size) > (int)sy || current->hasError())
- {
- rObj.fillRegion(getInnerWidth() - 15,
- (int)sy,
- 15,
- (int)(sy + MAX(yOffset, 1)),
- f);
- }
- if (current->isHidden())
- {
- if (!hiddenStop)
- {
- hiddenStop = current->zAfter(true, 0);
- }
- }
- current = current->zAfter(false, 0);
- sy += size;
- }
- errorDescription->render(rObj);
- rObj.releaseDrawOptions();
- }
- }
- Text Framework::JSON::JsonEditor::getContent()
- {
- return content ? content->getRecursiveContent() : Text("");
- }
- Text Framework::JSON::JsonEditor::getSelectedContent()
- {
- Text result = "";
- if (selectionStart.line && selectionEnd.line)
- {
- if (selectionStart.line == selectionEnd.line)
- {
- Text* tmp = selectionStart.line->getContent().getTeilText(
- selectionStart.column, selectionEnd.column);
- result.append(*tmp);
- tmp->release();
- }
- else
- {
- Text* tmp = selectionStart.line->getContent().getTeilText(
- selectionStart.column,
- selectionStart.line->getContent().getLength());
- result.append(*tmp);
- tmp->release();
- Stack<EditableJsonElement*> stack(0);
- stack.push(selectionStart.line);
- while (stack.getSize())
- {
- EditableJsonElement* current = stack.pop();
- if (current->zMextSibling())
- {
- stack.push(current->zMextSibling());
- }
- else if (stack.getSize() == 0 && current->zParent())
- {
- EditableJsonElement* parent = current->zParent();
- while (parent)
- {
- if (parent->zMextSibling())
- {
- stack.push(current->zParent()->zMextSibling());
- break;
- }
- parent = parent->zParent();
- }
- }
- if (current->zFirstChildren())
- {
- stack.push(current->zFirstChildren());
- }
- if (current == selectionEnd.line)
- {
- break;
- }
- if (current != selectionStart.line)
- {
- result += current->getContent();
- }
- }
- tmp = selectionEnd.line->getContent().getTeilText(
- 0, selectionEnd.column);
- result.append(*tmp);
- tmp->release();
- }
- }
- return result;
- }
- JSONValue* Framework::JSON::JsonEditor::getValidContent()
- {
- return nullptr; // TODO
- }
- void Framework::JSON::JsonEditor::scrollToLine(int line, ScrollTargetPos pos)
- {
- if (pos == Top || pos == Bottom)
- {
- if (line >= renderStartLine && line < renderStopLine)
- {
- return; // line is already visible
- }
- }
- EditableJsonElement* element = content;
- if (line == 1)
- {
- scrollToLine(line, {content, 0}, pos);
- return;
- }
- int l = 1;
- int column = 0;
- while (element)
- {
- int lineCount = element->lineCount();
- if (lineCount + l >= line)
- {
- column = element->getContent().positionOf('\n', line - l - 1) + 1;
- break;
- }
- l += lineCount;
- EditableJsonElement* tmp = element->zAfter(true, &l);
- if (l >= line)
- {
- column = element->getContent().positionOf('\n', lineCount - 1) + 1;
- break;
- }
- element = tmp;
- }
- EditorPosition target = {element, column};
- unifyPosition(target);
- scrollToLine(line, target, pos);
- }
- void Framework::JSON::JsonEditor::scrollToLine(
- EditorPosition target, ScrollTargetPos pos)
- {
- if (!target.line || !target.line->isVisible())
- {
- return;
- }
- int lineNumber = 0;
- if (!content->lineCount(true, true, target.line, lineNumber))
- {
- Text* part = target.line->getContent().getTeilText(0, target.column);
- lineNumber += part->countOf('\n');
- part->release();
- if (pos == Top || pos == Bottom)
- {
- if (lineNumber >= renderStartLine && lineNumber < renderStopLine)
- {
- return; // line is already visible
- }
- }
- scrollToLine(lineNumber, target, pos);
- }
- }
- void Framework::JSON::JsonEditor::scrollToLine(
- int lineNum, EditorPosition target, ScrollTargetPos pos)
- {
- if (!target.line || !target.line->isVisible())
- {
- return;
- }
- if (pos == Top || pos == Bottom)
- {
- if (lineNum >= renderStartLine && lineNum < renderStopLine)
- {
- return; // line is already visible
- }
- }
- if (pos == Top)
- {
- renderStart = target;
- const char* content = renderStart.line->getContent();
- while (
- renderStart.column > 0 && content[renderStart.column - 1] != '\n')
- {
- renderStart.column--;
- }
- renderStartLine = lineNum;
- }
- else
- {
- int linesUntilStart
- = pos == Bottom ? renderedLines - 1 : renderedLines / 2 - 1;
- if (linesUntilStart >= lineNum)
- {
- renderStart = {content, 0};
- renderStartLine = 1;
- return;
- }
- EditableJsonElement* element = target.line;
- EditableJsonElement* before = element;
- while (linesUntilStart >= 0)
- {
- if (!before)
- {
- break;
- }
- element = before;
- int newLines = 0;
- if (element == target.line)
- {
- Text* part
- = element->getContent().getTeilText(0, target.column);
- newLines = part->countOf('\n');
- part->release();
- }
- else
- {
- newLines = element->lineCount();
- }
- if (newLines > linesUntilStart)
- {
- renderStart = {element,
- element->getContent().positionOf(
- '\n', newLines - linesUntilStart - 1)
- + 1};
- unifyPosition(renderStart);
- renderStartLine = lineNum - linesUntilStart;
- return;
- }
- lineNum -= newLines;
- linesUntilStart -= newLines;
- before = element->zBefore(this->content, true, &lineNum);
- }
- renderStart = {element, 0};
- renderStartLine = lineNum;
- }
- }
|