mainmenu.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import {
  4. ArrayExt
  5. } from '@phosphor/algorithm';
  6. import {
  7. CommandRegistry
  8. } from '@phosphor/commands';
  9. import {
  10. Token
  11. } from '@phosphor/coreutils';
  12. import {
  13. Menu, MenuBar
  14. } from '@phosphor/widgets';
  15. import {
  16. IFileMenu, FileMenu
  17. } from './file';
  18. import {
  19. IEditMenu, EditMenu
  20. } from './edit';
  21. import {
  22. IHelpMenu, HelpMenu
  23. } from './help';
  24. import {
  25. IKernelMenu, KernelMenu
  26. } from './kernel';
  27. import {
  28. IRunMenu, RunMenu
  29. } from './run';
  30. import {
  31. IViewMenu, ViewMenu
  32. } from './view';
  33. /* tslint:disable */
  34. /**
  35. * The main menu token.
  36. */
  37. export
  38. const IMainMenu = new Token<IMainMenu>('@jupyterlab/apputils:IMainMenu');
  39. /* tslint:enable */
  40. /**
  41. * The main menu interface.
  42. */
  43. export
  44. interface IMainMenu {
  45. /**
  46. * Add a new menu to the main menu bar.
  47. */
  48. addMenu(menu: Menu, options?: IMainMenu.IAddOptions): void;
  49. /**
  50. * The application "File" menu.
  51. */
  52. readonly fileMenu: IFileMenu;
  53. /**
  54. * The application "Edit" menu.
  55. */
  56. readonly editMenu: IEditMenu;
  57. /**
  58. * The application "View" menu.
  59. */
  60. readonly viewMenu: IViewMenu;
  61. /**
  62. * The application "Help" menu.
  63. */
  64. readonly helpMenu: IHelpMenu;
  65. /**
  66. * The application "Kernel" menu.
  67. */
  68. readonly kernelMenu: IKernelMenu;
  69. /**
  70. * The application "Run" menu.
  71. */
  72. readonly runMenu: IRunMenu;
  73. }
  74. /**
  75. * The namespace for IMainMenu attached interfaces.
  76. */
  77. export
  78. namespace IMainMenu {
  79. /**
  80. * The options used to add a menu to the main menu.
  81. */
  82. export
  83. interface IAddOptions {
  84. /**
  85. * The rank order of the menu among its siblings.
  86. */
  87. rank?: number;
  88. }
  89. }
  90. /**
  91. * The main menu class. It is intended to be used as a singleton.
  92. */
  93. export
  94. class MainMenu extends MenuBar implements IMainMenu {
  95. /**
  96. * Construct the main menu bar.
  97. */
  98. constructor(commands: CommandRegistry) {
  99. super();
  100. this.editMenu = new EditMenu({ commands });
  101. this.fileMenu = new FileMenu({ commands });
  102. this.helpMenu = new HelpMenu({ commands });
  103. this.kernelMenu = new KernelMenu({ commands });
  104. this.runMenu = new RunMenu({ commands });
  105. this.viewMenu = new ViewMenu({ commands });
  106. this.addMenu(this.fileMenu.menu, { rank: 0 });
  107. this.addMenu(this.editMenu.menu, { rank: 1 });
  108. this.addMenu(this.runMenu.menu, { rank: 2 });
  109. this.addMenu(this.kernelMenu.menu, { rank: 3 });
  110. this.addMenu(this.viewMenu.menu, { rank: 4 });
  111. this.addMenu(this.helpMenu.menu, { rank: 1000 });
  112. }
  113. /**
  114. * The application "Edit" menu.
  115. */
  116. readonly editMenu: EditMenu;
  117. /**
  118. * The application "File" menu.
  119. */
  120. readonly fileMenu: FileMenu;
  121. /**
  122. * The application "Help" menu.
  123. */
  124. readonly helpMenu: HelpMenu;
  125. /**
  126. * The application "Kernel" menu.
  127. */
  128. readonly kernelMenu: KernelMenu;
  129. /**
  130. * The application "Run" menu.
  131. */
  132. readonly runMenu: RunMenu;
  133. /**
  134. * The application "View" menu.
  135. */
  136. readonly viewMenu: ViewMenu;
  137. /**
  138. * Add a new menu to the main menu bar.
  139. */
  140. addMenu(menu: Menu, options: IMainMenu.IAddOptions = {}): void {
  141. if (ArrayExt.firstIndexOf(this.menus, menu) > -1) {
  142. return;
  143. }
  144. let rank = 'rank' in options ? options.rank : 100;
  145. let rankItem = { menu, rank };
  146. let index = ArrayExt.upperBound(this._items, rankItem, Private.itemCmp);
  147. // Upon disposal, remove the menu and its rank reference.
  148. menu.disposed.connect(this._onMenuDisposed, this);
  149. ArrayExt.insert(this._items, index, rankItem);
  150. /**
  151. * Create a new menu.
  152. */
  153. this.insertMenu(index, menu);
  154. }
  155. /**
  156. * Dispose of the resources held by the menu bar.
  157. */
  158. dispose(): void {
  159. this.editMenu.dispose();
  160. this.fileMenu.dispose();
  161. this.helpMenu.dispose();
  162. this.kernelMenu.dispose();
  163. this.runMenu.dispose();
  164. this.viewMenu.dispose();
  165. super.dispose();
  166. }
  167. /**
  168. * Handle the disposal of a menu.
  169. */
  170. private _onMenuDisposed(menu: Menu): void {
  171. this.removeMenu(menu);
  172. let index = ArrayExt.findFirstIndex(this._items, item => item.menu === menu);
  173. if (index !== -1) {
  174. ArrayExt.removeAt(this._items, index);
  175. }
  176. }
  177. private _items: Private.IRankItem[] = [];
  178. }
  179. /**
  180. * A namespace for private data.
  181. */
  182. namespace Private {
  183. /**
  184. * An object which holds a menu and its sort rank.
  185. */
  186. export
  187. interface IRankItem {
  188. /**
  189. * The menu for the item.
  190. */
  191. menu: Menu;
  192. /**
  193. * The sort rank of the menu.
  194. */
  195. rank: number;
  196. }
  197. /**
  198. * A comparator function for menu rank items.
  199. */
  200. export
  201. function itemCmp(first: IRankItem, second: IRankItem): number {
  202. return first.rank - second.rank;
  203. }
  204. }