Bug 390379 - [Performance] Seemingly excessive calls to contextManager
diff --git a/bundles/org.eclipse.e4.ui.services/src/org/eclipse/e4/ui/internal/services/ContextContextService.java b/bundles/org.eclipse.e4.ui.services/src/org/eclipse/e4/ui/internal/services/ContextContextService.java index ce839b9..90629d3 100644 --- a/bundles/org.eclipse.e4.ui.services/src/org/eclipse/e4/ui/internal/services/ContextContextService.java +++ b/bundles/org.eclipse.e4.ui.services/src/org/eclipse/e4/ui/internal/services/ContextContextService.java
@@ -25,6 +25,10 @@ private IEclipseContext eclipseContext; private ContextManager contextManager; + + private boolean deferUpdates = false; + + private int cachingRef = 0; public ContextContextService(IEclipseContext context) { eclipseContext = context; @@ -40,6 +44,10 @@ * String) */ public void activateContext(String id) { + if (deferUpdates) { + deferActivateContext(id); + return; + } LinkedList<String> locals = (LinkedList<String>) eclipseContext .getLocal(LOCAL_CONTEXTS); if (locals == null) { @@ -54,7 +62,76 @@ } } } + + /** + * Informs the manager that a batch operation has started. + * <p> + * <b>Note:</b> You must insure that if you call + * <code>deferUpdates(true)</code> that nothing in your batched operation + * will prevent the matching call to <code>deferUpdates(false)</code>. + * </p> + * + * @param defer + * true when starting a batch operation false when ending the + * operation + * + * @since 4.3 + */ + public void deferUpdates(boolean defer) { + if(defer) { + cachingRef ++; + if (cachingRef==1) { + setEventCaching(true); + } + }else { + cachingRef--; + if (cachingRef==0) { + setEventCaching(false); + } + } + } + private void deferActivateContext(String id) { + LinkedList<String> locals = (LinkedList<String>) eclipseContext + .getLocal(LOCAL_CONTEXTS+".a"); + if (locals == null) { + locals = new LinkedList<String>(); + eclipseContext.set(LOCAL_CONTEXTS+ ".a", locals); + } + locals.add(id); + } + + private void setEventCaching(boolean cache) { + if (cache) { + deferUpdates = true; + return; + } + + deferUpdates = false; + LinkedList<String> locals = (LinkedList<String>) eclipseContext + .getLocal(LOCAL_CONTEXTS); + if (locals == null) { + locals = new LinkedList<String>(); + } + LinkedList<String> activates = (LinkedList<String>) eclipseContext + .getLocal(LOCAL_CONTEXTS + ".a"); + if (activates != null) { + eclipseContext.remove(LOCAL_CONTEXTS + ".a"); + for (String id : activates) { + locals.add(id); + } + } + LinkedList<String> deactivates = (LinkedList<String>) eclipseContext + .getLocal(LOCAL_CONTEXTS + ".d"); + if (deactivates != null) { + eclipseContext.remove(LOCAL_CONTEXTS + ".d"); + for (String id : deactivates) { + locals.remove(id); + } + } + eclipseContext.set(LOCAL_CONTEXTS, locals.clone()); + } + /* * (non-Javadoc) * @@ -63,6 +140,10 @@ * .String) */ public void deactivateContext(String id) { + if (deferUpdates) { + deferDeactivateContext(id); + return; + } LinkedList<String> locals = (LinkedList<String>) eclipseContext .getLocal(LOCAL_CONTEXTS); if (locals != null && locals.remove(id)) { @@ -74,6 +155,16 @@ } } + private void deferDeactivateContext(String id) { + LinkedList<String> locals = (LinkedList<String>) eclipseContext + .getLocal(LOCAL_CONTEXTS+".d"); + if (locals == null) { + locals = new LinkedList<String>(); + eclipseContext.set(LOCAL_CONTEXTS+ ".d", locals); + } + locals.add(id); + } + /* * (non-Javadoc) *
diff --git a/bundles/org.eclipse.e4.ui.services/src/org/eclipse/e4/ui/services/EContextService.java b/bundles/org.eclipse.e4.ui.services/src/org/eclipse/e4/ui/services/EContextService.java index ffaa03b..a754b2c 100644 --- a/bundles/org.eclipse.e4.ui.services/src/org/eclipse/e4/ui/services/EContextService.java +++ b/bundles/org.eclipse.e4.ui.services/src/org/eclipse/e4/ui/services/EContextService.java
@@ -22,4 +22,6 @@ public void deactivateContext(String id); public Collection<String> getActiveContextIds(); + + public void deferUpdates(boolean defer); }
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceImpl.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceImpl.java index 20138a8..89df348 100644 --- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceImpl.java +++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceImpl.java
@@ -46,6 +46,7 @@ import org.eclipse.e4.ui.model.application.ui.basic.MWindow; import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicFactoryImpl; import org.eclipse.e4.ui.model.application.ui.menu.MToolBar; +import org.eclipse.e4.ui.services.EContextService; import org.eclipse.e4.ui.services.IServiceConstants; import org.eclipse.e4.ui.workbench.IPresentationEngine; import org.eclipse.e4.ui.workbench.UIEvents; @@ -125,6 +126,9 @@ @Inject private IEventBroker eventBroker; + @Inject + private EContextService contextService; + private PartActivationHistory partActivationHistory; private MPart activePart; @@ -544,32 +548,37 @@ UIEvents.publishEvent(UIEvents.UILifeCycle.ACTIVATE, part); return; } + contextService.deferUpdates(true); + try { + // record any sibling into the activation history if necessary, this will allow it to be + // reselected again in the future as it will be an activation candidate in the future, + // this + // prevents other unrendered elements from being selected arbitrarily which would cause + // unwanted bundle activation + recordStackActivation(part); - // record any sibling into the activation history if necessary, this will allow it to be - // reselected again in the future as it will be an activation candidate in the future, this - // prevents other unrendered elements from being selected arbitrarily which would cause - // unwanted bundle activation - recordStackActivation(part); + delegateBringToTop(part); + window.getParent().setSelectedElement(window); - delegateBringToTop(part); - window.getParent().setSelectedElement(window); + partActivationHistory.activate(part, activateBranch); - partActivationHistory.activate(part, activateBranch); + Object object = part.getObject(); + if (object != null && requiresFocus) { + try { + ContextInjectionFactory.invoke(object, Focus.class, part.getContext(), null); - Object object = part.getObject(); - if (object != null && requiresFocus) { - try { - ContextInjectionFactory.invoke(object, Focus.class, part.getContext(), null); - - firePartActivated(part); - UIEvents.publishEvent(UIEvents.UILifeCycle.ACTIVATE, part); - } catch (InjectionException e) { - log("Failed to grant focus to part", "Failed to grant focus to part ({0})", //$NON-NLS-1$ //$NON-NLS-2$ - part.getElementId(), e); - } catch (RuntimeException e) { - log("Failed to grant focus to part via DI", //$NON-NLS-1$ - "Failed to grant focus via DI to part ({0})", part.getElementId(), e); //$NON-NLS-1$ + firePartActivated(part); + UIEvents.publishEvent(UIEvents.UILifeCycle.ACTIVATE, part); + } catch (InjectionException e) { + log("Failed to grant focus to part", "Failed to grant focus to part ({0})", //$NON-NLS-1$ //$NON-NLS-2$ + part.getElementId(), e); + } catch (RuntimeException e) { + log("Failed to grant focus to part via DI", //$NON-NLS-1$ + "Failed to grant focus via DI to part ({0})", part.getElementId(), e); //$NON-NLS-1$ + } } + } finally { + contextService.deferUpdates(false); } }
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/contexts/ContextService.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/contexts/ContextService.java index f471cbe..4205cbc 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/contexts/ContextService.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/contexts/ContextService.java
@@ -92,6 +92,7 @@ */ public void deferUpdates(boolean defer) { contextManager.deferUpdates(defer); + contextService.deferUpdates(defer); } /*