mainmenu.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  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. ISettingsMenu, SettingsMenu
  32. } from './settings';
  33. import {
  34. IViewMenu, ViewMenu
  35. } from './view';
  36. import {
  37. ITabsMenu, TabsMenu
  38. } from './tabs';
  39. /* tslint:disable */
  40. /**
  41. * The main menu token.
  42. */
  43. export
  44. const IMainMenu = new Token<IMainMenu>('@jupyterlab/apputils:IMainMenu');
  45. /* tslint:enable */
  46. /**
  47. * The main menu interface.
  48. */
  49. export
  50. interface IMainMenu {
  51. /**
  52. * Add a new menu to the main menu bar.
  53. */
  54. addMenu(menu: Menu, options?: IMainMenu.IAddOptions): void;
  55. /**
  56. * The application "File" menu.
  57. */
  58. readonly fileMenu: IFileMenu;
  59. /**
  60. * The application "Edit" menu.
  61. */
  62. readonly editMenu: IEditMenu;
  63. /**
  64. * The application "View" menu.
  65. */
  66. readonly viewMenu: IViewMenu;
  67. /**
  68. * The application "Help" menu.
  69. */
  70. readonly helpMenu: IHelpMenu;
  71. /**
  72. * The application "Kernel" menu.
  73. */
  74. readonly kernelMenu: IKernelMenu;
  75. /**
  76. * The application "Run" menu.
  77. */
  78. readonly runMenu: IRunMenu;
  79. /**
  80. * The application "Settings" menu.
  81. */
  82. readonly settingsMenu: ISettingsMenu;
  83. /**
  84. * The application "Tabs" menu.
  85. */
  86. readonly tabsMenu: ITabsMenu;
  87. }
  88. /**
  89. * The namespace for IMainMenu attached interfaces.
  90. */
  91. export
  92. namespace IMainMenu {
  93. /**
  94. * The options used to add a menu to the main menu.
  95. */
  96. export
  97. interface IAddOptions {
  98. /**
  99. * The rank order of the menu among its siblings.
  100. */
  101. rank?: number;
  102. }
  103. }
  104. /**
  105. * The main menu class. It is intended to be used as a singleton.
  106. */
  107. export
  108. class MainMenu extends MenuBar implements IMainMenu {
  109. /**
  110. * Construct the main menu bar.
  111. */
  112. constructor(commands: CommandRegistry) {
  113. super();
  114. this.editMenu = new EditMenu({ commands });
  115. this.fileMenu = new FileMenu({ commands });
  116. this.helpMenu = new HelpMenu({ commands });
  117. this.kernelMenu = new KernelMenu({ commands });
  118. this.runMenu = new RunMenu({ commands });
  119. this.settingsMenu = new SettingsMenu({ commands });
  120. this.viewMenu = new ViewMenu({ commands });
  121. this.tabsMenu = new TabsMenu({ commands });
  122. this.addMenu(this.fileMenu.menu, { rank: 0 });
  123. this.addMenu(this.editMenu.menu, { rank: 1 });
  124. this.addMenu(this.viewMenu.menu, { rank: 2 });
  125. this.addMenu(this.runMenu.menu, { rank: 3 });
  126. this.addMenu(this.kernelMenu.menu, { rank: 4 });
  127. this.addMenu(this.tabsMenu.menu, { rank: 500 });
  128. this.addMenu(this.settingsMenu.menu, { rank: 999 });
  129. this.addMenu(this.helpMenu.menu, { rank: 1000 });
  130. }
  131. /**
  132. * The application "Edit" menu.
  133. */
  134. readonly editMenu: EditMenu;
  135. /**
  136. * The application "File" menu.
  137. */
  138. readonly fileMenu: FileMenu;
  139. /**
  140. * The application "Help" menu.
  141. */
  142. readonly helpMenu: HelpMenu;
  143. /**
  144. * The application "Kernel" menu.
  145. */
  146. readonly kernelMenu: KernelMenu;
  147. /**
  148. * The application "Run" menu.
  149. */
  150. readonly runMenu: RunMenu;
  151. /**
  152. * The application "Settings" menu.
  153. */
  154. readonly settingsMenu: SettingsMenu;
  155. /**
  156. * The application "View" menu.
  157. */
  158. readonly viewMenu: ViewMenu;
  159. /**
  160. * The application "Tabs" menu.
  161. */
  162. readonly tabsMenu: TabsMenu;
  163. /**
  164. * Add a new menu to the main menu bar.
  165. */
  166. addMenu(menu: Menu, options: IMainMenu.IAddOptions = {}): void {
  167. if (ArrayExt.firstIndexOf(this.menus, menu) > -1) {
  168. return;
  169. }
  170. let rank = 'rank' in options ? options.rank : 100;
  171. let rankItem = { menu, rank };
  172. let index = ArrayExt.upperBound(this._items, rankItem, Private.itemCmp);
  173. // Upon disposal, remove the menu and its rank reference.
  174. menu.disposed.connect(this._onMenuDisposed, this);
  175. ArrayExt.insert(this._items, index, rankItem);
  176. /**
  177. * Create a new menu.
  178. */
  179. this.insertMenu(index, menu);
  180. }
  181. /**
  182. * Dispose of the resources held by the menu bar.
  183. */
  184. dispose(): void {
  185. this.editMenu.dispose();
  186. this.fileMenu.dispose();
  187. this.helpMenu.dispose();
  188. this.kernelMenu.dispose();
  189. this.runMenu.dispose();
  190. this.settingsMenu.dispose();
  191. this.viewMenu.dispose();
  192. this.tabsMenu.dispose();
  193. super.dispose();
  194. }
  195. /**
  196. * Handle the disposal of a menu.
  197. */
  198. private _onMenuDisposed(menu: Menu): void {
  199. this.removeMenu(menu);
  200. let index = ArrayExt.findFirstIndex(this._items, item => item.menu === menu);
  201. if (index !== -1) {
  202. ArrayExt.removeAt(this._items, index);
  203. }
  204. }
  205. private _items: Private.IRankItem[] = [];
  206. }
  207. /**
  208. * A namespace for private data.
  209. */
  210. namespace Private {
  211. /**
  212. * An object which holds a menu and its sort rank.
  213. */
  214. export
  215. interface IRankItem {
  216. /**
  217. * The menu for the item.
  218. */
  219. menu: Menu;
  220. /**
  221. * The sort rank of the menu.
  222. */
  223. rank: number;
  224. }
  225. /**
  226. * A comparator function for menu rank items.
  227. */
  228. export
  229. function itemCmp(first: IRankItem, second: IRankItem): number {
  230. return first.rank - second.rank;
  231. }
  232. }