Page 1 of 2 1 2 LastLast
Results 1 to 15 of 16

Thread: TUndo class

  1. #1

    TUndo class

    Hoi,

    Heeft iemand wel eens Undo/Redo functies in zijn/haar app gemaakt? Ik wil graag dit soort functies inbouwen maar nu ik er zo over nadenk lijkt het me moeilijker dan eerst gedacht. Weet iemand misschien algemene methodes voor Undo/Redo functies?

    Doei!
    Jeroen

  2. #2
    Het hangt er natuurlijk een beetje vanaf wat je precies wilt undo'en en redo'en, maar het komt er natuurlijk in het kort op neer dat je de status van voor een bepaalde actie wilt opslaan. Deze gegevens kun je opslaan in een object of een record wanneer je maar 1 undo actie wilt kunnen bewaren, of in een array of list van records of objecten wanneer je meerdere acties wilt kunnen undo'en.

    Dat kun je doen door de actie terug te draaien, of door alle data van voor de actie op te slaan.
    Bijvoorbeeld: Wanneer je een stuk tekst hebt en je tikt daar een letter tussen, dan kun je opslaan dat je die ene letter hebt getypt op die bepaalde positie. Je kunt dan wanneer je undo wilt doen terug springen naar de positie en daar 1 teken weghalen.
    De andere oplossing is om alle data op te slaan voordat je de letter typt.

    De eerste methode spaart resources en biedt ook de mogelijk om de laatste actie te herhalen, maar is bij implementatie foutgevoeliger. De tweede methode is makkelijker te implementeren, maar kost meer resources en biedt niet de redo mogelijkheid.
    Welke voor jou de beste oplossing is, moet je zelf bepalen. Eventueel kun je ze combineren.
    1+1=b

  3. #3
    Bedankt voor je reply! Ik ben bezig met een grafische 3d editor (zie http://www.gamefortress.com/~delgine) en denk dat ik een combinatie van deze twee mogelijkheden nodig zal hebben.

    Als ik bijvoorbeeld een 3d object verplaats (aan de hand van een 3d vector), dan kan ik het ID van het object opslaan en de omgekeerde vector. Dan kan ik daarna datzelfde object weer terugverplaatsen naar zijn originele plaats door die omgekeerde vector te gebruiken.
    Maar als ik nu een 3d object verwijder, dan moet ik eigelijk dat object in zijn geheel opslaan zodat ik hem later eventueel weer terug kan plaatsen in de 'scene'. Dit is zo'n beetje wat jij bedoelt, of niet?

    Wat ik me ook afvraag is hoe je zoiets het best kunt implementeren. Ik zat zelf te denken aan een soort generieke TUndo class waarbinnen ik dan de verschillende data op kan slaan (dus een ID, een vector, een object en weet ik wat meer). Maarja... dan wordt die TUndo class dus een soort container voor allerlei data (waarbij ik van tevoren niet weet wat ik erin op moet slaan en dus ruimte moet hebben voor alle soorten data), wat misschien niet zo'n mooie en/of lastige implementatie betekent. Heeft iemand hier goeie ideeen over?

    Jeroen
    If you can't solve the problem, it isn't a problem... - DeleD - 3D editor project - www.delgine.com

  4. #4
    Niemand die hier iets nuttigs over te zeggen heeft??
    If you can't solve the problem, it isn't a problem... - DeleD - 3D editor project - www.delgine.com

  5. #5
    Misschien een raar idee, maar een nette manier om dit op te zetten lijkt me:

    Maak een generieke actie (abstracte) klasse, of een actie interface, met methodes 'do' en 'undo'. Maak daar bijvoorbeeld twee subclasses van (pseudocode):

    Code:
    Actie = class //(of interface)
      public
        procedure do; abstract;
        procedure undo; abstract;
    end;
    
    MoveActie = class(Actie)
      private
        target : object
        richting : vector 
      public
         constructor create(v : vector)
         procedure do; override;
         procedure undo; override;
    end;
    
    DeleteActie = class(Actie)
      private
        deletedObject : object
      public
         constructor create(o : object)
         procedure do; override;
         procedure undo; override;
    end;
    Laat vervolgens de code die iets verplaatst niet de verplaatsing uitvoeren, maar een MoveActie aanmaken met de goede verplaatsing erin, en dan de do() aanroepen, en dat object aan de undolijst toevoegen. Undo'en is dan een kwestie van de verschillende undo's aanroepen, redo'en van de goede do's opnieuw aanroepen.

    e.e.a. moet natuurlijk aan jouw situatie aangepast worden, maar dit zo nog wel eens een zinnige algemene opzet kunnen zijn.

    "Hope this helps"
    Met vriendelijke groet,

    Wouter van Atteveldt

  6. #6
    Ik zou beide opties eens uitproberen. Je zou gewoon na iedere actie een versie van je tekening kunnen opslaan (in geheugen of op schijf), een undo is dan een kwestie van je vorige versie pakken. Dat is op zich redelijk eenvoudig te maken, maar het gebruikt nogal wat resources. De tweede optie is alle acties opslaan (na het laden of maken van een bestand) en deze acties uit je lijst verwijderen. Een undo is dan je bestand opnieuw opbouwen tot en met de laatste actie voor je undo.
    Marcel

  7. #7
    Bedankt voor de reacties dusver! Over het algemeen zijn de reacties een weerspiegelijk van wat ik zelf in gedachten had, dus denk ik dat ik al aardig in de goede richting zat. Bedankt dus voor het bevestigen van mijn ideeen.

    Wouter, ik zat ook te denken om alle acties in afzonderlijke classes te zetten. Maar dan maakt het wel weer ingewikkelder. Tot nu toe heeft een 3d object (TPrimitive) zijn eigen Move/Scale/etc functies en dus kan een TPrimitive aardig op zichzelf functioneren. Als ik nu Actie classes ga maken, dan maak ik de TPrimitive daar dus eigelijk afhankelijk van... Eerst dacht ik dat dat niet zo'n tof idee was, maar nu ik over Undo nadenk, lijkt het toch best handig. Bedankt, ik denk dat ik het in die richting verder zal zoeken. :-)
    If you can't solve the problem, it isn't a problem... - DeleD - 3D editor project - www.delgine.com

  8. #8
    Met als gevaar dat ik dingen zeg die je zelf ook al bedacht had: Je hoeft je TPrimitive helemaal niet afhankelijk te maken van acties, maar alleen de code die iets met TPrimitive doet...
    Met vriendelijke groet,

    Wouter van Atteveldt

  9. #9
    Registered User
    Join Date
    Apr 2002
    Location
    Ekeren,Belgi?½
    Posts
    18
    Dit "probleem" houd me al enige tijd bezig.
    Als voorbeeld nemen we bijvoorbeeld een tekstbestand.
    We laden dit van schijf, en vervolgens maak je een lijst (DO-list) met elke verandering die je aanbrengt in de tekst. Elke verandering krijgt een cijfer, te beginnen bij 1 dan 2 enz.
    Als je dan na 10 veranderingen de laatste 2 wilt ongedaan maken, haal je terug het bestand van schijf op en doe de eerste acht (=10-2) veranderingen.
    Dit vraagt misschien iets meer tijd maar verbruikt maar weinig geheugen tov Marcel's idee.
    Na een 'Save' schrijf je de veranderde tekst op schijf en wis je de 'DO'-list.
    Dit heeft volgens mij als voordeel dat je GEEN undo-akties moet gaan uitvinden (de do-akties heb je al gemaakt) en er komt weinig extra programmeerwerk aan te pas.
    Je moet juist de do-akties met alle parameters kunnen noteren en omschrijven (om in een lijstje te kunnen zetten). Volgens mij moet dit voor bijna elk soort programma mogelijk zijn.

    Jurgen

  10. #10
    Senior Member PsychoMark's Avatar
    Join Date
    Nov 2001
    Location
    Raamsdonksveer
    Posts
    10,269
    Helemaal mee eens, op een kleine wijziging na:


    Originally posted by JKE
    Na een 'Save' schrijf je de veranderde tekst op schijf en wis je de 'DO'-list.

    ...dit vind ik persoonlijk een van de meest irritante instellingen die Delphi by default heeft . Ik heb nogal de neiging om vaak op Ctrl-S te raggen, en als ik dan wil Undo-en is alles weg. Dat is exact de reden waarom ik liever een Undo-mogelijkheid inbouw dan een Do-mogelijkheid zoals jij beschrijft... je kan gewoon de laatste versie opslaan in het geheugen / op schijf en Undo-en wat je wilt. Nog een bijkomend voordeel: als je 200 wijzigingen hebt aangebracht en alleen de laatste wilt toepassen scheelt je dat enorm veel tijd, met jouw techniek moet je dan 199 wijzigingen gaan aflopen
    Qui custodiet ipsos custodes

  11. #11
    Registered User
    Join Date
    Apr 2002
    Location
    Ekeren,Belgi?½
    Posts
    18
    Dat is waar, maar je zou een back-up file kunnen maken MET de 'do-list' , bij een save. Maar dan rijzen er weer nieuwe problemen....
    Maar zoals ik zelf al zei, deze manier neemt meer tijd in beslag maar dan wel een minimum aan geheugen tov het tussentijds opslaan van alles.


    Maar van alle mogelijkheden lijkt dit (voor mij) toch de meest voor de hand liggende.

    (tussen haakjes) als je 199 wijzigingen doet zonder tussendoor op te slaan kom je wel eens voor verassingen te staan

    Jurgen

  12. #12
    notice-itter SvG's Avatar
    Join Date
    Apr 2002
    Location
    's-Hertogenbosch
    Posts
    4,865
    Je moet er ook rekening mee houden wat je een undo waard vindt, zo vindt word het soms nodig om niet voor elk character een undo te maken, maar pas als je iets anders gaat doen dan typen. Dat vindt ik soms vrij irri, want soms wil ik alleen een paar dingen veranderen, en dan haalt word meteen de hele zin weg.
    Lijkt me ook wel een goed punt
    !

  13. #13
    Senior Member PsychoMark's Avatar
    Join Date
    Nov 2001
    Location
    Raamsdonksveer
    Posts
    10,269
    Het is niet echt een handig praktijkvoorbeeld die 200, maar je hebt best gebruikers die minder opslaan dan de gemiddelde programmeur, en leg dan maar eens uit waarom je applicatie zo enorm traag wordt

    Ik ben het echter wel met je eens dat wijzigingen opgeslagen moeten worden ipv een complete kopie, de manier waarop verschillen echter onze meningen (do vs. undo)...



    [Edit]

    @SVG: het gaat hier toch om een 3D objecten editor, dus dat lijkt me geen issue
    Qui custodiet ipsos custodes

  14. #14
    Nou, in feite heeft SVG best een aardig punt. Als ik bijvoorbeeld een 3d object verplaats, dan doe ik dat door de mouse te draggen. Op elk mousemove event roep ik object.move aan. Maar ik wil natuurlijk niet op elk mousemove event een Undo aanmaken want dan krijg ik dus wel heel erg veel Undo opdrachten. Ik moet dus het begin- en eindpunt (op mousedown en mouseup) van de move weten en dat dus gebruiken bij een eventuele Undo. Dat lijkt dus heel erg veel op het teksttype voorbeeldje van SVG.

    Hoe dan ook, dat soort dingen maakt de uiteindelijke implementatie van Undo in mijn app toch best lastiger dan ik in eerste instantie dacht... maar goed, das dan ook de uitdaging, nietwaar?
    If you can't solve the problem, it isn't a problem... - DeleD - 3D editor project - www.delgine.com

  15. #15
    notice-itter SvG's Avatar
    Join Date
    Apr 2002
    Location
    's-Hertogenbosch
    Posts
    4,865
    Misschien kun je hier een BeginDrag ( zelf maken natuurlijk ) procedure laten afvuren voor zo'n undo actie. De procedure slaat de huidige positie op van het object. De undo is dan simpelweg de positie weer goedzetten van het object.
    !

Page 1 of 2 1 2 LastLast

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. Een singleton class implementeren
    By GolezTrol in forum Tiphoek
    Replies: 0
    Last Post: 12-Oct-04, 12:52
  2. De theorie achter een class methods
    By Dees in forum Algemeen
    Replies: 15
    Last Post: 23-Jul-04, 15:51
  3. MediaPlayer + class
    By Tischnoetentoet in forum Algemeen
    Replies: 7
    Last Post: 08-Apr-04, 11:21
  4. Replies: 7
    Last Post: 13-Feb-03, 23:56

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •