/*******************************************************************************
* Copyright (c) 2010, 2015 IBM Corporation and others.
* 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
******************************************************************************/
package org.eclipse.e4.ui.tests.workbench;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.ui.di.Focus;
import org.eclipse.e4.ui.internal.workbench.E4Workbench;
import org.eclipse.e4.ui.internal.workbench.swt.E4Application;
import org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.MUILabel;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer;
import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
import org.eclipse.e4.ui.model.application.ui.menu.MToolControl;
import org.eclipse.e4.ui.tests.Activator;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.IPartListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Text;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
/**
* Ensure that setting focus to a widget within an non-active part causes the
* part to be activated while not changing the focus.
*/
public class PartFocusTest {
protected IEclipseContext appContext;
protected E4Workbench wb;
protected EPartService eps;
protected MWindow window;
protected MPart part;
protected MToolControl toolControl;
protected MPart otherPart;
private EModelService ems;
@Before
public void setUp() throws Exception {
appContext = E4Application.createDefaultContext();
appContext.set(E4Workbench.PRESENTATION_URI_ARG,
PartRenderingEngine.engineURI);
ems = appContext.get(EModelService.class);
window = ems.createModelElement(MWindow.class);
window.setWidth(500);
window.setHeight(500);
MPartSashContainer sash = ems.createModelElement(MPartSashContainer.class);
window.getChildren().add(sash);
window.setSelectedElement(sash);
MPartStack stack = ems.createModelElement(MPartStack.class);
sash.getChildren().add(stack);
sash.setSelectedElement(stack);
part = ems.createModelElement(MPart.class);
part.setElementId("Part");
part.setLabel("Part");
part.setToolbar(ems.createModelElement(MToolBar.class));
part.setContributionURI(Activator.asURI(PartBackend.class));
stack.getChildren().add(part);
toolControl = ems.createModelElement(MToolControl.class);
toolControl.setElementId("ToolControl");
toolControl.setContributionURI(Activator.asURI(TextField.class));
part.getToolbar().getChildren().add(toolControl);
stack = ems.createModelElement(MPartStack.class);
sash.getChildren().add(stack);
sash.setSelectedElement(stack);
otherPart = ems.createModelElement(MPart.class);
otherPart.setElementId("OtherPart");
otherPart.setLabel("OtherPart");
otherPart.setContributionURI(Activator.asURI(PartBackend.class));
stack.getChildren().add(otherPart);
MApplication application = ems.createModelElement(MApplication.class);
application.getChildren().add(window);
application.setContext(appContext);
appContext.set(MApplication.class, application);
wb = new E4Workbench(application, appContext);
wb.createAndRunUI(window);
eps = window.getContext().get(EPartService.class);
// ensure the parts are populated and the contributions instantiated
eps.activate(part);
eps.activate(otherPart);
processEvents();
// ensure our model backend objects are created
assertNotNull(part.getObject());
assertNotNull(toolControl.getObject());
assertNotNull(otherPart.getObject());
assertNotNull(part.getWidget());
assertNotNull(toolControl.getWidget());
assertNotNull(otherPart.getWidget());
// ensure focus is set to otherPart.text1
eps.activate(otherPart);
processEvents();
assertTrue(((PartBackend) otherPart.getObject()).text1.isFocusControl());
}
@After
public void tearDown() throws Exception {
if (wb != null) {
wb.close();
}
appContext.dispose();
}
private void processEvents() {
// renderer.run(window, appContext);
Display display = Display.getCurrent();
if (display.isDisposed()) {
return;
}
try {
while (display.readAndDispatch()) {
appContext.processWaiting();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testFocusChangesOnExplicitPartActivation() {
assertFalse(((PartBackend) part.getObject()).text1.isFocusControl());
eps.activate(part);
processEvents();
assertTrue(((PartBackend) part.getObject()).text1.isFocusControl());
}
@Ignore
@Test
public void XXXtestNoFocusChangeOnExplicitWidgetSelection() {
assertFalse(((PartBackend) part.getObject()).text1.isFocusControl());
((TextField) toolControl.getObject()).text.setFocus();
processEvents();
assertEquals(part.getElementId(), eps.getActivePart().getElementId());
assertFalse(((PartBackend) part.getObject()).text1.isFocusControl());
assertTrue(((TextField) toolControl.getObject()).text.isFocusControl());
}
@Test
public void testNoActivationOnExplicitInPartWidgetSelection() {
assertTrue(eps.getActivePart() == otherPart);
assertTrue(((PartBackend) otherPart.getObject()).text1.isFocusControl());
final boolean[] changed = new boolean[] { false };
eps.addPartListener(new IPartListener() {
@Override
public void partVisible(MPart part) {
changed[0] = true;
}
@Override
public void partHidden(MPart part) {
changed[0] = true;
}
@Override
public void partDeactivated(MPart part) {
changed[0] = true;
}
@Override
public void partBroughtToTop(MPart part) {
changed[0] = true;
}
@Override
public void partActivated(MPart part) {
changed[0] = true;
}
});
((PartBackend) otherPart.getObject()).text2.setFocus();
processEvents();
assertTrue(((PartBackend) otherPart.getObject()).text2.isFocusControl());
assertFalse(changed[0]);
}
}
/**
* A simple part backend that creates two text fields. On a focus request, set
* the focus to the first text field.
*/
class PartBackend {
@Inject
public Composite parent;
@Inject
MPart part;
public Text text1;
public Text text2;
public PartBackend() {
}
@PostConstruct
public void init() {
text1 = new Text(parent, SWT.SINGLE);
text2 = new Text(parent, SWT.SINGLE);
text1.setText(part.getLabel() + " text1");
text1.setText(part.getLabel() + " text2");
}
@Focus
public void setFocus() {
// can test if called by checking if text1.isFocusControl()
// System.out.println(part.getLabel() + ": setFocus to text1");
text1.setFocus();
}
@PreDestroy
public void dispose() {
// System.out.println(part.getLabel() + ": destroyed");
}
}
/**
* A simple text field for a tool control.
*/
class TextField {
@Inject
Composite parent;
@Inject
MUILabel element;
public Text text;
public TextField() {
}
@PostConstruct
public void init() {
// System.out.println("TextField created");
text = new Text(parent, SWT.SINGLE);
text.setText(element.getLabel() + " text");
}
@PreDestroy
public void dispose() {
// System.out.println("TextField destroyed");
}
}