diff --git a/src/DocumentManager.js b/src/DocumentManager.js index 946c123981f..cd2e5eed855 100644 --- a/src/DocumentManager.js +++ b/src/DocumentManager.js @@ -99,53 +99,44 @@ define(function(require, exports, module) { this._editor = editor; // Dirty-bit tracking - editor.setOption("onChange", this._updateDirty.bind(this)); - this._savedUndoPosition = editor.historySize().undo; // should always be 0, but just to be safe... + editor.setOption("onChange", this._handleEditorChange.bind(this)); + this.isDirty = false; } /** - * @private - * TODO: we should close on whether private fields are declared on the prototype like this - * @type {number} - */ - Document.prototype._savedUndoPosition = 0; - - /** - * @return {string} The editor's current contents; may not be saved to disk + * @return {string} The document's current contents; may not be saved to disk * yet. Returns null if the file was not yet read and no editor was * created. */ Document.prototype.getText = function() { - console.assert(this._editor != null); - return this._editor.getValue(); } + /** + * Sets the contents of the document. + * @param {!string} text The text to replace the contents of the document with. + */ + Document.prototype.setText = function(text) { + this._editor.setValue(text); + } + /** * @private */ - Document.prototype._updateDirty = function() { + Document.prototype._handleEditorChange = function() { if (this._editor == null) { return; } - // If we've undone past the undo position at the last save, and there is no redo stack, - // then we can never get back to a non-dirty state. - var historySize = this._editor.historySize(); - if (historySize.undo < this._savedUndoPosition && historySize.redo == 0) { - this._savedUndoPosition = -1; - } - var newIsDirty = (this._editor.historySize().undo != this._savedUndoPosition); - - if (this.isDirty != newIsDirty) { - this.isDirty = newIsDirty; - - // Dispatch event + // On any change, mark the file dirty. In the future, we should make it so that if you + // undo back to the last saved state, we mark the file clean. + var wasDirty = this.isDirty; + this.isDirty = true; + + // If file just became dirty, notify listeners, and add it to working set (if not already there) + if (!wasDirty) { $(exports).triggerHandler("dirtyFlagChange", this); - - // If file just became dirty, add it to working set (if not already there) - if (newIsDirty) - addToWorkingSet(this); + addToWorkingSet(this); } } @@ -155,8 +146,8 @@ define(function(require, exports, module) { return; } - this._savedUndoPosition = this._editor.historySize().undo; - this._updateDirty(); + this.isDirty = false; + $(exports).triggerHandler("dirtyFlagChange", this); } /* (pretty toString(), to aid debugging) */ diff --git a/test/spec/FileCommandHandlers-test.js b/test/spec/FileCommandHandlers-test.js index 8beeb4d258f..5d7b83a59ec 100644 --- a/test/spec/FileCommandHandlers-test.js +++ b/test/spec/FileCommandHandlers-test.js @@ -146,7 +146,7 @@ define(function(require, exports, module) { describe("Dirty File Handling", function() { - it("should report not dirty after undo", function() { + beforeEach(function() { var didOpen = false, gotError = false; runs(function() { @@ -155,29 +155,15 @@ define(function(require, exports, module) { .fail(function() { gotError = true; }); }); waitsFor(function() { return didOpen && !gotError; }, "FILE_OPEN timeout", 1000); + }); + it("should report clean immediately after opening a file", function() { runs(function() { - // change editor content, followed by undo - var editor = DocumentManager.getCurrentDocument()._editor; - editor.setValue(TEST_JS_NEW_CONTENT); - editor.undo(); - - // verify Document dirty status - expect(editor.getValue()).toBe(TEST_JS_CONTENT); expect(DocumentManager.getCurrentDocument().isDirty).toBe(false); }); }); - + it("should report dirty when modified", function() { - var didOpen = false, gotError = false; - - runs(function() { - CommandManager.execute(Commands.FILE_OPEN, {fullPath: testPath + "/test.js"}) - .done(function() { didOpen = true; }) - .fail(function() { gotError = true; }); - }); - waitsFor(function() { return didOpen && !gotError; }, "FILE_OPEN timeout", 1000); - runs(function() { // change editor content var editor = DocumentManager.getCurrentDocument()._editor; @@ -199,15 +185,6 @@ define(function(require, exports, module) { }); it("should report dirty after undo and redo", function() { - var didOpen = false, gotError = false; - - runs(function() { - CommandManager.execute(Commands.FILE_OPEN, {fullPath: testPath + "/test.js"}) - .done(function() { didOpen = true; }) - .fail(function() { gotError = true; }); - }); - waitsFor(function() { return didOpen && !gotError; }, "FILE_OPEN timeout", 1000); - runs(function() { // change editor content, followed by undo and redo var editor = DocumentManager.getCurrentDocument()._editor; @@ -222,6 +199,33 @@ define(function(require, exports, module) { expect(DocumentManager.getCurrentDocument().isDirty).toBe(true); }); }); + + it("should report clean after being marked clean", function() { + runs(function() { + var document = DocumentManager.getCurrentDocument(); + document.setText(TEST_JS_NEW_CONTENT); + document.markClean(); + expect(document.isDirty).toBe(false); + }); + }); + + // This test is not currently valid. For issue 152, we have temporarily decided to make it so + // the file is always dirty as soon as you make a change, regardless of whether you undo back to + // its last saved state. In the future, we might restore this behavior. +/* + it("should report not dirty after undo", function() { + runs(function() { + // change editor content, followed by undo + var editor = DocumentManager.getCurrentDocument()._editor; + editor.setValue(TEST_JS_NEW_CONTENT); + editor.undo(); + + // verify Document dirty status + expect(editor.getValue()).toBe(TEST_JS_CONTENT); + expect(DocumentManager.getCurrentDocument().isDirty).toBe(false); + }); + }); +*/ }); // TODO (jasonsj): experiment with mocks instead of real UI