panel.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import { Kernel, KernelMessage, Session } from '@jupyterlab/services';
  4. import { Token } from '@phosphor/coreutils';
  5. import { Message } from '@phosphor/messaging';
  6. import { ISignal, Signal } from '@phosphor/signaling';
  7. import { IClientSession } from '@jupyterlab/apputils';
  8. import { DocumentWidget } from '@jupyterlab/docregistry';
  9. import { RenderMimeRegistry } from '@jupyterlab/rendermime';
  10. import { INotebookModel } from './model';
  11. import { Notebook } from './widget';
  12. /**
  13. * The class name added to notebook panels.
  14. */
  15. const NOTEBOOK_PANEL_CLASS = 'jp-NotebookPanel';
  16. const NOTEBOOK_PANEL_TOOLBAR_CLASS = 'jp-NotebookPanel-toolbar';
  17. const NOTEBOOK_PANEL_NOTEBOOK_CLASS = 'jp-NotebookPanel-notebook';
  18. /**
  19. * A widget that hosts a notebook toolbar and content area.
  20. *
  21. * #### Notes
  22. * The widget keeps the document metadata in sync with the current
  23. * kernel on the context.
  24. */
  25. export class NotebookPanel extends DocumentWidget<Notebook, INotebookModel> {
  26. /**
  27. * Construct a new notebook panel.
  28. */
  29. constructor(options: DocumentWidget.IOptions<Notebook, INotebookModel>) {
  30. super(options);
  31. // Set up CSS classes
  32. this.addClass(NOTEBOOK_PANEL_CLASS);
  33. this.toolbar.addClass(NOTEBOOK_PANEL_TOOLBAR_CLASS);
  34. this.content.addClass(NOTEBOOK_PANEL_NOTEBOOK_CLASS);
  35. // Set up things related to the context
  36. this.content.model = this.context.model;
  37. this.context.session.kernelChanged.connect(
  38. this._onKernelChanged,
  39. this
  40. );
  41. this.revealed.then(() => {
  42. // Set the document edit mode on initial open if it looks like a new document.
  43. if (this.content.widgets.length === 1) {
  44. let cellModel = this.content.widgets[0].model;
  45. if (cellModel.type === 'code' && cellModel.value.text === '') {
  46. this.content.mode = 'edit';
  47. }
  48. }
  49. });
  50. }
  51. /**
  52. * A signal emitted when the panel has been activated.
  53. */
  54. get activated(): ISignal<this, void> {
  55. return this._activated;
  56. }
  57. /**
  58. * The client session used by the panel.
  59. */
  60. get session(): IClientSession {
  61. return this.context.session;
  62. }
  63. /**
  64. * The content factory for the notebook.
  65. *
  66. * TODO: deprecate this in favor of the .content attribute
  67. *
  68. */
  69. get contentFactory(): Notebook.IContentFactory {
  70. return this.content.contentFactory;
  71. }
  72. /**
  73. * The rendermime instance for the notebook.
  74. *
  75. * TODO: deprecate this in favor of the .content attribute
  76. *
  77. */
  78. get rendermime(): RenderMimeRegistry {
  79. return this.content.rendermime;
  80. }
  81. /**
  82. * The notebook used by the widget.
  83. */
  84. readonly content: Notebook;
  85. /**
  86. * The model for the widget.
  87. */
  88. get model(): INotebookModel {
  89. return this.content ? this.content.model : null;
  90. }
  91. /**
  92. * Set URI fragment identifier.
  93. */
  94. setFragment(fragment: string) {
  95. this.context.ready.then(() => {
  96. this.content.setFragment(fragment);
  97. });
  98. }
  99. /**
  100. * Dispose of the resources used by the widget.
  101. */
  102. dispose(): void {
  103. this.content.dispose();
  104. super.dispose();
  105. }
  106. /**
  107. * Handle `'activate-request'` messages.
  108. */
  109. protected onActivateRequest(msg: Message): void {
  110. super.onActivateRequest(msg);
  111. // TODO: do we still need to emit this signal? Who is using it?
  112. this._activated.emit(void 0);
  113. }
  114. /**
  115. * Handle a change in the kernel by updating the document metadata.
  116. */
  117. private _onKernelChanged(
  118. sender: any,
  119. args: Session.IKernelChangedArgs
  120. ): void {
  121. if (!this.model || !args.newValue) {
  122. return;
  123. }
  124. let { newValue } = args;
  125. newValue.ready.then(() => {
  126. if (this.model) {
  127. this._updateLanguage(newValue.info.language_info);
  128. }
  129. });
  130. this._updateSpec(newValue);
  131. }
  132. /**
  133. * Update the kernel language.
  134. */
  135. private _updateLanguage(language: KernelMessage.ILanguageInfo): void {
  136. this.model.metadata.set('language_info', language);
  137. }
  138. /**
  139. * Update the kernel spec.
  140. */
  141. private _updateSpec(kernel: Kernel.IKernelConnection): void {
  142. kernel.getSpec().then(spec => {
  143. if (this.isDisposed) {
  144. return;
  145. }
  146. this.model.metadata.set('kernelspec', {
  147. name: kernel.name,
  148. display_name: spec.display_name,
  149. language: spec.language
  150. });
  151. });
  152. }
  153. private _activated = new Signal<this, void>(this);
  154. }
  155. /**
  156. * A namespace for `NotebookPanel` statics.
  157. */
  158. export namespace NotebookPanel {
  159. /**
  160. * A content factory interface for NotebookPanel.
  161. */
  162. export interface IContentFactory extends Notebook.IContentFactory {
  163. /**
  164. * Create a new content area for the panel.
  165. */
  166. createNotebook(options: Notebook.IOptions): Notebook;
  167. }
  168. /**
  169. * The default implementation of an `IContentFactory`.
  170. */
  171. export class ContentFactory extends Notebook.ContentFactory
  172. implements IContentFactory {
  173. /**
  174. * Create a new content area for the panel.
  175. */
  176. createNotebook(options: Notebook.IOptions): Notebook {
  177. return new Notebook(options);
  178. }
  179. }
  180. /**
  181. * Default content factory for the notebook panel.
  182. */
  183. export const defaultContentFactory: ContentFactory = new ContentFactory();
  184. /* tslint:disable */
  185. /**
  186. * The notebook renderer token.
  187. */
  188. export const IContentFactory = new Token<IContentFactory>(
  189. '@jupyterlab/notebook:IContentFactory'
  190. );
  191. /* tslint:enable */
  192. }