mainmenu.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import { MenuSvg } from '@jupyterlab/ui-components';
  4. import { ArrayExt } from '@lumino/algorithm';
  5. import { CommandRegistry } from '@lumino/commands';
  6. import { Menu, MenuBar } from '@lumino/widgets';
  7. import { FileMenu } from './file';
  8. import { EditMenu } from './edit';
  9. import { HelpMenu } from './help';
  10. import { KernelMenu } from './kernel';
  11. import { RunMenu } from './run';
  12. import { SettingsMenu } from './settings';
  13. import { ViewMenu } from './view';
  14. import { TabsMenu } from './tabs';
  15. import { IMainMenu } from './tokens';
  16. /**
  17. * The main menu class. It is intended to be used as a singleton.
  18. */
  19. export class MainMenu extends MenuBar implements IMainMenu {
  20. /**
  21. * Construct the main menu bar.
  22. */
  23. constructor(commands: CommandRegistry) {
  24. super();
  25. this.editMenu = new EditMenu({ commands });
  26. this.fileMenu = new FileMenu({ commands });
  27. this.helpMenu = new HelpMenu({ commands });
  28. this.kernelMenu = new KernelMenu({ commands });
  29. this.runMenu = new RunMenu({ commands });
  30. this.settingsMenu = new SettingsMenu({ commands });
  31. this.viewMenu = new ViewMenu({ commands });
  32. this.tabsMenu = new TabsMenu({ commands });
  33. this.addMenu(this.fileMenu.menu, { rank: 1 });
  34. this.addMenu(this.editMenu.menu, { rank: 2 });
  35. this.addMenu(this.viewMenu.menu, { rank: 3 });
  36. this.addMenu(this.runMenu.menu, { rank: 4 });
  37. this.addMenu(this.kernelMenu.menu, { rank: 5 });
  38. this.addMenu(this.tabsMenu.menu, { rank: 500 });
  39. this.addMenu(this.settingsMenu.menu, { rank: 999 });
  40. this.addMenu(this.helpMenu.menu, { rank: 1000 });
  41. }
  42. /**
  43. * The application "Edit" menu.
  44. */
  45. readonly editMenu: EditMenu;
  46. /**
  47. * The application "File" menu.
  48. */
  49. readonly fileMenu: FileMenu;
  50. /**
  51. * The application "Help" menu.
  52. */
  53. readonly helpMenu: HelpMenu;
  54. /**
  55. * The application "Kernel" menu.
  56. */
  57. readonly kernelMenu: KernelMenu;
  58. /**
  59. * The application "Run" menu.
  60. */
  61. readonly runMenu: RunMenu;
  62. /**
  63. * The application "Settings" menu.
  64. */
  65. readonly settingsMenu: SettingsMenu;
  66. /**
  67. * The application "View" menu.
  68. */
  69. readonly viewMenu: ViewMenu;
  70. /**
  71. * The application "Tabs" menu.
  72. */
  73. readonly tabsMenu: TabsMenu;
  74. /**
  75. * Add a new menu to the main menu bar.
  76. */
  77. addMenu(menu: Menu, options: IMainMenu.IAddOptions = {}): void {
  78. // override default renderer with svg-supporting renderer
  79. MenuSvg.overrideDefaultRenderer(menu);
  80. if (ArrayExt.firstIndexOf(this.menus, menu) > -1) {
  81. return;
  82. }
  83. const rank = 'rank' in options ? options.rank : 100;
  84. const rankItem = { menu, rank };
  85. const index = ArrayExt.upperBound(this._items, rankItem, Private.itemCmp);
  86. // Upon disposal, remove the menu and its rank reference.
  87. menu.disposed.connect(this._onMenuDisposed, this);
  88. ArrayExt.insert(this._items, index, rankItem);
  89. /**
  90. * Create a new menu.
  91. */
  92. this.insertMenu(index, menu);
  93. }
  94. /**
  95. * Dispose of the resources held by the menu bar.
  96. */
  97. dispose(): void {
  98. this.editMenu.dispose();
  99. this.fileMenu.dispose();
  100. this.helpMenu.dispose();
  101. this.kernelMenu.dispose();
  102. this.runMenu.dispose();
  103. this.settingsMenu.dispose();
  104. this.viewMenu.dispose();
  105. this.tabsMenu.dispose();
  106. super.dispose();
  107. }
  108. /**
  109. * Handle the disposal of a menu.
  110. */
  111. private _onMenuDisposed(menu: Menu): void {
  112. this.removeMenu(menu);
  113. const index = ArrayExt.findFirstIndex(
  114. this._items,
  115. item => item.menu === menu
  116. );
  117. if (index !== -1) {
  118. ArrayExt.removeAt(this._items, index);
  119. }
  120. }
  121. private _items: Private.IRankItem[] = [];
  122. }
  123. /**
  124. * A namespace for private data.
  125. */
  126. namespace Private {
  127. /**
  128. * An object which holds a menu and its sort rank.
  129. */
  130. export interface IRankItem {
  131. /**
  132. * The menu for the item.
  133. */
  134. menu: Menu;
  135. /**
  136. * The sort rank of the menu.
  137. */
  138. rank: number;
  139. }
  140. /**
  141. * A comparator function for menu rank items.
  142. */
  143. export function itemCmp(first: IRankItem, second: IRankItem): number {
  144. return first.rank - second.rank;
  145. }
  146. }