index.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import {
  4. findIndex, indexOf, upperBound
  5. } from 'phosphor/lib/algorithm/searching';
  6. import {
  7. Vector
  8. } from 'phosphor/lib/collections/vector';
  9. import {
  10. Token
  11. } from 'phosphor/lib/core/token';
  12. import {
  13. Menu
  14. } from 'phosphor/lib/ui/menu';
  15. import {
  16. MenuBar
  17. } from 'phosphor/lib/ui/menubar';
  18. /* tslint:disable */
  19. /**
  20. * The main menu token.
  21. */
  22. export
  23. const IMainMenu = new Token<IMainMenu>('jupyter.services.main-menu');
  24. /* tslint:enable */
  25. /**
  26. * The main menu interface.
  27. */
  28. export
  29. interface IMainMenu {
  30. /**
  31. * Add a new menu to the main menu bar.
  32. */
  33. addMenu(menu: Menu, options: IAddMenuOptions): void;
  34. }
  35. /**
  36. * The options used to add a menu to the main menu.
  37. */
  38. export
  39. interface IAddMenuOptions {
  40. /**
  41. * The rank order of the menu among its siblings.
  42. */
  43. rank?: number;
  44. }
  45. /**
  46. * The main menu class. It is intended to be used as a singleton.
  47. */
  48. export
  49. class MainMenu extends MenuBar implements IMainMenu {
  50. /**
  51. * Add a new menu to the main menu bar.
  52. */
  53. addMenu(menu: Menu, options: IAddMenuOptions = {}): void {
  54. if (indexOf(this.menus, menu) > -1) {
  55. return;
  56. }
  57. let rank = 'rank' in options ? options.rank : 100;
  58. let rankItem = { menu, rank };
  59. let index = upperBound(this._items, rankItem, Private.itemCmp);
  60. // Upon disposal, remove the menu and its rank reference.
  61. menu.disposed.connect(this._onMenuDisposed, this);
  62. this._items.insert(index, rankItem);
  63. this.insertMenu(index, menu);
  64. }
  65. /**
  66. * Handle the disposal of a menu.
  67. */
  68. private _onMenuDisposed(menu: Menu): void {
  69. this.removeMenu(menu);
  70. let index = findIndex(this._items, item => item.menu === menu);
  71. if (index !== -1) {
  72. this._items.removeAt(index);
  73. }
  74. }
  75. private _items = new Vector<Private.IRankItem>();
  76. }
  77. /**
  78. * A namespace for private data.
  79. */
  80. namespace Private {
  81. /**
  82. * An object which holds a menu and its sort rank.
  83. */
  84. export
  85. interface IRankItem {
  86. /**
  87. * The menu for the item.
  88. */
  89. menu: Menu;
  90. /**
  91. * The sort rank of the menu.
  92. */
  93. rank: number;
  94. }
  95. /**
  96. * A comparator function for menu rank items.
  97. */
  98. export
  99. function itemCmp(first: IRankItem, second: IRankItem): number {
  100. return first.rank - second.rank;
  101. }
  102. }