-
-
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
[WIP] Partial merge of ModelDB proposal. #2039
Changes from 1 commit
6ea67c5
afe67f2
9b91bd7
263ff65
f8f7e47
50b1ee5
37430f5
41983f7
a826612
2cbbd9f
5c2664b
d5485fd
94714a2
3b6c581
7b31f38
2443722
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 |
---|---|---|
|
@@ -18,7 +18,7 @@ import { | |
} from '@jupyterlab/coreutils'; | ||
|
||
import { | ||
IObservableJSON, ObservableJSON | ||
IObservableJSON, IModelDB, IObservableValue | ||
} from '@jupyterlab/coreutils'; | ||
|
||
import { | ||
|
@@ -121,14 +121,32 @@ class CellModel extends CodeEditor.Model implements ICellModel { | |
* Construct a cell model from optional cell content. | ||
*/ | ||
constructor(options: CellModel.IOptions) { | ||
super(); | ||
super({modelDB: options.modelDB}); | ||
|
||
this.value.changed.connect(this.onGenericChange, this); | ||
|
||
let cellType = this.modelDB.createValue('type'); | ||
cellType.set(this.type); | ||
|
||
let observableMetadata = this.modelDB.createJSON('metadata'); | ||
observableMetadata.changed.connect(this.onGenericChange, this); | ||
|
||
let cell = options.cell; | ||
let trusted = this.modelDB.createValue('trusted'); | ||
if (!cell) { | ||
trusted.set(false); | ||
return; | ||
} | ||
this._trusted = !!cell.metadata['trusted']; | ||
trusted.set(!!cell.metadata['trusted']); | ||
delete cell.metadata['trusted']; | ||
trusted.changed.connect((value, args) => { | ||
this.onTrustedChanged(args.newValue as boolean); | ||
this.stateChanged.emit({ | ||
name: 'trusted', | ||
oldValue: args.oldValue, | ||
newValue: args.newValue | ||
}); | ||
}); | ||
|
||
if (Array.isArray(cell.source)) { | ||
this.value.text = (cell.source as string[]).join('\n'); | ||
|
@@ -143,10 +161,10 @@ class CellModel extends CodeEditor.Model implements ICellModel { | |
delete metadata['collapsed']; | ||
delete metadata['scrolled']; | ||
} | ||
|
||
for (let key in metadata) { | ||
this._metadata.set(key, metadata[key]); | ||
observableMetadata.set(key, metadata[key]); | ||
} | ||
this._metadata.changed.connect(this.onGenericChange, this); | ||
} | ||
|
||
/** | ||
|
@@ -168,35 +186,25 @@ class CellModel extends CodeEditor.Model implements ICellModel { | |
* The metadata associated with the cell. | ||
*/ | ||
get metadata(): IObservableJSON { | ||
return this._metadata; | ||
return this.modelDB.get('metadata') as IObservableJSON; | ||
} | ||
|
||
/** | ||
* Get the trusted state of the model. | ||
*/ | ||
get trusted(): boolean { | ||
return this._trusted; | ||
return (this.modelDB.get('trusted') as IObservableValue).get() as boolean; | ||
} | ||
|
||
/** | ||
* Set the trusted state of the model. | ||
*/ | ||
set trusted(newValue: boolean) { | ||
if (this._trusted === newValue) { | ||
let oldValue = this.trusted; | ||
if (oldValue === newValue) { | ||
return; | ||
} | ||
let oldValue = this._trusted; | ||
this._trusted = newValue; | ||
this.onTrustedChanged(newValue); | ||
this.stateChanged.emit({ name: 'trusted', oldValue, newValue }); | ||
} | ||
|
||
/** | ||
* Dispose of the resources held by the model. | ||
*/ | ||
dispose(): void { | ||
this._metadata.dispose(); | ||
super.dispose(); | ||
(this.modelDB.get('trusted') as IObservableValue).set(newValue); | ||
} | ||
|
||
/** | ||
|
@@ -231,9 +239,6 @@ class CellModel extends CodeEditor.Model implements ICellModel { | |
protected onGenericChange(): void { | ||
this.contentChanged.emit(void 0); | ||
} | ||
|
||
private _metadata = new ObservableJSON(); | ||
private _trusted = false; | ||
} | ||
|
||
|
||
|
@@ -250,6 +255,16 @@ namespace CellModel { | |
* The source cell data. | ||
*/ | ||
cell?: nbformat.IBaseCell; | ||
|
||
/** | ||
* An IModelDB in which to store cell data. | ||
*/ | ||
modelDB?: IModelDB; | ||
|
||
/** | ||
* A unique identifier for this cell. | ||
*/ | ||
uuid?: string; | ||
} | ||
} | ||
|
||
|
@@ -307,13 +322,27 @@ class CodeCellModel extends CellModel implements ICodeCellModel { | |
let trusted = this.trusted; | ||
let cell = options.cell as nbformat.ICodeCell; | ||
let outputs: nbformat.IOutput[] = []; | ||
if (cell && cell.cell_type === 'code') { | ||
this.executionCount = cell.execution_count; | ||
outputs = cell.outputs; | ||
let executionCount = this.modelDB.createValue('executionCount'); | ||
if (!executionCount.get()) { | ||
if (cell && cell.cell_type === 'code') { | ||
executionCount.set(cell.execution_count || null); | ||
outputs = cell.outputs; | ||
} else { | ||
executionCount.set(null); | ||
} | ||
} | ||
executionCount.changed.connect((value, args) => { | ||
this.contentChanged.emit(void 0); | ||
this.stateChanged.emit({ | ||
name: 'executionCount', | ||
oldValue: args.oldValue, | ||
newValue: args.newValue }); | ||
}); | ||
|
||
this._outputs = factory.createOutputArea({ | ||
trusted, | ||
values: outputs | ||
values: outputs, | ||
modelDB: this.modelDB | ||
}); | ||
this._outputs.stateChanged.connect(this.onGenericChange, this); | ||
} | ||
|
@@ -329,16 +358,14 @@ class CodeCellModel extends CellModel implements ICodeCellModel { | |
* The execution count of the cell. | ||
*/ | ||
get executionCount(): nbformat.ExecutionCount { | ||
return this._executionCount || null; | ||
return (this.modelDB.get('executionCount') as IObservableValue).get() as number || null; | ||
} | ||
set executionCount(newValue: nbformat.ExecutionCount) { | ||
if (newValue === this._executionCount) { | ||
let oldValue = this.executionCount; | ||
if (newValue === oldValue) { | ||
return; | ||
} | ||
let oldValue = this.executionCount; | ||
this._executionCount = newValue || null; | ||
this.contentChanged.emit(void 0); | ||
this.stateChanged.emit({ name: 'executionCount', oldValue, newValue }); | ||
(this.modelDB.get('executionCount') as IObservableValue).set(newValue || null); | ||
} | ||
|
||
/** | ||
|
@@ -372,15 +399,12 @@ class CodeCellModel extends CellModel implements ICodeCellModel { | |
|
||
/** | ||
* Handle a change to the trusted state. | ||
* | ||
* The default implementation is a no-op. | ||
*/ | ||
onTrustedChanged(value: boolean): void { | ||
this._outputs.trusted = value; | ||
} | ||
|
||
private _outputs: IOutputAreaModel = null; | ||
private _executionCount: nbformat.ExecutionCount = null; | ||
} | ||
|
||
|
||
|
@@ -392,12 +416,7 @@ namespace CodeCellModel { | |
/** | ||
* The options used to initialize a `CodeCellModel`. | ||
*/ | ||
export interface IOptions { | ||
/** | ||
* The source cell data. | ||
*/ | ||
cell?: nbformat.IBaseCell; | ||
|
||
export interface IOptions extends CellModel.IOptions { | ||
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. Should be a new line after export |
||
/** | ||
* The factory for output area model creation. | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,15 +14,8 @@ import { | |
} from '@phosphor/signaling'; | ||
|
||
import { | ||
IChangedArgs | ||
} from '@jupyterlab/coreutils'; | ||
|
||
import { | ||
IObservableString, ObservableString | ||
} from '@jupyterlab/coreutils'; | ||
|
||
import { | ||
IObservableMap, ObservableMap | ||
IModelDB, ModelDB, IObservableValue, | ||
IObservableMap, IObservableString, IChangedArgs | ||
} from '@jupyterlab/coreutils'; | ||
|
||
|
||
|
@@ -40,7 +33,7 @@ namespace CodeEditor { | |
* A zero-based position in the editor. | ||
*/ | ||
export | ||
interface IPosition { | ||
interface IPosition extends JSONObject { | ||
/** | ||
* The cursor line number. | ||
*/ | ||
|
@@ -78,7 +71,7 @@ namespace CodeEditor { | |
* A range. | ||
*/ | ||
export | ||
interface IRange { | ||
interface IRange extends JSONObject { | ||
/** | ||
* The position of the first character in the current range. | ||
* | ||
|
@@ -102,7 +95,7 @@ namespace CodeEditor { | |
* A selection style. | ||
*/ | ||
export | ||
interface ISelectionStyle { | ||
interface ISelectionStyle extends JSONObject { | ||
/** | ||
* A class name added to a selection. | ||
*/ | ||
|
@@ -186,8 +179,26 @@ namespace CodeEditor { | |
*/ | ||
constructor(options?: Model.IOptions) { | ||
options = options || {}; | ||
this._value = new ObservableString(options.value); | ||
this._mimetype = options.mimeType || 'text/plain'; | ||
|
||
if(options.modelDB) { | ||
this.modelDB = options.modelDB; | ||
} else { | ||
this.modelDB = new ModelDB(); | ||
} | ||
|
||
let value = this.modelDB.createString('value'); | ||
value.text = value.text || options.value || ''; | ||
let mimeType = this.modelDB.createValue('mimeType'); | ||
mimeType.set(options.mimeType || 'text/plain'); | ||
this.modelDB.createMap<ITextSelection[]>('selections'); | ||
|
||
mimeType.changed.connect((val, args)=>{ | ||
this._mimeTypeChanged.emit({ | ||
name: 'mimeType', | ||
oldValue: args.oldValue as string, | ||
newValue: args.newValue as string | ||
}); | ||
}); | ||
} | ||
|
||
/** | ||
|
@@ -201,33 +212,28 @@ namespace CodeEditor { | |
* Get the value of the model. | ||
*/ | ||
get value(): IObservableString { | ||
return this._value; | ||
return this.modelDB.get('value') as IObservableString; | ||
} | ||
|
||
/** | ||
* Get the selections for the model. | ||
*/ | ||
get selections(): IObservableMap<ITextSelection[]> { | ||
return this._selections; | ||
return this.modelDB.get('selections') as IObservableMap<ITextSelection[]>; | ||
} | ||
|
||
/** | ||
* A mime type of the model. | ||
*/ | ||
get mimeType(): string { | ||
return this._mimetype; | ||
return (this.modelDB.get('mimeType') as IObservableValue).get() as string; | ||
} | ||
set mimeType(newValue: string) { | ||
const oldValue = this._mimetype; | ||
const oldValue = this.mimeType; | ||
if (oldValue === newValue) { | ||
return; | ||
} | ||
this._mimetype = newValue; | ||
this._mimeTypeChanged.emit({ | ||
name: 'mimeType', | ||
oldValue, | ||
newValue | ||
}); | ||
(this.modelDB.get('mimeType') as IObservableValue).set(newValue); | ||
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 do you think about adding 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. Sure, that works. It would also be possible to just keep a reference to the |
||
} | ||
|
||
/** | ||
|
@@ -246,13 +252,10 @@ namespace CodeEditor { | |
} | ||
this._isDisposed = true; | ||
Signal.clearData(this); | ||
this._selections.dispose(); | ||
this._value.dispose(); | ||
} | ||
|
||
private _value: ObservableString; | ||
private _selections = new ObservableMap<ITextSelection[]>(); | ||
private _mimetype: string; | ||
|
||
protected modelDB: IModelDB = null; | ||
private _isDisposed = false; | ||
private _mimeTypeChanged = new Signal<this, IChangedArgs<string>>(this); | ||
} | ||
|
@@ -567,6 +570,11 @@ namespace CodeEditor { | |
* The mimetype of the model. | ||
*/ | ||
mimeType?: string; | ||
|
||
/** | ||
* An optional modelDB for storing model state. | ||
*/ | ||
modelDB?: IModelDB; | ||
} | ||
} | ||
} |
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.
As a general pattern we don't connect signals to anonymous functions, because they won't be cleared by
Signal.clearData(this)
.