{"id":292,"date":"2015-06-04T11:43:28","date_gmt":"2015-06-04T11:43:28","guid":{"rendered":"http:\/\/www.colorwave.it\/blog\/?p=292"},"modified":"2015-06-08T12:21:45","modified_gmt":"2015-06-08T12:21:45","slug":"la-gestione-degli-undo-e-delle-revisioni-dei-documenti","status":"publish","type":"post","link":"https:\/\/www.colorwave.it\/blog\/framework\/la-gestione-degli-undo-e-delle-revisioni-dei-documenti\/admin\/2015\/06\/","title":{"rendered":"Il paradigma Undo\/Redo e revisioni documenti"},"content":{"rendered":"<p>In questo articolo descriveremo le classi che gestiscono la\u00a0struttura di undo\/redo per i documenti \u00a0generati e gestiti dalle API di Colibri.<\/p>\n<p>Vedremo che, in pratica, non esiste differenza fra la gestione delle revisioni dei documenti (ad esempio le varianti colore) e le strutture che permettono le operazioni di undo\/redo: sono formalmente la stessa cosa, semplicemente le revisioni sono salvate con il documento, mentre le informazioni undo\/redo esistono fino a quando il documento rimane aperto.<\/p>\n<p>Abbiamo scritto che la gestione undo\/redo ha come oggetto i documenti definiti attraverso le API di Colibri. Nella realt\u00e0 il paradigma undo\/redo ha come oggetto la classe <a href=\"https:\/\/www.colorwave.it\/blog\/?p=265\">OPERATION_CALL,<\/a> \u00a0e di conseguenza tutte le classi derivate, come ad esempio DB_OBJECT e DOCUMENT che deriva da essa. Quindi per gestire lo stato di undo\/redo su una classe baster\u00e0 derivarla da OPERATION_CALL..<\/p>\n<p><!--nextpage--><br \/>\nTutte le classi che descriveremo appartengono al namespace ACTIONS. \u00a0Questo raggruppamento gestisce, come si intuisce dal nome, le possibili azioni e modifiche relative ad un oggetto.<\/p>\n<p>La prima classe definita nel namespace \u00e8 la classe ACTION, \u00a0che definisce una lista di\u00a0metodi, che sono ereditati, e di funzioni di interfaccia che devono essere ridefinite dalle classi derivate.<\/p>\n<p>Dalla classe ACTION deriveranno tutte le operazioni di undo\/redo specifiche delle classi. La classe ACTION deriva a sua volta da DB_OBJECT, la quale eredita, fra le altre l&#8217;interfaccia OPERATION_CALL. Si pu\u00f2 intuire quindi che tutte le classi che hanno l&#8217;interfaccia ACTION a loro volta possono essere oggetto di undo\/redo, in una struttura logica completamente recursiva!<\/p>\n<p>A titolo esemplificativo riportiamo il diagramma completo della classe AREA_RESTORE, il cui compito \u00e8 gestire le operazioni di ripristino di aree di un documento<\/p>\n<figure id=\"attachment_325\" aria-describedby=\"caption-attachment-325\" style=\"width: 619px\" class=\"wp-caption aligncenter\"><a  href=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/06\/ClassDiagram81.png?ssl=1\" data-rel=\"lightbox-gallery-0\" data-rl_title=\"\" data-rl_caption=\"\" data-imagelightbox=\"0\" title=\"\"><img fetchpriority=\"high\" decoding=\"async\" data-attachment-id=\"325\" data-permalink=\"https:\/\/www.colorwave.it\/blog\/framework\/la-gestione-degli-undo-e-delle-revisioni-dei-documenti\/admin\/2015\/06\/attachment\/classdiagram8-2\/\" data-orig-file=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/06\/ClassDiagram81.png?fit=619%2C431&amp;ssl=1\" data-orig-size=\"619,431\" 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=\"ClassDiagram8\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/06\/ClassDiagram81.png?fit=300%2C209&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/06\/ClassDiagram81.png?fit=619%2C431&amp;ssl=1\" tabindex=\"0\" role=\"button\" class=\"wp-image-325 size-full\" src=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/06\/ClassDiagram81.png?resize=619%2C431&#038;ssl=1\" alt=\"ClassDiagram8\" width=\"619\" height=\"431\" srcset=\"https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/06\/ClassDiagram81.png?w=619&amp;ssl=1 619w, https:\/\/i0.wp.com\/www.colorwave.it\/blog\/wp-content\/uploads\/2015\/06\/ClassDiagram81.png?resize=300%2C209&amp;ssl=1 300w\" sizes=\"(max-width: 619px) 100vw, 619px\" data-recalc-dims=\"1\" \/><\/a><figcaption id=\"caption-attachment-325\" class=\"wp-caption-text\">Diagramma della classe AREA_RESTORE<\/figcaption><\/figure>\n<p>L&#8217;altra classe base contenuta nel namespace \u00e8 la DOCUMENT_HISTORY che, come si intuisce, gestisce la storia delle revisioni di un documento. Come ho gi\u00e0 accennato, in questo\u00a0contesto \u00a0usiamo il termine <em>documento\u00a0<\/em>nell&#8217;accezione di <em>classe che espone l&#8217;interfaccia\u00a0OPERATION_CALL, <\/em>quindi in un&#8217;accezione completamente astratta, con consistente necessariamente in oggetti visuali come un testo o immagine..<br \/>\n<!--nextpage--><br \/>\nla classe ACTION \u00e8 \u00a0l&#8217;interfaccia di gestione di azioni su un documento. da questa classe derivano le azioni specifiche di undo\/redo eseguite su un documento. La classe espone una funzione di gestione della memoria, che permette al programmatore l&#8217;allocazione e disallocazione automatica di buffer; contiene inoltre tre metodi virtuali che saranno riscritti nelle classi derivate.<\/p>\n<h3>Malloc()<\/h3>\n<p>La classe mette a disposizione una funzione Malloc, il cui compito e di allocare un blocco di memoria utilizzabile dalle istanze derivate o all&#8217;interno dei documenti durante la costruzione dell&#8217;azione undo\u00a0(ad esempio per allocare un buffer assegnato ad un&#8217;area immagine copiata..)<br \/>\nLa memoria allocata verr\u00e0 liberata automaticamente alla distruzione della classe<\/p>\n<h3>FilePush() e FilePop() scrittura su file delle azioni<\/h3>\n<p>Le due funzioni sono virtuali e devono essere riscritte dalle classi derivate. Consistono nell&#8217;interfaccia di salvataggio e richiamo dell&#8217;azione da un file:\u00a0\u00e8 compito della classe derivata da ACTION decidere se effettuare il flush o meno su file. In genere la strategia \u00e8 quella di decidere internamente alla classe se vale la pena liberare la memoria temporaneamente fino al FilePop successivo;<\/p>\n<h3>Do(OPERATIN_CALL *doc) \u00a0esecuzione delle operazioni di Undo\/Redo<\/h3>\n<p>La funzione virtuale Do(), \u00a0esegue l&#8217;azione di undo\/redo su un documento doc passato come argomento.\u00a0Di seguito \u00e8 riportata la funzione usata nella classe AREA_RESTORE<\/p>\n<p>[sourcecode language=&#8221;cpp&#8221;]<br \/>\nbool AREA_RESTORE::Do(OPERATION_CALL *doc)<br \/>\n{<br \/>\nGETSTR<br \/>\n___SENDER(doc,OP_RESTORE_AREA)<br \/>\nA_PUSH(this)<br \/>\n___SENDER_END<br \/>\nreturn RECEIVER_RESPONSE;<br \/>\n}<br \/>\n[\/sourcecode]<br \/>\n<span style=\"color: #008080;\">La funzione controlla che per prima cosa che il comando OP_RESTORE_AREA sia riconosciuto dal documento, quindi esegue la chiamata\u00a0al receiver di doc.<\/span><\/p>\n<p>Per maggiori dettagli sul paradigma SENDER\/RECEIVER leggere <a href=\"https:\/\/www.colorwave.it\/blog\/?p=265\">questo articolo<\/a><\/p>\n<p><!--nextpage--><br \/>\nDOCUMENT_HISTORY \u00e8 la classe di gestione della lista delle azioni effettuate su un documento (OPERATION_CALL). \u00a0Il modo migliore per utilizzare questa interfaccia \u00e8 quella di dichiararla pubblica su una classe; La classe DB_OBJECT gi\u00e0 contiene l&#8217;interfaccia DOCUMENT_HISTORY, quindi qualunque classe derivata da essa gi\u00e0 contiene l&#8217;interfaccia alla storia del documento. Ad esempio la classe SPECTRAL_IMAGE, che gestisce le immagini spettrali di Colibri, derivando\u00a0da DB_OBJECT eredita anche DOCUMENT_HISTORY.<\/p>\n<p>La classe mette a disposizione un insieme di metodi per la gestione della lista delle azioni; \u00e8\u00a0una FIFO che viene\u00a0popolata con il metodo Push e Redo, e svuotata con i metodi Pop, Undo, Flush.<\/p>\n<p>La lista delle azioni Undo\/Redo non \u00e8 \u00a0limitata: questo significa che l&#8217;uso della classe permette di gestire un numero qualunque di azioni di undo, limite posto\u00a0solo dalle dimensioni della memoria e del disco a disposizione.<\/p>\n<h3>SetDocument(OPERATION_CALL *doc)<\/h3>\n<p>Questo metodo deve essere richiamato nel costruttore della classe per assegnare il documento di riferimento; Per le classi derivate da DB_OBJECT non \u00e8 necessario richiamare questo metodo, poich\u00e9 l&#8217;assegnazione \u00e8 fatta nel costruttore di DB_OBJECT (vedi esempio che segue)<\/p>\n<p>[sourcecode language=&#8221;cpp&#8221;]<br \/>\nDB_OBJECT::DB_OBJECT(void)<br \/>\n{<br \/>\nSetDocument(this); \/\/ assegna il documento al DOCUMENT_HISTORY<br \/>\n}<br \/>\n[\/sourcecode]<\/p>\n<p>Con questo metodo si informa l&#8217;interfaccia DOCUMENT_HISTORY che tutte le operazioni successive di Undo e Redo saranno relative al documento passato.<\/p>\n<h3>Push(ACTION *action)<\/h3>\n<p>Il metodo \u00e8 usato per aggiungere alla lista un&#8217;azione di undo.<\/p>\n<h3><strong>Pop()<\/strong><\/h3>\n<p>Il metodo rimuove l&#8217;ultimo elemento inserito nella lista; chiamate successive di Pop svuotano la lista delle azioni in sospeso, dalla pi\u00f9 recente alla pi\u00f9 vecchia. In genere non esiste necessit\u00e0 di usare questa funzione, a meno che l&#8217;applicazione specifica non lo richiedA.<\/p>\n<h3><strong>Flush()<\/strong><\/h3>\n<p>Azzera la lista delle azioni di undo\/redo. Il metodo \u00e8 chiamato internamente dal distruttore di\u00a0DOCUMENT_HISTORY, ma pu\u00f2 essere richiamato comunque anche dall&#8217;applicazione. Tutte le operazioni di svuotamento della lista distruggono le istanze delle classi ACTION inserite con Push(); pertanto tutte le ACTION, sempre allocate dall&#8217;esterno, verranno distrutte nella\u00a0DOCUMENT_HISTORY in modo completamente trasparente al programmatore che usa l&#8217;API di Colibri.<\/p>\n<h3>Undo()<\/h3>\n<p>esegue undo sull&#8217;ultima azione inserita in ordine cronologico, rimuove l&#8217;azione e genera un&#8217;azione di redo nella lista dei redo.<\/p>\n<h3>Redo()<\/h3>\n<p>E&#8217; l&#8217;operazione inversa di Undo(); l&#8217;ultima operazione inserita dalla Undo() viene ripristinata nella lista degli undo e rimossa da quella dei redo.<\/p>\n<h4><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=\" size-full wp-image-283 alignleft\" 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>\u00a0<span style=\"text-decoration: underline;\">Nota<\/span>:<\/h4>\n<p>Le classi fin qui descritte\u00a0gestiscono l&#8217;infrastruttura delle operazioni di Undo\/Redo ma, come si pu\u00f2 capire dal fatto che gestiscono documenti derivati da OPERATION_CALL, comunicano con questi attraverso i metodi di questa interfaccia; A conclusione dell&#8217;articolo propongo un esempio concreto di come questi metodi sono applicati in Colibr\u00ec: la gestione undo\/redo nella classe SPECTRAL_IMAGE.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In questo articolo descriveremo le classi che gestiscono la\u00a0struttura di undo\/redo per i documenti \u00a0generati e gestiti dalle API di Colibri. Vedremo che, in pratica, non esiste differenza fra la gestione delle revisioni dei documenti (ad esempio le varianti colore) e le&#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":[24,19,25],"tags":[],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p9rwsf-4I","jetpack_likes_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/posts\/292"}],"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=292"}],"version-history":[{"count":53,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/posts\/292\/revisions"}],"predecessor-version":[{"id":402,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/posts\/292\/revisions\/402"}],"wp:attachment":[{"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/media?parent=292"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/categories?post=292"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.colorwave.it\/blog\/wp-json\/wp\/v2\/tags?post=292"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}