Bug 551066 - [Reveal Service] Revealing a control does not work within a category
Defer finding the renderer of the control because in the case of a
control within a category view it will not be rendered until the
category itself is first revealed by a prior reveal step.
Change-Id: Id0a7c876a08d7dbc706f2ee41fecc039897d7561
Signed-off-by: Christian W. Damus <give.a.damus@gmail.com>
diff --git a/bundles/org.eclipse.emfforms.swt.core/src/org/eclipse/emfforms/internal/swt/core/ControlRevealProvider.java b/bundles/org.eclipse.emfforms.swt.core/src/org/eclipse/emfforms/internal/swt/core/ControlRevealProvider.java
index 6fe0c20..b67a936 100644
--- a/bundles/org.eclipse.emfforms.swt.core/src/org/eclipse/emfforms/internal/swt/core/ControlRevealProvider.java
+++ b/bundles/org.eclipse.emfforms.swt.core/src/org/eclipse/emfforms/internal/swt/core/ControlRevealProvider.java
@@ -17,8 +17,9 @@
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecp.view.model.common.di.annotations.Renderer;
+import org.eclipse.emf.ecp.view.model.common.AbstractRenderer;
import org.eclipse.emf.ecp.view.model.common.di.annotations.ViewService;
+import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
import org.eclipse.emf.ecp.view.spi.model.VControl;
import org.eclipse.emf.ecp.view.spi.model.VViewPackage;
import org.eclipse.emfforms.bazaar.Bid;
@@ -62,20 +63,36 @@
}
/**
- * Create a terminal reveal step to focus into the specific setting control in a
- * container {@code element}.
+ * Create a terminal reveal step to focus into the specific setting {@code control}
+ * in a that presents a {@code feature} or an {@code object}.
*
- * @param renderer the renderer of the control to reveal
+ * @param control the control to reveal
* @param object the object to reveal
* @param feature the feature of the domain {@code object} to reveal
+ * @param context the view-model context in which the {@code control} is rendered
* @return the specific control reveal step
*/
@Create
- public RevealStep reveal(@Renderer AbstractSWTRenderer<?> renderer, EObject object,
- EStructuralFeature feature) {
+ public RevealStep reveal(VControl control, EObject object,
+ EStructuralFeature feature, ViewModelContext context) {
- return RevealStep.reveal(renderer.getVElement(), object, feature,
- () -> Display.getDefault().asyncExec(renderer::scrollToReveal));
+ return RevealStep.reveal(control, object, feature,
+ // Scroll to reveal the control in the future, when it has been
+ // rendered by the previous reveal step (bug 551066)
+ () -> Display.getDefault().asyncExec(() -> scrollToReveal(control, context)));
+ }
+
+ /**
+ * Scroll to reveal the rendered {@code control}.
+ *
+ * @param control a control rendered in some {@code context}
+ * @param context the context in which the {@code control} is rendered
+ */
+ private void scrollToReveal(VControl control, ViewModelContext context) {
+ final AbstractRenderer<?> renderer = AbstractRenderer.getRenderer(control, context);
+ if (renderer instanceof AbstractSWTRenderer<?>) {
+ ((AbstractSWTRenderer<?>) renderer).scrollToReveal();
+ }
}
}
diff --git a/tests/org.eclipse.emf.ecp.view.categorization.swt.test/src/org/eclipse/emf/ecp/view/spi/categorization/swt/CategorizationRevealProvider_PTest.java b/tests/org.eclipse.emf.ecp.view.categorization.swt.test/src/org/eclipse/emf/ecp/view/spi/categorization/swt/CategorizationRevealProvider_PTest.java
index 1170953..1ed1106 100644
--- a/tests/org.eclipse.emf.ecp.view.categorization.swt.test/src/org/eclipse/emf/ecp/view/spi/categorization/swt/CategorizationRevealProvider_PTest.java
+++ b/tests/org.eclipse.emf.ecp.view.categorization.swt.test/src/org/eclipse/emf/ecp/view/spi/categorization/swt/CategorizationRevealProvider_PTest.java
@@ -13,16 +13,21 @@
******************************************************************************/
package org.eclipse.emf.ecp.view.spi.categorization.swt;
+import static org.eclipse.emf.ecp.common.spi.UniqueSetting.createSetting;
import static org.eclipse.emf.ecp.view.test.common.spi.EMFMocking.eMock;
import static org.eclipse.emf.ecp.view.test.common.spi.EMFMocking.withESettings;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import java.util.ArrayList;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcoreFactory;
+import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecp.test.common.DefaultRealm;
import org.eclipse.emf.ecp.view.internal.categorization.swt.CategorizationRevealProvider;
import org.eclipse.emf.ecp.view.spi.categorization.model.VCategorization;
@@ -32,7 +37,11 @@
import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
import org.eclipse.emf.ecp.view.spi.model.VContainedContainer;
import org.eclipse.emf.ecp.view.spi.model.VContainer;
+import org.eclipse.emf.ecp.view.spi.model.VControl;
import org.eclipse.emf.ecp.view.spi.model.VElement;
+import org.eclipse.emf.ecp.view.spi.model.VViewFactory;
+import org.eclipse.emf.ecp.view.spi.vertical.model.VVerticalFactory;
+import org.eclipse.emf.ecp.view.spi.vertical.model.VVerticalLayout;
import org.eclipse.emf.ecp.view.test.common.spi.EMFFormsRevealServiceFixture;
import org.eclipse.emf.ecp.view.test.common.spi.EMFFormsViewContextFixture.DomainModel;
import org.eclipse.emf.ecp.view.test.common.spi.EMFFormsViewContextFixture.ViewModel;
@@ -41,6 +50,7 @@
import org.eclipse.emf.ecp.view.test.common.swt.spi.SWTViewTestHelper;
import org.eclipse.emfforms.bazaar.Bid;
import org.eclipse.emfforms.bazaar.Create;
+import org.eclipse.emfforms.spi.core.services.controlmapper.EMFFormsSettingToControlMapper;
import org.eclipse.emfforms.spi.core.services.reveal.EMFFormsRevealProvider;
import org.eclipse.emfforms.spi.core.services.reveal.RevealStep;
import org.eclipse.swt.widgets.Shell;
@@ -61,9 +71,8 @@
private final VCategorizationElement categorizations = VCategorizationFactory.eINSTANCE
.createCategorizationElement();
- @EMock
@DomainModel
- private EObject rootObject;
+ private final EObject rootObject = EcoreFactory.eINSTANCE.createEClass();
@EMock
private EObject obj1;
@@ -192,6 +201,40 @@
verify(reveal).run();
}
+ /**
+ * Integration test for revealing a specific control (by feature) within a tree categorization,
+ * which is the scenario that didn't work as reported in <a href="http://eclip.se/551066">bug 551066</a>.
+ * The test relies on the fact that the non-default category containing the control to be revealed
+ * would not end up being selected if the control within did not provide a successful reveal step.
+ *
+ * @see <a href="http://eclip.se/551066">bug 551066</a>
+ */
+ @Test
+ public void revealSpecificControlInTree() {
+ final VVerticalLayout vertical = VVerticalFactory.eINSTANCE.createVerticalLayout();
+ cat3.setComposite(vertical);
+
+ final VControl control = VViewFactory.eINSTANCE.createControl();
+ final EStructuralFeature feature = EcorePackage.Literals.ENAMED_ELEMENT__NAME;
+ control.setDomainModelReference(feature);
+ vertical.getChildren().add(control);
+
+ // Revealing a control requires the settings mapper
+ final EMFFormsSettingToControlMapper mapper = mock(EMFFormsSettingToControlMapper.class);
+ when(mapper.hasControlsFor(rootObject)).thenReturn(true);
+ when(mapper.hasMapping(createSetting(rootObject, feature), control)).thenReturn(true);
+ fixture.putService(EMFFormsSettingToControlMapper.class, mapper);
+
+ render();
+
+ fixture.reveal(rootObject, feature);
+
+ // The category would only be selected if the control within it was revealed.
+ // In the case of bug 551066, context injection of the ControlRevealProvider failed
+ // to create the provider because the name control renderer was not yet available
+ assertThat("The category was not selected", categorizations.getCurrentSelection(), is(cat3));
+ }
+
//
// Test framework
//