summaryrefslogtreecommitdiff
path: root/src/generic/util/undo.h
blob: e82283f684625eec941b3fa10c1b607d721833fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// undo.h       -*-c++-*-
//
//  Copyright 2000 Daniel Burrows
//
//  

#ifndef UNDO_H
#define UNDO_H

#include <list>

#include <sigc++/signal.h>

/** \brief A generic structure for undo information.
 * 
 *  \file undo.h
 */

class undoable
// represents an action which can be undone.
{
public:
  virtual void undo()=0;
  // Undoes the action (doh! :) )

  virtual ~undoable() {}
};

class undo_group:public undoable
//  Groups several undo actions into a single shot -- does them from first to
// last..
{
  std::list<undoable *> items;
public:
  virtual void undo()
  {
    for(std::list<undoable *>::iterator i=items.begin(); i!=items.end(); i++)
      (*i)->undo();
  }

  void add_item(undoable *item)
  {
    items.push_front(item);
  }

  bool empty() {return items.empty();}

  virtual ~undo_group()
  {
    for(std::list<undoable *>::iterator i=items.begin(); i!=items.end(); i++)
      delete *i;
  }
};

class undo_list
//  A very very simple way to allow things to be undone.  It takes 
// responsibility for deleting pointers that it's given.
{
  std::list<undoable *> items;
  std::list<unsigned int> floors;
public:
  undo_list() {floors.push_back(0);}

  void undo();

  void add_item(undoable *item)
    // Inserts an item into the stack of undoable actions
  {
    items.push_front(item);
    changed();
  }

  void clear_items();

  unsigned int size() {return items.size();}
  void collapse_to(unsigned int prev_size);
  void revert_to(unsigned int prev_size);
  // These can be used to place a 'mark' in the undo stack at a given point,
  // then either collapse actions after that point to a single action
  // (collapse_to) or revert them altogether (revert_to)

  void push_floor(unsigned int floor);
  void pop_floor();

  /** \brief Emitted after a new entry is added to the list and after
   *  an entry is removed from the list.
   */
  sigc::signal0<void> changed;

  virtual ~undo_list()
  {
    for(std::list<undoable *>::iterator i=items.begin(); i!=items.end(); i++)
      delete (*i);
  }
};

#endif