-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve context handling #4453
Improve context handling #4453
Changes from 59 commits
7a5bd00
78df852
db40067
1e298d7
2e93f83
9c7c4a8
92d58d0
3816766
6ede2da
0ff19f6
4aa4de6
58a7a4b
3fc6bde
1107f69
12dfc8e
af12ced
55f8b32
631d0e1
8b3b7e1
db7fc2d
c90b59b
c3496d1
f7b03da
78e85c3
b60aaf5
1a6b58d
11ffaaf
cbb1b6a
6554c24
b0a3234
5d9d5db
7ecb3c8
447ab04
ebac5f0
ae8b29b
087d1d9
0468ec2
ae892b4
ba2802f
672e843
57b5c07
99c6c45
5a21d5a
7b618ba
ec7d693
d72fd54
ce1abda
5da4760
64212a6
5027e9e
f12be48
7bb239a
56e5766
427a67e
4efcad2
21040a0
bf94b1e
d031011
dba0b63
414fd43
413f401
63c41c1
3ab6372
6749792
693810c
ac907af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,11 +67,12 @@ class MainAreaWidget<T extends Widget = Widget> extends Widget { | |
this.title.changed.connect(this._updateContentTitle, this); | ||
content.disposed.connect(() => this.dispose()); | ||
|
||
if (options.populated) { | ||
if (options.reveal) { | ||
layout.addWidget(spinner); | ||
this.populated = options.populated; | ||
this.populated.then(() => { | ||
this._isPopulated = true; | ||
// Make sure the ready promise is a Promise<void> to avoid leaking any | ||
// results. | ||
this._reveal = options.reveal.then(() => { | ||
this._isRevealed = true; | ||
const active = document.activeElement === spinner.node; | ||
spinner.dispose(); | ||
layout.addWidget(content); | ||
|
@@ -88,13 +89,14 @@ class MainAreaWidget<T extends Widget = Widget> extends Widget { | |
BoxLayout.setStretch(error, 1); | ||
spinner.dispose(); | ||
layout.addWidget(error); | ||
throw(error); | ||
}); | ||
// Handle no populated promise. | ||
} else { | ||
spinner.dispose(); | ||
layout.addWidget(content); | ||
this._isPopulated = true; | ||
this.populated = Promise.resolve(void 0); | ||
this._isRevealed = true; | ||
this._reveal = Promise.resolve(undefined); | ||
} | ||
} | ||
|
||
|
@@ -109,16 +111,18 @@ class MainAreaWidget<T extends Widget = Widget> extends Widget { | |
readonly toolbar: Toolbar; | ||
|
||
/** | ||
* Whether the widget is fully populated. | ||
* Whether the widget is revealed. | ||
*/ | ||
get isPopulated(): boolean { | ||
return this._isPopulated; | ||
get isRevealed(): boolean { | ||
return this._isRevealed; | ||
} | ||
|
||
/** | ||
* A promise that resolves when the widget is fully populated. | ||
* A promise that resolves when the widget is ready to be revealed. | ||
*/ | ||
readonly populated: Promise<void>; | ||
get reveal(): Promise<void> { | ||
return this._reveal; | ||
} | ||
|
||
/** | ||
* Handle the DOM events for the widget. | ||
|
@@ -135,7 +139,7 @@ class MainAreaWidget<T extends Widget = Widget> extends Widget { | |
case 'mouseup': | ||
case 'mouseout': | ||
let target = event.target as HTMLElement; | ||
if (this._isPopulated && | ||
if (this._isRevealed && | ||
this.toolbar.node.contains(document.activeElement) && | ||
target.tagName !== 'SELECT') { | ||
this._focusContent(); | ||
|
@@ -166,7 +170,7 @@ class MainAreaWidget<T extends Widget = Widget> extends Widget { | |
* Handle `'activate-request'` messages. | ||
*/ | ||
protected onActivateRequest(msg: Message): void { | ||
if (this._isPopulated) { | ||
if (this._isRevealed) { | ||
this._focusContent(); | ||
} else { | ||
this._spinner.node.focus(); | ||
|
@@ -222,16 +226,21 @@ class MainAreaWidget<T extends Widget = Widget> extends Widget { | |
* Give focus to the content. | ||
*/ | ||
private _focusContent(): void { | ||
// Focus the content node if we aren't already focused on it or a | ||
// descendent. | ||
if (!this.content.node.contains(document.activeElement)) { | ||
this.content.node.focus(); | ||
} | ||
// Give the content a chance to activate. | ||
|
||
// Activate the content asynchronously (which may change the focus). | ||
this.content.activate(); | ||
} | ||
|
||
private _changeGuard = false; | ||
private _isPopulated = false; | ||
private _spinner = new Spinner(); | ||
|
||
private _isRevealed = false; | ||
private _reveal: Promise<void>; | ||
} | ||
|
||
|
||
|
@@ -256,8 +265,37 @@ namespace MainAreaWidget { | |
toolbar?: Toolbar; | ||
|
||
/** | ||
* An optional promise for when the content is fully populated. | ||
* An optional promise for when the content is ready to be revealed. | ||
*/ | ||
reveal?: Promise<any>; | ||
} | ||
|
||
/** | ||
* An options object for main area widget subclasses providing their own | ||
* default content. | ||
* | ||
* #### Notes | ||
* This makes it easier to have a subclass that provides its own default | ||
* content. This can go away once we upgrade to TypeScript 2.8 and have an | ||
* easy way to make a single property optional, ala | ||
* https://stackoverflow.com/a/46941824 | ||
*/ | ||
export | ||
interface IOptionsOptionalContent<T extends Widget = Widget> extends Widget.IOptions { | ||
/** | ||
* The child widget to wrap. | ||
*/ | ||
content?: T; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is your current thinking on ownership issues for the content of a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It has to transfer ownership to the MainAreaWidget. In phosphor, widgets reparent/own their children, dispose their children, move their children in the DOM to be under them, etc. |
||
|
||
/** | ||
* The toolbar to use for the widget. Defaults to an empty toolbar. | ||
*/ | ||
toolbar?: Toolbar; | ||
|
||
/** | ||
* An optional promise for when the content is ready to be revealed. | ||
*/ | ||
populated?: Promise<void>; | ||
reveal?: Promise<any>; | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought this sentence was kind of misleading. File views sharing the same model do communicate with each other. Perhaps "Different models for the same file path"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.