Skip to content

Commit

Permalink
CE: Wip Refactor undo/redo for multiple cursors
Browse files Browse the repository at this point in the history
  • Loading branch information
jxarco committed Jan 31, 2024
1 parent 83e4d92 commit 22d6d65
Showing 1 changed file with 81 additions and 42 deletions.
123 changes: 81 additions & 42 deletions build/components/codeeditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -1220,7 +1220,7 @@ class CodeEditor {
let cursor = document.createElement( 'div' );
cursor.className = "cursor";
cursor.innerHTML = " ";
cursor.isMainCursor = isMain;
cursor.isMain = isMain;
cursor._left = position * this.charWidth;
cursor.style.left = "calc( " + cursor._left + "px + " + this.xPadding + " )";
cursor._top = line * this.lineHeight;
Expand All @@ -1234,15 +1234,15 @@ class CodeEditor {
get: (v) => { return cursor._line },
set: (v) => {
cursor._line = v;
if( cursor.isMainCursor ) this._setActiveLine( v );
if( cursor.isMain ) this._setActiveLine( v );
}
} );

Object.defineProperty( cursor, 'position', {
get: (v) => { return cursor._position },
set: (v) => {
cursor._position = v;
if( cursor.isMainCursor ) this._updateDataInfoPanel( "@cursor-pos", "Col " + v );
if( cursor.isMain ) this._updateDataInfoPanel( "@cursor-pos", "Col " + v );
}
} );

Expand Down Expand Up @@ -1277,6 +1277,10 @@ class CodeEditor {

_addUndoStep( cursor, force, deleteRedo = true ) {

// Only the mainc cursor stores undo steps
if( !cursor.isMain )
return;

const d = new Date();
const current = d.getTime();

Expand All @@ -1285,7 +1289,7 @@ class CodeEditor {
if( !this._lastTime ) {
this._lastTime = current;
} else {
if( ( current - this._lastTime ) > 3000 ){
if( ( current - this._lastTime ) > 2000 ){
this._lastTime = null;
} else {
// If time not enough, reset timer
Expand All @@ -1303,10 +1307,7 @@ class CodeEditor {

this.code.undoSteps.push( {
lines: LX.deepCopy( this.code.lines ),
cursor: this.saveCursor( cursor ),
numCursors: this.cursors.childElementCount,
line: cursor.line,
position: cursor.position
cursors: this.saveCursors()
} );
}

Expand All @@ -1315,39 +1316,69 @@ class CodeEditor {
if( !this.code.undoSteps.length )
return;

const inner_undo = () => {
this._addRedoStep( cursor );

if( !this.code.undoSteps.length )
return;
// Extract info from the last code state
const step = this.code.undoSteps.pop();

const step = this.code.undoSteps.pop();
this.code.lines = step.lines;
this.processLines();
this.restoreCursor( cursor, step.cursor );
cursor.print();
};
// Set old state lines
this.code.lines = step.lines;
this.processLines();

this._addRedoStep( cursor );
this._removeSecondaryCursors();

// If the undo step was stored using more than 1 cursor,
// make sure we undo all at once
for( let i = 0; i < step.cursors.length; ++i )
{
var currentCursor = this.cursors.children[ i ];

const last_step = this.code.undoSteps[ this.code.undoSteps.length - 1 ];
// Generate new if needed
if( !currentCursor )
currentCursor = this._addCursor();

for( var i = 0; i < last_step.numCursors; ++i )
inner_undo();
this.restoreCursor( currentCursor, step.cursors[ i ] );
}
}

_addRedoStep( cursor ) {

// Only the mainc cursor stores redo steps
if( !cursor.isMain )
return;

this.code.redoSteps.push( {
lines: LX.deepCopy( this.code.lines ),
cursor: this.saveCursor( cursor ),
line: cursor.line,
position: cursor.position
cursors: this.saveCursors()
} );
}

_doRedo( cursor ) {

if( !this.code.redoSteps.length )
return;

this._addUndoStep( cursor, true, false);

// Extract info from the next saved code state
const step = this.code.redoSteps.pop();

// Set old state lines
this.code.lines = step.lines;
this.processLines();

this._removeSecondaryCursors();

for( let i = 0; i < step.cursors.length; ++i )
{
var currentCursor = this.cursors.children[ i ];

// Generate new if needed
if( !currentCursor )
currentCursor = this._addCursor();

this.restoreCursor( currentCursor, step.cursors[ i ] );
}
}

_changeLanguage( lang ) {

this.code.language = lang;
Expand Down Expand Up @@ -1961,15 +1992,17 @@ class CodeEditor {
if( !cursor )
break;

this.processKeyAtCursor( e, key, cursor );
this._processKeyAtCursor( e, key, cursor );
}

// Global keys

this.processGlobalKeys( e, key );
this._processGlobalKeys( e, key );
}

async processGlobalKeys( e, key ) {
async _processGlobalKeys( e, key ) {

let cursor = this._getCurrentCursor();

if( e.ctrlKey || e.metaKey )
{
Expand All @@ -1988,6 +2021,12 @@ class CodeEditor {
case 's': // save
this.onsave( this.getText() );
break;
case 'y': // redo
this._doRedo( cursor );
break;
case 'z': // undo
this._doUndo( cursor );
break;
case '+': // increase size
this._increaseFontSize();
break;
Expand All @@ -1998,7 +2037,7 @@ class CodeEditor {
}
}

async processKeyAtCursor( e, key, cursor ) {
async _processKeyAtCursor( e, key, cursor ) {

const skip_undo = e.detail.skip_undo ?? false;

Expand Down Expand Up @@ -2032,18 +2071,6 @@ class CodeEditor {
this._cutContent( cursor );
this.hideAutoCompleteBox();
return;
case 'y': // redo
if( !this.code.redoSteps.length )
return;
this._addUndoStep( cursor, true, false);
const redo_step = this.code.redoSteps.pop();
this.code.lines = redo_step.lines;
this.processLines();
this.restoreCursor( cursor, redo_step.cursor );
return;
case 'z': // undo
this._doUndo( cursor );
return;
case 'arrowdown': // add cursor below only for the main cursor..
if( isLastCursor && this.code.lines[ lidx + 1 ] != undefined )
{
Expand Down Expand Up @@ -3046,6 +3073,18 @@ class CodeEditor {
return state;
}

saveCursors() {

var cursors = [];

for( let cursor of this.cursors.children )
{
cursors.push( this.saveCursor( cursor ) );
}

return cursors;
}

restoreCursor( cursor, state ) {

cursor.position = state.position ?? 0;
Expand Down

0 comments on commit 22d6d65

Please sign in to comment.