📄 backgroundcontentprovider.java
字号:
/******************************************************************************* * Copyright (c) 2005, 2006 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.jface.viewers.deferred;import java.util.Comparator;import org.eclipse.core.runtime.IProgressMonitor;import org.eclipse.core.runtime.NullProgressMonitor;import org.eclipse.jface.resource.JFaceResources;import org.eclipse.jface.util.Assert;import org.eclipse.jface.viewers.AcceptAllFilter;import org.eclipse.jface.viewers.IFilter;import org.eclipse.jface.viewers.deferred.ConcurrentTableUpdator.Range;/** * Contains the algorithm for performing background sorting and filtering in a virtual * table. This is the real implementation for <code>DeferredContentProvider</code>. * However, this class will work with anything that implements <code>AbstractVirtualTable</code> * rather than being tied to a <code>TableViewer</code>. * * <p> * This is package visiblity since it currently only needs to be used in one place, * but it could potentially be made public if there was a need to use the same background * sorting algorithm for something other than a TableViewer. * </p> * * <p> * Information flow is like this: * </p> * <ol> * <li>IConcurrentModel sends unordered elements to BackgroundContentProvider (in a background thread)</li> * <li>BackgroundContentProvider sorts, filters, and sends element/index pairs to * ConcurrentTableUpdator (in a background thread)</li> * <li>ConcurrentTableUpdator batches the updates and sends them to an AbstractVirtualTable * (in the UI thread)</li> * </ol> * * <p> * Internally, sorting is done using a <code>LazySortedCollection</code>. This data structure * allows the content provider to locate and sort the visible range without fully sorting * all elements in the table. It also supports fast cancellation, allowing the visible range * to change in the middle of a sort without discarding partially-sorted information from * the previous range. * </p> * * @since 3.1 *//* package */ final class BackgroundContentProvider { /** * Sorting message string */ private static final String SORTING = JFaceResources.getString("Sorting"); //$NON-NLS-1$ /** * Table limit. -1 if unlimited */ private int limit = -1; /** * Model that is currently providing input to this content provider. */ private IConcurrentModel model; /** * Current sort order */ private volatile Comparator sortOrder; /** * True iff the content provider has */ private volatile IFilter filter = AcceptAllFilter.getInstance(); /** * Queued changes */ private ChangeQueue changeQueue = new ChangeQueue(); /** * Listener that gets callbacks from the model */ private IConcurrentModelListener listener = new IConcurrentModelListener() { /* (non-Javadoc) * @see org.eclipse.jface.viewers.deferred.IConcurrentModelListener#add(java.lang.Object[]) */ public void add(Object[] added) { BackgroundContentProvider.this.add(added); } /* (non-Javadoc) * @see org.eclipse.jface.viewers.deferred.IConcurrentModelListener#remove(java.lang.Object[]) */ public void remove(Object[] removed) { BackgroundContentProvider.this.remove(removed); } /* (non-Javadoc) * @see org.eclipse.jface.viewers.deferred.IConcurrentModelListener#setContents(java.lang.Object[]) */ public void setContents(Object[] newContents) { BackgroundContentProvider.this.setContents(newContents); } /* (non-Javadoc) * @see org.eclipse.jface.viewers.deferred.IConcurrentModelListener#update(java.lang.Object[]) */ public void update(Object[] changed) { BackgroundContentProvider.this.update(changed); } }; /** * Object that posts updates to the UI thread. Must synchronize on * sortMutex when accessing. */ private ConcurrentTableUpdator updator; private IProgressMonitor sortingProgressMonitor = new NullProgressMonitor(); private Thread sortThread = null; private volatile FastProgressReporter sortMon = new FastProgressReporter(); private volatile Range range = new Range(0,0); /** * Creates a new background content provider * * @param table table that will receive updates * @param model data source * @param sortOrder initial sort order */ public BackgroundContentProvider(AbstractVirtualTable table, IConcurrentModel model, Comparator sortOrder) { updator = new ConcurrentTableUpdator(table); this.model = model; this.sortOrder = sortOrder; model.addListener(listener); } /** * Cleans up this content provider, detaches listeners, frees up memory, etc. * Must be the last public method called on this object. */ public void dispose() { cancelSortJob(); updator.dispose(); model.removeListener(listener); } /** * Force a refresh. Asks the model to re-send its complete contents. */ public void refresh() { if (updator.isDisposed()) { return; } model.requestUpdate(listener); } /** * Called from sortJob. Sorts the elements defined by sortStart and sortLength. * Schedules a UI update when finished. * * @param mon monitor where progress will be reported */ private void doSort(IProgressMonitor mon) { // Workaround for some weirdness in the Jobs framework: if you cancel a monitor // for a job that has ended and reschedule that same job, it will start // the job with a monitor that is already cancelled. We can workaround this by // removing all references to the progress monitor whenever the job terminates, // but this would require additional synchronize blocks (which are slow) and more // complexity. Instead, we just un-cancel the monitor at the start of each job. mon.setCanceled(false); mon.beginTask(SORTING, 100); // Create a LazySortedCollection Comparator order = sortOrder; IFilter f = filter; LazySortedCollection collection = new LazySortedCollection(order); // Fill it in with all existing known objects Object[] knownObjects = updator.getKnownObjects(); for (int i = 0; i < knownObjects.length; i++) { Object object = knownObjects[i]; if (object != null) { collection.add(object); } } boolean dirty = false; int prevSize = knownObjects.length; updator.setTotalItems(prevSize); // Start processing changes while(true) { // If the sort order has changed, build a new LazySortedCollection with // the new comparator if (order != sortOrder) { dirty = true; order = sortOrder; // Copy all elements from the old collection to the new one LazySortedCollection newCollection = new LazySortedCollection(order); Object[] items = collection.getItems(false); for (int j = 0; j < items.length && order == sortOrder; j++) { Object item = items[j]; newCollection.add(item); } // If the sort order changed again, re-loop if (order != sortOrder) { continue; } collection = newCollection; continue; } // If the filter has changed if (f != filter) { dirty = true; f = filter; Object[] items = collection.getItems(false); // Remove any items that don't pass the new filter for (int j = 0; j < items.length && f == filter; j++) { Object toTest = items[j]; if (!f.select(toTest)) { collection.remove(toTest); } } continue; } // If there are pending changes, process one of them if (!changeQueue.isEmpty()) { dirty = true; ChangeQueue.Change next = changeQueue.dequeue(); switch(next.getType()) { case ChangeQueue.ADD: { filteredAdd(collection, next.getElements(), f); break; } case ChangeQueue.REMOVE: { Object[] toRemove = next.getElements(); flush(toRemove, collection); collection.removeAll(toRemove); break; } case ChangeQueue.UPDATE: { Object[] items = next.getElements(); for (int i = 0; i < items.length; i++) { Object item = items[i]; if (collection.contains(item)) { // TODO: write a collection.update(...) method collection.remove(item); collection.add(item); updator.clear(item); } } break; } case ChangeQueue.SET: { Object[] items = next.getElements(); collection.clear(); filteredAdd(collection, items, f);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -