Здравствуйте, всех с прошедшими праздниками
Есть у меня код undo/redo
Сначала написал свой а затем взял из WYSIWYG редактора господ Merlin и Dimchansky класс History, в нем то же самое поведение массива
Добавляю итем в массив истории
При последовательном добавлении все нормально, новый элемент становится в конец массива
А если сделать несколько раз (или даже один раз) undo, новый элемент становится в предпоследнюю "ячейку" массива
Точнее даже сказать так:
После добавления в массив элемента я трэйсом вывожу этот массив, также и ПЕРЕД операцией добавления я вывожу его тоже трэйсом
А при нажатии на undo последующем действии (записывается новый итем истории) уже при выводе ДО добавления итема, основной массив УЖЕ содержит почему-то добавляемый элемент, причем он становится всегда в предпоследнюю "ячейку" массива
Черте что
Вот часть трэйса

Код:
добавление нового элемента: сейчас массив длиной в 2 pointer=2
Добавляемый элемент: matrix.a=1.175897479057312 matrix.b=-0.44668155908584595 matrix.c=0.44668155908584595
__historyStorage массив до изменения длины:
_step_ '0' matrix.a=1 matrix.b=0 matrix.c=0
_step_ '1' matrix.a=0.9348256587982178 matrix.b=-0.3551069498062134 matrix.c=0.3551069498062134
======================
__MainArray массив после изменения:
_step_ '0' matrix.a=1 matrix.b=0 matrix.c=0
_step_ '1' matrix.a=0.9348256587982178 matrix.b=-0.3551069498062134 matrix.c=0.3551069498062134
_step_ '2' matrix.a=1.175897479057312 matrix.b=-0.44668155908584595 matrix.c=0.44668155908584595
В массиве записаны 3 состояния
stepUp - Это UNDO
Отмотали на 1 назад
добавление нового элемента: сейчас массив длиной в 3 pointer=1
Добавляемый элемент: matrix.a=0.6870874762535095 matrix.b=0.7265746593475342 matrix.c=-0.7265746593475342
ОБРАТИТЕ ВНИМАНИЕ НА ЭЛЕМЕНТЫ МАССИВА ДО ЕГО ИЗМЕНЕНИЯ
СРАВНИТЕ ЭЛЕМЕНТЫ МАССИВОВ
__historyStorage массив до изменения длины:
_step_ '0' matrix.a=1 matrix.b=0 matrix.c=0
_step_ '1' matrix.a=0.68708749240745 matrix.b=0.7265746595673742 matrix.c=-0.7265746595673742
_step_ '2' matrix.a=1.175897479057312 matrix.b=-0.44668155908584595 matrix.c=0.44668155908584595
Добавляемый элемент "лезет" в предпоследнюю "ячейку" массива
CORRECTING...
======================
__MainArray массив после изменения:
_step_ '0' matrix.a=1 matrix.b=0 matrix.c=0
_step_ '1' matrix.a=0.6870874762535095 matrix.b=0.7265746593475342 matrix.c=-0.7265746593475342
Почему же так происходит ?
Вот код класса

Код AS3:
/**
* Класс с историей действий
*/
package div0.classes.history {
import flash.events.*;
import flash.display.MovieClip;
public class History extends MovieClip{
private var dataDonor:MovieClip;
private var MainArray:Array=new Array();
// глубина буфера истории
private var historyDepth:uint;
// массив, содержащий итемы истории
private var historyStorage:Array=new Array();
// указатель на текущее состояние в массиве истории
private var pointer:int = 0;
private var i:int;
private var historyUnit:historyItem;
private var UndoBtn:MovieClip;
private var RedoBtn:MovieClip;
public function History(depth:uint,undo:MovieClip,redo:MovieClip,dD:MovieClip):void{
trace("parent="+parent);
historyDepth = depth;
UndoBtn=undo;
RedoBtn=redo;
dataDonor=dD;
RedoBtn.disable();
UndoBtn.disable();
}
// корректируем список redo, если до этого была операция отмены и были трансформации
public function correct():void{
trace("CORRECTING...");
if ( emptyHistoryBuffer() && pointer != historyStorage.length) return;
historyStorage = historyStorage.slice(0, pointer);
}
// добавляем в историю состояние
public function addHistoryItem():void{
var AddItem:historyItem=new historyItem(dataDonor.picTransform,dataDonor.colorsTransform,Math.random());
historyStorage=MainArray.concat();
for(var t:int=0;t<historyStorage.length;t++){
if(AddItem==historyStorage[t]){
trace("добавляемый элемент уже существует !!!!");
}
}
trace("\nдобавление нового элемента: сейчас массив длиной в "+historyStorage.length+" pointer="+pointer);
trace("Добавляемый элемент: matrix.a="+AddItem.transformObject.matr.a+" matrix.b="+AddItem.transformObject.matr.b+" matrix.c="+AddItem.transformObject.matr.c);
trace("__historyStorage массив до изменения длины:");
for(i=0;i<historyStorage.length;i++){
trace("_step_ '"+i+"' matrix.a="+historyStorage[i].transformObject.matr.a+" matrix.b="+historyStorage[i].transformObject.matr.b+" matrix.c="+historyStorage[i].transformObject.matr.c);
}
if ( !historyStorage ){
historyStorage = new Array();
}
if (pointer != historyStorage.length){
correct();
}
// если буфер истории полон, сдвигаем (выталкиваем) первые элементы и добавляем в конец новое состояние
while ( historyStorage.length >= historyDepth ) {
historyStorage.shift();
}
historyStorage.push(AddItem);
//pointer=historyStorage.length;
//historyStorage[pointer]=AddItem;
MainArray=historyStorage.concat();
pointer = historyStorage.length;
RedoBtn.disable();
UndoBtn.enable();
trace("======================\n__MainArray массив после изменения:");
for(var u:int=0;u<MainArray.length;u++){
trace("_step_ '"+u+"' matrix.a="+MainArray[u].transformObject.matr.a+" matrix.b="+MainArray[u].transformObject.matr.b+" matrix.c="+MainArray[u].transformObject.matr.c);
}
}
// отмена действия (undo)
public function stepUp():historyItem{
trace("stepUp");
//trace("emptyHistoryBuffer()="+emptyHistoryBuffer());
RedoBtn.enable();
historyUnit=null;
if (emptyHistoryBuffer()){
return historyUnit;
}
if (pointer == historyStorage.length) {
//addHistoryItem();
pointer--;
}
if ( pointer-- <= 0){
pointer = 0;
UndoBtn.disable();
}
historyStorage=MainArray.concat();
historyUnit = historyStorage[pointer];
return historyUnit;
}
// повтор действия (redo)
public function stepDown():historyItem{
UndoBtn.enable();
historyUnit=null;
if ( emptyHistoryBuffer() ){
return historyUnit;
}
if ( pointer++ >= (historyStorage.length - 1)) {
pointer = historyStorage.length - 1;
RedoBtn.disable();
}else {
historyStorage=MainArray.concat();
historyUnit = historyStorage[pointer];
}
return historyUnit;
}
public function clearHistory():void{
trace("CLEARING HISTORY");
//historyArray=new Array();
historyStorage.length
RedoBtn.disable();
UndoBtn.disable();
pointer=0;
}
// проверка на существование массива действий
private function emptyHistoryBuffer():Boolean{
return ( !historyStorage || historyStorage.length == 0 );
}
}
}