index.ts 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import 'es6-promise/auto'; // polyfill Promise on IE
  4. import {
  5. CommandRegistry
  6. } from '@phosphor/commands';
  7. import {
  8. DockPanel, Menu, SplitPanel, Widget
  9. } from '@phosphor/widgets';
  10. import {
  11. ServiceManager
  12. } from '@jupyterlab/services';
  13. import {
  14. Dialog, showDialog
  15. } from '@jupyterlab/apputils';
  16. import {
  17. FileBrowser, FileBrowserModel
  18. } from '@jupyterlab/filebrowser';
  19. import {
  20. DocumentManager
  21. } from '@jupyterlab/docmanager';
  22. import {
  23. DocumentRegistry, TextModelFactory
  24. } from '@jupyterlab/docregistry';
  25. import {
  26. CodeMirrorEditorFactory, CodeMirrorMimeTypeService
  27. } from '@jupyterlab/codemirror';
  28. import {
  29. FileEditorFactory
  30. } from '@jupyterlab/fileeditor';
  31. import '@jupyterlab/default-theme/style/index.css';
  32. import '../index.css';
  33. function main(): void {
  34. let manager = new ServiceManager();
  35. manager.ready.then(() => {
  36. createApp(manager);
  37. });
  38. }
  39. function createApp(manager: ServiceManager.IManager): void {
  40. let widgets: Widget[] = [];
  41. let activeWidget: Widget;
  42. let opener = {
  43. open: (widget: Widget) => {
  44. if (widgets.indexOf(widget) === -1) {
  45. dock.addWidget(widget, { mode: 'tab-after' });
  46. widgets.push(widget);
  47. }
  48. dock.activateWidget(widget);
  49. activeWidget = widget;
  50. widget.disposed.connect((w: Widget) => {
  51. let index = widgets.indexOf(w);
  52. widgets.splice(index, 1);
  53. });
  54. }
  55. };
  56. let docRegistry = new DocumentRegistry();
  57. let docManager = new DocumentManager({
  58. registry: docRegistry,
  59. manager,
  60. opener
  61. });
  62. let mFactory = new TextModelFactory();
  63. let editorServices = {
  64. factoryService: new CodeMirrorEditorFactory(),
  65. mimeTypeService: new CodeMirrorMimeTypeService()
  66. };
  67. let wFactory = new FileEditorFactory({
  68. editorServices,
  69. factoryOptions: {
  70. name: 'Editor',
  71. modelName: 'text',
  72. fileExtensions: ['*'],
  73. defaultFor: ['*'],
  74. preferKernel: false,
  75. canStartKernel: true
  76. }
  77. });
  78. docRegistry.addModelFactory(mFactory);
  79. docRegistry.addWidgetFactory(wFactory);
  80. let commands = new CommandRegistry();
  81. let fbModel = new FileBrowserModel({ manager });
  82. let fbWidget = new FileBrowser({
  83. id: 'filebrowser',
  84. commands,
  85. model: fbModel,
  86. manager: docManager,
  87. });
  88. let panel = new SplitPanel();
  89. panel.id = 'main';
  90. panel.addWidget(fbWidget);
  91. SplitPanel.setStretch(fbWidget, 0);
  92. let dock = new DockPanel();
  93. panel.addWidget(dock);
  94. SplitPanel.setStretch(dock, 1);
  95. dock.spacing = 8;
  96. document.addEventListener('focus', event => {
  97. for (let i = 0; i < widgets.length; i++) {
  98. let widget = widgets[i];
  99. if (widget.node.contains(event.target as HTMLElement)) {
  100. activeWidget = widget;
  101. break;
  102. }
  103. }
  104. });
  105. commands.addCommand('file-open', {
  106. label: 'Open',
  107. icon: 'fa fa-folder-open-o',
  108. mnemonic: 0,
  109. execute: () => { fbWidget.open(); }
  110. });
  111. commands.addCommand('file-rename', {
  112. label: 'Rename',
  113. icon: 'fa fa-edit',
  114. mnemonic: 0,
  115. execute: () => { fbWidget.rename(); }
  116. });
  117. commands.addCommand('file-save', {
  118. execute: () => {
  119. let context = docManager.contextForWidget(activeWidget);
  120. context.save();
  121. }
  122. });
  123. commands.addCommand('file-cut', {
  124. label: 'Cut',
  125. icon: 'fa fa-cut',
  126. execute: () => { fbWidget.cut(); }
  127. });
  128. commands.addCommand('file-copy', {
  129. label: 'Copy',
  130. icon: 'fa fa-copy',
  131. mnemonic: 0,
  132. execute: () => { fbWidget.copy(); }
  133. });
  134. commands.addCommand('file-delete', {
  135. label: 'Delete',
  136. icon: 'fa fa-remove',
  137. mnemonic: 0,
  138. execute: () => { fbWidget.delete(); }
  139. });
  140. commands.addCommand('file-duplicate', {
  141. label: 'Duplicate',
  142. icon: 'fa fa-copy',
  143. mnemonic: 0,
  144. execute: () => { fbWidget.duplicate(); }
  145. });
  146. commands.addCommand('file-paste', {
  147. label: 'Paste',
  148. icon: 'fa fa-paste',
  149. mnemonic: 0,
  150. execute: () => { fbWidget.paste(); }
  151. });
  152. commands.addCommand('file-download', {
  153. label: 'Download',
  154. icon: 'fa fa-download',
  155. execute: () => { fbWidget.download(); }
  156. });
  157. commands.addCommand('file-shutdown-kernel', {
  158. label: 'Shutdown Kernel',
  159. icon: 'fa fa-stop-circle-o',
  160. execute: () => { fbWidget.shutdownKernels(); }
  161. });
  162. commands.addCommand('file-dialog-demo', {
  163. label: 'Dialog Demo',
  164. execute: () => { dialogDemo(); }
  165. });
  166. commands.addCommand('file-info-demo', {
  167. label: 'Info Demo',
  168. execute: () => {
  169. let msg = 'The quick brown fox jumped over the lazy dog';
  170. showDialog({
  171. title: 'Cool Title',
  172. body: msg,
  173. buttons: [Dialog.okButton()]
  174. });
  175. }
  176. });
  177. commands.addKeyBinding({
  178. keys: ['Enter'],
  179. selector: '.jp-DirListing',
  180. command: 'file-open'
  181. });
  182. commands.addKeyBinding({
  183. keys: ['Accel S'],
  184. selector: '.jp-CodeMirrorEditor',
  185. command: 'file-save'
  186. });
  187. window.addEventListener('keydown', (event) => {
  188. commands.processKeydownEvent(event);
  189. });
  190. let menu = new Menu({ commands });
  191. menu.addItem({ command: 'file-open' });
  192. menu.addItem({ command: 'file-rename' });
  193. menu.addItem({ command: 'file-remove' });
  194. menu.addItem({ command: 'file-duplicate' });
  195. menu.addItem({ command: 'file-delete' });
  196. menu.addItem({ command: 'file-cut' });
  197. menu.addItem({ command: 'file-copy' });
  198. menu.addItem({ command: 'file-paste' });
  199. menu.addItem({ command: 'file-shutdown-kernel' });
  200. menu.addItem({ command: 'file-dialog-demo' });
  201. menu.addItem({ command: 'file-info-demo' });
  202. // Add a context menu to the dir listing.
  203. let node = fbWidget.node.getElementsByClassName('jp-DirListing-content')[0];
  204. node.addEventListener('contextmenu', (event: MouseEvent) => {
  205. event.preventDefault();
  206. let x = event.clientX;
  207. let y = event.clientY;
  208. menu.open(x, y);
  209. });
  210. Widget.attach(panel, document.body);
  211. window.onresize = () => panel.update();
  212. }
  213. /**
  214. * Create a non-functional dialog demo.
  215. */
  216. function dialogDemo(): void {
  217. let body = document.createElement('div');
  218. let input = document.createElement('input');
  219. input.value = 'Untitled.ipynb';
  220. let selector = document.createElement('select');
  221. let option0 = document.createElement('option');
  222. option0.value = 'python';
  223. option0.text = 'Python 3';
  224. selector.appendChild(option0);
  225. let option1 = document.createElement('option');
  226. option1.value = 'julia';
  227. option1.text = 'Julia';
  228. selector.appendChild(option1);
  229. body.appendChild(input);
  230. body.appendChild(selector);
  231. showDialog({
  232. title: 'Create new notebook'
  233. });
  234. }
  235. window.onload = main;