@@ -37,7 +37,10 @@ type |
| 37 |
Pattern: TPattern; |
37 |
Pattern: TPattern; |
| 38 |
end; |
38 |
end; |
| 39 |
|
39 |
|
| 40 |
TUndoRedoAction = array[0..3] of TSavedPattern; |
40 |
TSavedPatternSet = array[0..3] of TSavedPattern; |
|
|
41 |
TUndoRedoAction = record |
|
|
42 |
Before, After: TSavedPatternSet; |
|
|
43 |
end; |
| 41 |
TUndoDeque = TDeque<TUndoRedoAction>; |
44 |
TUndoDeque = TDeque<TUndoRedoAction>; |
| 42 |
TRedoStack = TStack<TUndoRedoAction>; |
45 |
TRedoStack = TStack<TUndoRedoAction>; |
| 43 |
|
46 |
|
@@ -74,7 +77,8 @@ type |
| 74 |
procedure DoPaste(var Msg: TLMessage); message LM_PASTE; |
77 |
procedure DoPaste(var Msg: TLMessage); message LM_PASTE; |
| 75 |
procedure DoCopy(var Msg: TLMessage); message LM_COPY; |
78 |
procedure DoCopy(var Msg: TLMessage); message LM_COPY; |
| 76 |
procedure DoCut(var Msg: TLMessage); message LM_CUT; |
79 |
procedure DoCut(var Msg: TLMessage); message LM_CUT; |
| 77 |
procedure SaveUndoState; |
80 |
procedure BeginUndoAction; |
|
|
81 |
procedure EndUndoAction; |
| 78 |
|
82 |
|
| 79 |
procedure RenderSelectedArea; |
83 |
procedure RenderSelectedArea; |
| 80 |
procedure ClampCursors; |
84 |
procedure ClampCursors; |
@@ -115,6 +119,8 @@ type |
| 115 |
DragSelCursor, DragSelOther: TSelectionPos; |
119 |
DragSelCursor, DragSelOther: TSelectionPos; |
| 116 |
DragOffsetY: Integer; |
120 |
DragOffsetY: Integer; |
| 117 |
|
121 |
|
|
|
122 |
NestedUndoCount: Integer; |
|
|
123 |
CurrentUndoAction: TUndoRedoAction; |
| 118 |
Performed: TUndoDeque; |
124 |
Performed: TUndoDeque; |
| 119 |
Recall: TRedoStack; |
125 |
Recall: TRedoStack; |
| 120 |
|
126 |
|
@@ -226,6 +232,7 @@ begin |
| 226 |
|
232 |
|
| 227 |
Self.PatternMap := PatternMap; |
233 |
Self.PatternMap := PatternMap; |
| 228 |
|
234 |
|
|
|
235 |
NestedUndoCount := 0; |
| 229 |
Performed := TUndoDeque.Create; |
236 |
Performed := TUndoDeque.Create; |
| 230 |
Recall := TRedoStack.Create; |
237 |
Recall := TRedoStack.Create; |
| 231 |
|
238 |
|
@@ -388,6 +395,8 @@ begin |
| 388 |
MouseButtonDown := False; |
395 |
MouseButtonDown := False; |
| 389 |
|
396 |
|
| 390 |
if DraggingSelection then begin |
397 |
if DraggingSelection then begin |
|
|
398 |
BeginUndoAction; |
|
|
399 |
|
| 391 |
Selection := GetSelection; |
400 |
Selection := GetSelection; |
| 392 |
EraseSelection; |
401 |
EraseSelection; |
| 393 |
PerformPaste(Selection, DragSelCursor); |
402 |
PerformPaste(Selection, DragSelCursor); |
@@ -395,7 +404,8 @@ begin |
| 395 |
Other := DragSelOther; |
404 |
Other := DragSelOther; |
| 396 |
|
405 |
|
| 397 |
DraggingSelection := False; |
406 |
DraggingSelection := False; |
| 398 |
SaveUndoState; |
407 |
|
|
|
408 |
EndUndoAction; |
| 399 |
end; |
409 |
end; |
| 400 |
|
410 |
|
| 401 |
NormalizeCursors; |
411 |
NormalizeCursors; |
@@ -415,8 +425,7 @@ procedure TTrackerGrid.KeyDown(var Key: Word; Shift: TShiftState); |
| 415 |
begin |
425 |
begin |
| 416 |
inherited KeyDown(Key, Shift); |
426 |
inherited KeyDown(Key, Shift); |
| 417 |
|
427 |
|
| 418 |
if Key in [VK_CONTROL, VK_SHIFT] then Exit; |
428 |
if Key in [VK_CONTROL, VK_SHIFT, VK_DELETE] then Exit; |
| 419 |
if Key in [VK_DELETE] then Exit; |
|
|
| 420 |
|
429 |
|
| 421 |
case Key of |
430 |
case Key of |
| 422 |
VK_UP: Dec(Cursor.Y); |
431 |
VK_UP: Dec(Cursor.Y); |
@@ -448,7 +457,7 @@ begin |
| 448 |
if (Cursor.Y > High(TPattern)) or (Cursor.Y < Low(TPattern)) then |
457 |
if (Cursor.Y > High(TPattern)) or (Cursor.Y < Low(TPattern)) then |
| 449 |
if Assigned(OnCursorOutOfBounds) then OnCursorOutOfBounds; |
458 |
if Assigned(OnCursorOutOfBounds) then OnCursorOutOfBounds; |
| 450 |
|
459 |
|
| 451 |
if not (ssShift in Shift) then |
460 |
if Shift = [] then |
| 452 |
Other := Cursor; |
461 |
Other := Cursor; |
| 453 |
|
462 |
|
| 454 |
ClampCursors; |
463 |
ClampCursors; |
@@ -518,6 +527,8 @@ var |
| 518 |
Selection: TSelection; |
527 |
Selection: TSelection; |
| 519 |
I: Integer; |
528 |
I: Integer; |
| 520 |
begin |
529 |
begin |
|
|
530 |
BeginUndoAction; |
|
|
531 |
|
| 521 |
Selection := GetPastedCells; |
532 |
Selection := GetPastedCells; |
| 522 |
I := Cursor.Y; |
533 |
I := Cursor.Y; |
| 523 |
while I <= High(TPattern) do begin |
534 |
while I <= High(TPattern) do begin |
@@ -527,15 +538,17 @@ begin |
| 527 |
end; |
538 |
end; |
| 528 |
|
539 |
|
| 529 |
Invalidate; |
540 |
Invalidate; |
| 530 |
SaveUndoState; |
541 |
EndUndoAction; |
| 531 |
end; |
542 |
end; |
| 532 |
|
543 |
|
| 533 |
procedure TTrackerGrid.DoPaste(var Msg: TLMessage); |
544 |
procedure TTrackerGrid.DoPaste(var Msg: TLMessage); |
| 534 |
begin |
545 |
begin |
|
|
546 |
BeginUndoAction; |
|
|
547 |
|
| 535 |
PerformPaste(GetPastedCells); |
548 |
PerformPaste(GetPastedCells); |
| 536 |
|
549 |
|
| 537 |
Invalidate; |
550 |
Invalidate; |
| 538 |
SaveUndoState; |
551 |
EndUndoAction; |
| 539 |
end; |
552 |
end; |
| 540 |
|
553 |
|
| 541 |
procedure TTrackerGrid.DoCopy(var Msg: TLMessage); |
554 |
procedure TTrackerGrid.DoCopy(var Msg: TLMessage); |
@@ -549,45 +562,66 @@ begin |
| 549 |
EraseSelection; |
562 |
EraseSelection; |
| 550 |
end; |
563 |
end; |
| 551 |
|
564 |
|
| 552 |
procedure TTrackerGrid.SaveUndoState; |
565 |
procedure TTrackerGrid.BeginUndoAction; |
| 553 |
var |
566 |
var |
| 554 |
Actn: TUndoRedoAction; |
|
|
| 555 |
I: Integer; |
567 |
I: Integer; |
| 556 |
begin |
568 |
begin |
| 557 |
// First, clear out the recall stack |
569 |
if NestedUndoCount = 0 then begin |
| 558 |
while not Recall.IsEmpty do |
570 |
// Save the "before" to our current undo action, so that EndUndoAction |
| 559 |
Recall.Pop; |
571 |
// can save the "after" and commit it to the Performed stack. |
|
|
572 |
CurrentUndoAction := Default(TUndoRedoAction); |
|
|
573 |
for I := Low(Patterns) to High(Patterns) do |
|
|
574 |
with CurrentUndoAction.Before[I] do begin |
|
|
575 |
Pattern := Patterns[I]^; |
|
|
576 |
PatternNumber := PatternNumbers[I]; |
|
|
577 |
end; |
|
|
578 |
end; |
| 560 |
|
579 |
|
| 561 |
// Create the state we need to save |
580 |
Inc(NestedUndoCount); |
| 562 |
Actn := Default(TUndoRedoAction); |
581 |
end; |
| 563 |
for I := Low(Patterns) to High(Patterns) do |
582 |
|
| 564 |
with Actn[I] do begin |
583 |
procedure TTrackerGrid.EndUndoAction; |
| 565 |
Pattern := Patterns[I]^; |
584 |
var |
| 566 |
PatternNumber := PatternNumbers[I]; |
585 |
I: Integer; |
| 567 |
end; |
586 |
begin |
|
|
587 |
if NestedUndoCount = 1 then begin |
|
|
588 |
// First, clear out the recall stack |
|
|
589 |
while not Recall.IsEmpty do |
|
|
590 |
Recall.Pop; |
|
|
591 |
|
|
|
592 |
// Save the "after" to our current undo action |
|
|
593 |
for I := Low(Patterns) to High(Patterns) do |
|
|
594 |
with CurrentUndoAction.After[I] do begin |
|
|
595 |
Pattern := Patterns[I]^; |
|
|
596 |
PatternNumber := PatternNumbers[I]; |
|
|
597 |
end; |
| 568 |
|
598 |
|
| 569 |
// Push it into the performed queue |
599 |
// Commit the action to the Performed stack |
| 570 |
Performed.PushFront(Actn); |
600 |
Performed.PushFront(CurrentUndoAction); |
| 571 |
while Performed.Size > UNDO_STACK_SIZE do |
601 |
|
| 572 |
Performed.PopBack; |
602 |
// Keep the stack size, at maximum, UNDO_STACK_SIZE |
|
|
603 |
while Performed.Size > UNDO_STACK_SIZE do |
|
|
604 |
Performed.PopBack; |
|
|
605 |
end; |
|
|
606 |
|
|
|
607 |
Dec(NestedUndoCount); |
| 573 |
end; |
608 |
end; |
| 574 |
|
609 |
|
| 575 |
procedure TTrackerGrid.DoUndo; |
610 |
procedure TTrackerGrid.DoUndo; |
| 576 |
var |
611 |
var |
| 577 |
OldState, NewState: TUndoRedoAction; |
612 |
State: TUndoRedoAction; |
| 578 |
I: Integer; |
613 |
I: Integer; |
| 579 |
begin |
614 |
begin |
| 580 |
if Performed.IsEmpty then Exit; |
615 |
if Performed.IsEmpty then Exit; |
| 581 |
|
616 |
|
| 582 |
OldState := Performed.Front; |
617 |
State := Performed.Front; |
| 583 |
Performed.PopFront; |
618 |
Performed.PopFront; |
| 584 |
NewState := Performed.Front; |
|
|
| 585 |
|
619 |
|
| 586 |
Recall.Push(OldState); |
620 |
Recall.Push(State); |
| 587 |
|
621 |
|
| 588 |
for I := Low(NewState) to High(NewState) do begin |
622 |
for I := Low(State.Before) to High(State.Before) do begin |
| 589 |
LoadPattern(I, NewState[I].PatternNumber); |
623 |
LoadPattern(I, State.Before[I].PatternNumber); |
| 590 |
Patterns[I]^ := NewState[I].Pattern; |
624 |
Patterns[I]^ := State.Before[I].Pattern; |
| 591 |
end; |
625 |
end; |
| 592 |
|
626 |
|
| 593 |
Invalidate; |
627 |
Invalidate; |
@@ -605,9 +639,9 @@ begin |
| 605 |
|
639 |
|
| 606 |
Performed.PushFront(State); |
640 |
Performed.PushFront(State); |
| 607 |
|
641 |
|
| 608 |
for I := Low(State) to High(State) do begin |
642 |
for I := Low(State.After) to High(State.After) do begin |
| 609 |
LoadPattern(I, State[I].PatternNumber); |
643 |
LoadPattern(I, State.After[I].PatternNumber); |
| 610 |
Patterns[I]^ := State[I].Pattern; |
644 |
Patterns[I]^ := State.After[I].Pattern; |
| 611 |
end; |
645 |
end; |
| 612 |
|
646 |
|
| 613 |
Invalidate; |
647 |
Invalidate; |
@@ -684,6 +718,8 @@ procedure TTrackerGrid.IncrementSelection(Note, Instrument, Volume, EffectCode, |
| 684 |
var |
718 |
var |
| 685 |
Pos: TSelectionPos; |
719 |
Pos: TSelectionPos; |
| 686 |
begin |
720 |
begin |
|
|
721 |
BeginUndoAction; |
|
|
722 |
|
| 687 |
NormalizeCursors; |
723 |
NormalizeCursors; |
| 688 |
|
724 |
|
| 689 |
Pos := Cursor; |
725 |
Pos := Cursor; |
@@ -705,7 +741,7 @@ begin |
| 705 |
end; |
741 |
end; |
| 706 |
|
742 |
|
| 707 |
Invalidate; |
743 |
Invalidate; |
| 708 |
SaveUndoState |
744 |
EndUndoAction |
| 709 |
end; |
745 |
end; |
| 710 |
|
746 |
|
| 711 |
procedure TTrackerGrid.InterpolateSelection; |
747 |
procedure TTrackerGrid.InterpolateSelection; |
@@ -714,6 +750,8 @@ var |
| 714 |
Pos: TSelectionPos; |
750 |
Pos: TSelectionPos; |
| 715 |
StartCell: TCell; |
751 |
StartCell: TCell; |
| 716 |
begin |
752 |
begin |
|
|
753 |
BeginUndoAction; |
|
|
754 |
|
| 717 |
NormalizeCursors; |
755 |
NormalizeCursors; |
| 718 |
|
756 |
|
| 719 |
if Cursor.Y = Other.Y then Exit; |
757 |
if Cursor.Y = Other.Y then Exit; |
@@ -740,16 +778,18 @@ begin |
| 740 |
end; |
778 |
end; |
| 741 |
|
779 |
|
| 742 |
Invalidate; |
780 |
Invalidate; |
| 743 |
SaveUndoState |
781 |
EndUndoAction |
| 744 |
end; |
782 |
end; |
| 745 |
|
783 |
|
| 746 |
procedure TTrackerGrid.OpenEffectEditor; |
784 |
procedure TTrackerGrid.OpenEffectEditor; |
| 747 |
begin |
785 |
begin |
|
|
786 |
BeginUndoAction; |
|
|
787 |
|
| 748 |
frmEffectEditor.Cell := @Patterns[Cursor.X]^[Cursor.Y]; |
788 |
frmEffectEditor.Cell := @Patterns[Cursor.X]^[Cursor.Y]; |
| 749 |
frmEffectEditor.ShowModal; |
789 |
frmEffectEditor.ShowModal; |
| 750 |
|
790 |
|
| 751 |
Invalidate; |
791 |
Invalidate; |
| 752 |
SaveUndoState |
792 |
EndUndoAction |
| 753 |
end; |
793 |
end; |
| 754 |
|
794 |
|
| 755 |
procedure TTrackerGrid.EraseSelection; |
795 |
procedure TTrackerGrid.EraseSelection; |
@@ -757,6 +797,8 @@ var |
| 757 |
X: TSelectionPos; |
797 |
X: TSelectionPos; |
| 758 |
R: Integer; |
798 |
R: Integer; |
| 759 |
begin |
799 |
begin |
|
|
800 |
BeginUndoAction; |
|
|
801 |
|
| 760 |
NormalizeCursors; |
802 |
NormalizeCursors; |
| 761 |
|
803 |
|
| 762 |
for R := Cursor.Y to Other.Y do begin |
804 |
for R := Cursor.Y to Other.Y do begin |
@@ -769,13 +811,14 @@ begin |
| 769 |
end; |
811 |
end; |
| 770 |
|
812 |
|
| 771 |
Invalidate; |
813 |
Invalidate; |
| 772 |
SaveUndoState; |
814 |
EndUndoAction; |
| 773 |
end; |
815 |
end; |
| 774 |
|
816 |
|
| 775 |
procedure TTrackerGrid.InputNote(Key: Word); |
817 |
procedure TTrackerGrid.InputNote(Key: Word); |
| 776 |
var |
818 |
var |
| 777 |
Temp: Integer; |
819 |
Temp: Integer; |
| 778 |
begin |
820 |
begin |
|
|
821 |
BeginUndoAction; |
| 779 |
Temp := -1; |
822 |
Temp := -1; |
| 780 |
|
823 |
|
| 781 |
with Patterns[Cursor.X]^[Cursor.Y] do |
824 |
with Patterns[Cursor.X]^[Cursor.Y] do |
@@ -795,13 +838,14 @@ begin |
| 795 |
end; |
838 |
end; |
| 796 |
|
839 |
|
| 797 |
Invalidate; |
840 |
Invalidate; |
| 798 |
SaveUndoState; |
841 |
EndUndoAction; |
| 799 |
end; |
842 |
end; |
| 800 |
|
843 |
|
| 801 |
procedure TTrackerGrid.InputInstrument(Key: Word); |
844 |
procedure TTrackerGrid.InputInstrument(Key: Word); |
| 802 |
var |
845 |
var |
| 803 |
Temp: Nibble; |
846 |
Temp: Nibble; |
| 804 |
begin |
847 |
begin |
|
|
848 |
BeginUndoAction; |
| 805 |
with Patterns[Cursor.X]^[Cursor.Y] do begin |
849 |
with Patterns[Cursor.X]^[Cursor.Y] do begin |
| 806 |
if Key = VK_DELETE then Instrument := 0 |
850 |
if Key = VK_DELETE then Instrument := 0 |
| 807 |
else if KeycodeToHexNumber(Key, Temp) and InRange(Temp, 0, 9) then |
851 |
else if KeycodeToHexNumber(Key, Temp) and InRange(Temp, 0, 9) then |
@@ -809,7 +853,7 @@ begin |
| 809 |
end; |
853 |
end; |
| 810 |
|
854 |
|
| 811 |
Invalidate; |
855 |
Invalidate; |
| 812 |
SaveUndoState; |
856 |
EndUndoAction; |
| 813 |
end; |
857 |
end; |
| 814 |
|
858 |
|
| 815 |
procedure TTrackerGrid.InputVolume(Key: Word); |
859 |
procedure TTrackerGrid.InputVolume(Key: Word); |
@@ -819,6 +863,7 @@ end; |
| 819 |
|
863 |
|
| 820 |
procedure TTrackerGrid.InputEffectCode(Key: Word); |
864 |
procedure TTrackerGrid.InputEffectCode(Key: Word); |
| 821 |
begin |
865 |
begin |
|
|
866 |
BeginUndoAction; |
| 822 |
with Patterns[Cursor.X]^[Cursor.Y] do |
867 |
with Patterns[Cursor.X]^[Cursor.Y] do |
| 823 |
if Key = VK_DELETE then begin |
868 |
if Key = VK_DELETE then begin |
| 824 |
EffectCode := 0; |
869 |
EffectCode := 0; |
@@ -827,13 +872,14 @@ begin |
| 827 |
else KeycodeToHexNumber(Key, EffectCode); |
872 |
else KeycodeToHexNumber(Key, EffectCode); |
| 828 |
|
873 |
|
| 829 |
Invalidate; |
874 |
Invalidate; |
| 830 |
SaveUndoState; |
875 |
EndUndoAction; |
| 831 |
end; |
876 |
end; |
| 832 |
|
877 |
|
| 833 |
procedure TTrackerGrid.InputEffectParams(Key: Word); |
878 |
procedure TTrackerGrid.InputEffectParams(Key: Word); |
| 834 |
var |
879 |
var |
| 835 |
Temp: Nibble; |
880 |
Temp: Nibble; |
| 836 |
begin |
881 |
begin |
|
|
882 |
BeginUndoAction; |
| 837 |
with Patterns[Cursor.X]^[Cursor.Y] do |
883 |
with Patterns[Cursor.X]^[Cursor.Y] do |
| 838 |
if Key = VK_DELETE then begin |
884 |
if Key = VK_DELETE then begin |
| 839 |
EffectCode := 0; |
885 |
EffectCode := 0; |
@@ -843,7 +889,7 @@ begin |
| 843 |
EffectParams.Value := ((EffectParams.Value mod $10) * $10) + Temp; |
889 |
EffectParams.Value := ((EffectParams.Value mod $10) * $10) + Temp; |
| 844 |
|
890 |
|
| 845 |
Invalidate; |
891 |
Invalidate; |
| 846 |
SaveUndoState; |
892 |
EndUndoAction; |
| 847 |
end; |
893 |
end; |
| 848 |
|
894 |
|
| 849 |
procedure TTrackerGrid.RenderRow(Row: Integer); |
895 |
procedure TTrackerGrid.RenderRow(Row: Integer); |
@@ -1189,6 +1235,7 @@ procedure TTrackerGrid.InsertRowInPatternAtCursor(Pattern: Integer); |
| 1189 |
var |
1235 |
var |
| 1190 |
I: Integer; |
1236 |
I: Integer; |
| 1191 |
begin |
1237 |
begin |
|
|
1238 |
BeginUndoAction; |
| 1192 |
NormalizeCursors; |
1239 |
NormalizeCursors; |
| 1193 |
|
1240 |
|
| 1194 |
for I := High(TPattern) downto Cursor.Y do |
1241 |
for I := High(TPattern) downto Cursor.Y do |
@@ -1197,26 +1244,27 @@ begin |
| 1197 |
BlankCell(Patterns[Pattern]^[Cursor.Y]); |
1244 |
BlankCell(Patterns[Pattern]^[Cursor.Y]); |
| 1198 |
|
1245 |
|
| 1199 |
Invalidate; |
1246 |
Invalidate; |
| 1200 |
SaveUndoState; |
1247 |
EndUndoAction; |
| 1201 |
end; |
1248 |
end; |
| 1202 |
|
1249 |
|
| 1203 |
procedure TTrackerGrid.InsertRowInAllAtCursor; |
1250 |
procedure TTrackerGrid.InsertRowInAllAtCursor; |
| 1204 |
var |
1251 |
var |
| 1205 |
I: Integer; |
1252 |
I: Integer; |
| 1206 |
begin |
1253 |
begin |
| 1207 |
for I := Low(Patterns) to High(Patterns) do begin |
1254 |
BeginUndoAction; |
|
|
1255 |
|
|
|
1256 |
for I := Low(Patterns) to High(Patterns) do |
| 1208 |
InsertRowInPatternAtCursor(I); |
1257 |
InsertRowInPatternAtCursor(I); |
| 1209 |
Performed.PopFront; // hack, maybe change the way this works later |
|
|
| 1210 |
end; |
|
|
| 1211 |
|
1258 |
|
| 1212 |
Invalidate; |
1259 |
Invalidate; |
| 1213 |
SaveUndoState; |
1260 |
EndUndoAction; |
| 1214 |
end; |
1261 |
end; |
| 1215 |
|
1262 |
|
| 1216 |
procedure TTrackerGrid.DeleteRowInPatternAtCursor(Pattern: Integer); |
1263 |
procedure TTrackerGrid.DeleteRowInPatternAtCursor(Pattern: Integer); |
| 1217 |
var |
1264 |
var |
| 1218 |
I: Integer; |
1265 |
I: Integer; |
| 1219 |
begin |
1266 |
begin |
|
|
1267 |
BeginUndoAction; |
| 1220 |
NormalizeCursors; |
1268 |
NormalizeCursors; |
| 1221 |
|
1269 |
|
| 1222 |
for I := Cursor.Y to High(TPattern)-1 do |
1270 |
for I := Cursor.Y to High(TPattern)-1 do |
@@ -1225,20 +1273,20 @@ begin |
| 1225 |
BlankCell(Patterns[Pattern]^[High(TPattern)]); |
1273 |
BlankCell(Patterns[Pattern]^[High(TPattern)]); |
| 1226 |
|
1274 |
|
| 1227 |
Invalidate; |
1275 |
Invalidate; |
| 1228 |
SaveUndoState; |
1276 |
EndUndoAction; |
| 1229 |
end; |
1277 |
end; |
| 1230 |
|
1278 |
|
| 1231 |
procedure TTrackerGrid.DeleteRowInAllAtCursor; |
1279 |
procedure TTrackerGrid.DeleteRowInAllAtCursor; |
| 1232 |
var |
1280 |
var |
| 1233 |
I: Integer; |
1281 |
I: Integer; |
| 1234 |
begin |
1282 |
begin |
| 1235 |
for I := Low(Patterns) to High(Patterns) do begin |
1283 |
BeginUndoAction; |
|
|
1284 |
|
|
|
1285 |
for I := Low(Patterns) to High(Patterns) do |
| 1236 |
DeleteRowInPatternAtCursor(I); |
1286 |
DeleteRowInPatternAtCursor(I); |
| 1237 |
Performed.PopFront; // hack, maybe change the way this works later |
|
|
| 1238 |
end; |
|
|
| 1239 |
|
1287 |
|
| 1240 |
Invalidate; |
1288 |
Invalidate; |
| 1241 |
SaveUndoState; |
1289 |
EndUndoAction; |
| 1242 |
end; |
1290 |
end; |
| 1243 |
|
1291 |
|
| 1244 |
procedure TTrackerGrid.SelectAll; |
1292 |
procedure TTrackerGrid.SelectAll; |