PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/eclipse_SDK-3.7.1/plugins/org.eclipse.debug.ui.source_3.7.101.v20110817_r371/org/eclipse/debug/internal/ui/views/memory/renderings/AsyncVirtualContentTableViewer.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 483 lines | 365 code | 75 blank | 43 comment | 46 complexity | 45fa0364e2ee1513e6f9f28b7e1c4298 MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright (c) 2006, 2007 IBM Corporation and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors:
  9. * IBM Corporation - initial API and implementation
  10. *******************************************************************************/
  11. package org.eclipse.debug.internal.ui.views.memory.renderings;
  12. import java.math.BigInteger;
  13. import java.util.ArrayList;
  14. import org.eclipse.core.runtime.IProgressMonitor;
  15. import org.eclipse.core.runtime.ISafeRunnable;
  16. import org.eclipse.core.runtime.IStatus;
  17. import org.eclipse.core.runtime.ListenerList;
  18. import org.eclipse.core.runtime.SafeRunner;
  19. import org.eclipse.core.runtime.Status;
  20. import org.eclipse.debug.internal.ui.DebugUIPlugin;
  21. import org.eclipse.debug.internal.ui.viewers.AsynchronousModel;
  22. import org.eclipse.debug.internal.ui.viewers.AsynchronousTableViewer;
  23. import org.eclipse.debug.internal.ui.viewers.model.provisional.IStatusMonitor;
  24. import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor;
  25. import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil;
  26. import org.eclipse.jface.viewers.CellEditor;
  27. import org.eclipse.swt.events.SelectionAdapter;
  28. import org.eclipse.swt.events.SelectionEvent;
  29. import org.eclipse.swt.events.SelectionListener;
  30. import org.eclipse.swt.widgets.Composite;
  31. import org.eclipse.swt.widgets.ScrollBar;
  32. import org.eclipse.swt.widgets.Table;
  33. import org.eclipse.swt.widgets.TableColumn;
  34. import org.eclipse.swt.widgets.TableItem;
  35. import org.eclipse.ui.progress.UIJob;
  36. abstract public class AsyncVirtualContentTableViewer extends AsynchronousTableViewer {
  37. private Object fPendingTopIndexKey;
  38. private ArrayList fTopIndexQueue = new ArrayList();
  39. private boolean fPendingResizeColumns;
  40. private ListenerList fVirtualContentListeners;
  41. private SelectionListener fScrollSelectionListener;
  42. private ListenerList fPresentationErrorListeners;
  43. private Object fTopIndexKey;
  44. public static boolean DEBUG_DYNAMIC_LOADING = false;
  45. public AsyncVirtualContentTableViewer(Composite parent, int style) {
  46. super(parent, style);
  47. fVirtualContentListeners = new ListenerList();
  48. fPresentationErrorListeners = new ListenerList();
  49. initScrollBarListener();
  50. }
  51. private void initScrollBarListener()
  52. {
  53. ScrollBar scroll = getTable().getVerticalBar();
  54. fScrollSelectionListener = new SelectionAdapter() {
  55. public void widgetSelected(SelectionEvent e) {
  56. handleScrollBarSelection();
  57. }};
  58. scroll.addSelectionListener(fScrollSelectionListener);
  59. }
  60. public void setTopIndex(Object key)
  61. {
  62. fPendingTopIndexKey = key;
  63. attemptSetTopIndex();
  64. }
  65. protected Object getPendingSetTopIndexKey()
  66. {
  67. return fPendingTopIndexKey;
  68. }
  69. protected void handlePresentationFailure(IStatusMonitor monitor, IStatus status) {
  70. notifyPresentationError(monitor, status);
  71. }
  72. public void disposeColumns()
  73. {
  74. // clean up old columns
  75. TableColumn[] oldColumns = getTable().getColumns();
  76. for (int i=0; i<oldColumns.length; i++)
  77. {
  78. oldColumns[i].dispose();
  79. }
  80. }
  81. public void disposeCellEditors()
  82. {
  83. // clean up old cell editors
  84. CellEditor[] oldCellEditors = getCellEditors();
  85. if (oldCellEditors != null)
  86. {
  87. for (int i=0; i<oldCellEditors.length; i++)
  88. {
  89. oldCellEditors[i].dispose();
  90. }
  91. }
  92. }
  93. /**
  94. * Resize column to the preferred size.
  95. */
  96. public void resizeColumnsToPreferredSize() {
  97. fPendingResizeColumns = true;
  98. fPendingResizeColumns = attemptResizeColumnsToPreferredSize();
  99. }
  100. private boolean attemptResizeColumnsToPreferredSize()
  101. {
  102. if (fPendingResizeColumns)
  103. {
  104. if(!hasPendingUpdates()) {
  105. UIJob job = new UIJob("packcolumns"){ //$NON-NLS-1$
  106. public IStatus runInUIThread(IProgressMonitor monitor) {
  107. Table table = getTable();
  108. if (!table.isDisposed())
  109. {
  110. // if table size is zero, the rendering has not been made visible
  111. // cannot pack until the rendering is visible
  112. if (table.getSize().x > 0)
  113. {
  114. TableColumn[] columns = table.getColumns();
  115. for (int i=0 ;i<columns.length-1; i++)
  116. {
  117. columns[i].pack();
  118. }
  119. }
  120. else
  121. {
  122. fPendingResizeColumns = true;
  123. }
  124. }
  125. return Status.OK_STATUS;
  126. }};
  127. job.setSystem(true);
  128. job.schedule();
  129. return false;
  130. }
  131. }
  132. return fPendingResizeColumns;
  133. }
  134. /**
  135. * Attempts to update any pending setTopIndex
  136. *
  137. * @param reveal whether to reveal the selection
  138. */
  139. protected synchronized void attemptSetTopIndex() {
  140. if (fPendingTopIndexKey != null) {
  141. Object remaining = doAttemptSetTopIndex(fPendingTopIndexKey);
  142. if (remaining == null)
  143. {
  144. fPendingTopIndexKey = remaining;
  145. }
  146. }
  147. }
  148. private synchronized Object doAttemptSetTopIndex(final Object topIndexKey)
  149. {
  150. final int i = getVirtualContentModel().indexOfKey(topIndexKey);
  151. if (i >= 0)
  152. {
  153. UIJob job = new UIJob("set top index"){ //$NON-NLS-1$
  154. public IStatus runInUIThread(IProgressMonitor monitor) {
  155. if (getTable().isDisposed())
  156. {
  157. fTopIndexQueue.clear();
  158. return Status.OK_STATUS;
  159. }
  160. int idx = getVirtualContentModel().indexOfKey(topIndexKey);
  161. if (idx >= 0)
  162. {
  163. if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
  164. System.out.println("actual set top index: " + ((BigInteger)topIndexKey).toString(16)); //$NON-NLS-1$
  165. fPendingTopIndexKey = null;
  166. setTopIndexKey(topIndexKey);
  167. getTable().setTopIndex(idx);
  168. tableTopIndexSetComplete();
  169. if (getTable().getTopIndex() != idx )
  170. {
  171. if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
  172. System.out.println(">>> FAILED set top index : " + ((BigInteger)topIndexKey).toString(16)); //$NON-NLS-1$
  173. // only retry if we have pending updates
  174. if (hasPendingUpdates())
  175. {
  176. if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
  177. System.out.println(">>> Retry top index: " + ((BigInteger)topIndexKey).toString(16)); //$NON-NLS-1$
  178. fPendingTopIndexKey = topIndexKey;
  179. }
  180. }
  181. }
  182. else
  183. {
  184. if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
  185. System.out.println("cannot find key, put it back to the queue: " + topIndexKey); //$NON-NLS-1$
  186. fPendingTopIndexKey = topIndexKey;
  187. }
  188. // remove the top index key from queue when it is processed
  189. removeKeyFromQueue(topIndexKey);
  190. return Status.OK_STATUS;
  191. }};
  192. // set top index does not happen immediately, keep track of
  193. // all pending set top index
  194. addKeyToQueue(topIndexKey);
  195. job.setSystem(true);
  196. job.schedule();
  197. return topIndexKey;
  198. }
  199. return topIndexKey;
  200. }
  201. protected void tableTopIndexSetComplete()
  202. {
  203. }
  204. public void addVirtualContentListener(IVirtualContentListener listener)
  205. {
  206. fVirtualContentListeners.add(listener);
  207. }
  208. public void removeVirtualContentListener(IVirtualContentListener listener)
  209. {
  210. fVirtualContentListeners.remove(listener);
  211. }
  212. protected void notifyListenersAtBufferStart()
  213. {
  214. int topIdx = getTable().getTopIndex();
  215. Object[] listeners = fVirtualContentListeners.getListeners();
  216. for (int i = 0; i < listeners.length; i++) {
  217. final IVirtualContentListener listener = (IVirtualContentListener) listeners[i];
  218. if (topIdx < listener.getThreshold(IVirtualContentListener.BUFFER_START))
  219. {
  220. SafeRunner.run(new ISafeRunnable() {
  221. public void run() throws Exception {
  222. listener.handledAtBufferStart();
  223. }
  224. public void handleException(Throwable exception) {
  225. DebugUIPlugin.log(exception);
  226. }
  227. });
  228. }
  229. }
  230. }
  231. protected void notifyListenersAtBufferEnd()
  232. {
  233. Object[] listeners = fVirtualContentListeners.getListeners();
  234. int topIdx = getTable().getTopIndex();
  235. int bottomIdx = topIdx + getNumberOfVisibleLines();
  236. int elementsCnt = getVirtualContentModel().getElements().length;
  237. int numLinesLeft = elementsCnt - bottomIdx;
  238. for (int i = 0; i < listeners.length; i++) {
  239. final IVirtualContentListener listener = (IVirtualContentListener) listeners[i];
  240. if (numLinesLeft <= listener.getThreshold(IVirtualContentListener.BUFFER_END))
  241. {
  242. SafeRunner.run(new ISafeRunnable() {
  243. public void run() throws Exception {
  244. listener.handleAtBufferEnd();
  245. }
  246. public void handleException(Throwable exception) {
  247. DebugUIPlugin.log(exception);
  248. }
  249. });
  250. }
  251. }
  252. }
  253. protected void handleScrollBarSelection()
  254. {
  255. // ignore event if there is pending set top index in the queue
  256. if (!fTopIndexQueue.isEmpty())
  257. return;
  258. topIndexChanged();
  259. }
  260. public void topIndexChanged()
  261. {
  262. if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
  263. {
  264. MemorySegment a = (MemorySegment)getTable().getItem(getTable().getTopIndex()).getData();
  265. System.out.println(Thread.currentThread().getName() + " " + this + " handle scroll bar moved: top index: " + a.getAddress().toString(16)); //$NON-NLS-1$ //$NON-NLS-2$
  266. }
  267. setTopIndexKey(getVirtualContentModel().getKey(getTable().getTopIndex()));
  268. notifyListenersAtBufferStart();
  269. notifyListenersAtBufferEnd();
  270. }
  271. protected void setTopIndexKey(Object key)
  272. {
  273. fTopIndexKey = key;
  274. }
  275. protected Object getTopIndexKey()
  276. {
  277. return fTopIndexKey;
  278. }
  279. protected synchronized void preservingSelection(Runnable updateCode) {
  280. Object oldTopIndexKey = null;
  281. if (fPendingTopIndexKey == null) {
  282. // preserve selection
  283. oldTopIndexKey = getTopIndexKey();
  284. }
  285. else
  286. {
  287. oldTopIndexKey = fPendingTopIndexKey;
  288. }
  289. try {
  290. // perform the update
  291. updateCode.run();
  292. } finally {
  293. if (oldTopIndexKey != null)
  294. {
  295. setTopIndex(oldTopIndexKey);
  296. }
  297. }
  298. }
  299. public void addPresentationErrorListener(IPresentationErrorListener errorListener)
  300. {
  301. fPresentationErrorListeners.add(errorListener);
  302. }
  303. public void removePresentationErrorListener(IPresentationErrorListener errorListener)
  304. {
  305. fPresentationErrorListeners.remove(errorListener);
  306. }
  307. private void notifyPresentationError(final IStatusMonitor monitor, final IStatus status)
  308. {
  309. Object[] listeners = fPresentationErrorListeners.getListeners();
  310. for (int i = 0; i < listeners.length; i++) {
  311. if (listeners[i] instanceof IPresentationErrorListener)
  312. {
  313. final IPresentationErrorListener listener = (IPresentationErrorListener)listeners[i];
  314. SafeRunner.run(new ISafeRunnable() {
  315. public void run() throws Exception {
  316. listener.handlePresentationFailure(monitor, status);
  317. }
  318. public void handleException(Throwable exception) {
  319. DebugUIPlugin.log(exception);
  320. }
  321. });
  322. }
  323. }
  324. }
  325. protected AsynchronousModel createModel() {
  326. return createVirtualContentTableModel();
  327. }
  328. abstract protected AbstractVirtualContentTableModel createVirtualContentTableModel();
  329. private void addKeyToQueue(Object topIndexKey)
  330. {
  331. synchronized(fTopIndexQueue){
  332. if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
  333. System.out.println(" >>> add to top index queue: " + ((BigInteger)topIndexKey).toString(16)); //$NON-NLS-1$
  334. fTopIndexQueue.add(topIndexKey);
  335. }
  336. }
  337. private void removeKeyFromQueue(Object topIndexKey)
  338. {
  339. synchronized(fTopIndexQueue){
  340. if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
  341. System.out.println(" >>> remove frome top index queue: " + ((BigInteger)topIndexKey).toString(16)); //$NON-NLS-1$
  342. fTopIndexQueue.remove(topIndexKey);
  343. }
  344. }
  345. public AbstractVirtualContentTableModel getVirtualContentModel()
  346. {
  347. if (getModel() instanceof AbstractVirtualContentTableModel)
  348. return (AbstractVirtualContentTableModel) getModel();
  349. return null;
  350. }
  351. private int getNumberOfVisibleLines()
  352. {
  353. Table table = getTable();
  354. int height = table.getSize().y;
  355. // when table is not yet created, height is zero
  356. if (height == 0)
  357. {
  358. // make use of the table viewer to estimate table size
  359. height = table.getParent().getSize().y;
  360. }
  361. // height of border
  362. int border = table.getHeaderHeight();
  363. // height of scroll bar
  364. int scroll = table.getHorizontalBar().getSize().y;
  365. // height of table is table's area minus border and scroll bar height
  366. height = height-border-scroll;
  367. // calculate number of visible lines
  368. int lineHeight = getMinTableItemHeight(table);
  369. int numberOfLines = height/lineHeight;
  370. if (numberOfLines <= 0)
  371. return 20;
  372. return numberOfLines;
  373. }
  374. private int getMinTableItemHeight(Table table){
  375. // Hack to get around Linux GTK problem.
  376. // On Linux GTK, table items have variable item height as
  377. // carriage returns are actually shown in a cell. Some rows will be
  378. // taller than others. When calculating number of visible lines, we
  379. // need to find the smallest table item height. Otherwise, the rendering
  380. // underestimates the number of visible lines. As a result the rendering
  381. // will not be able to get more memory as needed.
  382. if (MemoryViewUtil.isLinuxGTK())
  383. {
  384. // check each of the items and find the minimum
  385. TableItem[] items = table.getItems();
  386. int minHeight = table.getItemHeight();
  387. for (int i=0; i<items.length; i++)
  388. {
  389. if (items[i].getData() != null)
  390. minHeight = Math.min(items[i].getBounds(0).height, minHeight);
  391. }
  392. return minHeight;
  393. }
  394. return table.getItemHeight();
  395. }
  396. protected void updateComplete(IStatusMonitor monitor) {
  397. super.updateComplete(monitor);
  398. attemptSetTopIndex();
  399. if (monitor instanceof ILabelRequestMonitor)
  400. {
  401. fPendingResizeColumns = attemptResizeColumnsToPreferredSize();
  402. }
  403. }
  404. protected boolean hasPendingSetTopIndex()
  405. {
  406. return !fTopIndexQueue.isEmpty();
  407. }
  408. }