Deshacer

Estoy pensando en cómo implementar el sistema de deshacer/rehacer de TBO, y no se cuál sería la mejor forma de hacerlo.
Las dos opciones que estoy barajando son:
1. Guardar el estado. La idea es que antes de cada operación que se pueda deshacer se guarde el estado actual del documento en la lista de deshacer.
pros: creo que es fácil de implementar/mantener
contras: El coste en memoria puede ser considerable, y clonar el estado en cada operación puede ser computacionalmente costoso.
2. Guardar la operación y su inversa. La idea es que antes de cada operación que se pueda deshacer se guarde la operación a realizar junto con su inversa en la lista de deshacer.
pros: Menor coste tanto en memoria como de calculo.
contras: Pueden existir operaciones cuya inversa sea muy compleja.
Me decanto por la segunda opción, pero lo mismo debería mirar un poco el código de gimp o inkscape un poco para ver qué es lo que hacen.



Hola Daniel, te dejo un comentario en este post si ninguna relación con el contenido del mismo, perdón por ello pero quería sacarme una duda.
TBO está buenísimo, realmente y he visto que la manipulación de objetos cairo que haces es realmente avanzada. Quería saber por qué no has utilizado clutter para este fin, porque a primera vista parecería EL toolkit para hacerlo.
Solo eso, era una pequeña duda.
Saludos y felicitaciones.
- reply
Submitted by diega (not verified) on Thu, 09/09/2010 - 10:11.Te cuento el sistema que usa Eclipse que también lo he visto en varios programas más.
Todas las operaciones que se hace sobre un documento son clases que extienen de la interfaz Command que tiene un método do/undo que hay que implementar. Por ejemplo podemos tener un comando para crear un elemento en el documento, otro para borrarlo, otro para cambiarle el color, etc. No se debería poder modificar el documento si no es a través de Commands.
Las acciones del usuario instancian Commands, cada Command que se crea se guarda en una pila para poder deshacer/rehacer.
La implementación de los métodos do/undo depende de cada comando, si borras un elemento, lo normal es que guardes ese elemento borrado en una variable dentro del mismo Command y cuando se llame a undo pueda restaurarlo. De esta forma, dependiendo del comando se puede optar por guardar el estado o aplicar la operación inversa.
- reply
Submitted by Monigote (not verified) on Thu, 09/09/2010 - 10:11.(Bueno, como veo que el anti-spam ha pasado de mí, vuelvo a escribir el mismo comentario sin HTML...)
Cada vez que hagas un cambio:
1. Haz una copia temporal del archivo antiguo.
2. Guarda el archivo nuevo.
3. Usa `diff` para generar una lista de cambios (reversible) entre ambas versiones (lo que viene siendo un parche, vamos).
4. Borra el archivo antiguo.
Ahora, para deshacer, simplemente tienes que leer la lista de parches y aplicar `patch -R` para deshacer (revertir a una versión anterior) o `patch` para rehacer.
No hace falta que uses `diff` y `patch` directamente si ves que va a ser muy lento y que podrías implementar algo similar por tu cuenta, pero esa es la idea. De hecho, quizá podrías implementar todas las acciones en forma de parches.
- reply
Submitted by cousteau (not verified) on Thu, 09/09/2010 - 10:09.