KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > debug > internal > ui > views > memory > renderings > AsyncVirtualContentTableViewer


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
12 package org.eclipse.debug.internal.ui.views.memory.renderings;
13
14 import java.math.BigInteger JavaDoc;
15 import java.util.ArrayList JavaDoc;
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 JavaDoc fPendingTopIndexKey;
43     private ArrayList JavaDoc fTopIndexQueue = new ArrayList JavaDoc();
44     
45     private boolean fPendingResizeColumns;
46     private ListenerList fVirtualContentListeners;
47     private SelectionListener fScrollSelectionListener;
48     private ListenerList fPresentationErrorListeners;
49     private Object JavaDoc 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 JavaDoc key)
71     {
72         fPendingTopIndexKey = key;
73         attemptSetTopIndex();
74     }
75     
76     protected Object JavaDoc 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         // clean up old columns
88
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         // clean up old cell editors
99
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     /**
111      * Resize column to the preferred size.
112      */

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"){ //$NON-NLS-1$
124

125                     public IStatus runInUIThread(IProgressMonitor monitor) {
126                         Table table = getTable();
127                         
128                         if (!table.isDisposed())
129                         {
130                             // if table size is zero, the rendering has not been made visible
131
// cannot pack until the rendering is visible
132
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     /**
156      * Attempts to update any pending setTopIndex
157      *
158      * @param reveal whether to reveal the selection
159      */

160     protected synchronized void attemptSetTopIndex() {
161         if (fPendingTopIndexKey != null) {
162             Object JavaDoc remaining = doAttemptSetTopIndex(fPendingTopIndexKey);
163             if (remaining == null)
164             {
165                 fPendingTopIndexKey = remaining;
166             }
167         }
168     }
169     
170     private synchronized Object JavaDoc doAttemptSetTopIndex(final Object JavaDoc topIndexKey)
171     {
172         final int i = getVirtualContentModel().indexOfKey(topIndexKey);
173         if (i >= 0)
174         {
175             UIJob job = new UIJob("set top index"){ //$NON-NLS-1$
176

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 JavaDoc)topIndexKey).toString(16)); //$NON-NLS-1$
189
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 JavaDoc)topIndexKey).toString(16)); //$NON-NLS-1$
198

199                                 // only retry if we have pending updates
200
if (hasPendingUpdates())
201                                 {
202                                     if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
203                                         System.out.println(">>> Retry top index: " + ((BigInteger JavaDoc)topIndexKey).toString(16)); //$NON-NLS-1$
204

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); //$NON-NLS-1$
213
fPendingTopIndexKey = topIndexKey;
214                         }
215                         
216                         // remove the top index key from queue when it is processed
217
removeKeyFromQueue(topIndexKey);
218                         
219                     return Status.OK_STATUS;
220                 }};
221                 
222             // set top index does not happen immediately, keep track of
223
// all pending set top index
224
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 JavaDoc[] 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 JavaDoc {
259                         listener.handledAtBufferStart();
260                     }
261                     public void handleException(Throwable JavaDoc exception) {
262                         DebugUIPlugin.log(exception);
263                     }
264                 });
265             }
266         }
267      }
268      
269      protected void notifyListenersAtBufferEnd()
270      {
271         Object JavaDoc[] 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 JavaDoc {
283                         listener.handleAtBufferEnd();
284                     }
285                     public void handleException(Throwable JavaDoc exception) {
286                         DebugUIPlugin.log(exception);
287                     }
288                 });
289             }
290         }
291      }
292      
293     protected void handleScrollBarSelection()
294     {
295 // ignore event if there is pending set top index in the queue
296
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)); //$NON-NLS-1$ //$NON-NLS-2$
307
}
308
309         setTopIndexKey(getVirtualContentModel().getKey(getTable().getTopIndex()));
310
311         notifyListenersAtBufferStart();
312         notifyListenersAtBufferEnd();
313     }
314     
315     protected void setTopIndexKey(Object JavaDoc key)
316     {
317         fTopIndexKey = key;
318     }
319     
320     protected Object JavaDoc getTopIndexKey()
321     {
322         return fTopIndexKey;
323     }
324
325     protected synchronized void preservingSelection(Runnable JavaDoc updateCode) {
326         Object JavaDoc oldTopIndexKey = null;
327         if (fPendingTopIndexKey == null) {
328             // preserve selection
329
oldTopIndexKey = getTopIndexKey();
330         }
331         else
332         {
333             oldTopIndexKey = fPendingTopIndexKey;
334         }
335         
336         try {
337
338             // perform the update
339
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 JavaDoc[] 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 JavaDoc {
370                         listener.handlePresentationFailure(monitor, status);
371                     }
372                     public void handleException(Throwable JavaDoc 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 JavaDoc topIndexKey)
387     {
388         synchronized(fTopIndexQueue){
389             if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
390                 System.out.println(" >>> add to top index queue: " + ((BigInteger JavaDoc)topIndexKey).toString(16)); //$NON-NLS-1$
391
fTopIndexQueue.add(topIndexKey);
392         }
393     }
394     
395     private void removeKeyFromQueue(Object JavaDoc topIndexKey)
396     {
397         synchronized(fTopIndexQueue){
398             if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
399                 System.out.println(" >>> remove frome top index queue: " + ((BigInteger JavaDoc)topIndexKey).toString(16)); //$NON-NLS-1$
400
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         // when table is not yet created, height is zero
417
if (height == 0)
418         {
419             // make use of the table viewer to estimate table size
420
height = table.getParent().getSize().y;
421         }
422         
423         // height of border
424
int border = table.getHeaderHeight();
425         
426         // height of scroll bar
427
int scroll = table.getHorizontalBar().getSize().y;
428
429         // height of table is table's area minus border and scroll bar height
430
height = height-border-scroll;
431
432         // calculate number of visible lines
433
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         // Hack to get around Linux GTK problem.
446
// On Linux GTK, table items have variable item height as
447
// carriage returns are actually shown in a cell. Some rows will be
448
// taller than others. When calculating number of visible lines, we
449
// need to find the smallest table item height. Otherwise, the rendering
450
// underestimates the number of visible lines. As a result the rendering
451
// will not be able to get more memory as needed.
452
if (MemoryViewUtil.isLinuxGTK())
453         {
454             // check each of the items and find the minimum
455
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