@theia/core 1.62.0-next.3 → 1.62.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/i18n/nls.cs.json +158 -13
- package/i18n/nls.de.json +158 -13
- package/i18n/nls.es.json +158 -13
- package/i18n/nls.fr.json +158 -13
- package/i18n/nls.hu.json +158 -13
- package/i18n/nls.it.json +158 -13
- package/i18n/nls.ja.json +158 -13
- package/i18n/nls.json +159 -14
- package/i18n/nls.ko.json +158 -13
- package/i18n/nls.pl.json +158 -13
- package/i18n/nls.pt-br.json +158 -13
- package/i18n/nls.ru.json +158 -13
- package/i18n/nls.tr.json +158 -13
- package/i18n/nls.zh-cn.json +158 -13
- package/i18n/nls.zh-tw.json +158 -13
- package/lib/browser/catalog.json +206 -33
- package/lib/browser/common-frontend-contribution.d.ts +1 -1
- package/lib/browser/common-frontend-contribution.d.ts.map +1 -1
- package/lib/browser/common-frontend-contribution.js +13 -11
- package/lib/browser/common-frontend-contribution.js.map +1 -1
- package/lib/browser/context-menu-renderer.d.ts +14 -3
- package/lib/browser/context-menu-renderer.d.ts.map +1 -1
- package/lib/browser/context-menu-renderer.js +23 -1
- package/lib/browser/context-menu-renderer.js.map +1 -1
- package/lib/browser/frontend-application-module.d.ts.map +1 -1
- package/lib/browser/frontend-application-module.js +1 -3
- package/lib/browser/frontend-application-module.js.map +1 -1
- package/lib/browser/hover-service.d.ts.map +1 -1
- package/lib/browser/hover-service.js +7 -0
- package/lib/browser/hover-service.js.map +1 -1
- package/lib/browser/menu/action-menu-node.d.ts +36 -0
- package/lib/browser/menu/action-menu-node.d.ts.map +1 -0
- package/lib/browser/menu/action-menu-node.js +113 -0
- package/lib/browser/menu/action-menu-node.js.map +1 -0
- package/lib/browser/menu/browser-context-menu-renderer.d.ts +12 -4
- package/lib/browser/menu/browser-context-menu-renderer.d.ts.map +1 -1
- package/lib/browser/menu/browser-context-menu-renderer.js +12 -13
- package/lib/browser/menu/browser-context-menu-renderer.js.map +1 -1
- package/lib/browser/menu/browser-menu-module.d.ts.map +1 -1
- package/lib/browser/menu/browser-menu-module.js +4 -0
- package/lib/browser/menu/browser-menu-module.js.map +1 -1
- package/lib/browser/menu/browser-menu-node-factory.d.ts +13 -0
- package/lib/browser/menu/browser-menu-node-factory.d.ts.map +1 -0
- package/lib/browser/menu/browser-menu-node-factory.js +54 -0
- package/lib/browser/menu/browser-menu-node-factory.js.map +1 -0
- package/lib/browser/menu/browser-menu-plugin.d.ts +12 -30
- package/lib/browser/menu/browser-menu-plugin.d.ts.map +1 -1
- package/lib/browser/menu/browser-menu-plugin.js +78 -159
- package/lib/browser/menu/browser-menu-plugin.js.map +1 -1
- package/lib/browser/menu/composite-menu-node.d.ts +49 -0
- package/lib/browser/menu/composite-menu-node.d.ts.map +1 -0
- package/lib/browser/menu/composite-menu-node.js +127 -0
- package/lib/browser/menu/composite-menu-node.js.map +1 -0
- package/lib/browser/menu/menu.spec.d.ts.map +1 -0
- package/lib/{common → browser}/menu/menu.spec.js +38 -13
- package/lib/browser/menu/menu.spec.js.map +1 -0
- package/lib/browser/open-with-service.d.ts +1 -1
- package/lib/browser/saveable-service.d.ts.map +1 -1
- package/lib/browser/saveable-service.js +6 -1
- package/lib/browser/saveable-service.js.map +1 -1
- package/lib/browser/shell/application-shell.d.ts +7 -5
- package/lib/browser/shell/application-shell.d.ts.map +1 -1
- package/lib/browser/shell/application-shell.js +82 -28
- package/lib/browser/shell/application-shell.js.map +1 -1
- package/lib/browser/shell/index.d.ts +1 -0
- package/lib/browser/shell/index.d.ts.map +1 -1
- package/lib/browser/shell/index.js +1 -0
- package/lib/browser/shell/index.js.map +1 -1
- package/lib/browser/shell/sidebar-bottom-menu-widget.d.ts.map +1 -1
- package/lib/browser/shell/sidebar-bottom-menu-widget.js +2 -1
- package/lib/browser/shell/sidebar-bottom-menu-widget.js.map +1 -1
- package/lib/browser/shell/sidebar-menu-widget.d.ts +4 -1
- package/lib/browser/shell/sidebar-menu-widget.d.ts.map +1 -1
- package/lib/browser/shell/sidebar-menu-widget.js +14 -1
- package/lib/browser/shell/sidebar-menu-widget.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.d.ts +66 -8
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.d.ts.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js +161 -8
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.d.ts +18 -32
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.d.ts.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js +52 -88
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.d.ts +17 -21
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.d.ts.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.js +9 -9
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts +7 -39
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js +30 -238
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js +13 -13
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.d.ts +56 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.d.ts.map +1 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.js +208 -0
- package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.js.map +1 -0
- package/lib/browser/shell/tab-bars.d.ts.map +1 -1
- package/lib/browser/shell/tab-bars.js +2 -1
- package/lib/browser/shell/tab-bars.js.map +1 -1
- package/lib/browser/shell/theia-dock-panel.d.ts +4 -10
- package/lib/browser/shell/theia-dock-panel.d.ts.map +1 -1
- package/lib/browser/shell/theia-dock-panel.js +7 -84
- package/lib/browser/shell/theia-dock-panel.js.map +1 -1
- package/lib/browser/shell/theia-split-panel.d.ts +6 -0
- package/lib/browser/shell/theia-split-panel.d.ts.map +1 -0
- package/lib/browser/shell/theia-split-panel.js +56 -0
- package/lib/browser/shell/theia-split-panel.js.map +1 -0
- package/lib/browser/tree/tree-widget.d.ts +1 -0
- package/lib/browser/tree/tree-widget.d.ts.map +1 -1
- package/lib/browser/tree/tree-widget.js +6 -0
- package/lib/browser/tree/tree-widget.js.map +1 -1
- package/lib/browser/view-container.d.ts +6 -3
- package/lib/browser/view-container.d.ts.map +1 -1
- package/lib/browser/view-container.js +36 -26
- package/lib/browser/view-container.js.map +1 -1
- package/lib/browser/window/default-secondary-window-service.d.ts +1 -0
- package/lib/browser/window/default-secondary-window-service.d.ts.map +1 -1
- package/lib/browser/window/default-secondary-window-service.js +3 -0
- package/lib/browser/window/default-secondary-window-service.js.map +1 -1
- package/lib/common/listener.d.ts +21 -0
- package/lib/common/listener.d.ts.map +1 -0
- package/lib/common/listener.js +81 -0
- package/lib/common/listener.js.map +1 -0
- package/lib/common/listener.spec.d.ts +2 -0
- package/lib/common/listener.spec.d.ts.map +1 -0
- package/lib/common/listener.spec.js +255 -0
- package/lib/common/listener.spec.js.map +1 -0
- package/lib/common/menu/index.d.ts +2 -3
- package/lib/common/menu/index.d.ts.map +1 -1
- package/lib/common/menu/index.js +2 -3
- package/lib/common/menu/index.js.map +1 -1
- package/lib/common/menu/menu-model-registry.d.ts +37 -50
- package/lib/common/menu/menu-model-registry.d.ts.map +1 -1
- package/lib/common/menu/menu-model-registry.js +176 -225
- package/lib/common/menu/menu-model-registry.js.map +1 -1
- package/lib/common/menu/menu-types.d.ts +58 -96
- package/lib/common/menu/menu-types.d.ts.map +1 -1
- package/lib/common/menu/menu-types.js +43 -39
- package/lib/common/menu/menu-types.js.map +1 -1
- package/lib/common/messaging/proxy-factory.d.ts.map +1 -1
- package/lib/common/messaging/proxy-factory.js +4 -0
- package/lib/common/messaging/proxy-factory.js.map +1 -1
- package/lib/electron-browser/menu/electron-context-menu-renderer.d.ts +15 -5
- package/lib/electron-browser/menu/electron-context-menu-renderer.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-context-menu-renderer.js +21 -14
- package/lib/electron-browser/menu/electron-context-menu-renderer.js.map +1 -1
- package/lib/electron-browser/menu/electron-main-menu-factory.d.ts +4 -16
- package/lib/electron-browser/menu/electron-main-menu-factory.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-main-menu-factory.js +84 -104
- package/lib/electron-browser/menu/electron-main-menu-factory.js.map +1 -1
- package/lib/electron-browser/menu/electron-menu-contribution.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-menu-contribution.js +1 -4
- package/lib/electron-browser/menu/electron-menu-contribution.js.map +1 -1
- package/lib/electron-browser/menu/electron-menu-module.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-menu-module.js +5 -0
- package/lib/electron-browser/menu/electron-menu-module.js.map +1 -1
- package/lib/electron-browser/window/electron-secondary-window-service.d.ts +1 -0
- package/lib/electron-browser/window/electron-secondary-window-service.d.ts.map +1 -1
- package/lib/electron-browser/window/electron-secondary-window-service.js +20 -0
- package/lib/electron-browser/window/electron-secondary-window-service.js.map +1 -1
- package/lib/electron-browser/window/electron-window-service.d.ts +3 -0
- package/lib/electron-browser/window/electron-window-service.d.ts.map +1 -1
- package/lib/electron-browser/window/electron-window-service.js +10 -1
- package/lib/electron-browser/window/electron-window-service.js.map +1 -1
- package/lib/electron-main/theia-electron-window.d.ts.map +1 -1
- package/lib/electron-main/theia-electron-window.js +2 -0
- package/lib/electron-main/theia-electron-window.js.map +1 -1
- package/package.json +7 -8
- package/src/browser/common-frontend-contribution.ts +14 -14
- package/src/browser/context-menu-renderer.ts +33 -5
- package/src/browser/frontend-application-module.ts +1 -7
- package/src/browser/hover-service.ts +7 -0
- package/src/browser/menu/action-menu-node.ts +128 -0
- package/src/browser/menu/browser-context-menu-renderer.ts +18 -11
- package/src/browser/menu/browser-menu-module.ts +4 -0
- package/src/browser/menu/browser-menu-node-factory.ts +48 -0
- package/src/browser/menu/browser-menu-plugin.ts +80 -168
- package/src/browser/menu/composite-menu-node.ts +140 -0
- package/src/{common → browser}/menu/menu.spec.ts +47 -15
- package/src/browser/open-with-service.ts +1 -1
- package/src/browser/saveable-service.ts +6 -1
- package/src/browser/shell/application-shell.ts +91 -29
- package/src/browser/shell/index.ts +1 -0
- package/src/browser/shell/sidebar-bottom-menu-widget.tsx +2 -1
- package/src/browser/shell/sidebar-menu-widget.tsx +12 -2
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.tsx +239 -0
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts +59 -102
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-types.ts +14 -23
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.ts +14 -14
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.tsx +34 -261
- package/src/browser/shell/tab-bar-toolbar/tab-toolbar-item.tsx +251 -0
- package/src/browser/shell/tab-bars.ts +2 -1
- package/src/browser/shell/theia-dock-panel.ts +10 -91
- package/src/browser/shell/theia-split-panel.ts +56 -0
- package/src/browser/style/hover-service.css +6 -1
- package/src/browser/style/index.css +3 -11
- package/src/browser/style/view-container.css +17 -31
- package/src/browser/tree/tree-widget.tsx +7 -0
- package/src/browser/view-container.ts +51 -30
- package/src/browser/window/default-secondary-window-service.ts +4 -0
- package/src/common/listener.spec.ts +315 -0
- package/src/common/listener.ts +88 -0
- package/src/common/menu/index.ts +2 -3
- package/src/common/menu/menu-model-registry.ts +187 -230
- package/src/common/menu/menu-types.ts +82 -128
- package/src/common/messaging/proxy-factory.ts +4 -1
- package/src/electron-browser/menu/electron-context-menu-renderer.ts +29 -13
- package/src/electron-browser/menu/electron-main-menu-factory.ts +92 -116
- package/src/electron-browser/menu/electron-menu-contribution.ts +1 -4
- package/src/electron-browser/menu/electron-menu-module.ts +6 -1
- package/src/electron-browser/window/electron-secondary-window-service.ts +22 -0
- package/src/electron-browser/window/electron-window-service.ts +11 -1
- package/src/electron-main/theia-electron-window.ts +2 -0
- package/lib/common/menu/action-menu-node.d.ts +0 -20
- package/lib/common/menu/action-menu-node.d.ts.map +0 -1
- package/lib/common/menu/action-menu-node.js +0 -57
- package/lib/common/menu/action-menu-node.js.map +0 -1
- package/lib/common/menu/composite-menu-node.d.ts +0 -47
- package/lib/common/menu/composite-menu-node.d.ts.map +0 -1
- package/lib/common/menu/composite-menu-node.js +0 -96
- package/lib/common/menu/composite-menu-node.js.map +0 -1
- package/lib/common/menu/composite-menu-node.spec.d.ts +0 -2
- package/lib/common/menu/composite-menu-node.spec.d.ts.map +0 -1
- package/lib/common/menu/composite-menu-node.spec.js +0 -68
- package/lib/common/menu/composite-menu-node.spec.js.map +0 -1
- package/lib/common/menu/menu-adapter.d.ts +0 -36
- package/lib/common/menu/menu-adapter.d.ts.map +0 -1
- package/lib/common/menu/menu-adapter.js +0 -93
- package/lib/common/menu/menu-adapter.js.map +0 -1
- package/lib/common/menu/menu.spec.d.ts.map +0 -1
- package/lib/common/menu/menu.spec.js.map +0 -1
- package/lib/common/test/mock-menu.d.ts +0 -8
- package/lib/common/test/mock-menu.d.ts.map +0 -1
- package/lib/common/test/mock-menu.js +0 -35
- package/lib/common/test/mock-menu.js.map +0 -1
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.ts +0 -31
- package/src/common/menu/action-menu-node.ts +0 -65
- package/src/common/menu/composite-menu-node.spec.ts +0 -67
- package/src/common/menu/composite-menu-node.ts +0 -116
- package/src/common/menu/menu-adapter.ts +0 -103
- package/src/common/test/mock-menu.ts +0 -35
- /package/lib/{common → browser}/menu/menu.spec.d.ts +0 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2025 ST Microelectronics and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
18
|
+
|
|
19
|
+
import { expect } from 'chai';
|
|
20
|
+
import { ListenerList } from './listener';
|
|
21
|
+
|
|
22
|
+
describe('ListenerList<T, U>', () => {
|
|
23
|
+
let listenerList: ListenerList<any, any>;
|
|
24
|
+
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
listenerList = new ListenerList<any, any>();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe('registration and disposal', () => {
|
|
30
|
+
it('should register a single listener and allow it to be invoked', () => {
|
|
31
|
+
let listenerCalled = false;
|
|
32
|
+
const testEvent = { data: 'test' };
|
|
33
|
+
let receivedEvent: any;
|
|
34
|
+
const listener = (e: any) => {
|
|
35
|
+
listenerCalled = true;
|
|
36
|
+
receivedEvent = e;
|
|
37
|
+
return 'result';
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
listenerList.registration(listener);
|
|
41
|
+
|
|
42
|
+
let callbackCalled = false;
|
|
43
|
+
let callbackValue: any;
|
|
44
|
+
listenerList.invoke(testEvent, value => {
|
|
45
|
+
callbackCalled = true;
|
|
46
|
+
callbackValue = value;
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
expect(listenerCalled).to.be.true;
|
|
50
|
+
expect(receivedEvent).to.equal(testEvent);
|
|
51
|
+
expect(callbackCalled).to.be.true;
|
|
52
|
+
expect(callbackValue).to.equal('result');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should return a Disposable when a listener is registered', () => {
|
|
56
|
+
const listener = () => { };
|
|
57
|
+
const disposable = listenerList.registration(listener);
|
|
58
|
+
expect(disposable).to.exist;
|
|
59
|
+
expect(typeof disposable.dispose).to.equal('function');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should remove the listener when the Disposable is disposed', () => {
|
|
63
|
+
let listenerCallCount = 0;
|
|
64
|
+
const listener = () => {
|
|
65
|
+
listenerCallCount++;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const disposable = listenerList.registration(listener);
|
|
69
|
+
disposable.dispose();
|
|
70
|
+
|
|
71
|
+
listenerList.invoke({}, () => { });
|
|
72
|
+
|
|
73
|
+
expect(listenerCallCount).to.equal(0);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should register multiple listeners and invoke all of them', () => {
|
|
77
|
+
let listener1Called = false;
|
|
78
|
+
let listener2Called = false;
|
|
79
|
+
const results: any[] = [];
|
|
80
|
+
|
|
81
|
+
const listener1 = (e: any) => { listener1Called = true; return e + 1; };
|
|
82
|
+
const listener2 = (e: any) => { listener2Called = true; return e + 2; };
|
|
83
|
+
|
|
84
|
+
listenerList.registration(listener1);
|
|
85
|
+
listenerList.registration(listener2);
|
|
86
|
+
|
|
87
|
+
listenerList.invoke(10, value => {
|
|
88
|
+
results.push(value);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
expect(listener1Called).to.be.true;
|
|
92
|
+
expect(listener2Called).to.be.true;
|
|
93
|
+
expect(results).to.deep.equal([11, 12]);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should dispose of a specific listener among multiple, leaving others active', () => {
|
|
97
|
+
let listener1CallCount = 0;
|
|
98
|
+
let listener2CallCount = 0;
|
|
99
|
+
const results: any[] = [];
|
|
100
|
+
|
|
101
|
+
const listener1 = (e: any) => { listener1CallCount++; return 'L1'; };
|
|
102
|
+
const listener2 = (e: any) => { listener2CallCount++; return 'L2'; };
|
|
103
|
+
|
|
104
|
+
const disposable1 = listenerList.registration(listener1);
|
|
105
|
+
listenerList.registration(listener2);
|
|
106
|
+
|
|
107
|
+
disposable1.dispose();
|
|
108
|
+
|
|
109
|
+
listenerList.invoke({}, value => {
|
|
110
|
+
results.push(value);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
expect(listener1CallCount).to.equal(0);
|
|
114
|
+
expect(listener2CallCount).to.equal(1);
|
|
115
|
+
expect(results).to.deep.equal(['L2']);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('should handle disposing a listener that was already disposed (no error)', () => {
|
|
119
|
+
const listener = () => { };
|
|
120
|
+
const disposable = listenerList.registration(listener);
|
|
121
|
+
|
|
122
|
+
disposable.dispose(); // First dispose
|
|
123
|
+
expect(() => disposable.dispose()).to.not.throw(); // Second dispose
|
|
124
|
+
|
|
125
|
+
// Ensure no listeners are invoked
|
|
126
|
+
let invokeCallbackCalled = false;
|
|
127
|
+
listenerList.invoke({}, () => { invokeCallbackCalled = true; });
|
|
128
|
+
expect(invokeCallbackCalled).to.be.false;
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('should correctly transition internal listeners from single object to array', () => {
|
|
132
|
+
const results: string[] = [];
|
|
133
|
+
const callback = (value: string) => results.push(value);
|
|
134
|
+
|
|
135
|
+
const listener1 = () => 'one';
|
|
136
|
+
listenerList.registration(listener1);
|
|
137
|
+
listenerList.invoke({}, callback);
|
|
138
|
+
expect(results).to.deep.equal(['one']);
|
|
139
|
+
results.length = 0; // Clear results
|
|
140
|
+
|
|
141
|
+
const listener2 = () => 'two';
|
|
142
|
+
listenerList.registration(listener2); // This should transition internal listeners to an array
|
|
143
|
+
listenerList.invoke({}, callback);
|
|
144
|
+
expect(results).to.deep.equal(['one', 'two']);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('should correctly transition internal listeners from array to single object or undefined upon disposal', () => {
|
|
148
|
+
const results: string[] = [];
|
|
149
|
+
const callback = (value: string) => results.push(value);
|
|
150
|
+
|
|
151
|
+
const listener1 = () => 'one';
|
|
152
|
+
const listener2 = () => 'two';
|
|
153
|
+
const listener3 = () => 'three';
|
|
154
|
+
|
|
155
|
+
const d1 = listenerList.registration(listener1);
|
|
156
|
+
const d2 = listenerList.registration(listener2);
|
|
157
|
+
const d3 = listenerList.registration(listener3); // listeners: [l1, l2, l3]
|
|
158
|
+
|
|
159
|
+
d2.dispose(); // listeners: [l1, l3]
|
|
160
|
+
listenerList.invoke({}, callback);
|
|
161
|
+
expect(results).to.deep.equal(['one', 'three']);
|
|
162
|
+
results.length = 0;
|
|
163
|
+
|
|
164
|
+
d1.dispose(); // listeners: [l3] (should become single object)
|
|
165
|
+
listenerList.invoke({}, callback);
|
|
166
|
+
expect(results).to.deep.equal(['three']);
|
|
167
|
+
results.length = 0;
|
|
168
|
+
|
|
169
|
+
// Verify it's a single object by checking the internal structure if possible,
|
|
170
|
+
// or by behavior (e.g. adding another makes it an array of two)
|
|
171
|
+
// For this test, we'll infer from behavior that if it works, it's correct.
|
|
172
|
+
// Add another listener, then remove the current single one (d3)
|
|
173
|
+
const listener4 = () => 'four';
|
|
174
|
+
const d4 = listenerList.registration(listener4); // Now should be [l3, l4]
|
|
175
|
+
listenerList.invoke({}, callback);
|
|
176
|
+
expect(results).to.include.members(['three', 'four']);
|
|
177
|
+
expect(results.length).to.equal(2);
|
|
178
|
+
results.length = 0;
|
|
179
|
+
|
|
180
|
+
d3.dispose(); // Now should be [l4] (single object)
|
|
181
|
+
listenerList.invoke({}, callback);
|
|
182
|
+
expect(results).to.deep.equal(['four']);
|
|
183
|
+
results.length = 0;
|
|
184
|
+
|
|
185
|
+
d4.dispose();
|
|
186
|
+
listenerList.invoke({}, callback);
|
|
187
|
+
expect(results.length).to.equal(0);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('should correctly transition listeners to empty when last listener is removed', () => {
|
|
191
|
+
const results: string[] = [];
|
|
192
|
+
const callback = (value: string) => results.push(value);
|
|
193
|
+
|
|
194
|
+
const listener1 = () => 'one';
|
|
195
|
+
const d1 = listenerList.registration(listener1);
|
|
196
|
+
listenerList.invoke({}, callback);
|
|
197
|
+
expect(results).to.deep.equal(['one']);
|
|
198
|
+
results.length = 0;
|
|
199
|
+
|
|
200
|
+
d1.dispose();
|
|
201
|
+
listenerList.invoke({}, callback);
|
|
202
|
+
expect(results.length).to.equal(0);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
describe('invoke', () => {
|
|
207
|
+
it('should not invoke callback if no listeners are registered', () => {
|
|
208
|
+
let callbackCalled = false;
|
|
209
|
+
listenerList.invoke({}, () => {
|
|
210
|
+
callbackCalled = true;
|
|
211
|
+
});
|
|
212
|
+
expect(callbackCalled).to.be.false;
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('should pass the event object correctly to a single listener', () => {
|
|
216
|
+
const testEvent = { id: 1, value: 'data' };
|
|
217
|
+
let receivedEvent: any = undefined;
|
|
218
|
+
const listener = (e: any) => {
|
|
219
|
+
receivedEvent = e;
|
|
220
|
+
};
|
|
221
|
+
listenerList.registration(listener);
|
|
222
|
+
listenerList.invoke(testEvent, () => { });
|
|
223
|
+
expect(receivedEvent).to.deep.equal(testEvent);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('should pass the event object correctly to multiple listeners', () => {
|
|
227
|
+
const testEvent = { id: 2, value: 'more data' };
|
|
228
|
+
let eventForL1: any = undefined;
|
|
229
|
+
let eventForL2: any = undefined;
|
|
230
|
+
|
|
231
|
+
const listener1 = (e: any) => { eventForL1 = e; };
|
|
232
|
+
const listener2 = (e: any) => { eventForL2 = e; };
|
|
233
|
+
|
|
234
|
+
listenerList.registration(listener1);
|
|
235
|
+
listenerList.registration(listener2);
|
|
236
|
+
listenerList.invoke(testEvent, () => { });
|
|
237
|
+
|
|
238
|
+
expect(eventForL1).to.deep.equal(testEvent);
|
|
239
|
+
expect(eventForL2).to.deep.equal(testEvent);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it('should call the callback with the return value of a single listener', () => {
|
|
243
|
+
const expectedResult = 'unique_result';
|
|
244
|
+
const listener = () => expectedResult;
|
|
245
|
+
listenerList.registration(listener);
|
|
246
|
+
|
|
247
|
+
let actualResult: any;
|
|
248
|
+
listenerList.invoke({}, value => {
|
|
249
|
+
actualResult = value;
|
|
250
|
+
});
|
|
251
|
+
expect(actualResult).to.equal(expectedResult);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('should call the callback for each return value of multiple listeners', () => {
|
|
255
|
+
const resultL1 = 'res1';
|
|
256
|
+
const resultL2 = 'res2';
|
|
257
|
+
const collectedResults: any[] = [];
|
|
258
|
+
|
|
259
|
+
const listener1 = () => resultL1;
|
|
260
|
+
const listener2 = () => resultL2;
|
|
261
|
+
|
|
262
|
+
listenerList.registration(listener1);
|
|
263
|
+
listenerList.registration(listener2);
|
|
264
|
+
|
|
265
|
+
listenerList.invoke({}, value => {
|
|
266
|
+
collectedResults.push(value);
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
expect(collectedResults).to.have.lengthOf(2);
|
|
270
|
+
expect(collectedResults).to.include.members([resultL1, resultL2]);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it('should not invoke a listener after it has been disposed (re-check with invoke)', () => {
|
|
274
|
+
let callCount = 0;
|
|
275
|
+
const listener = () => { callCount++; };
|
|
276
|
+
const disposable = listenerList.registration(listener);
|
|
277
|
+
|
|
278
|
+
listenerList.invoke({}, () => { }); // Should call once
|
|
279
|
+
expect(callCount).to.equal(1);
|
|
280
|
+
|
|
281
|
+
disposable.dispose();
|
|
282
|
+
listenerList.invoke({}, () => { }); // Should not call again
|
|
283
|
+
expect(callCount).to.equal(1); // Still 1
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('should handle invocation when listeners are added and removed dynamically', () => {
|
|
287
|
+
const event1 = 'event1';
|
|
288
|
+
const event2 = 'event2';
|
|
289
|
+
const results: string[] = [];
|
|
290
|
+
const invokeCallback = (val: string) => results.push(val);
|
|
291
|
+
|
|
292
|
+
const listenerA = (e: string) => `A(${e})`;
|
|
293
|
+
const listenerB = (e: string) => `B(${e})`;
|
|
294
|
+
|
|
295
|
+
const dA = listenerList.registration(listenerA);
|
|
296
|
+
listenerList.invoke(event1, invokeCallback);
|
|
297
|
+
expect(results).to.deep.equal([`A(${event1})`]);
|
|
298
|
+
results.length = 0;
|
|
299
|
+
|
|
300
|
+
const dB = listenerList.registration(listenerB);
|
|
301
|
+
listenerList.invoke(event1, invokeCallback);
|
|
302
|
+
expect(results).to.deep.equal([`A(${event1})`, `B(${event1})`]); // Order is preserved
|
|
303
|
+
results.length = 0;
|
|
304
|
+
|
|
305
|
+
dA.dispose();
|
|
306
|
+
listenerList.invoke(event2, invokeCallback);
|
|
307
|
+
expect(results).to.deep.equal([`B(${event2})`]);
|
|
308
|
+
results.length = 0;
|
|
309
|
+
|
|
310
|
+
dB.dispose();
|
|
311
|
+
listenerList.invoke(event2, invokeCallback);
|
|
312
|
+
expect(results).to.deep.equal([]);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
});
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2025 ST Microelectronics and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { Disposable } from './disposable';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Ths code in this file implements a list of listeners that can be invoked sequentially with a callback to handle
|
|
21
|
+
* the results of the listener invocation.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
type Listener<T, U> = (e: T) => U;
|
|
25
|
+
interface ListenerRegistration<T, U> {
|
|
26
|
+
id: number,
|
|
27
|
+
listener: Listener<T, U>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export namespace Listener {
|
|
31
|
+
export type Registration<T, U = void> = (listener: (e: T) => U) => Disposable;
|
|
32
|
+
export const None: Registration<void, void> = () => Disposable.NULL;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Convenience function to await all listener invocations
|
|
36
|
+
* @param value The value to invoke the listeners with
|
|
37
|
+
* @param list the listener list to invoke
|
|
38
|
+
* @returns the return values from the listener invocation
|
|
39
|
+
*/
|
|
40
|
+
export async function await<T, U>(value: T, list: ListenerList<T, Promise<U>>): Promise<U[]> {
|
|
41
|
+
const promises: Promise<U>[] = [];
|
|
42
|
+
list.invoke(value, promise => {
|
|
43
|
+
promises.push(promise);
|
|
44
|
+
});
|
|
45
|
+
return await Promise.all(promises);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export class ListenerList<T, U> {
|
|
50
|
+
private listeners: ListenerRegistration<T, U> | (ListenerRegistration<T, U>)[] | undefined;
|
|
51
|
+
private registeredCount = 1; // start at 1 to prevent falsy madness
|
|
52
|
+
|
|
53
|
+
registration: Listener.Registration<T, U> = this.register.bind(this);
|
|
54
|
+
|
|
55
|
+
private register(listener: Listener<T, U>): Disposable {
|
|
56
|
+
const reg: ListenerRegistration<T, U> = { id: this.registeredCount++, listener };
|
|
57
|
+
if (!this.listeners) {
|
|
58
|
+
this.listeners = reg;
|
|
59
|
+
} else if (Array.isArray(this.listeners)) {
|
|
60
|
+
this.listeners.push(reg as ListenerRegistration<T, U>);
|
|
61
|
+
} else {
|
|
62
|
+
this.listeners = [this.listeners, reg];
|
|
63
|
+
}
|
|
64
|
+
return Disposable.create(() => {
|
|
65
|
+
this.remove(reg.id);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
private remove(id: number): void {
|
|
69
|
+
if (Array.isArray(this.listeners)) {
|
|
70
|
+
const index = this.listeners.findIndex(v => v.id === id);
|
|
71
|
+
if (index >= 0) {
|
|
72
|
+
this.listeners.splice(index, 1);
|
|
73
|
+
}
|
|
74
|
+
} else if (this.listeners && this.listeners.id === id) {
|
|
75
|
+
this.listeners = undefined;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
invoke(e: T, callback: (value: U) => void): void {
|
|
80
|
+
if (Array.isArray(this.listeners)) {
|
|
81
|
+
for (const l of this.listeners) {
|
|
82
|
+
callback(l.listener(e));
|
|
83
|
+
}
|
|
84
|
+
} else if (this.listeners) {
|
|
85
|
+
callback(this.listeners.listener(e));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
package/src/common/menu/index.ts
CHANGED
|
@@ -14,8 +14,7 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
export * from '
|
|
18
|
-
export * from '
|
|
19
|
-
export * from './menu-adapter';
|
|
17
|
+
export * from '../../browser/menu/action-menu-node';
|
|
18
|
+
export * from '../../browser/menu/composite-menu-node';
|
|
20
19
|
export * from './menu-model-registry';
|
|
21
20
|
export * from './menu-types';
|