diff --git a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/UIAllTests.java b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/UIAllTests.java index 2b869853689..f77ed00292a 100644 --- a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/UIAllTests.java +++ b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/UIAllTests.java @@ -56,6 +56,7 @@ import org.eclipse.e4.ui.workbench.renderers.swt.TabStateHandlerTest; import org.eclipse.e4.ui.workbench.renderers.swt.ThemeDefinitionChangedHandlerTest; import org.eclipse.e4.ui.workbench.renderers.swt.ToolBarManagerRendererTest; +import org.eclipse.e4.ui.workbench.renderers.swt.ToolControlRendererTest; import org.junit.platform.suite.api.SelectClasses; import org.junit.platform.suite.api.Suite; @@ -95,6 +96,7 @@ TabStateHandlerTest.class, ThemeDefinitionChangedHandlerTest.class, ToolBarManagerRendererTest.class, + ToolControlRendererTest.class, TopoSortTests.class, ExtensionsSortTests.class, HandlerActivationTest.class, diff --git a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolControlRendererTest.java b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolControlRendererTest.java new file mode 100644 index 00000000000..c48479587d8 --- /dev/null +++ b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolControlRendererTest.java @@ -0,0 +1,163 @@ +/******************************************************************************* + * Copyright (c) 2026 Lars Vogel and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Lars Vogel - initial API and implementation + *******************************************************************************/ +package org.eclipse.e4.ui.workbench.renderers.swt; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import jakarta.annotation.PostConstruct; +import jakarta.inject.Inject; + +import org.eclipse.e4.ui.model.application.MApplication; +import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar; +import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow; +import org.eclipse.e4.ui.model.application.ui.menu.MToolControl; +import org.eclipse.e4.ui.tests.rules.WorkbenchContextExtension; +import org.eclipse.e4.ui.workbench.IPresentationEngine; +import org.eclipse.e4.ui.workbench.modeling.EModelService; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class ToolControlRendererTest { + + private static final String BUNDLE_URI = "bundleclass://org.eclipse.e4.ui.tests/" + + ToolControlRendererTest.class.getName() + "$"; + + @RegisterExtension + public WorkbenchContextExtension contextRule = new WorkbenchContextExtension(); + + @Inject + private EModelService ems; + + @Inject + private MApplication application; + + private MTrimmedWindow window; + private MTrimBar trimBar; + + @BeforeEach + void setUp() { + window = ems.createModelElement(MTrimmedWindow.class); + application.getChildren().add(window); + + trimBar = ems.createModelElement(MTrimBar.class); + window.getTrimBars().add(trimBar); + } + + @Test + void testWidgetCreated() { + MToolControl toolControl = createToolControl("SimpleControl"); + trimBar.getChildren().add(toolControl); + + contextRule.createAndRunWorkbench(window); + + assertNotNull(toolControl.getWidget(), "Widget must be created for a MToolControl"); + } + + @Test + void testNoChildren_widgetIsNull() { + MToolControl toolControl = createToolControl("EmptyControl"); + trimBar.getChildren().add(toolControl); + + contextRule.createAndRunWorkbench(window); + + assertNull(toolControl.getWidget(), + "Widget must be null when the contribution creates no SWT children"); + } + + @Test + void testHiddenExplicitly_hidesControl() { + MToolControl toolControl = createToolControl("SimpleControl"); + trimBar.getChildren().add(toolControl); + + contextRule.createAndRunWorkbench(window); + + assertTrue(toolControl.isVisible(), "Control should be visible initially"); + + toolControl.getTags().add(IPresentationEngine.HIDDEN_EXPLICITLY); + contextRule.spinEventLoop(); + + assertFalse(toolControl.isVisible(), "Control should be hidden after HIDDEN_EXPLICITLY tag is added"); + } + + @Test + void testHiddenExplicitly_removeTag_restoresVisibility() { + MToolControl toolControl = createToolControl("SimpleControl"); + trimBar.getChildren().add(toolControl); + + contextRule.createAndRunWorkbench(window); + + toolControl.getTags().add(IPresentationEngine.HIDDEN_EXPLICITLY); + contextRule.spinEventLoop(); + assertFalse(toolControl.isVisible()); + + toolControl.getTags().remove(IPresentationEngine.HIDDEN_EXPLICITLY); + contextRule.spinEventLoop(); + + assertTrue(toolControl.isVisible(), "Visibility must be restored after HIDDEN_EXPLICITLY tag is removed"); + } + + @Test + void testHideableControls_haveIndependentMenus() { + MToolControl tc1 = createToolControl("SimpleControl"); + tc1.getTags().add("HIDEABLE"); + trimBar.getChildren().add(tc1); + + MToolControl tc2 = createToolControl("SimpleControl"); + tc2.getTags().add("HIDEABLE"); + trimBar.getChildren().add(tc2); + + contextRule.createAndRunWorkbench(window); + + Control widget1 = (Control) tc1.getWidget(); + Control widget2 = (Control) tc2.getWidget(); + + assertNotNull(widget1.getMenu(), "First HIDEABLE control must have a context menu"); + assertNotNull(widget2.getMenu(), "Second HIDEABLE control must have a context menu"); + assertNotSame(widget1.getMenu(), widget2.getMenu(), + "Each HIDEABLE control must have its own independent menu instance"); + assertFalse(widget1.getMenu().isDisposed(), + "First control's menu must not be disposed after second control is rendered"); + } + + private MToolControl createToolControl(String innerClassName) { + MToolControl tc = ems.createModelElement(MToolControl.class); + tc.setContributionURI(BUNDLE_URI + innerClassName); + return tc; + } + + // --- Contribution classes used by the tests --- + + public static class SimpleControl { + @PostConstruct + public void create(Composite parent) { + new Label(parent, SWT.NONE).setText("test"); + } + } + + public static class EmptyControl { + @PostConstruct + public void create(@SuppressWarnings("unused") Composite parent) { + // intentionally creates no SWT children + } + } +}