default.ts 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import * as CodeMirror
  4. from 'codemirror';
  5. import 'codemirror/mode/meta';
  6. import {
  7. Contents, Kernel
  8. } from '@jupyterlab/services';
  9. import {
  10. defineSignal, ISignal
  11. } from 'phosphor/lib/core/signaling';
  12. import {
  13. Widget
  14. } from 'phosphor/lib/ui/widget';
  15. import {
  16. IChangedArgs
  17. } from '../common/interfaces';
  18. import {
  19. DocumentRegistry
  20. } from './index';
  21. /**
  22. * The default implementation of a document model.
  23. */
  24. export
  25. class DocumentModel implements DocumentRegistry.IModel {
  26. /**
  27. * Construct a new document model.
  28. */
  29. constructor(languagePreference?: string) {
  30. this._defaultLang = languagePreference || '';
  31. }
  32. /**
  33. * A signal emitted when the document content changes.
  34. */
  35. contentChanged: ISignal<DocumentRegistry.IModel, void>;
  36. /**
  37. * A signal emitted when the document state changes.
  38. */
  39. stateChanged: ISignal<DocumentRegistry.IModel, IChangedArgs<any>>;
  40. /**
  41. * Get whether the model factory has been disposed.
  42. */
  43. get isDisposed(): boolean {
  44. return this._isDisposed;
  45. }
  46. /**
  47. * The dirty state of the document.
  48. */
  49. get dirty(): boolean {
  50. return this._dirty;
  51. }
  52. set dirty(newValue: boolean) {
  53. if (newValue === this._dirty) {
  54. return;
  55. }
  56. let oldValue = this._dirty;
  57. this._dirty = newValue;
  58. this.stateChanged.emit({ name: 'dirty', oldValue, newValue });
  59. }
  60. /**
  61. * The read only state of the document.
  62. */
  63. get readOnly(): boolean {
  64. return this._readOnly;
  65. }
  66. set readOnly(newValue: boolean) {
  67. if (newValue === this._readOnly) {
  68. return;
  69. }
  70. let oldValue = this._readOnly;
  71. this._readOnly = newValue;
  72. this.stateChanged.emit({ name: 'readOnly', oldValue, newValue });
  73. }
  74. /**
  75. * The default kernel name of the document.
  76. *
  77. * #### Notes
  78. * This is a read-only property.
  79. */
  80. get defaultKernelName(): string {
  81. return '';
  82. }
  83. /**
  84. * The default kernel language of the document.
  85. *
  86. * #### Notes
  87. * This is a read-only property.
  88. */
  89. get defaultKernelLanguage(): string {
  90. return this._defaultLang;
  91. }
  92. /**
  93. * Dispose of the resources held by the document manager.
  94. */
  95. dispose(): void {
  96. this._isDisposed = true;
  97. }
  98. /**
  99. * Serialize the model to a string.
  100. */
  101. toString(): string {
  102. return this._text;
  103. }
  104. /**
  105. * Deserialize the model from a string.
  106. *
  107. * #### Notes
  108. * Should emit a [contentChanged] signal.
  109. */
  110. fromString(value: string): void {
  111. if (this._text === value) {
  112. return;
  113. }
  114. this._text = value;
  115. this.contentChanged.emit(void 0);
  116. this.dirty = true;
  117. }
  118. /**
  119. * Serialize the model to JSON.
  120. */
  121. toJSON(): any {
  122. return JSON.stringify(this._text);
  123. }
  124. /**
  125. * Deserialize the model from JSON.
  126. *
  127. * #### Notes
  128. * Should emit a [contentChanged] signal.
  129. */
  130. fromJSON(value: any): void {
  131. this.fromString(JSON.parse(value));
  132. }
  133. private _text = '';
  134. private _defaultLang = '';
  135. private _dirty = false;
  136. private _readOnly = false;
  137. private _isDisposed = false;
  138. }
  139. // Define the signals for the `DocumentModel` class.
  140. defineSignal(DocumentModel.prototype, 'contentChanged');
  141. defineSignal(DocumentModel.prototype, 'stateChanged');
  142. /**
  143. * An implementation of a model factory for text files.
  144. */
  145. export
  146. class TextModelFactory implements DocumentRegistry.IModelFactory<DocumentRegistry.IModel> {
  147. /**
  148. * The name of the model type.
  149. *
  150. * #### Notes
  151. * This is a read-only property.
  152. */
  153. get name(): string {
  154. return 'text';
  155. }
  156. /**
  157. * The type of the file.
  158. *
  159. * #### Notes
  160. * This is a read-only property.
  161. */
  162. get contentType(): Contents.ContentType {
  163. return 'file';
  164. }
  165. /**
  166. * The format of the file.
  167. *
  168. * This is a read-only property.
  169. */
  170. get fileFormat(): Contents.FileFormat {
  171. return 'text';
  172. }
  173. /**
  174. * Get whether the model factory has been disposed.
  175. */
  176. get isDisposed(): boolean {
  177. return this._isDisposed;
  178. }
  179. /**
  180. * Dispose of the resources held by the model factory.
  181. */
  182. dispose(): void {
  183. this._isDisposed = true;
  184. }
  185. /**
  186. * Create a new model.
  187. *
  188. * @param languagePreference - An optional kernel language preference.
  189. *
  190. * @returns A new document model.
  191. */
  192. createNew(languagePreference?: string): DocumentRegistry.IModel {
  193. return new DocumentModel(languagePreference);
  194. }
  195. /**
  196. * Get the preferred kernel language given an extension.
  197. */
  198. preferredLanguage(ext: string): string {
  199. let mode = CodeMirror.findModeByExtension(ext.slice(1));
  200. if (mode) {
  201. return mode.mode;
  202. }
  203. }
  204. private _isDisposed = false;
  205. }
  206. /**
  207. * An implementation of a model factory for base64 files.
  208. */
  209. export
  210. class Base64ModelFactory extends TextModelFactory {
  211. /**
  212. * The name of the model type.
  213. *
  214. * #### Notes
  215. * This is a read-only property.
  216. */
  217. get name(): string {
  218. return 'base64';
  219. }
  220. /**
  221. * The type of the file.
  222. *
  223. * #### Notes
  224. * This is a read-only property.
  225. */
  226. get contentType(): Contents.ContentType {
  227. return 'file';
  228. }
  229. /**
  230. * The format of the file.
  231. *
  232. * This is a read-only property.
  233. */
  234. get fileFormat(): Contents.FileFormat {
  235. return 'base64';
  236. }
  237. }
  238. /**
  239. * The default implemetation of a widget factory.
  240. */
  241. export
  242. abstract class ABCWidgetFactory<T extends Widget, U extends DocumentRegistry.IModel> implements DocumentRegistry.IWidgetFactory<T, U> {
  243. /**
  244. * Construct a new `ABCWidgetFactory`.
  245. */
  246. constructor(options: DocumentRegistry.IWidgetFactoryOptions) {
  247. this._name = options.name;
  248. this._defaultFor = options.defaultFor ? options.defaultFor.slice() : [];
  249. this._fileExtensions = options.fileExtensions.slice();
  250. this._modelName = options.modelName || 'text';
  251. this._preferKernel = !!options.preferKernel;
  252. this._canStartKernel = !!options.canStartKernel;
  253. }
  254. /**
  255. * A signal emitted when a widget is created.
  256. */
  257. widgetCreated: ISignal<DocumentRegistry.IWidgetFactory<T, U>, T>;
  258. /**
  259. * Get whether the model factory has been disposed.
  260. */
  261. get isDisposed(): boolean {
  262. return this._isDisposed;
  263. }
  264. /**
  265. * Dispose of the resources held by the document manager.
  266. */
  267. dispose(): void {
  268. this._isDisposed = true;
  269. }
  270. /**
  271. * The name of the widget to display in dialogs.
  272. */
  273. get name(): string {
  274. return this._name;
  275. }
  276. /**
  277. * The file extensions the widget can view.
  278. */
  279. get fileExtensions(): string[] {
  280. return this._fileExtensions.slice();
  281. }
  282. /**
  283. * The registered name of the model type used to create the widgets.
  284. */
  285. get modelName(): string {
  286. return this._modelName;
  287. }
  288. /**
  289. * The file extensions for which the factory should be the default.
  290. */
  291. get defaultFor(): string[] {
  292. return this._defaultFor.slice();
  293. }
  294. /**
  295. * Whether the widgets prefer having a kernel started.
  296. */
  297. get preferKernel(): boolean {
  298. return this._preferKernel;
  299. }
  300. /**
  301. * Whether the widgets can start a kernel when opened.
  302. */
  303. get canStartKernel(): boolean {
  304. return this._canStartKernel;
  305. }
  306. /**
  307. * Create a new widget given a document model and a context.
  308. *
  309. * #### Notes
  310. * It should emit the [widgetCreated] signal with the new widget.
  311. */
  312. abstract createNew(context: DocumentRegistry.IContext<U>, kernel?: Kernel.IModel): T;
  313. private _isDisposed = false;
  314. private _name: string;
  315. private _canStartKernel: boolean;
  316. private _preferKernel: boolean;
  317. private _modelName: string;
  318. private _fileExtensions: string[];
  319. private _defaultFor: string[];
  320. }
  321. // Define the signals for the `ABCWidgetFactory` class.
  322. defineSignal(ABCWidgetFactory.prototype, 'widgetCreated');