Skip to content

Commit

Permalink
Merge pull request adobe#11820 from adobe/swmitra/SplitViewSameDoc
Browse files Browse the repository at this point in the history
Split View (Same Document)
  • Loading branch information
nethip committed Dec 11, 2015
2 parents 60eaca4 + ebcd796 commit ad260bb
Show file tree
Hide file tree
Showing 12 changed files with 176 additions and 88 deletions.
61 changes: 55 additions & 6 deletions src/document/Document.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ define(function (require, exports, module) {

EventDispatcher.makeEventDispatcher(Document.prototype);

/**
* List of editors which were initialized as master editors for this doc.
*/
Document.prototype._associatedFullEditors = [];

/**
* Number of clients who want this Document to stay alive. The Document is listed in
* DocumentManager._openDocuments whenever refCount > 0.
Expand Down Expand Up @@ -196,12 +201,16 @@ define(function (require, exports, module) {
*/
Document.prototype._makeEditable = function (masterEditor) {
if (this._masterEditor) {
console.error("Document is already editable");
} else {
this._text = null;
this._masterEditor = masterEditor;
masterEditor.on("change", this._handleEditorChange.bind(this));
//Already a master editor is associated , so preserve the old editor in list of full editors
if (this._associatedFullEditors.indexOf(this._masterEditor) < 0) {
this._associatedFullEditors.push(this._masterEditor);
}
}

this._text = null;
this._masterEditor = masterEditor;

masterEditor.on("change", this._handleEditorChange.bind(this));
};

/**
Expand All @@ -215,7 +224,42 @@ define(function (require, exports, module) {
} else {
// _text represents the raw text, so fetch without normalized line endings
this._text = this.getText(true);
this._masterEditor = null;
this._associatedFullEditors.splice(this._associatedFullEditors.indexOf(this._masterEditor), 1);

// Identify the most recently created full editor before this and set that as new master editor
if (this._associatedFullEditors.length > 0) {
this._masterEditor = this._associatedFullEditors[this._associatedFullEditors.length - 1];
} else {
this._masterEditor = null;
}
}
};

/**
* Toggles the master editor which has gained focus from a pool of full editors
* To be used internally by Editor only
*/
Document.prototype._toggleMasterEditor = function (masterEditor) {
// Do a check before processing the request to ensure inline editors are not being set as master editor
if (this._associatedFullEditors.indexOf(masterEditor) >= 0) {
if (this._masterEditor) {
// Already a master editor is associated , so preserve the old editor in list of editors
if (this._associatedFullEditors.indexOf(this._masterEditor) < 0) {
this._associatedFullEditors.push(this._masterEditor);
}
}
this._masterEditor = masterEditor;
}
};

/**
* Disassociates an editor from this document if present in the associated editor list
* To be used internally by Editor only when destroyed and not the current master editor for the document
*/
Document.prototype._disassociateEditor = function (editor) {
// Do a check before processing the request to ensure inline editors are not being handled
if (this._associatedFullEditors.indexOf(editor) >= 0) {
this._associatedFullEditors.splice(this._associatedFullEditors.indexOf(editor), 1);
}
};

Expand Down Expand Up @@ -409,6 +453,11 @@ define(function (require, exports, module) {
* @private
*/
Document.prototype._handleEditorChange = function (event, editor, changeList) {
// Handle editor change event only when it is originated from the master editor for this doc
if (this._masterEditor !== editor) {
return;
}

// TODO: This needs to be kept in sync with SpecRunnerUtils.createMockActiveDocument(). In the
// future, we should fix things so that we either don't need mock documents or that this
// is factored so it will just run in both.
Expand Down
9 changes: 6 additions & 3 deletions src/document/DocumentCommandHandlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -1115,13 +1115,15 @@ define(function (require, exports, module) {
var file,
promptOnly,
_forceClose,
_spawnedRequest,
paneId = MainViewManager.ACTIVE_PANE;

if (commandData) {
file = commandData.file;
promptOnly = commandData.promptOnly;
_forceClose = commandData._forceClose;
paneId = commandData.paneId || paneId;
_spawnedRequest = commandData.spawnedRequest || false;
}

// utility function for handleFileClose: closes document & removes from workingset
Expand All @@ -1146,8 +1148,9 @@ define(function (require, exports, module) {

var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);

if (doc && doc.isDirty && !_forceClose) {
// Document is dirty: prompt to save changes before closing
if (doc && doc.isDirty && !_forceClose && (MainViewManager.isExclusiveToPane(doc.file, paneId) || _spawnedRequest)) {
// Document is dirty: prompt to save changes before closing if only the document is exclusively
// listed in the requested pane or this is part of a list close request
var filename = FileUtils.getBaseName(doc.file.fullPath);

Dialogs.showModalDialog(
Expand Down Expand Up @@ -1245,7 +1248,7 @@ define(function (require, exports, module) {

} else if (unsavedDocs.length === 1) {
// Only one unsaved file: show the usual single-file-close confirmation UI
var fileCloseArgs = { file: unsavedDocs[0].file, promptOnly: promptOnly };
var fileCloseArgs = { file: unsavedDocs[0].file, promptOnly: promptOnly, spawnedRequest: true };

handleFileClose(fileCloseArgs).done(function () {
// still need to close any other, non-unsaved documents
Expand Down
3 changes: 3 additions & 0 deletions src/document/DocumentManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,9 @@ define(function (require, exports, module) {
exports.trigger("documentRefreshed", doc);
})
.on("_dirtyFlagChange", function (event, doc) {
// Modules listening on the doc instance notified about dirtyflag change
// To be used internally by Editor
doc.trigger("_dirtyFlagChange", doc);
exports.trigger("dirtyFlagChange", doc);
if (doc.isDirty) {
MainViewManager.addToWorkingSet(MainViewManager.ACTIVE_PANE, doc.file);
Expand Down
26 changes: 26 additions & 0 deletions src/editor/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ define(function (require, exports, module) {
TokenUtils = require("utils/TokenUtils"),
ValidationUtils = require("utils/ValidationUtils"),
ViewUtils = require("utils/ViewUtils"),
MainViewManager = require("view/MainViewManager"),
_ = require("thirdparty/lodash");

/** Editor preferences */
Expand Down Expand Up @@ -310,9 +311,12 @@ define(function (require, exports, module) {
this._handleDocumentChange = this._handleDocumentChange.bind(this);
this._handleDocumentDeleted = this._handleDocumentDeleted.bind(this);
this._handleDocumentLanguageChanged = this._handleDocumentLanguageChanged.bind(this);
this._doWorkingSetSync = this._doWorkingSetSync.bind(this);
document.on("change", this._handleDocumentChange);
document.on("deleted", this._handleDocumentDeleted);
document.on("languageChanged", this._handleDocumentLanguageChanged);
// To sync working sets if the view is for same doc across panes
document.on("_dirtyFlagChange", this._doWorkingSetSync);

var mode = this._getModeFromDocument();

Expand All @@ -325,6 +329,9 @@ define(function (require, exports, module) {

this._$messagePopover = null;

// To track which pane the editor is being attached to if it's a full editor
this._paneId = null;

// Editor supplies some standard keyboard behavior extensions of its own
var codeMirrorKeyMap = {
"Tab": function () { self._handleTabKey(); },
Expand Down Expand Up @@ -449,6 +456,20 @@ define(function (require, exports, module) {
EventDispatcher.makeEventDispatcher(Editor.prototype);
EventDispatcher.markDeprecated(Editor.prototype, "keyEvent", "'keydown/press/up'");

Editor.prototype.markPaneId = function (paneId) {
this._paneId = paneId;
// In case this Editor is initialized not as the first full editor for the document
// and the document is already dirty and present in another working set, make sure
// to add this documents to the new panes working set.
this._doWorkingSetSync(null, this.document);
};

Editor.prototype._doWorkingSetSync = function (event, doc) {
if (doc === this.document && this._paneId && this.document.isDirty) {
MainViewManager.addToWorkingSet(this._paneId, this.document.file, -1, false);
}
};

/**
* Removes this editor from the DOM and detaches from the Document. If this is the "master"
* Editor that is secretly providing the Document's backing state, then the Document reverts to
Expand All @@ -468,6 +489,7 @@ define(function (require, exports, module) {
this.document.off("change", this._handleDocumentChange);
this.document.off("deleted", this._handleDocumentDeleted);
this.document.off("languageChanged", this._handleDocumentLanguageChanged);
this.document.off("_dirtyFlagChange", this._doWorkingSetSync);

if (this._visibleRange) { // TextRange also refs the Document
this._visibleRange.dispose();
Expand All @@ -476,6 +498,8 @@ define(function (require, exports, module) {
// If we're the Document's master editor, disconnecting from it has special meaning
if (this.document._masterEditor === this) {
this.document._makeNonEditable();
} else {
this.document._disassociateEditor(this);
}

// Destroying us destroys any inline widgets we're hosting. Make sure their closeCallbacks
Expand Down Expand Up @@ -961,6 +985,8 @@ define(function (require, exports, module) {
this._codeMirror.on("focus", function () {
self._focused = true;
self.trigger("focus", self);
// Set this full editor as master editor for the document
self.document._toggleMasterEditor(self);
});

this._codeMirror.on("blur", function () {
Expand Down
8 changes: 3 additions & 5 deletions src/editor/EditorManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,9 @@ define(function (require, exports, module) {
var createdNewEditor = false,
editor = document._masterEditor;

if (!editor) {
//Check if a master editor is not set already or the current master editor doesn't belong
//to the pane container requested - to support creation of multiple full editors
if (!editor || editor._paneId !== pane.id) {
// Performance (see #4757) Chrome wastes time messing with selection
// that will just be changed at end, so clear it for now
if (window.getSelection && window.getSelection().empty) { // Chrome
Expand All @@ -552,10 +554,6 @@ define(function (require, exports, module) {
// Editor doesn't exist: populate a new Editor with the text
editor = _createFullEditorForDocument(document, pane, editorOptions);
createdNewEditor = true;
} else if (editor.$el.parent()[0] !== pane.$content[0]) {
// editor does exist but is not a child of the pane so add it to the
// pane (which will switch the view's container as well)
pane.addView(editor);
}

// show the view
Expand Down
18 changes: 16 additions & 2 deletions src/project/FileViewController.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
*/

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, $ */
/*global define, $, event */

/**
* Responsible for coordinating file selection between views by permitting only one view
Expand Down Expand Up @@ -148,6 +148,19 @@ define(function (require, exports, module) {
function openAndSelectDocument(fullPath, fileSelectionFocus, paneId) {
var result,
curDocChangedDueToMe = _curDocChangedDueToMe;

function _getDerivedPaneContext() {

function _secondPaneContext() {
return (event.ctrlKey || event.metaKey) && event.altKey ? MainViewManager.SECOND_PANE : null;
}

function _firstPaneContext() {
return (event.ctrlKey || event.metaKey) ? MainViewManager.FIRST_PANE : null;
}

return _secondPaneContext() || _firstPaneContext();
}

if (fileSelectionFocus !== PROJECT_MANAGER && fileSelectionFocus !== WORKING_SET_VIEW) {
console.error("Bad parameter passed to FileViewController.openAndSelectDocument");
Expand All @@ -160,8 +173,9 @@ define(function (require, exports, module) {
_curDocChangedDueToMe = true;

_fileSelectionFocus = fileSelectionFocus;


paneId = (paneId || MainViewManager.ACTIVE_PANE);
paneId = (paneId || _getDerivedPaneContext() || MainViewManager.ACTIVE_PANE);

// If fullPath corresonds to the current doc being viewed then opening the file won't
// trigger a currentFileChange event, so we need to trigger a documentSelectionFocusChange
Expand Down
2 changes: 1 addition & 1 deletion src/project/WorkingSetView.js
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ define(function (require, exports, module) {
if (tryClosing || e.which === MIDDLE_BUTTON) {
CommandManager
.execute(Commands.FILE_CLOSE, {file: sourceFile,
paneId: sourceView.paneId})
paneId: sourceView.paneId})
.always(function () {
postDropCleanup();
});
Expand Down
Loading

0 comments on commit ad260bb

Please sign in to comment.