undo.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /**
  2. \file undo.cpp
  3. \brief Undo/Redo functionality
  4. This program is free software under the GNU General Public
  5. License (>=v2). Read the file COPYING that comes with GRASS
  6. for details.
  7. (C) 2008 by The GRASS development team
  8. \author Martin Landa <landa.martin gmail.com>
  9. \date 2008
  10. */
  11. #include "driver.h"
  12. #include "digit.h"
  13. /**
  14. \brief Undo/Redo changes in geometry
  15. level=0 to revert all changes
  16. \param level level for undo/redo
  17. \return id of current chanset
  18. \return -2 on error
  19. */
  20. int Digit::Undo(int level)
  21. {
  22. int changesetLast;
  23. changesetLast = (int) changesets.size() - 1;
  24. if (changesetLast < 0)
  25. return changesetLast;
  26. if (changesetCurrent == -2) { /* value uninitialized */
  27. changesetCurrent = changesetLast;
  28. }
  29. if (level > 0 && changesetCurrent < 0) {
  30. changesetCurrent = 0;
  31. }
  32. if (level == 0) {
  33. /* 0 -> undo all */
  34. level = -changesetLast;
  35. }
  36. G_debug(2, "Digit.Undo(): changeset_last=%d, changeset_current=%d, level=%d",
  37. changesetLast, changesetCurrent, level);
  38. if (level < 0) { /* undo */
  39. if (changesetCurrent + level < -1)
  40. return changesetCurrent;
  41. for (int changeset = changesetCurrent; changeset >= changesetCurrent + level; --changeset) {
  42. ApplyChangeset(changeset, true);
  43. }
  44. }
  45. else if (level > 0) { /* redo */
  46. if (changesetCurrent + level > (int) changesets.size())
  47. return changesetCurrent;
  48. for (int changeset = changesetCurrent; changeset < changesetCurrent + level; ++changeset) {
  49. ApplyChangeset(changeset, false);
  50. }
  51. }
  52. changesetCurrent += level;
  53. G_debug(2, "Digit.Undo(): changeset_current=%d",
  54. changesetCurrent);
  55. return changesetCurrent;
  56. }
  57. /**
  58. \brief Apply changeset (undo/redo changeset)
  59. \param changeset changeset id
  60. \param undo if true -> undo otherwise redo
  61. \return 1 changeset applied
  62. \return 0 changeset not applied
  63. \return -1 on error
  64. */
  65. int Digit::ApplyChangeset(int changeset, bool undo)
  66. {
  67. int ret, line, type;
  68. if (changeset < 0 || changeset > (int) changesets.size())
  69. return -1;
  70. ret = 0;
  71. std::vector<action_meta> action = changesets[changeset];
  72. for (std::vector<action_meta>::const_reverse_iterator i = action.rbegin(), e = action.rend();
  73. i != e; ++i) {
  74. type = (*i).type;
  75. line = (*i).line;
  76. if ((undo && type == ADD) ||
  77. (!undo && type == DEL)) {
  78. if (Vect_line_alive(display->mapInfo, line)) {
  79. G_debug(3, "Digit.ApplyChangeset(): changeset=%d, action=add, line=%d -> deleted",
  80. changeset, line);
  81. Vect_delete_line(display->mapInfo, line);
  82. if (!ret)
  83. ret = 1;
  84. }
  85. else {
  86. G_debug(3, "Digit.ApplyChangeset(): changeset=%d, action=add, line=%d dead",
  87. changeset, (*i).line);
  88. }
  89. }
  90. else { /* DELETE */
  91. long offset = (*i).offset;
  92. if (!Vect_line_alive(display->mapInfo, line)) {
  93. G_debug(3, "Digit.ApplyChangeset(): changeset=%d, action=delete, line=%d -> added",
  94. changeset, line);
  95. if (Vect_restore_line(display->mapInfo, line, offset) < 0)
  96. return -1;
  97. if (!ret)
  98. ret = 1;
  99. }
  100. else {
  101. G_debug(3, "Digit.ApplyChangeset(): changeset=%d, action=delete, line=%d alive",
  102. changeset, line);
  103. }
  104. }
  105. }
  106. return ret;
  107. }
  108. /**
  109. \brief Add action to changeset
  110. \param type action type (ADD, DEL)
  111. \return 0 on success
  112. \return -1 on error
  113. */
  114. int Digit::AddActionToChangeset(int changeset, Digit::action_type type, int line)
  115. {
  116. long offset;
  117. if (!display->mapInfo) {
  118. display->DisplayMsg();
  119. return -1;
  120. }
  121. if (!Vect_line_alive(display->mapInfo, line)) {
  122. // display->DeadLineMsg(line);
  123. return -1;
  124. }
  125. offset = Vect_get_line_offset(display->mapInfo, line);
  126. action_meta data = { type, line, offset };
  127. if (changesets.find(changeset) == changesets.end()) {
  128. changesets[changeset] = std::vector<action_meta>();
  129. changesetCurrent = changeset;
  130. }
  131. changesets[changeset].push_back(data);
  132. G_debug (3, "Digit.AddActionToChangeset(): changeset=%d, type=%d, line=%d, offset=%ld",
  133. changeset, type, line, offset);
  134. return 0;
  135. }
  136. /**
  137. \brief Free changeset structures
  138. \param changeset changeset id
  139. */
  140. void Digit::FreeChangeset(int changeset)
  141. {
  142. if (changesets.find(changeset) == changesets.end())
  143. return;
  144. std::vector<action_meta> action = changesets[changeset];
  145. for (std::vector<action_meta>::iterator i = action.begin(), e = action.end();
  146. i != e; ++i) {
  147. ;
  148. }
  149. return;
  150. }
  151. /**
  152. \brief Remove action from changeset
  153. \param changeset changeset id
  154. \param type action type (ADD, DEL)
  155. \param line line id
  156. \return number of actions in changeset
  157. \return -1 on error
  158. */
  159. int Digit::RemoveActionFromChangeset(int changeset, Digit::action_type type, int line)
  160. {
  161. if (changesets.find(changeset) == changesets.end())
  162. return -1;
  163. std::vector<action_meta>& action = changesets[changeset];
  164. for (std::vector<action_meta>::iterator i = action.begin(); i != action.end(); ++i) {
  165. if ((*i).type == type && (*i).line == line) {
  166. G_debug (3, "Digit.RemoveActionFromChangeset(): changeset=%d, type=%d, line=%d",
  167. changeset, type, line);
  168. action.erase(i--);
  169. }
  170. }
  171. return action.size();
  172. }
  173. /**
  174. \brief Get undo level (number of active changesets)
  175. \return number
  176. */
  177. int Digit::GetUndoLevel()
  178. {
  179. return changesetCurrent;
  180. }