index.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import {
  4. ArrayExt, ArrayIterator, IIterator, map, toArray
  5. } from '@phosphor/algorithm';
  6. import {
  7. Token
  8. } from '@phosphor/coreutils';
  9. import {
  10. DisposableDelegate, IDisposable
  11. } from '@phosphor/disposable';
  12. import {
  13. h, VirtualNode
  14. } from '@phosphor/virtualdom';
  15. import {
  16. Widget
  17. } from '@phosphor/widgets';
  18. import {
  19. VDomModel, VDomRenderer
  20. } from '@jupyterlab/apputils';
  21. import '../style/index.css';
  22. /**
  23. * The command IDs used by the launcher plugin.
  24. */
  25. export
  26. namespace CommandIDs {
  27. export
  28. const show: string = 'launcher-jupyterlab:show';
  29. };
  30. /* tslint:disable */
  31. /**
  32. * The launcher token.
  33. */
  34. export
  35. const ILauncher = new Token<ILauncher>('jupyter.services.launcher');
  36. /* tslint:enable */
  37. /**
  38. * The class name added to LauncherWidget instances.
  39. */
  40. const LAUNCHER_CLASS = 'jp-LauncherWidget';
  41. /**
  42. * The class name added to LauncherWidget image nodes.
  43. */
  44. //const IMAGE_CLASS = 'jp-LauncherWidget-image';
  45. /**
  46. * The class name added to LauncherWidget text nodes.
  47. */
  48. const TEXT_CLASS = 'jp-LauncherWidget-text';
  49. /**
  50. * The class name added to LauncherWidget item nodes.
  51. */
  52. const ITEM_CLASS = 'jp-LauncherWidget-item';
  53. /**
  54. * The class name added to LauncherWidget body nodes.
  55. */
  56. const BODY_CLASS = 'jp-LauncherWidget-body';
  57. /**
  58. * The class name added to LauncherWidget dialog node.
  59. */
  60. const DIALOG_CLASS = 'jp-LauncherWidget-dialog';
  61. /**
  62. * The launcher interface.
  63. */
  64. export
  65. interface ILauncher {
  66. /**
  67. * Add a command item to the launcher, and trigger re-render event for parent
  68. * widget.
  69. *
  70. * @param options - The specification options for a launcher item.
  71. *
  72. * @returns A disposable that will remove the item from Launcher, and trigger
  73. * re-render event for parent widget.
  74. *
  75. */
  76. add(options: ILauncherItem): IDisposable;
  77. }
  78. /**
  79. * The specification for a launcher item.
  80. */
  81. export
  82. interface ILauncherItem {
  83. /**
  84. * The display name for the launcher item.
  85. */
  86. displayName: string;
  87. /**
  88. * The callback invoked to launch the item.
  89. *
  90. * The callback is invoked with a current working directory and the
  91. * name of the selected launcher item and returns a promise that
  92. * resolves to the widget that will replace the launcher widget.
  93. */
  94. callback: (cwd: string, name: string) => Widget | Promise<Widget>;
  95. /**
  96. * The icon class for the launcher item.
  97. *
  98. * #### Notes
  99. * This class name will be added to the icon node for the visual
  100. * representation of the launcher item.
  101. *
  102. * Multiple class names can be separated with white space.
  103. *
  104. * The default value is an empty string.
  105. */
  106. iconClass?: string;
  107. /**
  108. * The icon label for the launcher item.
  109. *
  110. * #### Notes
  111. * This label will be added as text to the icon node for the visual
  112. * representation of the launcher item.
  113. *
  114. * The default value is an empty string.
  115. */
  116. iconLabel?: string;
  117. /**
  118. * The identifier for the launcher item.
  119. *
  120. * The default value is the displayName.
  121. */
  122. name?: string;
  123. /**
  124. * The category for the launcher item.
  125. *
  126. * The default value is the displayName.
  127. */
  128. category?: string;
  129. /**
  130. * The rank for the launcher item.
  131. *
  132. * The rank is used as a tie-breaker when ordering launcher items
  133. * for display. Items are sorted in the following order:
  134. * 1. Category (locale order)
  135. * 2. Rank (lower is better)
  136. * 3. Label (locale order)
  137. *
  138. * The default rank is `Infinity`.
  139. */
  140. rank?: number;
  141. }
  142. /**
  143. * LauncherModel keeps track of the path to working directory and has a list of
  144. * LauncherItems, which the LauncherWidget will render.
  145. */
  146. export
  147. class LauncherModel extends VDomModel implements ILauncher {
  148. /**
  149. * Create a new launcher model.
  150. */
  151. constructor() {
  152. super();
  153. }
  154. /**
  155. * Add a command item to the launcher, and trigger re-render event for parent
  156. * widget.
  157. *
  158. * @param options - The specification options for a launcher item.
  159. *
  160. * @returns A disposable that will remove the item from Launcher, and trigger
  161. * re-render event for parent widget.
  162. *
  163. */
  164. add(options: ILauncherItem): IDisposable {
  165. // Create a copy of the options to circumvent mutations to the original.
  166. let item = JSON.parse(JSON.stringify(options));
  167. this._items.push(item);
  168. this.stateChanged.emit(void 0);
  169. return new DisposableDelegate(() => {
  170. ArrayExt.removeFirstOf(this._items, item);
  171. this.stateChanged.emit(void 0);
  172. });
  173. }
  174. /**
  175. * Return an iterator of launcher items.
  176. */
  177. items(): IIterator<ILauncherItem> {
  178. return new ArrayIterator(this._items);
  179. }
  180. private _items: ILauncherItem[] = [];
  181. }
  182. /**
  183. * A virtual-DOM-based widget for the Launcher.
  184. */
  185. export
  186. class LauncherWidget extends VDomRenderer<LauncherModel> {
  187. /**
  188. * Construct a new launcher widget.
  189. */
  190. constructor() {
  191. super();
  192. this.addClass(LAUNCHER_CLASS);
  193. }
  194. /**
  195. * Render the launcher to virtual DOM nodes.
  196. */
  197. protected render(): VirtualNode | VirtualNode[] {
  198. // Create an iterator that yields rendered item nodes.
  199. let children = map(this.model.items(), item => {
  200. let text = h.span({className: TEXT_CLASS }, item.displayName);
  201. return h.div({
  202. className: ITEM_CLASS,
  203. }, [text]);
  204. });
  205. let body = h.div({ className: BODY_CLASS }, toArray(children));
  206. return h.div({ className: DIALOG_CLASS }, [body]);
  207. }
  208. }