/** * Copyright (c) 2014 - 2017 Frank Appel * 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: * Frank Appel - initial API and implementation */ package com.codeaffine.eclipse.ui.progress; import static org.eclipse.core.runtime.Assert.isNotNull; import org.eclipse.core.runtime.jobs.IJobChangeListener; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.osgi.util.NLS; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.progress.IDeferredWorkbenchAdapter; import org.eclipse.ui.progress.IWorkbenchSiteProgressService; public class DeferredContentManager { private static final Object[] EMPTY_CHILDREN = new Object[ 0 ]; private final PendingUpdatePlaceHolderFactory placeHolderFactory; private final CompletionObserverList completionObservers; private final ProgressService progressService; private final ViewerAdapter viewerAdapter; private final Adapters adapters; public DeferredContentManager( ViewerAdapter viewerAdapter ) { this( viewerAdapter, new DefaultPlaceHolderFactory(), null ); } public DeferredContentManager( ViewerAdapter viewerAdapter, IWorkbenchPartSite site ) { this( viewerAdapter, new DefaultPlaceHolderFactory(), site ); } public DeferredContentManager( ViewerAdapter viewerAdapter, PendingUpdatePlaceHolderFactory placeHolderFactory ) { this( viewerAdapter, placeHolderFactory, null ); } public DeferredContentManager( ViewerAdapter viewerAdapter, PendingUpdatePlaceHolderFactory placeHolderFactory, IWorkbenchPartSite site ) { this.adapters = new Adapters(); this.completionObservers = new CompletionObserverList(); this.progressService = lookupProgressService( adapters, site ); this.placeHolderFactory = placeHolderFactory; this.viewerAdapter = viewerAdapter; } public boolean mayHaveChildren( Object element ) { isNotNull( element, ProgressMessages.DeferredTreeContentManager_NotDeferred ); IDeferredWorkbenchAdapter adapter = getAdapter( element ); return adapter != null && adapter.isContainer(); } public Object[] getChildren( Object parent ) { if( isDeferredAdapter( parent ) ) { return startDeferredFetchingOfChildren( parent ); } return EMPTY_CHILDREN; } public boolean isDeferredAdapter( Object element ) { return getAdapter( element ) != null; } public void cancel( Object parent ) { if( parent != null ) { Job.getJobManager().cancel( new DeferredContentJobFamily( this, parent ) ); } } public void addUpdateCompleteListener( IJobChangeListener listener ) { completionObservers.add( listener ); } public void removeUpdateCompleteListener( IJobChangeListener listener ) { completionObservers.remove( listener ); } protected IDeferredWorkbenchAdapter getAdapter( Object element ) { return adapters.getAdapter( element, IDeferredWorkbenchAdapter.class ); } private void startDeferredFetchingOfChildren( Object parent, PendingUpdatePlaceHolder placeHolder ) { cancel( parent ); progressService.schedule( new FetchJob( this, parent, placeHolder ) ); } protected void addChildren( Object parent, Object[] children ) { new UpdateJob( viewerAdapter, parent, children ).schedule(); } protected void clearPlaceholder( PendingUpdatePlaceHolder placeHolder ) { if( !placeHolder.isRemoved() && PlatformUI.isWorkbenchRunning() ) { new ClearJob( completionObservers, viewerAdapter, placeHolder ).schedule(); } } protected String getFetchJobName( Object parent, IDeferredWorkbenchAdapter adapter ) { return NLS.bind( ProgressMessages.DeferredTreeContentManager_FetchingName, adapter.getLabel( parent ) ); } private Object[] startDeferredFetchingOfChildren( Object parent ) { PendingUpdatePlaceHolder placeholder = placeHolderFactory.create(); startDeferredFetchingOfChildren( parent, placeholder ); return new Object[] { placeholder }; } private static ProgressService lookupProgressService( Adapters adapters, IWorkbenchPartSite site ) { return new ProgressService( adapters.getAdapter( site, IWorkbenchSiteProgressService.class ) ); } }