{"id":294,"date":"2015-06-08T12:19:47","date_gmt":"2015-06-08T12:19:47","guid":{"rendered":"http:\/\/www.colorwave.it\/blog\/?p=294"},"modified":"2016-02-03T15:09:47","modified_gmt":"2016-02-03T15:09:47","slug":"costruire-le-funzioni-di-undoredo","status":"publish","type":"post","link":"https:\/\/www.colorwave.it\/blog\/uncategorized\/costruire-le-funzioni-di-undoredo\/admin\/2015\/06\/","title":{"rendered":"Costruire le funzioni di Undo\/Redo"},"content":{"rendered":"<p>Questo articolo mostra come implementare le funzionalit\u00e0 di undo\/redo per una classe, la SPECTRAL_IMAGE.<br \/>\nPer prima cosa ricordiamo che SPECTRAL_IMAGE deriva dalla classe DOCUMENT, della quale \u00e8 di seguito mostrato il diagramma:<\/p>\n<p><a  href=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/06\/ClassDiagram9.png?ssl=1\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-imagelightbox=\"0\"><img fetchpriority=\"high\" decoding=\"async\" data-attachment-id=\"370\" data-permalink=\"https:\/\/www.colorwave.it\/blog\/uncategorized\/costruire-le-funzioni-di-undoredo\/admin\/2015\/06\/attachment\/classdiagram9\/\" data-orig-file=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/06\/ClassDiagram9.png?fit=763%2C337&amp;ssl=1\" data-orig-size=\"763,337\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ClassDiagram9\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/06\/ClassDiagram9.png?fit=300%2C133&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/06\/ClassDiagram9.png?fit=640%2C283&amp;ssl=1\" tabindex=\"0\" role=\"button\" class=\" wp-image-370 alignleft\" title=\"\" src=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/06\/ClassDiagram9.png?resize=600%2C265&#038;ssl=1\" alt=\"\" width=\"600\" height=\"265\" srcset=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/06\/ClassDiagram9.png?w=763&amp;ssl=1 763w, https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/06\/ClassDiagram9.png?resize=300%2C133&amp;ssl=1 300w\" sizes=\"(max-width: 600px) 100vw, 600px\" data-recalc-dims=\"1\" \/><\/a><\/p>\n<p>Come si nota, DOCUMENT ha ereditato da DB_OBJECT l&#8217;interfaccia DOCUMENT_HISTORY; pertanto, anche la classe SPECTRAL_IMAGE dispone della stessa interfaccia. Analizziamo ora nei particolari come implementare le azioni di Undo. Mostreremo come esempio l&#8217;aggiunta di una funzione di ripristino di un&#8217;area modificata.<\/p>\n<p>A questo scopo verr\u00e0 definita la classe AREA_RESTORE , derivata da ACTION, che ha la funzione di gestire il salvataggio e recupero dalla DOCUMENT_HISTORY dell&#8217;area.<\/p>\n<!--nextpage-->\n<p>Analizziamo la dichiarazione della classe<\/p>\n<p>[sourcecode language=&#8221;cpp&#8221;]<\/p>\n<p>class AFX_EXT_CLASS AREA_RESTORE : public ACTION<br \/>\n{<br \/>\npublic:<br \/>\nAREA_RESTORE(void);<br \/>\n~AREA_RESTORE(void);<\/p>\n<p>void *AllocArea(IRECT rect, int pxsize);<br \/>\nUBYTE *GetArea(IRECT *rect,float *angle);<br \/>\nvoid SetBitmap(Bitmap *img);<br \/>\nvoid *GetBitmap();<br \/>\nvirtual bool Do(class OPERATION_CALL *doc);<br \/>\nvirtual DB_OBJECT *New();<\/p>\n<p>USE_FILE<br \/>\nUSE_PRIVATE_STRUCT<br \/>\n};<br \/>\n[\/sourcecode]<\/p>\n<p>I metodi presenti nella classe sono in parte riscritture delle classi virtuali da ACTION, dalla quale \u00e8 derivata, ed in parte specifici delle funzioni svolte: sono funzioni riscritte la New(), la Do() e quelle definite nella macro USE_FILE; sono invece specifici della funzione la AllocArea, GetArea, GetBitmap e SetBitmap, il cui significato sar\u00e0 spiegato di seguito. In questo articolo analizzeremo solo le funzioni AllocArea e GetArea, in quanto utilizzate effettivamente nella SPECTRAL_IMAGE. Le altre due funzioni sono usate in altri contesti, e per ora non ne \u00e8 necessaria la descrizione.<\/p>\n<h3>AllocArea<\/h3>\n<p>La funzione alloca un buffer per la memorizzazione di un&#8217;area della bitmap. L&#8217;area \u00e8 allocata alle dimensioni definite nel parametro rect, e per dimensioni dei pixel pari a pxsize:<\/p>\n<p>[sourcecode language=&#8221;cpp&#8221;]<br \/>\nvoid *AREA_RESTORE::AllocArea(IRECT rect, int pxsize)<br \/>\n{<br \/>\nGETSTR<br \/>\nSTR-&gt;rect=rect;<br \/>\nSTR-&gt;buf=(UBYTE *)Malloc(rect.dx*rect.dy*pxsize);<br \/>\nreturn STR-&gt;buf;<br \/>\n}<br \/>\n[\/sourcecode]<\/p>\n<p>La funzione\u00a0\u00e8 molto semplice: sfrutta la Malloc della classe ACTIONdalla quale deriva per allocare un buffer void di dimensioni sufficienti alla memorizzazione dell&#8217;area (la memoria verr\u00e0 rilasciata automaticamente dal distruttore di ACTION). Viene rimandato un puntatore void alla memoria allocata.<\/p>\n<h3>GetArea<\/h3>\n<p>[sourcecode language=&#8221;cpp&#8221;]<\/p>\n<p>UBYTE *AREA_RESTORE::GetArea(IRECT *rect,float *angle)<br \/>\n{<br \/>\nGETSTR<br \/>\n*angle=STR-&gt;angle;<br \/>\n*rect=STR-&gt;rect;<br \/>\nreturn STR-&gt;buf;<br \/>\n}<\/p>\n<p>[\/sourcecode]<\/p>\n<p>La funzione rimanda il\u00a0buffer dell&#8217;area allocata da AllocArea per le azioni successive (ripristino o \u00a0inizializzazione, come spiegher\u00f2 di seguito).<\/p>\n<p>Ora sappiamo che AREA_RESTORE ha il banale compito di allocare la memoria necessaria al salvataggio di un&#8217;area, di permetterne l&#8217;accesso in modifica attraverso il suo puntatore ed in seguito eliminare il buffer quando non pi\u00f9 necessario. Analizzeremo ora il meccanismo nel quale \u00e8 inserita la classe. A questo scopo analizzeremo il modo in cui viene usata la classe in SPECTRAL_IMAGE.<\/p>\n<p><!--nextpage-->In colibr\u00ec \u00e8 definito un meccanismo di definizione ed interfazione fra gli oggetti documento e gli strumenti di modifica, tutti derivati dalla classe TOOL. In un altro articolo spiegheremo questo meccanismo. In questo contesto ci basta sapere che all&#8217;istanza della classe SPECTRAL_IMAGE, attraverso la gestione dei messaggi dei TOOL arrivano richieste di azione; una di queste, il taglio di un&#8217;area, arriver\u00e0 da un tool \u00a0di azione su\u00a0un&#8217;area. La funzione SPECTRAL_IMAGE::ReceiveToolInfo() che riceve la richiesta, individua il messaggio\u00a0OPCUT mandato dal tool e, di conseguenza, chiama una funzione CUT_RECT_AREA che esegue l&#8217;azione;<\/p>\n<p>[sourcecode language=&#8221;cpp&#8221;]<\/p>\n<p>static bool CUT_RECT_AREA(CLASS_STR, TOOLS::AREA_SELECTOR *tool)<br \/>\n{<br \/>\n\/\/ area interessata<br \/>\nfloat x,y,dx,dy;<br \/>\ntool-&gt;GetRectArea(&amp;x,&amp;y,&amp;dx,&amp;dy);<br \/>\nIRECT rect=_OBJ-&gt;GetPixelArea( x, y, dx, dy);<\/p>\n<p>ACTIONS::AREA_RESTORE *ars=GET_AREA(STR,rect); \/\/ copia l&#8217;area rettangolare..<br \/>\nif (ars) {<br \/>\nars-&gt;SetParam(MAGIC,_OBJ); \/\/ crea un parametro relativo all&#8217;origine dell&#8217;area..<br \/>\nars-&gt;SetBitmap(BMAP-&gt;GetBitmap(rect.x,rect.y,rect.dx,rect.dy));<br \/>\nACTIONS::CLIPBOARD::SetData(ars);<br \/>\nPUSH_AREA(STR,rect);<br \/>\n_OBJ-&gt;Clear(x,y,dx,dy);<br \/>\nSEND_APP_MESSAGE(MSG_REDRAW_DOCUMENT_VIEW,_OBJ);<br \/>\nreturn true;<br \/>\n}<br \/>\nreturn false;<\/p>\n<p>}<\/p>\n<p>[\/sourcecode]<\/p>\n<p>La funzione, statica nel file SPECTRAL_IMAGE.cpp. estrae le informazioni relative all&#8217;area da tagliare, chiama un&#8217;altra funzione locale, la GET_AREA, che estrae l&#8217;area spettrale relativa e inizializza con questa un buffer AREA_RESTORE; quindi assegna un parametro per ricordare l&#8217;origine dell&#8217;area (SetParams), estrae anche la Bitmap RGB di visualizzazione (SPECTRAL_IMAGE contiene sia la mappa spettrale dell&#8217;immagine che la sua rappresentazione rgb) e la assegna alla AREA_RESTORE. Per eventuali usi futuri assegna\u00a0alla CLIPBOARD l&#8217;area tagliata, quindi chiama la funzione PUSH_AREA<\/p>\n<p>[sourcecode language=&#8221;cpp&#8221;]<\/p>\n<p>static bool PUSH_AREA(CLASS_STR,IRECT rect)<br \/>\n{<br \/>\nACTIONS::AREA_RESTORE *ars=GET_AREA(STR,rect);<br \/>\nreturn _OBJ-&gt;Push(ars);<br \/>\n}<\/p>\n<p>[\/sourcecode]<\/p>\n<p>In questo esempio la AREA_RESTORE \u00e8 usata due volte: la prima per salvare nella clipboard di Colibri un&#8217;area (nella logica del comando CUT richiamato), La seconda, interna alla funzione PUSH_AREA per salvare l&#8217;area tagliata nella DOCUMENT_HISTORY (funzione Push() richiamata).<\/p>\n<p>CUT_RECT_AREA ha dunque svolto due compiti: Inserito l&#8217;area tagliata nella clipboard (l&#8217;area sar\u00e0 gestita da quest&#8217;ultima, e resa\u00a0disponibile alla eventuale richiesta di PASTE), e inserito l&#8217;area nella storia delle revisioni, per garantirne il ripristino se richiesto (Undo).\u00a0Vedremo ora come viene gestito il comando di Undo<\/p>\n<p><!--nextpage--> Dopo avere effettuato il CUT, un eventuale comando di UNDO arriva all&#8217;oggetto SPECTRAL_IMAGE attraverso l&#8217;oggetto WIDGET_IMAGE che lo \u00a0visualizza.<br \/>\nLa WIDGET_IMAGE, ricevuto il messaggio di UNDO (non \u00e8 importante ora capire come), semplicemente richiama il metodo Undo del documento contenuto<\/p>\n<p>[sourcecode language=&#8221;cpp&#8221;]<br \/>\nBEGIN_SLOT (ON_UNDO)<br \/>\n\/\/<br \/>\nif (_DOC)<br \/>\n_DOC-&gt;Undo();<br \/>\n\/\/<br \/>\nEND_SLOT<br \/>\n[\/sourcecode]<br \/>\nIl codice riportato mostra lo slot che intercetta il messaggio <strong>MsgUndo<\/strong>. Verificata l&#8217;esistenza del documento interno (_DOC), ne richiama la funzione Undo() ereditata attraverso DB_OBJECT (per saperne di pi\u00f9 leggere <a href=\"https:\/\/www.colorwave.it\/blog\/?p=292&amp;page=2\">questo articolo<\/a>).<\/p>\n<p><!--nextpage-->Di DOCUMENT_HISTORY ho gi\u00e0 scritto in <a href=\"https:\/\/www.colorwave.it\/blog\/?p=292&amp;page=4\">questo articolo<\/a>. E\u00e8 la classe che gestisce la lista Undo\/Redo e revisioni dei documenti.<\/p>\n<p>In particolare la funzione di ripristino di uno stato precedente\u00a0\u00e8 svolta dalla\u00a0funzione Undo, della quale si riporta il codice, molto semplice:<\/p>\n<p>[sourcecode language=&#8221;cpp&#8221;]<\/p>\n<p>bool DOCUMENT_HISTORY:: Undo()<br \/>\n{<br \/>\nGETSTR<br \/>\nif (!HISTORY)<br \/>\nreturn false;<br \/>\nCWaitCursor wait;<\/p>\n<p>ACTION *action;<br \/>\nif ( HISTORY-&gt;Pop(&amp;action)) {<br \/>\nbool res=action-&gt;Do(STR-&gt;doc);<br \/>\ndelete action;<br \/>\nreturn res;<br \/>\n}<br \/>\nreturn false;<br \/>\n}<\/p>\n<p>[\/sourcecode]<\/p>\n<p>La funzione, verificata la condizione di esistenza di una lista non vuota, estrae l&#8217;ultima ACTION\u00a0inserita nella fifo (funzione Pop()) \u00a0e richiama la funzione Do() della stessa. Alla Do viene passato il puntatore al documento di appartenenza. Quindi viene distrutta l&#8217;azione dopo averla eliminata dalla lista con la Pop.<\/p>\n<p>La Undo rimanda un valore true se l&#8217;azione \u00e8 stata effettuata correttamente (comunicazione ricevuta da ACTION::Do()<\/p>\n<p>In pratica la funzione di Undo \u00e8 semplicemente un router del messaggio, che viene passato all&#8217;istanza ACTION estratta dalla lista.<\/p>\n<p>La funzione ACTION::Do() \u00e8 gi\u00e0 stata descritta <a href=\"https:\/\/www.colorwave.it\/blog\/?p=292&amp;page=3\" target=\"_blank\">qui<\/a>; Nel caso della AREA_RESTORE, la classe derivata da ACTION aggetto di questo articolo, la Do() \u00a0manda il messaggio\u00a0OP_RESTORE_AREA alla SPECTRAL_IMAGE, che lo intercetta attraverso il codice che segue:<\/p>\n<p>[sourcecode language=&#8221;cpp&#8221;]<\/p>\n<p>_____SLOT(DO_RESTORE_AREA)<br \/>\nbool res=false;<br \/>\nif (PUT_AREA(OP_STR, (ACTIONS::AREA_RESTORE *)_A(0))) {<br \/>\nres= RECALC_IMAGE(OP_STR, (ACTIONS::AREA_RESTORE *)_A(0));<br \/>\nif (res)<br \/>\nSEND_APP_MESSAGE(MSG_REDRAW_DOCUMENT_VIEW,_OBJ);<br \/>\n}<br \/>\nreturn res;<br \/>\n_____END<br \/>\n[\/sourcecode]<\/p>\n<p>La funzione DO_RESTORE_AREA era dichiarata nella lista degli SLOT di ricezione dei messaggi esterni di SPECTRAL_IMAGE (vedi codice che segue)<\/p>\n<p>[sourcecode language=&#8221;cpp&#8221;]<br \/>\n_____SLOTS_____<br \/>\n&#8230;..<br \/>\n{ OP_RESTORE_AREA, DO_RESTORE_AREA },<br \/>\n&#8230;..<\/p>\n<p>_____SLOTS_END_____<\/p>\n<p>[\/sourcecode]<\/p>\n<p>Non ci resta che analizzare come la SPECTRAL_IMAGE ripristina l&#8217;area oggetto dell&#8217;undo.<\/p>\n<p><!--nextpage--> Lo slot DO_RESTORE_AREA della SPECTRAL_IMAGE richiama la funzione, statica al modulo, PUT_AREA, che \u00e8 incaricata di ripristinare l&#8217;area.<br \/>\nPer farlo individua nel parametro ricevuto _A(0) l&#8217;azione richiesta; quindi manda al framework la richiesta di ritracciamento di tutte le finestre del documento (potrebbero esserci pi\u00f9 viste del documento..)<\/p>\n<p>[sourcecode language=&#8221;cpp&#8221;]<br \/>\nstatic bool PUT_AREA(CLASS_STR,ACTIONS::AREA_RESTORE *ars)<br \/>\n{<br \/>\nIRECT rect;<br \/>\nfloat angle=0;<br \/>\nCHANDLER *buf= (CHANDLER *)ars-&gt;GetArea(&amp;rect,&amp;angle);<\/p>\n<p>if (!angle) {<br \/>\nint k=0;<br \/>\nfor (int yw=rect.y;ywGetIndexLine(yw);<br \/>\nif (line)<br \/>\nmemcpy(&amp;line[rect.x],buf+rect.dx*k,sizeof(CHANDLER)*rect.dx);<br \/>\n}<br \/>\n}<br \/>\nreturn true;<br \/>\n}<\/p>\n<p>[\/sourcecode]<br \/>\nNella funzione PUT_AREA, estratte le dimensioni e posizione dell&#8217;area salvata, viene effettuata l&#8217;operazione di ripristino dei pixel.<\/p>\n<!--nextpage-->\n<p>&nbsp;<\/p>\n<p><a  href=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/05\/fumetto.png?ssl=1\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-imagelightbox=\"1\" title=\"\"><img decoding=\"async\" data-attachment-id=\"283\" data-permalink=\"https:\/\/www.colorwave.it\/blog\/framework\/linterfaccia-operation_call\/admin\/2015\/05\/attachment\/fumetto\/\" data-orig-file=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/05\/fumetto.png?fit=24%2C24&amp;ssl=1\" data-orig-size=\"24,24\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"fumetto\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/05\/fumetto.png?fit=24%2C24&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/05\/fumetto.png?fit=24%2C24&amp;ssl=1\" tabindex=\"0\" role=\"button\" class=\"alignleft wp-image-283 size-full\" src=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/05\/fumetto.png?resize=24%2C24&#038;ssl=1\" alt=\"fumetto\" width=\"24\" height=\"24\" data-recalc-dims=\"1\" \/><\/a>\u00a0Come si pu\u00f2 osservare in questo articolo, tutta la gestione delle modifiche e della storia di un elemento derivato da DB_OBJECT \u00e8 gestito in modo completamente astratto rispetto all&#8217;oggetto. Solo le due azioni terminali di inizializzazione dell&#8217;azione e di ripristino sull&#8217;oggetto sono ovviamente specifiche dello stesso;<\/p>\n<p>tutto il ciclo \u00e8 effettuato sfruttando l&#8217;eredit\u00e0 delle interfacce di OPERATION_CALL, ACTION, PARAM e DOCUMENT_HISTORY. La classe WIDGET_DOCUMENT, di cui scriveremo prossimamente eredita da Wnd_Interface la gestione dei messaggi del sistema operativo;Quindi in modo completamente trasparente reidirizza la messaggistica verso le classi documento o widget ai quali \u00e8 collegata tramite gli slot.<\/p>\n<p>Il paradigma degli SLOT di colibri \u00e8 \u00a0alla base di tutta la gestione delle interazioni fra i suoi oggetti.<\/p>\n<p>L&#8217;interfaccia OPERATION_CALL, assegnabile\u00a0a qualunque oggetto costruito mediante le API di Colibri permette di attivare la connessione con SLOT appartenenti a moduli e dll differenti.<\/p>\n<p>L&#8217;interfaccia DOCUMENT_HISTORY pu\u00f2 essere assegnata anch&#8217;essa a qualunque classe, semplicemente dichiarandone l&#8217;eredit\u00e0. Questa condizione permette di gestire<em> la storia<\/em> di un qualunque oggetto, permettendone la navigazione attraverso i suoi stati, usando le funzioni standard previste nell&#8217;interfaccia.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Questo articolo mostra come implementare le funzionalit\u00e0 di undo\/redo per una classe, la SPECTRAL_IMAGE. Per prima cosa ricordiamo che SPECTRAL_IMAGE deriva dalla classe DOCUMENT, della quale \u00e8 di seguito mostrato il diagramma: Come si nota, DOCUMENT ha ereditato da DB_OBJECT l&#8217;interfaccia DOCUMENT_HISTORY;&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"footnotes":"","_jetpack_memberships_contains_paid_content":false,"jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[1],"tags":[],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p9rwsf-4K","jetpack_likes_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/posts\/294"}],"collection":[{"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/comments?post=294"}],"version-history":[{"count":32,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/posts\/294\/revisions"}],"predecessor-version":[{"id":401,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/posts\/294\/revisions\/401"}],"wp:attachment":[{"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/media?parent=294"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/categories?post=294"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/tags?post=294"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}