Focus control for Boot wizards
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2023 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
@@ -40,6 +40,8 @@ public class DynamicSection extends ReflowableSection {
|
||||
private Integer widthHint = DEFAULT_MIN_SIZE.y;
|
||||
private Integer heightHint = DEFAULT_MIN_SIZE.x;
|
||||
|
||||
private boolean isFocused;
|
||||
|
||||
public DynamicSection(IPageWithSections owner, LiveExpression<IPageSection> content) {
|
||||
super(owner);
|
||||
this.content = content;
|
||||
@@ -90,6 +92,9 @@ public class DynamicSection extends ReflowableSection {
|
||||
} else {
|
||||
validator.setDelegate(null);
|
||||
}
|
||||
if (isFocused) {
|
||||
newContents.setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -104,4 +109,12 @@ public class DynamicSection extends ReflowableSection {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocus() {
|
||||
isFocused = true;
|
||||
if (content.getValue() != null) {
|
||||
content.getValue().setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import java.util.List;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Point;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
import org.springframework.ide.eclipse.boot.core.initializr.InitializrServiceSpec.Dependency;
|
||||
import org.springframework.ide.eclipse.boot.livexp.ui.DynamicSection;
|
||||
import org.springframework.ide.eclipse.boot.wizard.CheckBoxesSection.CheckBoxModel;
|
||||
@@ -74,12 +73,12 @@ public class MultipleViewsDependencyPage extends WizardPageWithSections {
|
||||
|
||||
sections.add(createFrequentlyUsedSection(model));
|
||||
sections.add(createTwoColumnSection(model));
|
||||
return new GroupSection(this, null, sections.toArray(new WizardPageSection[0])).grabVertical(true);
|
||||
return new GroupSection(this, null, 2, sections.toArray(new WizardPageSection[0])).grabVertical(true);
|
||||
}
|
||||
|
||||
public WizardPageSection createTwoColumnSection(final NewSpringBootWizardModel model) {
|
||||
return new GroupSection(this,null,
|
||||
new GroupSection(this, null,
|
||||
return new GroupSection(this, null, 0,
|
||||
new GroupSection(this, null, 1,
|
||||
new CommentSection(this, "Available:"),
|
||||
getSearchSection(model),
|
||||
new GroupSection(this, "",
|
||||
@@ -113,14 +112,12 @@ public class MultipleViewsDependencyPage extends WizardPageWithSections {
|
||||
}
|
||||
|
||||
protected WizardPageSection getSearchSection(final NewSpringBootWizardModel model) {
|
||||
final SearchBoxSection searchBoxSection = new SearchBoxSection(this, model.getDependencyFilterBoxText()) {
|
||||
return new SearchBoxSection(this, model.getDependencyFilterBoxText()) {
|
||||
@Override
|
||||
protected String getSearchHint() {
|
||||
return "Type to search dependencies";
|
||||
}
|
||||
};
|
||||
PlatformUI.getWorkbench().getDisplay().asyncExec(() -> getControl().addListener(SWT.Show, event -> searchBoxSection.focusControl()));
|
||||
return new GroupSection(this, null, searchBoxSection.grabFocus(true));
|
||||
}
|
||||
|
||||
protected WizardPageSection createFrequentlyUsedSection(NewSpringBootWizardModel model) {
|
||||
@@ -134,4 +131,12 @@ public class MultipleViewsDependencyPage extends WizardPageWithSections {
|
||||
return frequentlyUsedSection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean visible) {
|
||||
super.setVisible(visible);
|
||||
if (visible) {
|
||||
getSections().get(0).setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -101,6 +101,7 @@ public class NewSpringBootWizard extends Wizard implements INewWizard, IImportWi
|
||||
super(owner, null);
|
||||
this.model = model;
|
||||
addSections(createSections().toArray(new WizardPageSection[0]));
|
||||
focusSectionIndex = 0;
|
||||
}
|
||||
|
||||
protected List<WizardPageSection> createSections() {
|
||||
@@ -174,10 +175,19 @@ public class NewSpringBootWizard extends Wizard implements INewWizard, IImportWi
|
||||
return new ProjectDetailsSection(this, dynamicModel);
|
||||
}
|
||||
return new CommentSection(this, NO_CONTENT_AVAILABLE);
|
||||
} ));
|
||||
}));
|
||||
|
||||
return ImmutableList.of(comboSection, dynamicSection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean visible) {
|
||||
super.setVisible(visible);
|
||||
if (visible) {
|
||||
getSections().get(1).setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015, 2020 Pivotal Software, Inc.
|
||||
* Copyright (c) 2015, 2023 Pivotal Software, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
@@ -14,8 +14,6 @@ import org.eclipse.jface.layout.GridDataFactory;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.ModifyEvent;
|
||||
import org.eclipse.swt.events.ModifyListener;
|
||||
import org.eclipse.swt.events.PaintEvent;
|
||||
import org.eclipse.swt.events.PaintListener;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
@@ -39,7 +37,6 @@ public class SearchBoxSection extends WizardPageSection implements Disposable {
|
||||
private Text searchBox;
|
||||
private LiveVariable<String> model;
|
||||
private ValueListener<String> modelListener;
|
||||
private boolean grabFocus;
|
||||
|
||||
public SearchBoxSection(IPageWithSections owner, LiveVariable<String> model) {
|
||||
super(owner);
|
||||
@@ -76,9 +73,6 @@ public class SearchBoxSection extends WizardPageSection implements Disposable {
|
||||
}
|
||||
}
|
||||
});
|
||||
if (grabFocus) {
|
||||
focusControl();
|
||||
}
|
||||
// IContentProposalProvider proposalProvider = new TagContentProposalProvider(viewModel);
|
||||
// ContentProposalAdapter caAdapter = new ContentProposalAdapter(searchBox, new TextContentAdapter(), proposalProvider, UIUtils.CTRL_SPACE, null);
|
||||
// caAdapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE);
|
||||
@@ -97,31 +91,15 @@ public class SearchBoxSection extends WizardPageSection implements Disposable {
|
||||
searchBox.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* When the control for this section is created, it will attempt to immediately grab
|
||||
* keyboard focus.
|
||||
*/
|
||||
public SearchBoxSection grabFocus(boolean grab) {
|
||||
this.grabFocus = grab;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void focusControl() {
|
||||
if (searchBox != null) {
|
||||
if (!searchBox.setFocus()) {
|
||||
searchBox.addPaintListener(new PaintListener() {
|
||||
@Override
|
||||
public void paintControl(PaintEvent e) {
|
||||
if (searchBox.setFocus()) {
|
||||
searchBox.removePaintListener(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Control getControl() {
|
||||
return searchBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocus() {
|
||||
if (searchBox != null && !searchBox.isDisposed()) {
|
||||
searchBox.setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -288,8 +288,6 @@ public class ChooseTypedContentSection extends WizardPageSection {
|
||||
}
|
||||
};
|
||||
|
||||
// PT 164654725 - IMPORTANT: set grab focus BEFORE creating content
|
||||
searchBox.grabFocus(true);
|
||||
searchBox.createContents(field);
|
||||
|
||||
Label fieldNameLabel = null;
|
||||
@@ -431,6 +429,14 @@ public class ChooseTypedContentSection extends WizardPageSection {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setFocus() {
|
||||
if (searchBox != null) {
|
||||
searchBox.setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// private String[] getLabels() {
|
||||
// String[] labels = new String[options.length];
|
||||
// for (int i = 0; i < labels.length; i++) {
|
||||
@@ -439,4 +445,6 @@ public class ChooseTypedContentSection extends WizardPageSection {
|
||||
// return labels;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -127,6 +127,7 @@ public class GSImportWizard extends Wizard implements IImportWizard, INewWizard
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void init(IWorkbench workbench, IStructuredSelection selection) {
|
||||
// this.workbench = workbench;
|
||||
// super.init(workbench, selection);
|
||||
|
||||
@@ -97,9 +97,10 @@ public class DependencyPage extends WizardPageWithSections {
|
||||
createDynamicSections(model, sections);
|
||||
}
|
||||
|
||||
GroupSection groupSection = new GroupSection(DependencyPage.this, null,
|
||||
GroupSection groupSection = new GroupSection(DependencyPage.this, null, 1,
|
||||
sections.toArray(new WizardPageSection[0]));
|
||||
groupSection.grabVertical(true);
|
||||
groupSection.setFocus();
|
||||
return groupSection;
|
||||
}
|
||||
};
|
||||
@@ -193,6 +194,12 @@ public class DependencyPage extends WizardPageWithSections {
|
||||
String message = ExceptionUtil.getMessage(e);
|
||||
setErrorMessage(message);
|
||||
Log.log(e);
|
||||
} finally {
|
||||
// After loading of starters data is completed set the focus to the search box.
|
||||
// It is highly unlikely that use had the time to switch focus to anything else.
|
||||
if (dynamicControlCreation.getValue() != null) {
|
||||
dynamicControlCreation.getValue().setFocus();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -204,8 +211,8 @@ public class DependencyPage extends WizardPageWithSections {
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public WizardPageSection createTwoColumnSection(final InitializrModel model) {
|
||||
return new GroupSection(this,null,
|
||||
new GroupSection(this, null,
|
||||
return new GroupSection(this, null, 0,
|
||||
new GroupSection(this, null, 1,
|
||||
new CommentSection(this, "Available:"),
|
||||
getSearchSection(model),
|
||||
new GroupSection(this, "",
|
||||
@@ -239,39 +246,13 @@ public class DependencyPage extends WizardPageWithSections {
|
||||
}
|
||||
|
||||
protected WizardPageSection getSearchSection(final InitializrModel model) {
|
||||
final SearchBoxSection searchBoxSection = new SearchBoxSection(this, model.searchBox.getText()) {
|
||||
return new SearchBoxSection(this, model.searchBox.getText()) {
|
||||
@Override
|
||||
protected String getSearchHint() {
|
||||
return "Type to search dependencies";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusControl() {
|
||||
Control searchControl = getControl();
|
||||
if (searchControl != null && !searchControl.isDisposed()) {
|
||||
searchControl.setFocus();
|
||||
}
|
||||
}
|
||||
}.grabFocus(true);
|
||||
|
||||
|
||||
// PT 174313406 - Async focus on search box. Dynamic creation seems to interfere with grabbing focus on the search box upon control creation
|
||||
// therefore set it asynchronously
|
||||
asyncSetFocus(searchBoxSection);
|
||||
return searchBoxSection;
|
||||
}
|
||||
|
||||
private void asyncSetFocus(SearchBoxSection searchBoxSection) {
|
||||
UIJob showJob = new UIJob("Focus search box") {
|
||||
|
||||
@Override
|
||||
public IStatus runInUIThread(IProgressMonitor monitor) {
|
||||
searchBoxSection.focusControl();
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
};
|
||||
showJob.setSystem(true);
|
||||
showJob.schedule(1000);
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
@@ -326,6 +307,17 @@ public class DependencyPage extends WizardPageWithSections {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean visible) {
|
||||
super.setVisible(visible);
|
||||
if (visible) {
|
||||
// Restore focus to search box when going back a page. There is no control that has the focus going back hence set it.
|
||||
if (dynamicControlCreation.getValue() != null) {
|
||||
dynamicControlCreation.getValue().setFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ErrorGroupSection {
|
||||
|
||||
private static final String NO_CONTENT = "No content available";
|
||||
|
||||
Reference in New Issue
Block a user