javaeclipsercpe4

How can i conditionally prevent a user from navigating to a different view/part in eclipse E4 RCP application?


I am trying to prevent a user from going to a different view/part in a perspective of eclipse E4 application.When i am trying to navigate to the same perspective and view,I am facing a stackOverflow exception due to recursively calling the showPart method by the framework.

NavigationHelper.showPerspective(CommonConstants.PERSPECTIVE1, getEclipseContext());
NavigationHelper.showPart(CommonConstants.VIEW1, getEclipseContext());
NavigationHelper.showPart(CommonConstants.VIEW2, getEclipseContext());

My showPart method lokks like this,

public static boolean showPart(String partId, IEclipseContext eclipseContext) {

        logger.debug("showPart::STARTED::" + partId);
        
        if (null == eclipseContext) {
            eclipseContext = getEclipseContext();
        }

        if (Model.getInstance().hasDataChanged()) {
            if (partId.equalsIgnoreCase(CommonConstants.VIEW1)
                    || partId.equalsIgnoreCase(CommonConstants.VIEW2)) {
                isNavigationSuccessful = true;
            } else {
                isNavigationSuccessful = false;
                Navigation.showWarning();
            }
        }

        if (isNavigationSuccessful) {                       
            findPartAndActivate(partId, eclipseContext, true);
        }
        logger.debug("isNavigationSuccessful = " + isNavigationSuccessful);
        logger.debug("showPart::END::" + partId);

        return isNavigationSuccessful;

    }

The findPartAndActivate looks like this

private static boolean findPartAndActivate(String partId, IEclipseContext eclipseContext, boolean giveFocus) {
        MTrimmedWindow applicationWindow = ((MTrimmedWindow) ((MApplication) eclipseContext.get(MApplication.class))
                .getChildren().get(0));
        IEclipseContext currentContext = applicationWindow.getContext();
        EPartService partService = currentContext.get(EPartService.class);
        EModelService modelService = currentContext.get(EModelService.class);
        MPart part = (MPart) modelService.find(partId, eclipseContext.get(MApplication.class).getChildren().get(0));        
        partService.activate(part, giveFocus);
        return true;
    }
    

The partDeactivated is invoked,once a user leaves from a part/View

 public void partDeactivated(@Active MPart part) {

            if (partInstance.getElementId() != part.getElementId()) {
                return;
            }                        
            
            if (transactionButton != null && !transactionButton.isDisposed() && transactionButton.isEnabled()
                    && isTransactionCompleted && NavigationHelper.getEditableViewInstance() != null && !partDeactivateFlag) {
                doTransaction();
                partDeactivateFlag = true;
            }

            if (Navigation.isPerspective()) {
                if (EModel.getInstance().hasDataChanged()/*&& !Model.getInstance().isSwitchFlag()*/) {
                    System.out.println("Changes");
                    //Model.getInstance().setSwitchFlag(true);
                    //partDeactivateFlag = true;
                    NavigationHelper.showPerspective(CommonConstants.PERSPECTIVE1, getEclipseContext());
                    NavigationHelper.showPart(CommonConstants.VIEW1, getEclipseContext());

                    NavigationHelper.showPart(CommonConstants.VIEW2, getEclipseContext());
                    
                    

                    
                }
            }
            viewDeactivated();  
        }        

    };

java.lang.StackOverflowError : null org.eclipse.e4.ui.workbench.modeling.ElementMatcher.select(ElementMatcher.java:71) org.eclipse.e4.ui.internal.workbench.ModelServiceImpl.findElementsRecursive(ModelServiceImpl.java:182) org.eclipse.e4.ui.internal.workbench.ModelServiceImpl.findElementsRecursive(ModelServiceImpl.java:317) org.eclipse.e4.ui.internal.workbench.ModelServiceImpl.findElementsRecursive(ModelServiceImpl.java:271) org.eclipse.e4.ui.internal.workbench.ModelServiceImpl.findElementsRecursive(ModelServiceImpl.java:271) org.eclipse.e4.ui.internal.workbench.ModelServiceImpl.findElementsRecursive(ModelServiceImpl.java:271) org.eclipse.e4.ui.internal.workbench.ModelServiceImpl.findElementsRecursive(ModelServiceImpl.java:251) org.eclipse.e4.ui.internal.workbench.ModelServiceImpl.findElementsRecursive(ModelServiceImpl.java:271) org.eclipse.e4.ui.internal.workbench.ModelServiceImpl.findElements(ModelServiceImpl.java:428) org.eclipse.e4.ui.internal.workbench.ModelServiceImpl.findElements(ModelServiceImpl.java:409) org.eclipse.e4.ui.internal.workbench.ModelServiceImpl.findElements(ModelServiceImpl.java:414) org.eclipse.e4.ui.internal.workbench.ModelServiceImpl.find(ModelServiceImpl.java:448)

This is the StackOverflow trace..

How can I solve this..?


Solution

  • Well the stack trace shows this is an error in your code. You are running NavigationHelper.showPart in a part deactivated listener, but your code is causing another part deactivate event which calls the deactivate listener again which calls showPart again and so on.

    You can't try to show a different part in the the part deactivate listener directly.

    One possibility is to use Display.asyncExec in the part deactivate listener to run the showPart after the deactivate event has completed.