Skip to content

Commit

Permalink
Initialize onboarding information for all stacks in shared area #1773
Browse files Browse the repository at this point in the history
The onboarding information is currently initialized for the primary
editor stack in the shared area. When the shared area is split into
multiple part stack showing editors side-by-side and closing the last
editor in the original part stack, the onboarding information controls
get lost together with that part stack.

With this change, onboarding information is embedded into every part
stack of the onboarding area, such that when closing one of them, the
information does not get lost. To this end, every part stack is in the
shared area is tagged as an editor stack and the onboarding information
is added to every tab folder of part stacks tagged as an editor stack.

Fixes #1773
  • Loading branch information
HeikoKlare committed Apr 3, 2024
1 parent 79baeed commit abbb25f
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Optional;
Expand Down Expand Up @@ -127,6 +128,8 @@ public class StackRenderer extends LazyStackRenderer {
private static final String ONBOARDING_IMAGE = "EditorStack.OnboardingImage"; //$NON-NLS-1$
private static final String ONBOARDING_TEXT = "EditorStack.OnboardingText"; //$NON-NLS-1$

private static final String EDITOR_STACK_ID = "EditorStack"; //$NON-NLS-1$

/**
* Id of a a control.
*/
Expand Down Expand Up @@ -198,6 +201,8 @@ public class StackRenderer extends LazyStackRenderer {
*/
public static final int ONBOARDING_SHOW_IMAGE_HEIGHT_THRESHOLD = 450;

private MPerspective currentPerspectiveForOnboarding;

private Image viewMenuImage;
private String viewMenuURI = "platform:/plugin/org.eclipse.e4.ui.workbench.renderers.swt/icons/full/elcl16/view_menu.png"; //$NON-NLS-1$

Expand Down Expand Up @@ -251,18 +256,19 @@ private void addItemToSet(List<CTabItem> itemsToSet, MPart parentParent) {
void subscribePerspectiveSwitched(
@UIEventTopic(UIEvents.UILifeCycle.PERSPECTIVE_SWITCHED) org.osgi.service.event.Event event) {
Object element = event.getProperty(EventTags.ELEMENT);
if (element instanceof MPerspective) {
setOnboarding((MPerspective) element);
if (element instanceof MPerspective perspective) {
currentPerspectiveForOnboarding = perspective;
getEditorTabFolders(perspective).forEach(this::initializeOnboardingInformationInEditorStack);
}
}

private void setOnboarding(MPerspective perspective) {
CTabFolder tabFolder = getEditorTabFolder(perspective);
if (tabFolder == null) {
private void initializeOnboardingInformationInEditorStack(CTabFolder editorStackTabFolder) {
MPerspective perspective = currentPerspectiveForOnboarding;
if (perspective == null) {
return;
}

Composite onboardingContainer = getChild(tabFolder, ONBOARDING_CONTAINER, Composite.class);
Composite onboardingContainer = getChild(editorStackTabFolder, ONBOARDING_CONTAINER, Composite.class);
if (onboardingContainer == null || onboardingContainer.isDisposed()) {
return;
}
Expand Down Expand Up @@ -694,6 +700,11 @@ public Object createWidget(MUIElement element, Object parent) {
return null;

MPartStack pStack = (MPartStack) element;
int location = modelService.getElementLocation(element);
boolean isInSharedArea = (location & EModelService.IN_SHARED_AREA) != 0;
if (isInSharedArea) {
pStack.getTags().add(EDITOR_STACK_ID);
}

Composite parentComposite = (Composite) parent;

Expand All @@ -708,12 +719,12 @@ public Object createWidget(MUIElement element, Object parent) {
CTabFolder tabFolder = new CTabFolder(parentComposite, style);
if (pStack.getTags().contains("EditorStack")) { //$NON-NLS-1$
createOnboardingControls(tabFolder);
initializeOnboardingInformationInEditorStack(tabFolder);
}
tabFolder.setMRUVisible(getMRUValue());

// Adjust the minimum chars based on the location
int location = modelService.getElementLocation(element);
if ((location & EModelService.IN_SHARED_AREA) != 0) {
if (isInSharedArea) {
tabFolder.setMinimumCharacters(MIN_EDITOR_CHARS);
tabFolder.setUnselectedCloseVisible(true);
} else {
Expand Down Expand Up @@ -1911,14 +1922,12 @@ protected boolean imageChanged() {
return this.imageChanged;
}

private CTabFolder getEditorTabFolder(MPerspective perspective) {
private Stream<CTabFolder> getEditorTabFolders(MPerspective perspective) {
Predicate<Object> tabFolders = CTabFolder.class::isInstance;
Function<Object, CTabFolder> toTabFolder = CTabFolder.class::cast;

List<MPartStack> elements = modelService.findElements(perspective, null, MPartStack.class,
List.of("EditorStack")); //$NON-NLS-1$
return elements.stream().map(MUIElement::getWidget).filter(tabFolders).map(toTabFolder).findFirst()
.orElse(null);
List<MPartStack> elements = modelService.findElements(perspective, null, MPartStack.class, List.of(EDITOR_STACK_ID));
return elements.stream().map(MUIElement::getWidget).filter(tabFolders).map(toTabFolder);
}

private <T extends Control> T getChild(Composite parent, String id, Class<T> type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,17 @@ public void testOnboardingNotRenderedForNonEditorStack() {

@Test
public void testOnboardingIsFilled() {
MPerspective perspective = createPerspective();
partStack.getTags().add("EditorStack");

contextRule.createAndRunWorkbench(window);
switchToPerspective(perspective);

CTabFolder tabFolder = (CTabFolder) partStack.getWidget();
assertFilledOnboardingInformation(tabFolder);
}

private MPerspective createPerspective() {
MPerspective perspective = ems.createModelElement(MPerspective.class);
perspective.getTags().add("persp.editorOnboardingText:Onboarding text");
perspective.getTags().add("persp.editorOnboardingImageUri:" + PART_ICON);
Expand All @@ -457,29 +468,56 @@ public void testOnboardingIsFilled() {
MPlaceholder placeholder = ems.createModelElement(MPlaceholder.class);
placeholder.setRef(partStack);
perspective.getChildren().add(placeholder);
return perspective;
}

partStack.getTags().add("EditorStack");

contextRule.createAndRunWorkbench(window);

private void switchToPerspective(MPerspective perspective) {
HashMap<String, Object> params = new HashMap<>();
params.put(UIEvents.EventTags.ELEMENT, perspective);

context.get(EventBroker.class).send(UIEvents.UILifeCycle.PERSPECTIVE_SWITCHED, params);
}

CTabFolder tabFolder = (CTabFolder) partStack.getWidget();
private void assertFilledOnboardingInformation(CTabFolder tabFolder) {
assertNotNull(tabFolder.getChildren());
assertEquals(3, tabFolder.getChildren().length);

Composite outerOnboardingComposite = (Composite) tabFolder.getChildren()[2];
Composite innerOnboardingComposite = (Composite) outerOnboardingComposite.getChildren()[0];
assertEquals(4, innerOnboardingComposite.getChildren().length);
Composite innerOnboardingComposite = null;
for (Control child : tabFolder.getChildren()) {
if (child instanceof Composite outerComposite) {
if (outerComposite.getChildren().length > 0 && outerComposite.getChildren()[0] instanceof Composite innerComposite) {
if (innerComposite.getChildren().length == 4) {
innerOnboardingComposite = innerComposite;
break;
}
}
}
}
assertNotNull(innerOnboardingComposite);
assertNotNull(((Label) innerOnboardingComposite.getChildren()[0]).getImage());
assertEquals("Onboarding text", ((Label) innerOnboardingComposite.getChildren()[1]).getText());
assertEquals("Find Actions", ((Label) innerOnboardingComposite.getChildren()[2]).getText());
assertEquals("STRG+3", ((Label) innerOnboardingComposite.getChildren()[3]).getText());
}

@Test
public void testOnboardingIsFilledForEveryEditorStack() {
MPerspective perspective = createPerspective();
partStack.getTags().add("EditorStack");

contextRule.createAndRunWorkbench(window);

// Create second editor stack
MPartStack secondPartStack = ems.createModelElement(MPartStack.class);
secondPartStack.getTags().add("EditorStack");
MPlaceholder placeholder = ems.createModelElement(MPlaceholder.class);
placeholder.setRef(secondPartStack);
perspective.getChildren().add(placeholder);
window.getChildren().add(secondPartStack);

switchToPerspective(perspective);

CTabFolder tabFolder = (CTabFolder) secondPartStack.getWidget();
assertFilledOnboardingInformation(tabFolder);
}

@Test
public void testOnboardingIsHiddenWhenEditorOpened() {
partStack.getTags().add("EditorStack");
Expand Down

0 comments on commit abbb25f

Please sign in to comment.