Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.

Commit ad260bb

Browse files
committed
Merge pull request #11820 from adobe/swmitra/SplitViewSameDoc
Split View (Same Document)
2 parents 60eaca4 + ebcd796 commit ad260bb

12 files changed

+176
-88
lines changed

src/document/Document.js

+55-6
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ define(function (require, exports, module) {
8383

8484
EventDispatcher.makeEventDispatcher(Document.prototype);
8585

86+
/**
87+
* List of editors which were initialized as master editors for this doc.
88+
*/
89+
Document.prototype._associatedFullEditors = [];
90+
8691
/**
8792
* Number of clients who want this Document to stay alive. The Document is listed in
8893
* DocumentManager._openDocuments whenever refCount > 0.
@@ -196,12 +201,16 @@ define(function (require, exports, module) {
196201
*/
197202
Document.prototype._makeEditable = function (masterEditor) {
198203
if (this._masterEditor) {
199-
console.error("Document is already editable");
200-
} else {
201-
this._text = null;
202-
this._masterEditor = masterEditor;
203-
masterEditor.on("change", this._handleEditorChange.bind(this));
204+
//Already a master editor is associated , so preserve the old editor in list of full editors
205+
if (this._associatedFullEditors.indexOf(this._masterEditor) < 0) {
206+
this._associatedFullEditors.push(this._masterEditor);
207+
}
204208
}
209+
210+
this._text = null;
211+
this._masterEditor = masterEditor;
212+
213+
masterEditor.on("change", this._handleEditorChange.bind(this));
205214
};
206215

207216
/**
@@ -215,7 +224,42 @@ define(function (require, exports, module) {
215224
} else {
216225
// _text represents the raw text, so fetch without normalized line endings
217226
this._text = this.getText(true);
218-
this._masterEditor = null;
227+
this._associatedFullEditors.splice(this._associatedFullEditors.indexOf(this._masterEditor), 1);
228+
229+
// Identify the most recently created full editor before this and set that as new master editor
230+
if (this._associatedFullEditors.length > 0) {
231+
this._masterEditor = this._associatedFullEditors[this._associatedFullEditors.length - 1];
232+
} else {
233+
this._masterEditor = null;
234+
}
235+
}
236+
};
237+
238+
/**
239+
* Toggles the master editor which has gained focus from a pool of full editors
240+
* To be used internally by Editor only
241+
*/
242+
Document.prototype._toggleMasterEditor = function (masterEditor) {
243+
// Do a check before processing the request to ensure inline editors are not being set as master editor
244+
if (this._associatedFullEditors.indexOf(masterEditor) >= 0) {
245+
if (this._masterEditor) {
246+
// Already a master editor is associated , so preserve the old editor in list of editors
247+
if (this._associatedFullEditors.indexOf(this._masterEditor) < 0) {
248+
this._associatedFullEditors.push(this._masterEditor);
249+
}
250+
}
251+
this._masterEditor = masterEditor;
252+
}
253+
};
254+
255+
/**
256+
* Disassociates an editor from this document if present in the associated editor list
257+
* To be used internally by Editor only when destroyed and not the current master editor for the document
258+
*/
259+
Document.prototype._disassociateEditor = function (editor) {
260+
// Do a check before processing the request to ensure inline editors are not being handled
261+
if (this._associatedFullEditors.indexOf(editor) >= 0) {
262+
this._associatedFullEditors.splice(this._associatedFullEditors.indexOf(editor), 1);
219263
}
220264
};
221265

@@ -409,6 +453,11 @@ define(function (require, exports, module) {
409453
* @private
410454
*/
411455
Document.prototype._handleEditorChange = function (event, editor, changeList) {
456+
// Handle editor change event only when it is originated from the master editor for this doc
457+
if (this._masterEditor !== editor) {
458+
return;
459+
}
460+
412461
// TODO: This needs to be kept in sync with SpecRunnerUtils.createMockActiveDocument(). In the
413462
// future, we should fix things so that we either don't need mock documents or that this
414463
// is factored so it will just run in both.

src/document/DocumentCommandHandlers.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -1115,13 +1115,15 @@ define(function (require, exports, module) {
11151115
var file,
11161116
promptOnly,
11171117
_forceClose,
1118+
_spawnedRequest,
11181119
paneId = MainViewManager.ACTIVE_PANE;
11191120

11201121
if (commandData) {
11211122
file = commandData.file;
11221123
promptOnly = commandData.promptOnly;
11231124
_forceClose = commandData._forceClose;
11241125
paneId = commandData.paneId || paneId;
1126+
_spawnedRequest = commandData.spawnedRequest || false;
11251127
}
11261128

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

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

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

11531156
Dialogs.showModalDialog(
@@ -1245,7 +1248,7 @@ define(function (require, exports, module) {
12451248

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

12501253
handleFileClose(fileCloseArgs).done(function () {
12511254
// still need to close any other, non-unsaved documents

src/document/DocumentManager.js

+3
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,9 @@ define(function (require, exports, module) {
586586
exports.trigger("documentRefreshed", doc);
587587
})
588588
.on("_dirtyFlagChange", function (event, doc) {
589+
// Modules listening on the doc instance notified about dirtyflag change
590+
// To be used internally by Editor
591+
doc.trigger("_dirtyFlagChange", doc);
589592
exports.trigger("dirtyFlagChange", doc);
590593
if (doc.isDirty) {
591594
MainViewManager.addToWorkingSet(MainViewManager.ACTIVE_PANE, doc.file);

src/editor/Editor.js

+26
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ define(function (require, exports, module) {
8080
TokenUtils = require("utils/TokenUtils"),
8181
ValidationUtils = require("utils/ValidationUtils"),
8282
ViewUtils = require("utils/ViewUtils"),
83+
MainViewManager = require("view/MainViewManager"),
8384
_ = require("thirdparty/lodash");
8485

8586
/** Editor preferences */
@@ -310,9 +311,12 @@ define(function (require, exports, module) {
310311
this._handleDocumentChange = this._handleDocumentChange.bind(this);
311312
this._handleDocumentDeleted = this._handleDocumentDeleted.bind(this);
312313
this._handleDocumentLanguageChanged = this._handleDocumentLanguageChanged.bind(this);
314+
this._doWorkingSetSync = this._doWorkingSetSync.bind(this);
313315
document.on("change", this._handleDocumentChange);
314316
document.on("deleted", this._handleDocumentDeleted);
315317
document.on("languageChanged", this._handleDocumentLanguageChanged);
318+
// To sync working sets if the view is for same doc across panes
319+
document.on("_dirtyFlagChange", this._doWorkingSetSync);
316320

317321
var mode = this._getModeFromDocument();
318322

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

326330
this._$messagePopover = null;
327331

332+
// To track which pane the editor is being attached to if it's a full editor
333+
this._paneId = null;
334+
328335
// Editor supplies some standard keyboard behavior extensions of its own
329336
var codeMirrorKeyMap = {
330337
"Tab": function () { self._handleTabKey(); },
@@ -449,6 +456,20 @@ define(function (require, exports, module) {
449456
EventDispatcher.makeEventDispatcher(Editor.prototype);
450457
EventDispatcher.markDeprecated(Editor.prototype, "keyEvent", "'keydown/press/up'");
451458

459+
Editor.prototype.markPaneId = function (paneId) {
460+
this._paneId = paneId;
461+
// In case this Editor is initialized not as the first full editor for the document
462+
// and the document is already dirty and present in another working set, make sure
463+
// to add this documents to the new panes working set.
464+
this._doWorkingSetSync(null, this.document);
465+
};
466+
467+
Editor.prototype._doWorkingSetSync = function (event, doc) {
468+
if (doc === this.document && this._paneId && this.document.isDirty) {
469+
MainViewManager.addToWorkingSet(this._paneId, this.document.file, -1, false);
470+
}
471+
};
472+
452473
/**
453474
* Removes this editor from the DOM and detaches from the Document. If this is the "master"
454475
* Editor that is secretly providing the Document's backing state, then the Document reverts to
@@ -468,6 +489,7 @@ define(function (require, exports, module) {
468489
this.document.off("change", this._handleDocumentChange);
469490
this.document.off("deleted", this._handleDocumentDeleted);
470491
this.document.off("languageChanged", this._handleDocumentLanguageChanged);
492+
this.document.off("_dirtyFlagChange", this._doWorkingSetSync);
471493

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

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

966992
this._codeMirror.on("blur", function () {

src/editor/EditorManager.js

+3-5
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,9 @@ define(function (require, exports, module) {
542542
var createdNewEditor = false,
543543
editor = document._masterEditor;
544544

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

561559
// show the view

src/project/FileViewController.js

+16-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
*/
2323

2424
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
25-
/*global define, $ */
25+
/*global define, $, event */
2626

2727
/**
2828
* Responsible for coordinating file selection between views by permitting only one view
@@ -148,6 +148,19 @@ define(function (require, exports, module) {
148148
function openAndSelectDocument(fullPath, fileSelectionFocus, paneId) {
149149
var result,
150150
curDocChangedDueToMe = _curDocChangedDueToMe;
151+
152+
function _getDerivedPaneContext() {
153+
154+
function _secondPaneContext() {
155+
return (event.ctrlKey || event.metaKey) && event.altKey ? MainViewManager.SECOND_PANE : null;
156+
}
157+
158+
function _firstPaneContext() {
159+
return (event.ctrlKey || event.metaKey) ? MainViewManager.FIRST_PANE : null;
160+
}
161+
162+
return _secondPaneContext() || _firstPaneContext();
163+
}
151164

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

162175
_fileSelectionFocus = fileSelectionFocus;
176+
163177

164-
paneId = (paneId || MainViewManager.ACTIVE_PANE);
178+
paneId = (paneId || _getDerivedPaneContext() || MainViewManager.ACTIVE_PANE);
165179

166180
// If fullPath corresonds to the current doc being viewed then opening the file won't
167181
// trigger a currentFileChange event, so we need to trigger a documentSelectionFocusChange

src/project/WorkingSetView.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ define(function (require, exports, module) {
765765
if (tryClosing || e.which === MIDDLE_BUTTON) {
766766
CommandManager
767767
.execute(Commands.FILE_CLOSE, {file: sourceFile,
768-
paneId: sourceView.paneId})
768+
paneId: sourceView.paneId})
769769
.always(function () {
770770
postDropCleanup();
771771
});

0 commit comments

Comments
 (0)