1 11 12 package org.eclipse.debug.internal.ui.views.memory.renderings; 13 14 import java.math.BigInteger ; 15 import java.util.ArrayList ; 16 17 import org.eclipse.core.runtime.IProgressMonitor; 18 import org.eclipse.core.runtime.ISafeRunnable; 19 import org.eclipse.core.runtime.IStatus; 20 import org.eclipse.core.runtime.ListenerList; 21 import org.eclipse.core.runtime.SafeRunner; 22 import org.eclipse.core.runtime.Status; 23 import org.eclipse.debug.internal.ui.DebugUIPlugin; 24 import org.eclipse.debug.internal.ui.viewers.AsynchronousModel; 25 import org.eclipse.debug.internal.ui.viewers.AsynchronousTableViewer; 26 import org.eclipse.debug.internal.ui.viewers.model.provisional.IStatusMonitor; 27 import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor; 28 import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil; 29 import org.eclipse.jface.viewers.CellEditor; 30 import org.eclipse.swt.events.SelectionAdapter; 31 import org.eclipse.swt.events.SelectionEvent; 32 import org.eclipse.swt.events.SelectionListener; 33 import org.eclipse.swt.widgets.Composite; 34 import org.eclipse.swt.widgets.ScrollBar; 35 import org.eclipse.swt.widgets.Table; 36 import org.eclipse.swt.widgets.TableColumn; 37 import org.eclipse.swt.widgets.TableItem; 38 import org.eclipse.ui.progress.UIJob; 39 40 abstract public class AsyncVirtualContentTableViewer extends AsynchronousTableViewer { 41 42 private Object fPendingTopIndexKey; 43 private ArrayList fTopIndexQueue = new ArrayList (); 44 45 private boolean fPendingResizeColumns; 46 private ListenerList fVirtualContentListeners; 47 private SelectionListener fScrollSelectionListener; 48 private ListenerList fPresentationErrorListeners; 49 private Object fTopIndexKey; 50 51 public static boolean DEBUG_DYNAMIC_LOADING = false; 52 53 public AsyncVirtualContentTableViewer(Composite parent, int style) { 54 super(parent, style); 55 fVirtualContentListeners = new ListenerList(); 56 fPresentationErrorListeners = new ListenerList(); 57 initScrollBarListener(); 58 } 59 60 private void initScrollBarListener() 61 { 62 ScrollBar scroll = getTable().getVerticalBar(); 63 fScrollSelectionListener = new SelectionAdapter() { 64 public void widgetSelected(SelectionEvent e) { 65 handleScrollBarSelection(); 66 }}; 67 scroll.addSelectionListener(fScrollSelectionListener); 68 } 69 70 public void setTopIndex(Object key) 71 { 72 fPendingTopIndexKey = key; 73 attemptSetTopIndex(); 74 } 75 76 protected Object getPendingSetTopIndexKey() 77 { 78 return fPendingTopIndexKey; 79 } 80 81 protected void handlePresentationFailure(IStatusMonitor monitor, IStatus status) { 82 notifyPresentationError(monitor, status); 83 } 84 85 public void disposeColumns() 86 { 87 TableColumn[] oldColumns = getTable().getColumns(); 89 90 for (int i=0; i<oldColumns.length; i++) 91 { 92 oldColumns[i].dispose(); 93 } 94 } 95 96 public void disposeCellEditors() 97 { 98 CellEditor[] oldCellEditors = getCellEditors(); 100 101 if (oldCellEditors != null) 102 { 103 for (int i=0; i<oldCellEditors.length; i++) 104 { 105 oldCellEditors[i].dispose(); 106 } 107 } 108 } 109 110 113 public void resizeColumnsToPreferredSize() { 114 fPendingResizeColumns = true; 115 fPendingResizeColumns = attemptResizeColumnsToPreferredSize(); 116 } 117 118 private boolean attemptResizeColumnsToPreferredSize() 119 { 120 if (fPendingResizeColumns) 121 { 122 if(!hasPendingUpdates()) { 123 UIJob job = new UIJob("packcolumns"){ 125 public IStatus runInUIThread(IProgressMonitor monitor) { 126 Table table = getTable(); 127 128 if (!table.isDisposed()) 129 { 130 if (table.getSize().x > 0) 133 { 134 TableColumn[] columns = table.getColumns(); 135 for (int i=0 ;i<columns.length-1; i++) 136 { 137 columns[i].pack(); 138 } 139 } 140 else 141 { 142 fPendingResizeColumns = true; 143 } 144 } 145 return Status.OK_STATUS; 146 }}; 147 job.setSystem(true); 148 job.schedule(); 149 return false; 150 } 151 } 152 return fPendingResizeColumns; 153 } 154 155 160 protected synchronized void attemptSetTopIndex() { 161 if (fPendingTopIndexKey != null) { 162 Object remaining = doAttemptSetTopIndex(fPendingTopIndexKey); 163 if (remaining == null) 164 { 165 fPendingTopIndexKey = remaining; 166 } 167 } 168 } 169 170 private synchronized Object doAttemptSetTopIndex(final Object topIndexKey) 171 { 172 final int i = getVirtualContentModel().indexOfKey(topIndexKey); 173 if (i >= 0) 174 { 175 UIJob job = new UIJob("set top index"){ 177 public IStatus runInUIThread(IProgressMonitor monitor) { 178 if (getTable().isDisposed()) 179 { 180 fTopIndexQueue.clear(); 181 return Status.OK_STATUS; 182 } 183 184 int idx = getVirtualContentModel().indexOfKey(topIndexKey); 185 if (idx >= 0) 186 { 187 if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING) 188 System.out.println("actual set top index: " + ((BigInteger )topIndexKey).toString(16)); fPendingTopIndexKey = null; 190 setTopIndexKey(topIndexKey); 191 getTable().setTopIndex(idx); 192 tableTopIndexSetComplete(); 193 194 if (getTable().getTopIndex() != idx ) 195 { 196 if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING) 197 System.out.println(">>> FAILED set top index : " + ((BigInteger )topIndexKey).toString(16)); 199 if (hasPendingUpdates()) 201 { 202 if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING) 203 System.out.println(">>> Retry top index: " + ((BigInteger )topIndexKey).toString(16)); 205 fPendingTopIndexKey = topIndexKey; 206 } 207 } 208 } 209 else 210 { 211 if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING) 212 System.out.println("cannot find key, put it back to the queue: " + topIndexKey); fPendingTopIndexKey = topIndexKey; 214 } 215 216 removeKeyFromQueue(topIndexKey); 218 219 return Status.OK_STATUS; 220 }}; 221 222 addKeyToQueue(topIndexKey); 225 226 job.setSystem(true); 227 job.schedule(); 228 return topIndexKey; 229 } 230 return topIndexKey; 231 } 232 233 protected void tableTopIndexSetComplete() 234 { 235 236 } 237 238 public void addVirtualContentListener(IVirtualContentListener listener) 239 { 240 fVirtualContentListeners.add(listener); 241 } 242 243 public void removeVirtualContentListener(IVirtualContentListener listener) 244 { 245 fVirtualContentListeners.remove(listener); 246 } 247 248 protected void notifyListenersAtBufferStart() 249 { 250 int topIdx = getTable().getTopIndex(); 251 Object [] listeners = fVirtualContentListeners.getListeners(); 252 253 for (int i = 0; i < listeners.length; i++) { 254 final IVirtualContentListener listener = (IVirtualContentListener) listeners[i]; 255 if (topIdx < listener.getThreshold(IVirtualContentListener.BUFFER_START)) 256 { 257 SafeRunner.run(new ISafeRunnable() { 258 public void run() throws Exception { 259 listener.handledAtBufferStart(); 260 } 261 public void handleException(Throwable exception) { 262 DebugUIPlugin.log(exception); 263 } 264 }); 265 } 266 } 267 } 268 269 protected void notifyListenersAtBufferEnd() 270 { 271 Object [] listeners = fVirtualContentListeners.getListeners(); 272 int topIdx = getTable().getTopIndex(); 273 int bottomIdx = topIdx + getNumberOfVisibleLines(); 274 int elementsCnt = getVirtualContentModel().getElements().length; 275 int numLinesLeft = elementsCnt - bottomIdx; 276 277 for (int i = 0; i < listeners.length; i++) { 278 final IVirtualContentListener listener = (IVirtualContentListener) listeners[i]; 279 if (numLinesLeft <= listener.getThreshold(IVirtualContentListener.BUFFER_END)) 280 { 281 SafeRunner.run(new ISafeRunnable() { 282 public void run() throws Exception { 283 listener.handleAtBufferEnd(); 284 } 285 public void handleException(Throwable exception) { 286 DebugUIPlugin.log(exception); 287 } 288 }); 289 } 290 } 291 } 292 293 protected void handleScrollBarSelection() 294 { 295 if (!fTopIndexQueue.isEmpty()) 297 return; 298 topIndexChanged(); 299 } 300 301 public void topIndexChanged() 302 { 303 if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING) 304 { 305 MemorySegment a = (MemorySegment)getTable().getItem(getTable().getTopIndex()).getData(); 306 System.out.println(Thread.currentThread().getName() + " " + this + " handle scroll bar moved: top index: " + a.getAddress().toString(16)); } 308 309 setTopIndexKey(getVirtualContentModel().getKey(getTable().getTopIndex())); 310 311 notifyListenersAtBufferStart(); 312 notifyListenersAtBufferEnd(); 313 } 314 315 protected void setTopIndexKey(Object key) 316 { 317 fTopIndexKey = key; 318 } 319 320 protected Object getTopIndexKey() 321 { 322 return fTopIndexKey; 323 } 324 325 protected synchronized void preservingSelection(Runnable updateCode) { 326 Object oldTopIndexKey = null; 327 if (fPendingTopIndexKey == null) { 328 oldTopIndexKey = getTopIndexKey(); 330 } 331 else 332 { 333 oldTopIndexKey = fPendingTopIndexKey; 334 } 335 336 try { 337 338 updateCode.run(); 340 } finally { 341 if (oldTopIndexKey != null) 342 { 343 setTopIndex(oldTopIndexKey); 344 } 345 } 346 347 } 348 349 public void addPresentationErrorListener(IPresentationErrorListener errorListener) 350 { 351 fPresentationErrorListeners.add(errorListener); 352 } 353 354 public void removePresentationErrorListener(IPresentationErrorListener errorListener) 355 { 356 fPresentationErrorListeners.remove(errorListener); 357 } 358 359 private void notifyPresentationError(final IStatusMonitor monitor, final IStatus status) 360 { 361 Object [] listeners = fPresentationErrorListeners.getListeners(); 362 363 for (int i = 0; i < listeners.length; i++) { 364 365 if (listeners[i] instanceof IPresentationErrorListener) 366 { 367 final IPresentationErrorListener listener = (IPresentationErrorListener)listeners[i]; 368 SafeRunner.run(new ISafeRunnable() { 369 public void run() throws Exception { 370 listener.handlePresentationFailure(monitor, status); 371 } 372 public void handleException(Throwable exception) { 373 DebugUIPlugin.log(exception); 374 } 375 }); 376 } 377 } 378 } 379 380 protected AsynchronousModel createModel() { 381 return createVirtualContentTableModel(); 382 } 383 384 abstract protected AbstractVirtualContentTableModel createVirtualContentTableModel(); 385 386 private void addKeyToQueue(Object topIndexKey) 387 { 388 synchronized(fTopIndexQueue){ 389 if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING) 390 System.out.println(" >>> add to top index queue: " + ((BigInteger )topIndexKey).toString(16)); fTopIndexQueue.add(topIndexKey); 392 } 393 } 394 395 private void removeKeyFromQueue(Object topIndexKey) 396 { 397 synchronized(fTopIndexQueue){ 398 if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING) 399 System.out.println(" >>> remove frome top index queue: " + ((BigInteger )topIndexKey).toString(16)); fTopIndexQueue.remove(topIndexKey); 401 } 402 } 403 404 public AbstractVirtualContentTableModel getVirtualContentModel() 405 { 406 if (getModel() instanceof AbstractVirtualContentTableModel) 407 return (AbstractVirtualContentTableModel) getModel(); 408 return null; 409 } 410 411 private int getNumberOfVisibleLines() 412 { 413 Table table = getTable(); 414 int height = table.getSize().y; 415 416 if (height == 0) 418 { 419 height = table.getParent().getSize().y; 421 } 422 423 int border = table.getHeaderHeight(); 425 426 int scroll = table.getHorizontalBar().getSize().y; 428 429 height = height-border-scroll; 431 432 int lineHeight = getMinTableItemHeight(table); 434 435 int numberOfLines = height/lineHeight; 436 437 if (numberOfLines <= 0) 438 return 20; 439 440 return numberOfLines; 441 } 442 443 private int getMinTableItemHeight(Table table){ 444 445 if (MemoryViewUtil.isLinuxGTK()) 453 { 454 TableItem[] items = table.getItems(); 456 int minHeight = table.getItemHeight(); 457 for (int i=0; i<items.length; i++) 458 { 459 if (items[i].getData() != null) 460 minHeight = Math.min(items[i].getBounds(0).height, minHeight); 461 } 462 463 return minHeight; 464 465 } 466 return table.getItemHeight(); 467 } 468 469 protected void updateComplete(IStatusMonitor monitor) { 470 super.updateComplete(monitor); 471 attemptSetTopIndex(); 472 if (monitor instanceof ILabelRequestMonitor) 473 { 474 fPendingResizeColumns = attemptResizeColumnsToPreferredSize(); 475 } 476 } 477 478 protected boolean hasPendingSetTopIndex() 479 { 480 return !fTopIndexQueue.isEmpty(); 481 } 482 483 } 484 | Popular Tags |