1 11 package org.eclipse.jface.viewers.deferred; 12 13 import java.util.Comparator ; 14 15 import org.eclipse.core.runtime.IProgressMonitor; 16 import org.eclipse.core.runtime.NullProgressMonitor; 17 import org.eclipse.jface.resource.JFaceResources; 18 import org.eclipse.core.runtime.Assert; 19 import org.eclipse.jface.viewers.AcceptAllFilter; 20 import org.eclipse.jface.viewers.IFilter; 21 import org.eclipse.jface.viewers.deferred.ConcurrentTableUpdator.Range; 22 23 56 final class BackgroundContentProvider { 57 58 61 private static final String SORTING = JFaceResources.getString("Sorting"); 63 66 private int limit = -1; 67 68 71 private IConcurrentModel model; 72 73 76 private volatile Comparator sortOrder; 77 78 81 private volatile IFilter filter = AcceptAllFilter.getInstance(); 82 83 86 private ChangeQueue changeQueue = new ChangeQueue(); 87 88 91 private IConcurrentModelListener listener = new IConcurrentModelListener() { 92 95 public void add(Object [] added) { 96 BackgroundContentProvider.this.add(added); 97 } 98 99 102 public void remove(Object [] removed) { 103 BackgroundContentProvider.this.remove(removed); 104 } 105 106 109 public void setContents(Object [] newContents) { 110 BackgroundContentProvider.this.setContents(newContents); 111 } 112 113 116 public void update(Object [] changed) { 117 BackgroundContentProvider.this.update(changed); 118 } 119 120 }; 121 122 126 private ConcurrentTableUpdator updator; 127 128 private IProgressMonitor sortingProgressMonitor = new NullProgressMonitor(); 129 private Thread sortThread = null; 130 131 private volatile FastProgressReporter sortMon = new FastProgressReporter(); 132 133 private volatile Range range = new Range(0,0); 134 135 142 public BackgroundContentProvider(AbstractVirtualTable table, 143 IConcurrentModel model, Comparator sortOrder) { 144 145 updator = new ConcurrentTableUpdator(table); 146 this.model = model; 147 this.sortOrder = sortOrder; 148 model.addListener(listener); 149 } 150 151 155 public void dispose() { 156 cancelSortJob(); 157 updator.dispose(); 158 model.removeListener(listener); 159 } 160 161 164 public void refresh() { 165 if (updator.isDisposed()) { 166 return; 167 } 168 model.requestUpdate(listener); 169 } 170 171 177 private void doSort(IProgressMonitor mon) { 178 179 mon.setCanceled(false); 186 187 mon.beginTask(SORTING, 100); 188 189 Comparator order = sortOrder; 191 IFilter f = filter; 192 LazySortedCollection collection = new LazySortedCollection(order); 193 194 Object [] knownObjects = updator.getKnownObjects(); 196 for (int i = 0; i < knownObjects.length; i++) { 197 Object object = knownObjects[i]; 198 if (object != null) { 199 collection.add(object); 200 } 201 } 202 203 boolean dirty = false; 204 int prevSize = knownObjects.length; 205 updator.setTotalItems(prevSize); 206 207 while(true) { 209 if (order != sortOrder) { 212 dirty = true; 213 order = sortOrder; 214 LazySortedCollection newCollection = new LazySortedCollection(order); 216 217 Object [] items = collection.getItems(false); 218 for (int j = 0; j < items.length && order == sortOrder; j++) { 219 Object item = items[j]; 220 221 newCollection.add(item); 222 } 223 224 if (order != sortOrder) { 226 continue; 227 } 228 collection = newCollection; 229 continue; 230 } 231 232 if (f != filter) { 234 dirty = true; 235 f = filter; 236 237 Object [] items = collection.getItems(false); 238 239 for (int j = 0; j < items.length && f == filter; j++) { 241 Object toTest = items[j]; 242 243 if (!f.select(toTest)) { 244 collection.remove(toTest); 245 } 246 } 247 continue; 248 } 249 250 if (!changeQueue.isEmpty()) { 252 dirty = true; 253 ChangeQueue.Change next = changeQueue.dequeue(); 254 255 switch(next.getType()) { 256 case ChangeQueue.ADD: { 257 filteredAdd(collection, next.getElements(), f); 258 break; 259 } 260 case ChangeQueue.REMOVE: { 261 Object [] toRemove = next.getElements(); 262 263 flush(toRemove, collection); 264 collection.removeAll(toRemove); 265 266 break; 267 } 268 case ChangeQueue.UPDATE: { 269 Object [] items = next.getElements(); 270 271 for (int i = 0; i < items.length; i++) { 272 Object item = items[i]; 273 274 if (collection.contains(item)) { 275 collection.remove(item); 277 collection.add(item); 278 updator.clear(item); 279 } 280 } 281 282 break; 283 } 284 case ChangeQueue.SET: { 285 Object [] items = next.getElements(); 286 collection.clear(); 287 filteredAdd(collection, items, f); 288 289 break; 290 } 291 } 292 293 continue; 294 } 295 296 int totalElements = collection.size(); 297 if (limit != -1) { 298 if (totalElements > limit) { 299 totalElements = limit; 300 } 301 } 302 303 if (totalElements != prevSize) { 304 prevSize = totalElements; 305 updator.setTotalItems(totalElements); 309 dirty = true; 310 } 311 312 if (!dirty) { 314 break; 315 } 316 317 try { 318 ConcurrentTableUpdator.Range updateRange = updator.getVisibleRange(); 319 sortMon = new FastProgressReporter(); 320 range = updateRange; 321 int sortStart = updateRange.start; 322 int sortLength = updateRange.length; 323 324 if (limit != -1) { 325 collection.retainFirst(limit, sortMon); 326 } 327 328 sortLength = Math.min(sortLength, totalElements - sortStart); 329 sortLength = Math.max(sortLength, 0); 330 331 Object [] objectsOfInterest = new Object [sortLength]; 332 333 collection.getRange(objectsOfInterest, sortStart, true, sortMon); 334 335 for (int i = 0; i < sortLength; i++) { 337 Object object = objectsOfInterest[i]; 338 updator.replace(object, sortStart + i); 339 } 340 341 objectsOfInterest = new Object [collection.size()]; 342 343 collection.getFirst(objectsOfInterest, true, sortMon); 344 345 for (int i = 0; i < totalElements; i++) { 347 Object object = objectsOfInterest[i]; 348 updator.replace(object, i); 349 } 350 351 } catch (InterruptedException e) { 352 continue; 353 } 354 355 dirty = false; 356 } 357 358 mon.done(); 359 } 360 361 365 private static void filteredAdd(LazySortedCollection collection, Object [] toAdd, IFilter filter) { 366 if (filter != AcceptAllFilter.getInstance()) { 367 for (int i = 0; i < toAdd.length; i++) { 368 Object object = toAdd[i]; 369 370 if (filter.select(object)) { 371 collection.add(object); 372 } 373 } 374 } else { 375 collection.addAll(toAdd); 376 } 377 } 378 379 384 public void setSortOrder(Comparator sorter) { 385 Assert.isNotNull(sorter); 386 this.sortOrder = sorter; 387 sortMon.cancel(); 388 refresh(); 389 } 390 391 396 public void setFilter(IFilter toSet) { 397 Assert.isNotNull(toSet); 398 this.filter = toSet; 399 sortMon.cancel(); 400 refresh(); 401 } 402 403 411 public void setLimit(int limit) { 412 this.limit = limit; 413 refresh(); 414 } 415 416 421 public int getLimit() { 422 return limit; 423 } 424 425 431 public void checkVisibleRange(int includeIndex) { 432 updator.checkVisibleRange(includeIndex); 433 ConcurrentTableUpdator.Range newRange = updator.getVisibleRange(); 434 ConcurrentTableUpdator.Range oldRange = range; 435 436 if (newRange.start != oldRange.start || newRange.length != oldRange.length) { 438 sortMon.cancel(); 439 } 440 } 441 442 445 private Object lock = new Object (); 446 447 450 private boolean sortThreadStarted = false; 451 452 455 private boolean sortScheduled = false; 456 457 private final class SortThread extends Thread { 458 private SortThread(String name) { 459 super(name); 460 } 461 462 public void run() { 463 loop: while (true) { 464 synchronized (lock) { 465 sortScheduled = false; 466 } 467 try { 468 doSort(sortingProgressMonitor); 470 } catch (Exception ex) { 471 } 473 synchronized (lock) { 474 if (sortScheduled) { 475 continue loop; 476 } 477 sortThreadStarted = false; 478 break loop; 479 } 480 } 481 } 482 } 483 484 488 private void makeDirty() { 489 synchronized (lock) { 490 sortMon.cancel(); 491 sortScheduled = true; 493 if (!sortThreadStarted) { 494 sortThreadStarted = true; 495 sortThread = new SortThread(SORTING); 496 sortThread.setDaemon(true); 497 sortThread.setPriority(Thread.NORM_PRIORITY - 1); 498 sortThread.start(); 499 } 500 } 501 } 502 503 509 private void cancelSortJob() { 510 sortMon.cancel(); 511 sortingProgressMonitor.setCanceled(true); 512 } 513 514 520 private void add(Object [] toAdd) { 521 changeQueue.enqueue(ChangeQueue.ADD, toAdd); 522 makeDirty(); 523 } 524 525 530 private void setContents(Object [] contents) { 531 changeQueue.enqueue(ChangeQueue.SET, contents); 532 makeDirty(); 533 } 534 535 540 private void remove(Object [] toRemove) { 541 changeQueue.enqueue(ChangeQueue.REMOVE, toRemove); 542 makeDirty(); 543 refresh(); 544 } 545 546 552 private void flush(Object [] toFlush, LazySortedCollection collection) { 553 for (int i = 0; i < toFlush.length; i++) { 554 Object item = toFlush[i]; 555 556 if (collection.contains(item)) { 557 updator.clear(item); 558 } 559 } 560 } 561 562 563 568 private void update(Object [] items) { 569 changeQueue.enqueue(ChangeQueue.UPDATE, items); 570 makeDirty(); 571 } 572 } 573 | Popular Tags |