Command Pattern

Share your advanced PureBasic knowledge/code with the community.
remi_meier
Enthusiast
Enthusiast
Posts: 468
Joined: Sat Dec 20, 2003 6:19 pm
Location: Switzerland

Command Pattern

Post by remi_meier »

Coded and not tested much as an alternative to the
Demento from this thread:
http://www.purebasic.fr/english/viewtop ... 12&t=42867

This software pattern allows one to modularize and
implement a straight forward undo/redo mechanism.
You can read more about it under
http://en.wikipedia.org/wiki/Command_pattern

Actually, even if it obviously screams to be implemented
in OOP, this was made in a hurry and therefore is
straight forward procedural PB :mrgreen:

have fun!

Code: Select all

Prototype command_do(*info)
Prototype command_undo(*info)
Prototype command_free_info(*info)


Structure COMMAND
  do.command_do
  undo.command_undo
  free.command_free_info
  *info
EndStructure

Structure UNDO_MANAGER
  List undo_stack.COMMAND()
  List redo_stack.COMMAND()
EndStructure




Procedure new_undo_manager()
  *um.UNDO_MANAGER = AllocateMemory(SizeOf(UNDO_MANAGER))
  InitializeStructure(*um, UNDO_MANAGER)
  ProcedureReturn *um
EndProcedure

Procedure delete_undo_manager(*um.UNDO_MANAGER)
  ClearStructure(*um, UNDO_MANAGER)
  FreeMemory(*um)
EndProcedure

Procedure add_command(*um.UNDO_MANAGER, do.command_do, undo.command_undo, free_info.command_free_info, *info)
  
  ForEach *um\redo_stack()
    With *um\redo_stack()
      \free(\info)
    EndWith 
  Next
  ClearList(*um\redo_stack())
  
  AddElement(*um\undo_stack())
  With *um\undo_stack()
    \info = *info
    \do = do
    \undo = undo
    \free = free_info
  EndWith
  
EndProcedure

Procedure do(*um.UNDO_MANAGER)
  *um\undo_stack()\do(*um\undo_stack()\info)
EndProcedure

Procedure undo(*um.UNDO_MANAGER)
   If ListSize(*um\undo_stack()) > 0
    *um\undo_stack()\undo(*um\undo_stack()\info)
    
    AddElement(*um\redo_stack())
    With *um\redo_stack()
      \info = *um\undo_stack()\info
      \do = *um\undo_stack()\do
      \undo = *um\undo_stack()\undo
      \free = *um\undo_stack()\free
    EndWith
    DeleteElement(*um\undo_stack())
  EndIf
EndProcedure


Procedure redo(*um.UNDO_MANAGER)
  If ListSize(*um\redo_stack()) > 0
    *um\redo_stack()\do(*um\redo_stack()\info)
    
    AddElement(*um\undo_stack())
    With *um\undo_stack()
      \info = *um\redo_stack()\info
      \do = *um\redo_stack()\do
      \undo = *um\redo_stack()\undo
      \free = *um\redo_stack()\free
    EndWith
    DeleteElement(*um\redo_stack())
  EndIf
EndProcedure


;------------------------------------------ here is one example command:
Structure REPLACE_CHAR
  *pos.Character
  char.c
  old_char.c
EndStructure

Procedure.i replace_char_get_info(*pos.Character, char.c)
  *info.REPLACE_CHAR = AllocateMemory(SizeOf (REPLACE_CHAR))
  With *info
    \pos = *pos
    \char = char
    \old_char = *pos\c
  EndWith
  
  ProcedureReturn *info  
EndProcedure

Procedure replace_char_free_info(*info.REPLACE_CHAR)
  FreeMemory(*info)
EndProcedure

Procedure replace_char_do(*info.REPLACE_CHAR)
  *info\pos\c = *info\char
EndProcedure

Procedure replace_char_undo(*info.REPLACE_CHAR)
  *info\pos\c = *info\old_char
EndProcedure



;------------------------------------------ example

string.s = "Hello World!"
um = new_undo_manager()

Debug string

add_command(um, @replace_char_do(), @replace_char_undo(), @replace_char_free_info(), replace_char_get_info(@string+4*SizeOf (Character), 'X'))
do(um)

Debug string

undo(um)

Debug string

redo(um)

Debug string
Athlon64 3700+, 1024MB Ram, Radeon X1600
User avatar
zxtunes.com
Enthusiast
Enthusiast
Posts: 375
Joined: Wed Apr 23, 2008 7:51 am
Location: Saint-Petersburg, Russia
Contact:

Re: Command Pattern

Post by zxtunes.com »

it looks interesting. :o
I do gfx editor, there are undo / redo, but with bug.
I will deal with your procedure.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Command Pattern

Post by netmaestro »

Looks very clean and something I'll be needing soon.

You post infrequently, but when you do it's always of great value. You possess a focus and clarity of thought that is rare in a coder of any level and you are a hero of mine. Thank you :D
BERESHEIT
remi_meier
Enthusiast
Enthusiast
Posts: 468
Joined: Sat Dec 20, 2003 6:19 pm
Location: Switzerland

Re: Command Pattern

Post by remi_meier »

netmaestro wrote:Looks very clean and something I'll be needing soon.

You post infrequently, but when you do it's always of great value. You possess a focus and clarity of thought that is rare in a coder of any level and you are a hero of mine. Thank you :D
Thank you :oops:
Athlon64 3700+, 1024MB Ram, Radeon X1600
boo
New User
New User
Posts: 1
Joined: Tue Dec 21, 2010 6:36 am

Re: Command Pattern

Post by boo »

Hello
Can anyone help me with the code, please. I programmed less frequently.
I want a Undo/Redo for a ListviewGadget, but it is too difficult for me.
I need help very soon.
Thank you very much.
Post Reply