Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: c0ce888e60899caf1586178c791ff6249f5134b3 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
                                                                                
                                                       








                                                                                 
                                                         


                            
                           
                          
 



                                                    



                                                 
                                                     









                                                                           


                                                                                     
                                                                              
                                                                 

                                                                                              

                                                                                            






                                                                                                 
                                                                                  








                                                                                             




                                                                 
                                                             

                                                                          
                                                        



                                                              
                                            
                                          
                                                  













                                                           
                                                    



                                                       
                                       
                                         

                                              

                                         

                                                

                                            






                                               
                                      


                                         
                                     
                                     
                                        
                                    



                                           
                                    
                                 

                                                

                                               




                                                   





































                                                                                                      

                                                                                                                                                     

















                                                                                                                

                                                                                                                                               

                                                                                                                 
        




                                                                                                

                                                              
        

                                           

                                                                                           















                                                                                                           







                                                                                 
























                                                                                                                                                        
                                                                                 














                                                                                                                                                       
                                                                                 




                                                                                             










                                                                                         
























                                                                        



                                                        


                                                    




















                                                                                          



























                                                                                                                                  



                                                       
                                                                   
                                     
                                                                   





                                                    

                                         

                                                           












                                                                           


                                                     


                                                 



                                                    


                                                                   
                                                              
        



                                                     

                                                                                     



                                                                            
                                                                                   




                                                                                      
                                                                                            





                                                                                      
                                                                                                




                                                                     

                                                                                        













                                                                                                             
                                                                                







                                                                                         


                                           



                                                                              
                                                                           










                                                                                    
                                                                         







                                                                                    
























                                                                                     


                                                                                                          
                                                                                               


                                                         





                                                                  



                                                                



                                                                                       
                                                            
                                                                                    
                                         
                                                       
                                                      


                                                                


                                                        
                



                                                           
                


                                 



                                                  











                                                                           


                        

                                                              






                                                                                                                        


                                                                         
                                                                       





                                                                                                   
                                                      


                                                                    







                                                                                                                              

                                                                                                      
                                





                                                                                                                              

                                                                           
                                                                                                       






                                                                                                                              

                                                                                                    

                                                                                                        


                                                                                

                                                                                                                                                                                                                                    
 




                                                                                                 



                                                                                                                                                            

                                                                                              
                                                                                                                                          



                                                                                        
                                                                                              
                                                











                                                                                                                            


                                                                                            
                                                



                                                                                                                             

                                                                                            

                                                  
                                                                     
                                                                                                        












                                                                                                                                             
                                                            






                                                                                                        
                                                                                                  

                                                                                                       



                                                                                                         



                                                                                                                                           








                                                                                                                            

                                                                




                                                                              
                                                                                            
                                                                                                                                                        
                                                



                                                                        




                                                        


                               


                                                                
                                                                                    
           


                                                                                    
                                     
                 

                                                                               




                                                                                               


                                                                                          

                 


                                                                     


                                           











                                                                  

                                                        
                                                                                                                                         
























                                                                                                                         
                                                                   





                                                                                                   
                                                                      







                                                                                













































                                                                                                                                                        
                                                                                                                                      



















































































                                                                                                                           


                                                                         
                                     
                                             

         


                                                                                                                         
                                                               


                                





                                                                                                                  
                                                                




                                                  

                                                                                
                                                                                                           

                                                    









                                                                                                                

                                                                              

                                                        

                                                                
                               
                 
                
                
                                                                                     


                                                                                                         


                                         
                                                            



                               









                                                                                                                    







                                                                                                           

                                                                                                                                                                



















                                                                                             
                                                                                                                              


                                                                  
                                                                                                                        


                                                                       
                                                                                                                        


                                                                    
                                                                                                                              






                                                                                                                                   






                                                          
                                                        

                                                         

                
















                                                                                                
                                                                                                                   


                                                                                          
                                                                                                                        



                                                                                       
                                                                                                                                   


                                                                                     
                                                                                                                              






                                                                                                                                   



                                                                                                                                                        

         



                                                                       


                                                                         
                                                                    



                                        










                                                                           











                                                                          







                                                            

                                                                                             

                                                           
                                                                                                    







                                                           
                                                                                                




                                    


















                                                                                            
                                                                     
         


                                                                


                                                                         
                                                
                                                                                           


                                                                      




                                                                                              
                                 
                                                                   

                         
                
                                        

         




















                                                                                                                           















                                                                                                   
                                                                                                                  





































                                                                                                                                              
                                                                                                               
































                                                                                                                                              
                                                                                  
           
                                                                                 
















































































































                                                                                                                                                          
 













































                                                                                 




                                 














                                                                                                
                                 



















                                                                                         

                                                                                                      
















                                                                                             

                                                       
           
                                                        
         


                                                        





















                                                                         




                                                       









                                                    

                                                         

























                                                                                                 
                                                                                                          
                

                                                                    
                                                     

                                       



                                      
                                                                               
                                                                                                         


                                                                                               
                 
                                                     


                                                                                
                                                                                                                                     









                                                                                    
                                                                           
                                                                                                     
                

                                                                                               
                 

                                                                     


                                                                              
                                                                                                                                 















                                                                                









                                                                                                







                                                                                              




























































                                                                                               









                                                                                        
           


                                                
   










                                                                                     

                     


                                                      
         
        


                                                                             




                                

                                   

                                  






                                             




























                                                                                                                      
                                                                         

                                                                




                                                                                                                                                                  
                                                   








































                                                                                                                                          



                                               




                                                                               
                                                          




                              


                                                                                   








































                                                                                                   


                                                                     















                                                                  
                                            


                                        
                                                                                               
                                                                          

                                                                             
                                                                                             














                                                                                                                                  




                                                                    
















                                                                                   


                                                 

                                                                                               
                
                                  
                 



                                                                                          
                




















                                                                                                                       








                                                                                


                                                 

                                                          
                 
                                                                                             
                 
                    
                                                
                

         




                                                                         
                                                        
           

                                                                           



                                                                                  

                           
                        

                                                                         
                                                                     















                                                                                                                

                                                                                   










                                                                                                                
        
                                              
                                                           

                                             










                                                                        



                                                                         



                                       



                                               

                                                            

                                          









                                                                                        







                                            


                                                                                
                                                        


















                                                                                         






                                                    



                                                                

                                                  
                                                                
                
                                          

                                                 
                                                                                          



                                                  
                                                                           











                                                          
                                                                      

                 
                                                                                











                                                                                                                                             









                                                                                                                                                          












                                                                                             

                                                                                              
                                                                                                  

                                        


                                                                                  











                                                                                                                                            
                                                          



















                                                                  
                                                        



















                                                                         

                                                                        









                                                                    
                                                                           







                                                                                         
                                                           
                                                        

                                                    


                                                                         
                                                                       
                                          










                                                                 

                                                              




                                            
                                                            


                    



                                                                 


                                                                            
                                                
                                                                                      
                                                                                
                                      


                                                                      







                                                                             
                 


                                                                                                          
                                               
                               
                 










                                                        






























                                                                                                             
                                 
                                                                                             







                                                                                                             


                            





                                                                                         




                                                                                                           
                         

                                    
                                  

                 
                                           



                                                                         

                                                                












                                                                                      
































                                                                 


                                                                  
                                
                                                            




                                





                                                                     
                                                                                                                                                










                                                
                                                                                                                                                         










                                                
                                                                                                                                                          










                                                               
                                                                                                                                           


















                                                                                                                                                

                                                                              














                                                                                         

                                                                              














                                                                                         

                                                                            














                                                                                       

                                                                                 


























































































































                                                                                                                            









                                                                                                                             








                                                                                                 

                                          
                                                                      













                                                                                                  
                                                                                 


                                                                                                                             

                                                 

































































































                                                                                                                                                

                                                                                    
                                 

                                                                                                                                                      


                                    
                                                                                                                 



















                                                                         
                                                                                               








                                                            



                                                                                                           

                                                                      




                                                                      
                                      




















                                                                                                                            
                                      




                                                                     





















                                                                                                          
                
                                       
         





                                                                      






































                                                                                                         




                                                                        















                                                                                   

                                                             






                                      

                                                                                                                                                    






                                                                                                         
                                                                                          
                 

         

                                  

                                  




















                                                                                                               
                        





                                                                                                                   
                         



                                                      
 















                                                                                                              
                         














                                                                                           
                 

         
                                   

                                   








                                                                                                              





                                                                                  






                                                                            




                                     




























                                                                                                                                 
 
/*******************************************************************************
 * Copyright (c) 2006, 2007 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.debug.internal.ui.memory.provisional;


import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Iterator;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IMemoryBlock;
import org.eclipse.debug.core.model.IMemoryBlockExtension;
import org.eclipse.debug.core.model.MemoryByte;
import org.eclipse.debug.internal.ui.DebugUIMessages;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
import org.eclipse.debug.internal.ui.memory.IPersistableDebugElement;
import org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IStatusMonitor;
import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil;
import org.eclipse.debug.internal.ui.views.memory.renderings.AbstractBaseTableRendering;
import org.eclipse.debug.internal.ui.views.memory.renderings.AbstractVirtualContentTableModel;
import org.eclipse.debug.internal.ui.views.memory.renderings.AsyncCopyTableRenderingAction;
import org.eclipse.debug.internal.ui.views.memory.renderings.AsyncPrintTableRenderingAction;
import org.eclipse.debug.internal.ui.views.memory.renderings.AsyncTableRenderingCellModifier;
import org.eclipse.debug.internal.ui.views.memory.renderings.AsyncTableRenderingViewer;
import org.eclipse.debug.internal.ui.views.memory.renderings.AsyncVirtualContentTableViewer;
import org.eclipse.debug.internal.ui.views.memory.renderings.CopyTableRenderingToClipboardAction;
import org.eclipse.debug.internal.ui.views.memory.renderings.FormatTableRenderingAction;
import org.eclipse.debug.internal.ui.views.memory.renderings.FormatTableRenderingDialog;
import org.eclipse.debug.internal.ui.views.memory.renderings.GoToAddressAction;
import org.eclipse.debug.internal.ui.views.memory.renderings.GoToAddressComposite;
import org.eclipse.debug.internal.ui.views.memory.renderings.IPresentationErrorListener;
import org.eclipse.debug.internal.ui.views.memory.renderings.IVirtualContentListener;
import org.eclipse.debug.internal.ui.views.memory.renderings.MemorySegment;
import org.eclipse.debug.internal.ui.views.memory.renderings.PendingPropertyChanges;
import org.eclipse.debug.internal.ui.views.memory.renderings.PrintTableRenderingAction;
import org.eclipse.debug.internal.ui.views.memory.renderings.ReformatAction;
import org.eclipse.debug.internal.ui.views.memory.renderings.ResetToBaseAddressAction;
import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingContentDescriptor;
import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingLine;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.memory.AbstractTableRendering;
import org.eclipse.debug.ui.memory.IMemoryBlockTablePresentation;
import org.eclipse.debug.ui.memory.IMemoryRendering;
import org.eclipse.debug.ui.memory.IMemoryRenderingContainer;
import org.eclipse.debug.ui.memory.IMemoryRenderingSite;
import org.eclipse.debug.ui.memory.IMemoryRenderingSynchronizationService;
import org.eclipse.debug.ui.memory.IMemoryRenderingType;
import org.eclipse.debug.ui.memory.IResettableMemoryRendering;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.IBasicPropertyConstants;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.IFontProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.dialogs.PropertyDialogAction;
import org.eclipse.ui.model.IWorkbenchAdapter;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.progress.UIJob;

/**
 * Abstract implementation of a table rendering.
 * <p>
 * Clients should subclass from this class if they wish to provide a
 * table rendering.
 * </p>
 * <p>
 *
 * The label of the rendering is constructed by retrieving the expression from
 * <code>IMemoryBlockExtension</code>.  For IMemoryBlock, the label is constructed
 * using the memory block's start address.
 * 
 * This rendering manages the change states of its memory bytes if the memory
 * block does not opt to manage the change states.  For IMemoryBlockExtension, if
 * the memory block returns false when #supportsChangeManagement() is called, this
 * rendering will calculate the change state for each byte when its content is updated.
 * Clients may manages the change states of its memory block by returning true when
 * #supportsChangeManagement() is called.  This will cause this rendering to stop
 * calculating the change states of the memory block.  Instead it would rely on the
 * attributes returned in the MemoryByte array to determine if a byte has changed.
 * For IMemoryBlock, this rendering will manage the change states its content.   
 * 
 *  When firing change event, be aware of the following:
 *  - whenever a change event is fired, the content provider for Memory View
 *    view checks to see if memory has actually changed.  
 *  - If memory has actually changed, a refresh will commence.  Changes to the memory block
 *    will be computed and will be shown with the delta icons.
 *  - If memory has not changed, content will not be refreshed.  However, previous delta information 
 * 	  will be erased.  The screen will be refreshed to show that no memory has been changed.  (All
 *    delta icons will be removed.)
 *    
 * Please note that these APIs will be called multiple times by the Memory View.
 * To improve performance, debug adapters need to cache the content of its memory block and only
 * retrieve updated data when necessary.
 * </p>

 * @since 3.2
 */
public abstract class AbstractAsyncTableRendering extends AbstractBaseTableRendering implements IPropertyChangeListener, IResettableMemoryRendering {

	/**
	 *  Property identifier for the selected address in a table rendering
	 *  This property is used for synchronization between renderings.
	 */
	public static final String PROPERTY_SELECTED_ADDRESS = AbstractTableRendering.PROPERTY_SELECTED_ADDRESS;
	
	/**
	 * Property identifier for the column size in a table rendering
	 * This property is used for synchronization between renderings.
	 */
	public static final String PROPERTY_COL_SIZE = AbstractTableRendering.PROPERTY_COL_SIZE;
	
	/**
	 * Property identifier for the top row address in a table rendering. 
	 * This property is used for synchronization between renderings.
	 */
	public static final String PROPERTY_TOP_ADDRESS = AbstractTableRendering.PROPERTY_TOP_ADDRESS;
	
	private static final String ID_ASYNC_TABLE_RENDERING_CONTEXT = "org.eclipse.debug.ui.memory.abstractasynctablerendering"; //$NON-NLS-1$
	private static final String ID_GO_TO_ADDRESS_COMMAND = "org.eclipse.debug.ui.command.gotoaddress"; //$NON-NLS-1$
	private static final String ID_NEXT_PAGE_COMMAND = "org.eclipse.debug.ui.command.nextpage"; //$NON-NLS-1$
	private static final String ID_PREV_PAGE_COMMAND = "org.eclipse.debug.ui.command.prevpage"; //$NON-NLS-1$
	
	/**
	 * Property identifier for the row size in a table rendering
	 * This property is used for synchronization between renderings.
	 */
	public static final String PROPERTY_ROW_SIZE = AbstractTableRendering.PROPERTY_ROW_SIZE;

	private static final int DEFAULT_BUFFER_THRESHOLD = 1;
	
	private boolean fActivated = false;
	
//	TODO:  review use of MemorySegment, need to be careful to ensure flexible hierarchy
	
	private class ToggleAddressColumnAction extends Action {

		public ToggleAddressColumnAction() {
			super();
			PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IDebugUIConstants.PLUGIN_ID
					+ ".ShowAddressColumnAction_context"); //$NON-NLS-1$
			updateActionLabel();
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.jface.action.IAction#run()
		 */
		public void run() {
			fIsShowAddressColumn = !fIsShowAddressColumn;
			if (!fIsShowAddressColumn)
			{
				fTableViewer.getTable().getColumn(0).setWidth(0);
			}
			else
			{
				fTableViewer.getTable().getColumn(0).pack();
			}
			updateActionLabel();
		}

		/**
		 * 
		 */
		private void updateActionLabel() {
			if (fIsShowAddressColumn) {
				setText(DebugUIMessages.ShowAddressColumnAction_0); 
			} else {
				setText(DebugUIMessages.ShowAddressColumnAction_1); 
			}
		}
	}
	
	private class NextPageAction extends Action
	{
		private NextPageAction()
		{
			super();
			setText(DebugUIMessages.AbstractTableRendering_4);
			PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IDebugUIConstants.PLUGIN_ID + ".NextPageAction_context"); //$NON-NLS-1$ 
		}

		public void run() {
			BigInteger address = fContentDescriptor.getLoadAddress();
			address = address.add(BigInteger.valueOf(getPageSizeInUnits()));
			handlePageStartAddressChanged(address);
		}
	}
	
	private class PrevPageAction extends Action
	{
		private PrevPageAction()
		{
			super();
			setText(DebugUIMessages.AbstractTableRendering_6);
			PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IDebugUIConstants.PLUGIN_ID + ".PrevPageAction_context"); //$NON-NLS-1$
		}

		public void run() {
			BigInteger address = fContentDescriptor.getLoadAddress();
			address = address.subtract(BigInteger.valueOf(getPageSizeInUnits()));
			handlePageStartAddressChanged(address);
		}
	}
	
	private class RenderingGoToAddressAction extends GoToAddressAction
	{
		public RenderingGoToAddressAction(AbstractBaseTableRendering rendering) {
			super(rendering);
		}
		
		public void run() {
			showGoToAddressComposite();
		}
	}
	
	private class SwitchPageJob extends UIJob {
		private Object fLock = new Object();
		private boolean fShowMessagePage = false;
		private String fMessage = ""; //$NON-NLS-1$

		private SwitchPageJob() {
			super("SwitchPageJob");//$NON-NLS-1$
			setSystem(true);
		}

		private void setShowMessagePage(boolean showMsg) {
			synchronized(fLock)
			{
				fShowMessagePage = showMsg;
			}
		}

		private void setMessage(String message) {
			synchronized(fLock)
			{
				fMessage = message;
			}
		}

		public IStatus runInUIThread(IProgressMonitor monitor) {
			
			if (fPageBook.isDisposed())
				return Status.OK_STATUS;
			
			String msgToShow = null;
			boolean showMsgPage = false;
			synchronized (fLock) {
				msgToShow = fMessage;
				showMsgPage = fShowMessagePage;
			}
			
			if (showMsgPage) {
				StyledText styleText = null;
				fShowMessage = true;

				styleText = fTextViewer.getTextWidget();

				if (styleText != null)
					styleText.setText(msgToShow);
				fPageBook.showPage(fTextViewer.getControl());
			} else {
				fShowMessage = false;
				fPageBook.showPage(fTableViewer.getControl().getParent());
			}
			return Status.OK_STATUS;
		}
	}
	
	
	private class SerialByObjectRule implements ISchedulingRule
	{
    	private Object fObject = null;
    	
    	public SerialByObjectRule(Object lock) {
    		fObject = lock;
    	}

		/* (non-Javadoc)
		 * @see org.eclipse.core.runtime.jobs.ISchedulingRule#contains(org.eclipse.core.runtime.jobs.ISchedulingRule)
		 */
		public boolean contains(ISchedulingRule rule) {
			return rule == this;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.core.runtime.jobs.ISchedulingRule#isConflicting(org.eclipse.core.runtime.jobs.ISchedulingRule)
		 */
		public boolean isConflicting(ISchedulingRule rule) {
			if (rule instanceof SerialByObjectRule) {
				SerialByObjectRule rRule = (SerialByObjectRule) rule;
				return fObject == rRule.fObject;
			}
			return false;
		}
	}
	
	private PageBook fPageBook;
	private AsyncTableRenderingViewer fTableViewer;
	private TextViewer fTextViewer;
	private Shell fToolTipShell;
	private MemoryViewPresentationContext fPresentationContext;
	private int fAddressableSize;
	private TableRenderingContentDescriptor fContentDescriptor;
	private int fBytePerLine;
	private int fColumnSize;
	private boolean fShowMessage = false;
	private String fLabel;
	private IWorkbenchAdapter fWorkbenchAdapter;
	private int fPageSize;
	private int fPreBufferSize = -1;
	private int fPostBufferSize = -1;
	private SashForm fSashForm;
	private GoToAddressComposite fGoToAddressComposite;
	
	// actions
	private GoToAddressAction fGoToAddressAction;
	private PrintTableRenderingAction fPrintViewTabAction;
	private CopyTableRenderingToClipboardAction fCopyToClipboardAction;
	private FormatTableRenderingAction fFormatRenderingAction;
	private ReformatAction fReformatAction;
	private ToggleAddressColumnAction fToggleAddressColumnAction;
	private ResetToBaseAddressAction fResetMemoryBlockAction;
	private PropertyDialogAction fPropertiesDialogAction;
	private NextPageAction fNextAction;
	private PrevPageAction fPrevAction;
	
	private ArrayList fContext = new ArrayList();
	private AbstractHandler fGoToAddressHandler;
	
	private AbstractHandler fNextPageHandler;
	private AbstractHandler fPrevPageHandler;
	
	private boolean fIsCreated = false;
	private boolean fIsDisposed = false;
	private boolean fIsShowAddressColumn = true;
	
	private SwitchPageJob fSwitchPageJob = new SwitchPageJob();
	private boolean fError = false;
	
	private PendingPropertyChanges fPendingSyncProperties;
	
	// list of menu listeners for popupMenuMgr.  
	private ArrayList fMenuListeners;
	private MenuManager fMenuMgr;
	
	private ISchedulingRule serialByRenderingRule = new SerialByObjectRule(this);
	
	/** 
	 * Identifier for an empty group preceding all context menu actions 
	 * (value <code>"popUpBegin"</code>).
	 */
	public static final String EMPTY_MEMORY_GROUP = "popUpBegin"; //$NON-NLS-1$
	
	/**
	 * Identifier for an empty group following navigation actions in the rendering
	 * (value <code>navigationGroup</code>).
	 */
	public static final String EMPTY_NAVIGATION_GROUP = "navigationGroup"; //$NON-NLS-1$
	
	/**
	 * Identifier for an empty group following actions that are only applicable in
	 * non-auto loading mode
	 * (value <code>nonAutoLoadGroup</code>).
	 */
	public static final String EMPTY_NON_AUTO_LOAD_GROUP = "nonAutoLoadGroup"; //$NON-NLS-1$
	
	/**
	 * Identifier for an empty group following properties actions
	 * (value <code>propertyGroup</code>).
	 */
	public static final String EMPTY_PROPERTY_GROUP = "propertyGroup"; //$NON-NLS-1$
	
	private ISelectionChangedListener fViewerSelectionChangedListener = new ISelectionChangedListener() {
		public void selectionChanged(SelectionChangedEvent event) {
			updateSyncTopAddress(getTopVisibleAddress());
			updateSyncSelectedAddress(getSelectedAddress());
		}
	};
	
	private SelectionAdapter fScrollBarSelectionListener = new SelectionAdapter() {
		public void widgetSelected(SelectionEvent e) {
			updateSyncTopAddress(getTopVisibleAddress());
		}
	};
	
	private IModelChangedListener fModelChangedListener = new IModelChangedListener() {
		public void modelChanged(IModelDelta delta, IModelProxy proxy) {
			if (delta.getElement() == getMemoryBlock())
			{
				showTable();
				updateRenderingLabel(isVisible());
			}
		}};
	
	private IVirtualContentListener fViewerListener = new IVirtualContentListener() {
		
		private int startThreshold;
		private int endThreshold;

		public void handledAtBufferStart() {
			if (getMemoryBlock() instanceof IMemoryBlockExtension)
			{
				if (isDynamicLoad() && startThreshold != 0)
				{
					BigInteger address = getTopVisibleAddress();
					if (address != null && !isAtTopLimit())
						reloadTable(address);
				}
			}
		}

		public void handleAtBufferEnd() {
			if (getMemoryBlock() instanceof IMemoryBlockExtension)
			{
				if (isDynamicLoad() && endThreshold != 0)
				{
					BigInteger address = getTopVisibleAddress();
					if (address != null && !isAtBottomLimit())
						reloadTable(address);
				}
			}
		}

		public int getThreshold(int bufferEndOrStart) {
			
			int threshold = DEFAULT_BUFFER_THRESHOLD;
			
			if (bufferEndOrStart == IVirtualContentListener.BUFFER_START)
			{
				if (threshold > getPreBufferSize())
				{
					threshold = getPreBufferSize();
				}
			}
			else
			{
				if (threshold > getPostBufferSize())
				{
					threshold = getPostBufferSize();
				}
			}
			
			if (bufferEndOrStart == IVirtualContentListener.BUFFER_START)
				startThreshold = threshold;
			else
				endThreshold = threshold;
			
			return threshold;
		}};
		
	private IPresentationErrorListener fPresentationErrorListener = new IPresentationErrorListener() {
		public void handlePresentationFailure(IStatusMonitor monitor, IStatus status) {
			showMessage(status.getMessage());
		}};
	
	
	/**
	 * Constructs a new table rendering of the specified type.
	 * 
	 * @param renderingId memory rendering type identifier
	 */
	public AbstractAsyncTableRendering(String renderingId) {
		super(renderingId);
	}

	
	/* (non-Javadoc)
	 * @see org.eclipse.debug.ui.memory.IResettableMemoryRendering#resetRendering()
	 */
	public void resetRendering() throws DebugException {
		BigInteger baseAddress = fContentDescriptor.getContentBaseAddress();
		reloadTable(baseAddress);
		fTableViewer.setSelection(baseAddress);
		fTableViewer.setTopIndex(baseAddress);

		updateSyncTopAddress(baseAddress);		
		updateSyncSelectedAddress(baseAddress);
	}

	public Control createControl(Composite parent) {
		
		fPageBook = new PageBook(parent, SWT.NONE);
		createMessagePage(fPageBook);
		createTableViewer(fPageBook);
		addListeners();
		
		return fPageBook;
	}
	
	/**
	 * Create the error page of this rendering
	 * @param parent
	 */
	private void createMessagePage(Composite parent)
	{
		if (fTextViewer == null)
		{
			fTextViewer = new TextViewer(parent, SWT.WRAP);	
			fTextViewer.setDocument(new Document());
			StyledText styleText = fTextViewer.getTextWidget();
			styleText.setEditable(false);
			styleText.setEnabled(false);
		}
	}
	
	/**
	 * @param parent
	 */
	private void createTableViewer(final Composite parent)
	{
		StringBuffer buffer = new StringBuffer();
		IMemoryRenderingType type = DebugUITools.getMemoryRenderingManager().getRenderingType(getRenderingId());
		buffer.append(type.getLabel());
		buffer.append(": "); //$NON-NLS-1$
		buffer.append(DebugUIMessages.AbstractAsyncTableRendering_2);
		
		Job job = new Job(buffer.toString()) {

			protected IStatus run(IProgressMonitor monitor) {
				
				// gather information from memory block
				initAddressableSize();					
				final BigInteger topVisibleAddress = getInitialTopVisibleAddress();
				BigInteger mbBaseAddress = null;
				try {
					mbBaseAddress = getMemoryBlockBaseAddress();
				} catch (DebugException e) {
					fError = true;
					showMessage(e.getMessage());
				}
				
				// if it takes too long to get the base address, and user has canceled
				// remove this rendering.
				if (monitor.isCanceled())
				{
					getMemoryRenderingContainer().removeMemoryRendering(AbstractAsyncTableRendering.this);
					return Status.CANCEL_STATUS;
				}
				
				final BigInteger finalMbBaseAddress = mbBaseAddress;
				final BigInteger initialSelectedAddress = getInitialSelectedAddress();
				
				if (monitor.isCanceled())
				{
					getMemoryRenderingContainer().removeMemoryRendering(AbstractAsyncTableRendering.this);
					return Status.CANCEL_STATUS;
				}
				
				createContentDescriptor(topVisibleAddress);
				
				// if it takes too long to get other information, and user has canceled
				// remove this rendering.
				if (monitor.isCanceled())
				{
					getMemoryRenderingContainer().removeMemoryRendering(AbstractAsyncTableRendering.this);
					return Status.CANCEL_STATUS;
				}
				
				// batch update on UI thread
				UIJob uiJob = new UIJob("Create Table Viewer UI Job"){ //$NON-NLS-1$
					public IStatus runInUIThread(IProgressMonitor progressMonitor) {
						
						if (fPageBook.isDisposed())
							return Status.OK_STATUS;
						
						fSashForm = new SashForm(parent, SWT.VERTICAL);
						fTableViewer = new AsyncTableRenderingViewer(AbstractAsyncTableRendering.this, fSashForm, SWT.VIRTUAL | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.HIDE_SELECTION | SWT.BORDER);

						GridData data = new GridData(GridData.FILL_BOTH);
						fTableViewer.getControl().setLayoutData(data);
						
						createGoToAddressComposite(fSashForm);
						hideGotoAddressComposite();
						
						IMemoryRenderingSite site = getMemoryRenderingContainer().getMemoryRenderingSite();
						IMemoryRenderingContainer container = getMemoryRenderingContainer();
						fPresentationContext = new MemoryViewPresentationContext(site, container, AbstractAsyncTableRendering.this);
						fTableViewer.setContext(fPresentationContext);
						
						// must call this after the context is created as the information is stored in the context
						getDynamicLoadFromPreference();
						getPageSizeFromPreference();
						
						int numberOfLines = getNumLinesToLoad();
						fContentDescriptor.setNumLines(numberOfLines);
						
						if (numberOfLines == 0)
						{
							// if the table viewer is not initialized yet, add listener
							// and load table when we can get the height of the table
							fTableViewer.getTable().addPaintListener(new PaintListener() {
								public void paintControl(PaintEvent e) {
									fTableViewer.getTable().removePaintListener(this);
									fContentDescriptor.setNumLines(getNumLinesToLoad());
									refresh();
								}});
						}
						
						BigInteger baseAddress = finalMbBaseAddress;
						if (baseAddress == null)
							baseAddress = BigInteger.ZERO;
						
						if (!(getMemoryBlock() instanceof IMemoryBlockExtension) || !isDynamicLoad())
						{		
							// If not extended memory block, do not create any buffer
							// no scrolling
							fContentDescriptor.setPreBuffer(0);
							fContentDescriptor.setPostBuffer(0);
						} 
						
						setupInitialFormat();
						fTableViewer.setCellModifier(newInternalCellModifier());
						fTableViewer.getTable().setHeaderVisible(true);
						fTableViewer.getTable().setLinesVisible(true);	
						fTableViewer.addPresentationErrorListener(fPresentationErrorListener);
						fTableViewer.setInput(getMemoryBlock());
						fTableViewer.resizeColumnsToPreferredSize();
						fTableViewer.setTopIndex(topVisibleAddress);
						
						fTableViewer.setSelection(initialSelectedAddress);

						// SET UP FONT		
						// set to a non-proportional font
						fTableViewer.getTable().setFont(JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME));
						
						if (!fError)
							showTable();
						
						fTableViewer.addVirtualContentListener(fViewerListener);
						
						// create context menu
						// create pop up menu for the rendering
						createActions();
						IMenuListener menuListener = new IMenuListener() {
							public void menuAboutToShow(IMenuManager mgr) {
								fillContextMenu(mgr);
							}
						};
						createPopupMenu(fTableViewer.getControl(), menuListener);
						createPopupMenu(fTableViewer.getCursor(), menuListener);
						
						fTableViewer.addSelectionChangedListener(fViewerSelectionChangedListener);
						fTableViewer.getTable().getVerticalBar().addSelectionListener(fScrollBarSelectionListener);
						
						// add resize listener to figure out number of visible lines 
						// so that the viewer get refreshed with the correct number of lines on the
						// next refresh request
						fTableViewer.getTable().addListener(SWT.Resize, new Listener() {
							public void handleEvent(Event event) {
								if (!fTableViewer.getTable().isDisposed())
									fContentDescriptor.setNumLines(getNumLinesToLoad());
							}});
						
						createToolTip();
						
						if (isActivated())
						{
							activatePageActions();
						}
						
						// now the rendering is successfully created
						fIsCreated = true;											
						
						return Status.OK_STATUS;
					}};
				uiJob.setSystem(true);
				uiJob.schedule();
					
				return Status.OK_STATUS;

			}};
			
		job.schedule();
	}
	
	/**
	 * Create popup menu for this rendering
	 * @param control - control to create the popup menu for
	 * @param menuListener - listener to notify when popup menu is about to show
	 */
	private void createPopupMenu(Control control, IMenuListener menuListener)
	{
		IMemoryRenderingContainer container = getMemoryRenderingContainer();
		if (fMenuMgr == null)
		{
			fMenuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
			fMenuMgr.setRemoveAllWhenShown(true);
			IMemoryRenderingSite site = container.getMemoryRenderingSite();
			String menuId = container.getId();
						
			ISelectionProvider selProvider = site.getSite().getSelectionProvider();
			
			addMenuListener(menuListener);

			site.getSite().registerContextMenu(menuId, fMenuMgr, selProvider);
		}
		
		addMenuListener(menuListener);
		
		Menu popupMenu = fMenuMgr.createContextMenu(control);
		control.setMenu(popupMenu);
	}


	private void addMenuListener(IMenuListener menuListener) {
		if (fMenuListeners == null)
			fMenuListeners = new ArrayList();
		
		if (!fMenuListeners.contains(menuListener))
		{
			fMenuMgr.addMenuListener(menuListener);
			fMenuListeners.add(menuListener);
		}
	}

	private BigInteger getInitialSelectedAddress() {
		// figure out selected address 
		BigInteger selectedAddress = (BigInteger) getSynchronizedProperty(AbstractAsyncTableRendering.PROPERTY_SELECTED_ADDRESS);
		if (selectedAddress == null)
		{
			if (getMemoryBlock() instanceof IMemoryBlockExtension) {
				try {
					selectedAddress = ((IMemoryBlockExtension) getMemoryBlock()).getBigBaseAddress();
				} catch (DebugException e) {
					selectedAddress = BigInteger.ZERO;
				}
				
				if (selectedAddress == null) {
					selectedAddress =BigInteger.ZERO;
				}

			} else {
				long address = getMemoryBlock().getStartAddress();
				selectedAddress = BigInteger.valueOf(address);
			}
		}
		return selectedAddress;
	}
	
	private void addListeners()
	{
		DebugUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this);
		addRenderingToSyncService();
		JFaceResources.getFontRegistry().addListener(this);
	}
	
	private void removeListeners()
	{
		DebugUIPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this);
		removeRenderingFromSyncService();
		JFaceResources.getFontRegistry().removeListener(this);
		
		Iterator iter = fMenuListeners.iterator();
		while (iter.hasNext())
		{
			fMenuMgr.removeMenuListener((IMenuListener)iter.next());
		}
		
		fMenuListeners.clear();
	}
	
	private void addRenderingToSyncService()
	{	
		IMemoryRenderingSynchronizationService syncService = getMemoryRenderingContainer().getMemoryRenderingSite().getSynchronizationService();
		
		if (syncService == null)
			return;
		
		syncService.addPropertyChangeListener(this, null);
	}
	
	private void removeRenderingFromSyncService()
	{
		IMemoryRenderingSynchronizationService syncService = getMemoryRenderingContainer().getMemoryRenderingSite().getSynchronizationService();
		
		if (syncService == null)
			return;
		
		syncService.removePropertyChangeListener(this);		
	}
	
	private void initAddressableSize()
	{
		// set up addressable size and figure out number of bytes required per line
		fAddressableSize = -1;
		try {
			if (getMemoryBlock() instanceof IMemoryBlockExtension)
				fAddressableSize = ((IMemoryBlockExtension)getMemoryBlock()).getAddressableSize();
			else
				fAddressableSize = 1;
		} catch (DebugException e1) {
			DebugUIPlugin.log(e1);
			// log error and default to 1
			fAddressableSize = 1;
			return;
			
		}
		if (fAddressableSize < 1)
		{
			DebugUIPlugin.logErrorMessage("Invalid addressable size"); //$NON-NLS-1$
			fAddressableSize = 1;
		}
	}
	
	private BigInteger getInitialTopVisibleAddress() {
		BigInteger topVisibleAddress = (BigInteger) getSynchronizedProperty(AbstractAsyncTableRendering.PROPERTY_TOP_ADDRESS);
		if (topVisibleAddress == null)
		{
			if (getMemoryBlock() instanceof IMemoryBlockExtension)
			{
				try {
					topVisibleAddress = ((IMemoryBlockExtension)getMemoryBlock()).getBigBaseAddress();
				} catch (DebugException e1) {
					topVisibleAddress = new BigInteger("0"); //$NON-NLS-1$
				}
			}
			else
			{
				topVisibleAddress = BigInteger.valueOf(getMemoryBlock().getStartAddress());
			}
		}
		return topVisibleAddress;
	}
	
	private void setupInitialFormat() {
		
		boolean validated = validateInitialFormat();
		
		if (!validated)
		{
			// pop up dialog to ask user for default values
			StringBuffer msgBuffer = new StringBuffer(DebugUIMessages.AbstractTableRendering_20);
			msgBuffer.append(" "); //$NON-NLS-1$
			msgBuffer.append(this.getLabel());
			msgBuffer.append("\n\n"); //$NON-NLS-1$
			msgBuffer.append(DebugUIMessages.AbstractTableRendering_16);
			msgBuffer.append("\n"); //$NON-NLS-1$
			msgBuffer.append(DebugUIMessages.AbstractTableRendering_18);
			msgBuffer.append("\n\n"); //$NON-NLS-1$
			
			int bytePerLine = fBytePerLine;
			int columnSize = fColumnSize;
			
			// initialize this value to populate the dialog properly
			fBytePerLine = getDefaultRowSize() / getAddressableSize();
			fColumnSize = getDefaultColumnSize() / getAddressableSize();

			FormatTableRenderingDialog dialog = new FormatTableRenderingDialog(this, DebugUIPlugin.getShell());
			dialog.openError(msgBuffer.toString());
			
			// restore to original value before formatting
			fBytePerLine = bytePerLine;
			fColumnSize = columnSize;
			
			bytePerLine = dialog.getRowSize() * getAddressableSize();
			columnSize = dialog.getColumnSize() * getAddressableSize();
			
			format(bytePerLine, columnSize);
		}
		else
		{
			// Row size is stored as number of addressable units in preference store
			int bytePerLine = getDefaultRowSize();
			// column size is now stored as number of addressable units
			int columnSize = getDefaultColumnSize();
			
			// format memory block with specified "bytesPerLine" and "columnSize"	
			boolean ok = format(bytePerLine, columnSize);
			
			if (!ok)
			{
				// this is to ensure that the rest of the rendering can be created
				// and we can recover from a format error
				format(bytePerLine, bytePerLine);
			}
		}
	}
	
	private boolean validateInitialFormat()
	{
		int rowSize = getDefaultRowSize();
		int columnSize = getDefaultColumnSize();
		
		if (rowSize < columnSize || rowSize % columnSize != 0 || rowSize == 0 || columnSize == 0)
		{
			return false;
		}
		return true;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.ui.memory.IMemoryRendering#getControl()
	 */
	public Control getControl() {
		return fPageBook.getParent();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
	 */
	public void propertyChange(PropertyChangeEvent event) {
		if (!fIsCreated)
			return;
		
		// if memory view table font has changed
		if (event.getProperty().equals(IInternalDebugUIConstants.FONT_NAME))
		{
			if (!fIsDisposed)
			{			
				Font memoryViewFont = JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME);
				setFont(memoryViewFont);	
			}
			return;
		}
		
		Object evtSrc = event.getSource();

		// always update page size, only refresh if the table is visible
		if (event.getProperty().equals(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PAGE_SIZE)) {
			getPageSizeFromPreference();
		}
		if (event.getProperty().equals(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PRE_BUFFER_SIZE))
		{
			getPreBufferSizeFromPreference();
			fContentDescriptor.setPreBuffer(getPreBufferSize());
		}
		if (event.getProperty().equals(IDebugPreferenceConstants.PREF_TABLE_RENDERING_POST_BUFFER_SIZE))
		{
			getPostBufferSizeFromPreference();
			fContentDescriptor.setPostBuffer(getPostBufferSize());	
		}
		
		// do not handle event if the rendering is displaying an error
		// or if it's not visible
		if (isDisplayingError() || !isVisible())
		{
			handlePropertiesChangeWhenHidden(event);
			return;
		}
		
		
		if (event.getProperty().equals(IDebugUIConstants.PREF_PADDED_STR) || 
			event.getProperty().equals(IDebugUIConstants.PREF_CHANGED_DEBUG_ELEMENT_COLOR) ||
			event.getProperty().equals(IDebugUIConstants.PREF_MEMORY_HISTORY_KNOWN_COLOR) ||
			event.getProperty().equals(IDebugUIConstants.PREF_MEMORY_HISTORY_UNKNOWN_COLOR))
		{
			if (!fIsDisposed)
			{
				fTableViewer.refresh(false);
			}
			return;
		}
		
		if (event.getProperty().equals(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PRE_BUFFER_SIZE) ||
			event.getProperty().equals(IDebugPreferenceConstants.PREF_TABLE_RENDERING_POST_BUFFER_SIZE))
		{
			if (!fIsDisposed)
			{
				fTableViewer.refresh(true);
			}
			return;
		}
		
		if (event.getProperty().equals(IDebugPreferenceConstants.PREF_DYNAMIC_LOAD_MEM)) {
			handleDyanicLoadChanged();
			return;
		}
		
		if (event.getProperty().equals(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PAGE_SIZE)) {
			if (!isDynamicLoad())
			{
				int pageSize = DebugUIPlugin.getDefault().getPreferenceStore().getInt(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PAGE_SIZE);
				handlePageSizeChanged(pageSize);
			}
			return;
		}
		
		if (evtSrc == this)
			return;
		
		if (evtSrc instanceof IMemoryRendering)
		{
			IMemoryRendering rendering = (IMemoryRendering)evtSrc;
			IMemoryBlock memoryBlock = rendering.getMemoryBlock();
			
			// do not handle event from renderings displaying other memory blocks
			if (memoryBlock != getMemoryBlock())
				return;
		}
	
		String propertyName = event.getProperty();
		Object value = event.getNewValue();
		
		if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_SELECTED_ADDRESS) && value instanceof BigInteger)
		{
			selectedAddressChanged((BigInteger)value);
		}
		else if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_COL_SIZE) && value instanceof Integer)
		{
			columnSizeChanged(((Integer)value).intValue());
		}
		else if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_ROW_SIZE) && value instanceof Integer)
		{
			rowSizeChanged(((Integer)value).intValue());
		}
		else if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_TOP_ADDRESS) && value instanceof BigInteger)
		{
			topVisibleAddressChanged((BigInteger)value);
		}
		else if (propertyName.equals(IInternalDebugUIConstants.PROPERTY_PAGE_START_ADDRESS) && value instanceof BigInteger)
		{
			handlePageStartAddressChanged((BigInteger)value);
		}
	}

	/**
	 * 
	 */
	private void handlePageSizeChanged(int pageSize) {
		fPageSize = pageSize;
		// only refresh if in non-auto-load mode
		fContentDescriptor.setNumLines(pageSize);
		refresh();
	}	
	
	private void handlePropertiesChangeWhenHidden(PropertyChangeEvent event)
	{
		if (fPendingSyncProperties == null)
			return;
		
		String propertyName = event.getProperty();
		Object value = event.getNewValue();
		
		if (event.getSource() instanceof IMemoryRendering)
		{
			IMemoryRendering rendering = (IMemoryRendering)event.getSource();
			if (rendering == this || rendering.getMemoryBlock() != getMemoryBlock())
			{
				return;
			}
		}
		
		if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_COL_SIZE) && value instanceof Integer)
		{
			fPendingSyncProperties.setColumnSize(((Integer)value).intValue());
		}
		else if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_ROW_SIZE) && value instanceof Integer)
		{
			fPendingSyncProperties.setRowSize(((Integer)value).intValue());
		}
		
		else if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_SELECTED_ADDRESS) && value instanceof BigInteger)
		{
			fPendingSyncProperties.setSelectedAddress((BigInteger)value);
		}
		else if (propertyName.equals(AbstractAsyncTableRendering.PROPERTY_TOP_ADDRESS) && value instanceof BigInteger)
		{
			fPendingSyncProperties.setTopVisibleAddress((BigInteger)value);
		}
		else if (propertyName.equals(IInternalDebugUIConstants.PROPERTY_PAGE_START_ADDRESS) && value instanceof BigInteger)
		{
			fPendingSyncProperties.setPageStartAddress((BigInteger)value);
		}
		else if (event.getProperty().equals(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PAGE_SIZE)) {
			int pageSize = DebugUIPlugin.getDefault().getPreferenceStore().getInt(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PAGE_SIZE);
			fPendingSyncProperties.setPageSize(pageSize);
		}
	}
	
	private void topVisibleAddressChanged(final BigInteger address)
	{
		final Runnable runnable = new Runnable() {
			public void run() {
				if (fTableViewer.getTable().isDisposed())
					return;
				
				doTopVisibleAddressChanged(address);
			}};
		runOnUIThread(runnable);
	}
	
	/**
	 * @param address
	 */
	private void doTopVisibleAddressChanged(final BigInteger address) {
		if (fIsDisposed)
			return;
		
		if (!isDynamicLoad())
		{
			fTableViewer.setTopIndex(address);
			fTableViewer.topIndexChanged();
			return;
		}
		
		if (!isAtTopBuffer(address) && !isAtBottomBuffer(address))
		{
			fTableViewer.setTopIndex(address);
			fTableViewer.topIndexChanged();
		}
		else
		{
			reloadTable(address);
		}
	}
	
	private boolean isAtBottomBuffer(BigInteger address)
	{
		int idx = fTableViewer.indexOf(address);
		if (idx < 0)
			return true;
		
		int bottomIdx = idx + getNumberOfVisibleLines();
		int elementsCnt = fTableViewer.getVirtualContentModel().getElements().length;
		int numLinesLeft = elementsCnt - bottomIdx;
		
		if (numLinesLeft < fViewerListener.getThreshold(IVirtualContentListener.BUFFER_END))
			return true;
		
		return false;
	}
	
	private boolean isAtTopBuffer(BigInteger address)
	{
		int topIdx = fTableViewer.indexOf(address);
		if (topIdx < fViewerListener.getThreshold(IVirtualContentListener.BUFFER_START))
			return true;
		
		return false;
	}
	
	private void runOnUIThread(final Runnable runnable)
	{
		if (Display.getCurrent() != null)	
		{
			runnable.run();
		}
		else
		{
			UIJob job = new UIJob("Async Table Rendering UI Job"){ //$NON-NLS-1$
	
				public IStatus runInUIThread(IProgressMonitor monitor) {
					runnable.run();
					return Status.OK_STATUS;
				}};
			job.setSystem(true);
			job.schedule();
		}
	}
	
	private void selectedAddressChanged(final BigInteger address)
	{
		Runnable runnable = new Runnable() {

			public void run() {			
				
				if (fTableViewer.getTable().isDisposed())
					return;
						
				// call this to make the table viewer to reload when needed
				int i = fTableViewer.indexOf(address);
				if (i < 0)
				{
					// the model may not have been populated yet,
					// try to predict if the address will be in the buffer
					boolean contained = isAddressBufferred(address);
					if (!contained)
						topVisibleAddressChanged(address);
				}
				fTableViewer.setSelection(address);
			}
		};
		
		runOnUIThread(runnable);
	}
	
	private boolean isAddressBufferred(BigInteger address)
	{
		// figure out the buffer top address
		BigInteger loadAddress = fContentDescriptor.getLoadAddress();
		loadAddress = MemoryViewUtil.alignToBoundary(loadAddress, getAddressableUnitPerLine());
		int unitPerLine = getAddressableUnitPerLine();
		
		loadAddress = loadAddress.subtract(BigInteger.valueOf(getPreBufferSize() * unitPerLine));
		
		// figure out the buffer end address
		int numLines = fContentDescriptor.getNumLines();
		BigInteger bufferEnd = loadAddress.add(BigInteger.valueOf(fContentDescriptor.getPostBuffer()*unitPerLine));
		bufferEnd = bufferEnd.add(BigInteger.valueOf(numLines*unitPerLine + unitPerLine));
		
		// see if the address is contained based on current content descriptor
		if (address.compareTo(loadAddress) >= 0 && address.compareTo(bufferEnd) <= 0)
			return true;
		
		return false;
	}
	
	private void setFont(Font font)
	{	
		// set font
		fTableViewer.getTable().setFont(font);
		fTableViewer.getCursor().setFont(font);		
	}
	
	private int getDefaultColumnSize() {
		
		// default to global preference store
		IPreferenceStore prefStore = DebugUITools.getPreferenceStore();
		int columnSize = prefStore.getInt(IDebugPreferenceConstants.PREF_COLUMN_SIZE);
		// actual column size is number of addressable units * size of the addressable unit
		columnSize = columnSize * getAddressableSize();
		
		// check synchronized col size
		Integer colSize = (Integer)getSynchronizedProperty(AbstractAsyncTableRendering.PROPERTY_COL_SIZE);
		if (colSize != null)
		{
			// column size is stored as actual number of bytes in synchronizer
			int syncColSize = colSize.intValue(); 
			if (syncColSize > 0)
			{
				columnSize = syncColSize;
			}	
		}
		else
		{
			IPersistableDebugElement elmt = (IPersistableDebugElement)getMemoryBlock().getAdapter(IPersistableDebugElement.class);
			int defaultColSize = -1;
			
			if (elmt != null)
			{
				if (elmt.supportsProperty(this, IDebugPreferenceConstants.PREF_COL_SIZE_BY_MODEL))
					defaultColSize = getDefaultFromPersistableElement(IDebugPreferenceConstants.PREF_COL_SIZE_BY_MODEL);
			}
			
			if (defaultColSize <= 0)
			{
				// if not provided, get default by model
				defaultColSize = getDefaultColumnSizeByModel(getMemoryBlock().getModelIdentifier());
			}
			
			if (defaultColSize > 0)
				columnSize = defaultColSize * getAddressableSize();
		}
		return columnSize;
	}

	private int getDefaultRowSize() {
		
		int rowSize = DebugUITools.getPreferenceStore().getInt(IDebugPreferenceConstants.PREF_ROW_SIZE);
		int bytePerLine = rowSize * getAddressableSize();
		
		// check synchronized row size
		Integer size = (Integer)getSynchronizedProperty(AbstractAsyncTableRendering.PROPERTY_ROW_SIZE);
		if (size != null)
		{
			// row size is stored as actual number of bytes in synchronizer
			int syncRowSize = size.intValue(); 
			if (syncRowSize > 0)
			{
				bytePerLine = syncRowSize;
			}	
		}
		else
		{
			int defaultRowSize = -1;
			IPersistableDebugElement elmt = (IPersistableDebugElement)getMemoryBlock().getAdapter(IPersistableDebugElement.class);
			if (elmt != null)
			{
				if (elmt.supportsProperty(this, IDebugPreferenceConstants.PREF_ROW_SIZE_BY_MODEL))
				{
					defaultRowSize = getDefaultFromPersistableElement(IDebugPreferenceConstants.PREF_ROW_SIZE_BY_MODEL);
					return defaultRowSize * getAddressableSize();
				}
			}
			
			if (defaultRowSize <= 0)
				// no synchronized property, ask preference store by id
				defaultRowSize = getDefaultRowSizeByModel(getMemoryBlock().getModelIdentifier());
			
			if (defaultRowSize > 0)
				bytePerLine = defaultRowSize * getAddressableSize();
		}
		return bytePerLine;
	}
	
	/**
	 * Returns the addressable size of this rendering's memory block in bytes.
	 * 
	 * @return the addressable size of this rendering's memory block in bytes
	 */
	public int getAddressableSize() {
		return fAddressableSize;
	}
	
	private Object getSynchronizedProperty(String propertyId)
	{
		IMemoryRenderingSynchronizationService syncService = getMemoryRenderingContainer().getMemoryRenderingSite().getSynchronizationService();
		
		if (syncService == null)
			return null;
		
		return syncService.getProperty(getMemoryBlock(), propertyId);	
	}
	
	private int getDefaultFromPersistableElement(String propertyId) {
		int defaultValue = -1;
		IPersistableDebugElement elmt = (IPersistableDebugElement)getMemoryBlock().getAdapter(IPersistableDebugElement.class);
		if (elmt != null)
		{
			try {
				Object valueMB = elmt.getProperty(this, propertyId);
				if (valueMB != null && !(valueMB instanceof Integer))
				{
					IStatus status = DebugUIPlugin.newErrorStatus("Model returned invalid type on " + propertyId, null); //$NON-NLS-1$
					DebugUIPlugin.log(status);
				}
				
				if (valueMB != null)
				{
					Integer value = (Integer)valueMB;
					defaultValue = value.intValue();
				}
			} catch (CoreException e) {
				DebugUIPlugin.log(e);
			}
		}
		return defaultValue;
	}
	
	/**
	 * @param modelId
	 * @return default number of addressable units per line for the model
	 */
	private int getDefaultRowSizeByModel(String modelId)
	{
		int row = DebugUITools.getPreferenceStore().getInt(getRowPrefId(modelId));
		if (row == 0)
		{
			DebugUITools.getPreferenceStore().setValue(getRowPrefId(modelId), IDebugPreferenceConstants.PREF_ROW_SIZE_DEFAULT);
		}
		
		row = DebugUITools.getPreferenceStore().getInt(getRowPrefId(modelId));
		return row;
		
	}
	
	/**
	 * @param modelId
	 * @return default number of addressable units per column for the model
	 */
	private int getDefaultColumnSizeByModel(String modelId)
	{
		int col = DebugUITools.getPreferenceStore().getInt(getColumnPrefId(modelId));
		if (col == 0)
		{
			DebugUITools.getPreferenceStore().setValue(getColumnPrefId(modelId), IDebugPreferenceConstants.PREF_COLUMN_SIZE_DEFAULT);
		}
		
		col = DebugUITools.getPreferenceStore().getInt(getColumnPrefId(modelId));
		return col;
	}
	
	
	private String getRowPrefId(String modelId) {
		String rowPrefId = IDebugPreferenceConstants.PREF_ROW_SIZE + ":" + modelId; //$NON-NLS-1$
		return rowPrefId;
	}

	private String getColumnPrefId(String modelId) {
		String colPrefId = IDebugPreferenceConstants.PREF_COLUMN_SIZE + ":" + modelId; //$NON-NLS-1$
		return colPrefId;
	}
	
	/**
	 * Format view tab based on the bytes per line and column.
	 * 
	 * @param bytesPerLine - number of bytes per line, possible values: (1 / 2 / 4 / 8 / 16) * addressableSize
	 * @param columnSize - number of bytes per column, possible values: (1 / 2 / 4 / 8 / 16) * addressableSize
	 * @return true if format is successful, false, otherwise
	 */
	public boolean format(int bytesPerLine, int columnSize)
	{	
		
		// bytes per cell must be divisible to bytesPerLine
		if (bytesPerLine % columnSize != 0)
		{
			return false;
		}
		
		if (bytesPerLine < columnSize)
		{
			return false;
		}
		
		// do not format if the view tab is already in that format
		if(fBytePerLine == bytesPerLine && fColumnSize == columnSize){
			return false;
		}
		
		fBytePerLine = bytesPerLine;
		fColumnSize = columnSize;
		formatViewer();

		updateSyncRowSize();
		updateSyncColSize();
		
		return true;
	}
		
	
	/**
	 * Returns the number of addressable units per row.
	 *  
	 * @return number of addressable units per row
	 */
	public int getAddressableUnitPerLine() {
		return fBytePerLine / getAddressableSize();
	}
	
	/**
	 * Returns the number of addressable units per column.
	 * 
	 * @return number of addressable units per column
	 */
	public int getAddressableUnitPerColumn() {
		return fColumnSize / getAddressableSize();
	}
	
	
	/**
	 * This method estimates the number of visible lines in the rendering
	 * table.  
	 * @return estimated number of visible lines in the table
	 */
	private int getNumberOfVisibleLines()
	{
		if(fTableViewer == null)
			return -1;
		
		Table table = fTableViewer.getTable();
		int height = fTableViewer.getTable().getSize().y;
		
		// when table is not yet created, height is zero
		if (height == 0)
		{
			// make use of the table viewer to estimate table size
			height = fTableViewer.getTable().getParent().getSize().y;
		}
		
		if (height == 0)
		{
			return 0;
		}
		
		// height of border
		int border = fTableViewer.getTable().getHeaderHeight();
		
		// height of scroll bar
		int scroll = fTableViewer.getTable().getHorizontalBar().getSize().y;

		// height of table is table's area minus border and scroll bar height		
		height = height-border-scroll;

		// calculate number of visible lines
		int lineHeight = getMinTableItemHeight(table);
		
		int numberOfLines = height/lineHeight;
		
		if (numberOfLines <= 0)
			return 0;
	
		return numberOfLines;		
	}
	
	private int getMinTableItemHeight(Table table){
		
		// Hack to get around Linux GTK problem.
		// On Linux GTK, table items have variable item height as
		// carriage returns are actually shown in a cell.  Some rows will be
		// taller than others.  When calculating number of visible lines, we
		// need to find the smallest table item height.  Otherwise, the rendering
		// underestimates the number of visible lines.  As a result the rendering
		// will not be able to get more memory as needed.
		if (MemoryViewUtil.isLinuxGTK())
		{
			// check each of the items and find the minimum
			TableItem[] items = table.getItems();
			int minHeight = table.getItemHeight();
			for (int i=0; i<items.length; i++)
			{
				if (items[i].getData() != null)
					minHeight = Math.min(items[i].getBounds(0).height, minHeight);
			}
			
			return minHeight;
				
		}
		return table.getItemHeight();
	}
	
	private BigInteger getMemoryBlockBaseAddress() throws DebugException
	{
		if (getMemoryBlock() instanceof IMemoryBlockExtension)
			return ((IMemoryBlockExtension)getMemoryBlock()).getBigBaseAddress();
		else
			return BigInteger.valueOf(getMemoryBlock().getStartAddress());
	}
	
	/**
	 * Displays the given message on the error page
	 * @param message - the message to display
	 */
	protected void showMessage(final String message)
	{
		fSwitchPageJob.setShowMessagePage(true);
		fSwitchPageJob.setMessage(message);
		fSwitchPageJob.schedule();
	}
	
	/**
	 * Returns the number of bytes displayed in a single column cell.
	 * 
	 * @return the number of bytes displayed in a single column cell
	 */
	public int getBytesPerColumn()
	{
		return fColumnSize;
	}

	/**
	 * Returns the number of bytes displayed in a row.
	 * 
	 * @return the number of bytes displayed in a row
	 */
	public int getBytesPerLine()
	{		
		return fBytePerLine;
	}
	
	/**
	 * Returns whether the error page is displayed.
	 * 
	 * @return whether the error page is displayed
	 */
	public boolean isDisplayingError()
	{
		return fShowMessage;
	}
	
	/**
	 * Displays the content of the table viewer.
	 */
	public void showTable()
	{
		fSwitchPageJob.setShowMessagePage(false);
		fSwitchPageJob.schedule();
	}
	
	private BigInteger getTopVisibleAddress() {
		
		if (fTableViewer == null)
			return BigInteger.valueOf(0);

		Table table = fTableViewer.getTable();
		int topIndex = table.getTopIndex();

		if (topIndex < 0) { return null; }

		if (table.getItemCount() > topIndex) 
		{
			MemorySegment topItem = (MemorySegment)table.getItem(topIndex).getData();
			if (topItem != null)
			{
				return topItem.getAddress();
			}
		}
		return null;
	}
	
	private  synchronized void  reloadTable(final BigInteger topAddress) {
		
		if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
			System.out.println(this + " reload at: " + topAddress.toString(16)); //$NON-NLS-1$
		
		fContentDescriptor.setLoadAddress(topAddress);
		fContentDescriptor.setNumLines(getNumLinesToLoad());
		fTableViewer.setTopIndex(topAddress);
		fTableViewer.refresh();

	}
	
	private boolean isAtTopLimit()
	{	
		BigInteger startAddress = fContentDescriptor.getStartAddress();
		startAddress = MemoryViewUtil.alignToBoundary(startAddress, getAddressableUnitPerLine());
		AbstractVirtualContentTableModel model = fTableViewer.getVirtualContentModel();
		
		if (model != null)
		{
			Object key = model.getKey(0);
			if (key instanceof BigInteger)
			{
				BigInteger startBufferAddress = (BigInteger)key;
				startBufferAddress = MemoryViewUtil.alignToBoundary(startBufferAddress, getAddressableUnitPerLine());
				
				if (startAddress.compareTo(startBufferAddress) == 0)
					return true;
			}
		}
		return false;
	}
	
	private boolean isAtBottomLimit()
	{
		BigInteger endAddress = fContentDescriptor.getEndAddress();
		endAddress = MemoryViewUtil.alignToBoundary(endAddress, getAddressableUnitPerLine());
		
		AbstractVirtualContentTableModel model = fTableViewer.getVirtualContentModel();
		if (model != null)
		{
			int numElements = model.getElements().length;
			Object key = model.getKey(numElements-1);
			if (key instanceof BigInteger)
			{
				BigInteger endBufferAddress = (BigInteger)key;
				endBufferAddress = MemoryViewUtil.alignToBoundary(endBufferAddress, getAddressableUnitPerLine());
				
				if (endAddress.compareTo(endBufferAddress) == 0)
					return true;
			}
		}
		
		return false;		
	}
	
	private void formatViewer() {
		
		fTableViewer.disposeColumns();
		fTableViewer.disposeCellEditors();
		doFormatTable();
		fTableViewer.setColumnHeaders(getColumnProperties());
		fTableViewer.showColumnHeader(true);
		
		Table table = fTableViewer.getTable();
		int colCnt = table.getColumnCount();
		CellEditor[] editors = new CellEditor[fTableViewer.getTable().getColumnCount()];
		for (int i=0; i<colCnt; i++)
		{
			editors[i] = createCellEditor(table, i);
		}
		
		fTableViewer.setCellEditors(editors);
		
		fTableViewer.formatViewer();
		
		// This resize needs to happen after the viewer has finished
		// getting the labels.
		// This fix is a hack to delay the resize until the viewer has a chance to get
		// the setData event from the UI thread.  Otherwise, the columns will be
		// squeezed together.
		UIJob job = new UIJob("resize to fit"){ //$NON-NLS-1$
			public IStatus runInUIThread(IProgressMonitor monitor) {
				resizeColumnsToPreferredSize();
				return Status.OK_STATUS;
			}};
		
		job.setSystem(true);
		job.schedule();
	}

	private void doFormatTable() {
		int bytesPerLine = getBytesPerLine();
		int columnSize = getBytesPerColumn();
		int numColumns = bytesPerLine/columnSize;
		
		Table table = fTableViewer.getTable();
		TableColumn column0 = new TableColumn(table,SWT.LEFT,0);
		column0.setText(DebugUIMessages.AbstractTableRendering_2); 
		
		// create new byte columns
		TableColumn [] byteColumns = new TableColumn[numColumns];		
		for (int i=0;i<byteColumns.length; i++)
		{
			TableColumn column = new TableColumn(table, SWT.LEFT, i+1);
			byteColumns[i] = column;
		}
		
		//Empty column for cursor navigation
		TableColumn emptyCol = new TableColumn(table,SWT.LEFT,byteColumns.length+1);
		emptyCol.setText(" "); //$NON-NLS-1$
		emptyCol.setWidth(1);
		emptyCol.setResizable(false);
	    table.setHeaderVisible(true);
	    
	    // allow clients to override column labels
	   setColumnHeadings();
	    
	}
	
	private String[] getColumnProperties()
	{
		int numColumns = getAddressableUnitPerLine()/getAddressableUnitPerColumn();
		// +2 to include properties for address and navigation column
		String[] columnProperties = new String[numColumns+2];
		columnProperties[0] = TableRenderingLine.P_ADDRESS;
		
		int addressableUnit = getAddressableUnitPerColumn();

		// use column beginning offset to the row address as properties
		for (int i=1; i<columnProperties.length-1; i++)
		{
			// column properties are stored as number of addressable units from the
			// the line address
			columnProperties[i] = Integer.toHexString((i-1)*addressableUnit);
		}
		
		// Empty column for cursor navigation
		columnProperties[columnProperties.length-1] = " "; //$NON-NLS-1$
		return columnProperties;
	}
	
   /**
     * Create a cell editor from the specified composite and column.
	 * @param composite parent composite that the cell editor is to be created from.
	 * @param column the column where the cell editor is required
	 * @return the cell editor for editing memory
	 * 
	 * @since 3.3
     *
	 */
	protected CellEditor createCellEditor(Composite composite, int column) {
	   
	   return new TextCellEditor(composite);
   }
       
   
   private ICellModifier newInternalCellModifier()
   {
	   return new AsyncTableRenderingCellModifier(this, createCellModifier());
   }
   
   	/**
   	 * Create a custom cell modifier for this rendering.  Return null
   	 * if the default cell modifier is to be used.
   	 * @return the cell modifier for this rendering, or <code>null</code> if the 
   	 * default cell modifier is to be used.
   	 * 
   	 * @since 3.3
   	 * 
   	 */
   	protected ICellModifier createCellModifier() {
       return null;
   	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.debug.ui.memory.AbstractMemoryRendering#dispose()
	 */
	public void dispose() {
		
		if (fIsDisposed)
			return;
		
		fIsDisposed = true;
		
		removeListeners();
		
		if (fMenuMgr != null)
		{
			fMenuMgr.removeAll();
			fMenuMgr.dispose();
			fMenuMgr = null;
		}
		
		if (fTableViewer != null)
		{
			if (fViewerListener != null)
				fTableViewer.removeVirtualContentListener(fViewerListener);
			
			if (fPresentationErrorListener != null)
				fTableViewer.removePresentationErrorListener(fPresentationErrorListener);
			
			fTableViewer.removeSelectionChangedListener(fViewerSelectionChangedListener);
			fTableViewer.getTable().getVerticalBar().removeSelectionListener(fScrollBarSelectionListener);
			
			fTableViewer.dispose();
		}
		
		fIsDisposed = true;
		
		super.dispose();
	}
	
	/**
	 * Updates the label of this rendering, optionally displaying the
	 * base address of this rendering's memory block.
	 * 
	 * @param showAddress whether to display the base address of this
	 *  rendering's memory block in this rendering's label
	 */
	protected void updateRenderingLabel(final boolean showAddress)
	{
		Job job = new Job("Update Rendering Label"){ //$NON-NLS-1$
			protected IStatus run(IProgressMonitor monitor) {
				if (fIsDisposed)
					return Status.OK_STATUS;
				fLabel = buildLabel(showAddress);
				firePropertyChangedEvent(new PropertyChangeEvent(AbstractAsyncTableRendering.this, IBasicPropertyConstants.P_TEXT, null, fLabel));
				return Status.OK_STATUS;
			}};
		job.setSystem(true);
		job.setRule(serialByRenderingRule);
		job.schedule();
	}
	
	private String buildLabel(boolean showAddress) {
		String label = ""; //$NON-NLS-1$
		if (getMemoryBlock() instanceof IMemoryBlockExtension)
		{
			label = ((IMemoryBlockExtension)getMemoryBlock()).getExpression();
			
			if (label.startsWith("&")) //$NON-NLS-1$
				label = "&" + label; //$NON-NLS-1$
			
			if (label == null)
			{
				label = DebugUIMessages.AbstractTableRendering_8; 
			}
			
			try {
				if (showAddress && ((IMemoryBlockExtension)getMemoryBlock()).getBigBaseAddress() != null)
				{	
					label += " : 0x"; //$NON-NLS-1$
					label += ((IMemoryBlockExtension)getMemoryBlock()).getBigBaseAddress().toString(16).toUpperCase();
				}
			} catch (DebugException e) {
				// do nothing, the label will not show the address
			}
		}
		else
		{
			long address = getMemoryBlock().getStartAddress();
			label = Long.toHexString(address).toUpperCase();
		}
		
		String preName = DebugUITools.getMemoryRenderingManager().getRenderingType(getRenderingId()).getLabel();
		
		if (preName != null)
			label += " <" + preName + ">"; //$NON-NLS-1$ //$NON-NLS-2$
		
		return decorateLabel(label);
	}
	
	/* Returns the label of this rendering.
	 * 
	 * @return label of this rendering
	 */
	public String getLabel() {
		
		if (fLabel == null)
		{
			fLabel = DebugUIMessages.AbstractAsyncTableRendering_1;
			updateRenderingLabel(isVisible());
		}
		
		return fLabel;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class)
	 */
	public Object getAdapter(Class adapter) {
		
		if (adapter == IColorProvider.class)
			return getColorProviderAdapter();
		
		if (adapter == ILabelProvider.class)
			return getLabelProviderAdapter();
		
		if (adapter == IFontProvider.class)
			return getFontProviderAdapter();
		
		if (adapter == IModelChangedListener.class)
		{
			return fModelChangedListener;
		}
		
		if (adapter == IWorkbenchAdapter.class)
		{
			// needed workbench adapter to fill the title of property page
			if (fWorkbenchAdapter == null) {
				fWorkbenchAdapter = new IWorkbenchAdapter() {
					public Object[] getChildren(Object o) {
						return new Object[0];
					}
	
					public ImageDescriptor getImageDescriptor(Object object) {
						return null;
					}
	
					public String getLabel(Object o) {
						return AbstractAsyncTableRendering.this.getLabel();
					}
	
					public Object getParent(Object o) {
						return null;
					}
				};
			}
			return fWorkbenchAdapter;
		}
		
		if (adapter == TableRenderingContentDescriptor.class)
			return getContentDescriptor();
		
		return super.getAdapter(adapter);
	}
	
	/**
	 * Returns the number of characters a byte will convert to
	 * or -1 if unknown.
	 * 
	 * @return the number of characters a byte will convert to
	 *  or -1 if unknown
	 */
	public int getNumCharsPerByte()
	{
		return -1;
	}
	
	/**
	 * Create actions for this rendering
	 */
	protected void createActions() {
		
		fCopyToClipboardAction = new AsyncCopyTableRenderingAction(this, fTableViewer);
		fGoToAddressAction = new RenderingGoToAddressAction(this);
		fResetMemoryBlockAction = new ResetToBaseAddressAction(this);
		
		fPrintViewTabAction = new AsyncPrintTableRenderingAction(this, fTableViewer);
		
		fFormatRenderingAction = new FormatTableRenderingAction(this);		
		fReformatAction = new ReformatAction(this);
		fToggleAddressColumnAction = new ToggleAddressColumnAction();
		
		IMemoryRenderingSite site = getMemoryRenderingContainer().getMemoryRenderingSite();
		if (site.getSite().getSelectionProvider() != null)
		{
			fPropertiesDialogAction = new PropertyDialogAction(site.getSite(),site.getSite().getSelectionProvider()); 
		}
		
		fNextAction = new NextPageAction();
		fPrevAction = new PrevPageAction();
	}
	
	/**
	 * Returns the currently selected address in this rendering.
	 * 
	 * @return the currently selected address in this rendering
	 */
	public BigInteger getSelectedAddress() {
		Object key = fTableViewer.getSelectionKey();
		
		if (key != null && key instanceof BigInteger)
			return (BigInteger)key;
		
		return null;
	}

	/**
	 * Returns the currently selected content in this rendering as MemoryByte.
	 * 
	 * @return the currently selected content in array of MemoryByte.  
	 * Returns an empty array if the selected address is out of buffered range.
	 */
	public MemoryByte[] getSelectedAsBytes()
	{
		if (getSelectedAddress() == null)
			return new MemoryByte[0];
		
		Object key = fTableViewer.getSelectionKey();
		AbstractVirtualContentTableModel model = fTableViewer.getVirtualContentModel();
		
		if (model != null)
		{
			model = (AbstractVirtualContentTableModel)fTableViewer.getModel();
			int row = model.indexOfKey(key);
			Object element = model.getElement(row);
			int col = model.columnOf(element, key);
		
			// check precondition
			if (col <= 0 || col > getBytesPerLine()/getBytesPerColumn())
			{
				return new MemoryByte[0];
			}
			
			if (!(element instanceof MemorySegment))
				return new MemoryByte[0];
			
			MemorySegment line = (MemorySegment)element;
			int offset = (col-1)*(getAddressableUnitPerColumn()*getAddressableSize());
			
			// make a copy of the bytes to ensure that data cannot be changed
			// by caller
			MemoryByte[] bytes = line.getBytes(offset, getAddressableUnitPerColumn()*getAddressableSize());
			MemoryByte[] retBytes = new MemoryByte[bytes.length];
			
			System.arraycopy(bytes, 0, retBytes, 0, bytes.length);
			return retBytes;
		}
		return new MemoryByte[0];
	}

	/**
	 * Returns the currently selected content in this rendering as a String.
	 * 
	 * @return the currently selected content in this rendering
	 */
	public String getSelectedAsString() {

		if (getSelectedAddress() == null)
			return ""; //$NON-NLS-1$
		
		MemoryByte[] bytes = getSelectedAsBytes();
		if (bytes.length > 0)
		{
			return getString(this.getRenderingId(), getSelectedAddress(), bytes);
		}
		else
			return ""; //$NON-NLS-1$
		
	}

	/**
	 * Moves the cursor to the specified address.
	 * Will load more memory if the address is not currently visible.
	 * 
	 * @param address address to position cursor at
	 * @throws DebugException if an exception occurs
	 */
	public void goToAddress(BigInteger address) throws DebugException {
		
		if (fTableViewer.getVirtualContentModel() == null)
			return;
		
		int i = fTableViewer.getVirtualContentModel().indexOfKey(address);

		if (i >= 0)
		{	
			// address is within range, set cursor and reveal
			fTableViewer.setSelection(address);
			updateSyncTopAddress(getTopVisibleAddress());
			updateSyncSelectedAddress(address);
		}
		else
		{
			// if not extended memory block
			// do not allow user to go to an address that's out of range
			if (!(getMemoryBlock() instanceof IMemoryBlockExtension))
			{
				Status stat = new Status(
				 IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(),
				 DebugException.NOT_SUPPORTED, DebugUIMessages.AbstractTableRendering_11, null  
				);
				DebugException e = new DebugException(stat);
				throw e;
			}

			BigInteger startAdd = fContentDescriptor.getStartAddress();
			BigInteger endAdd = fContentDescriptor.getEndAddress();
			
			if (address.compareTo(startAdd) < 0 ||
				address.compareTo(endAdd) > 0)
			{
				Status stat = new Status(
				 IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(),
				 DebugException.NOT_SUPPORTED, DebugUIMessages.AbstractTableRendering_11, null  
				);
				DebugException e = new DebugException(stat);
				throw e;
			}
	
			// load at the address
			fTableViewer.setSelection(address);
			reloadTable(address);
	
			updateSyncSelectedAddress(address);

			if (!isDynamicLoad())
			{						
				updateSyncPageStartAddress(address);
			}
			
			updateSyncTopAddress(address);
		}
	}			
	
	/**
	 * Refresh the table viewer with the current top visible address.
	 * Update labels in the memory rendering.
	 */
	public void refresh() {
		fTableViewer.refresh();
	}

	
	/**
	 * Resize column to the preferred size.
	 */
	public void resizeColumnsToPreferredSize() {
		fTableViewer.resizeColumnsToPreferredSize();
		if (!fIsShowAddressColumn)
		{
			final TableColumn column = fTableViewer.getTable().getColumn(0);
			column.addControlListener(new ControlListener() {

				public void controlMoved(ControlEvent e) {
				}

				public void controlResized(ControlEvent e) {
					column.removeControlListener(this);
					column.setWidth(0);
				}});
		}
	}

	/**
	 * Updates labels of this rendering.
	 */
	public void updateLabels()
	{
		UIJob job = new UIJob("updateLabels"){ //$NON-NLS-1$

			public IStatus runInUIThread(IProgressMonitor monitor) {
							
				// do not handle if the rendering is already disposed
				if (fPageBook.isDisposed())
					return Status.OK_STATUS;
				
				// update tab labels
				updateRenderingLabel(true);
				
				if (fTableViewer != null)
				{
					// update column labels
					setColumnHeadings();
					
					// rebuild cache and force labels to be refreshed
					fTableViewer.formatViewer();
				}
				return Status.OK_STATUS;
			}};
		job.setSystem(true);
		job.schedule();
	}
	
	/**
	 * Fills the context menu for this rendering
	 * 
	 * @param menu menu to fill
	 */
	protected void fillContextMenu(IMenuManager menu) {	
		
		menu.add(new Separator(EMPTY_MEMORY_GROUP));
		menu.add(new Separator());
		menu.add(fResetMemoryBlockAction);
		menu.add(fGoToAddressAction);
		menu.add(new Separator(EMPTY_NAVIGATION_GROUP));
		
		menu.add(new Separator());
		menu.add(fFormatRenderingAction);

		if (!isDynamicLoad() && getMemoryBlock() instanceof IMemoryBlockExtension)
		{		
			menu.add(new Separator());
			menu.add(fPrevAction);
			menu.add(fNextAction);
			menu.add(new Separator(EMPTY_NON_AUTO_LOAD_GROUP));
		}
		
		menu.add(new Separator());
		menu.add(fReformatAction);
		menu.add(fToggleAddressColumnAction);
		menu.add(new Separator());
		menu.add(fCopyToClipboardAction);
		menu.add(fPrintViewTabAction);
		if (fPropertiesDialogAction != null)
		{
			menu.add(new Separator());
			menu.add(fPropertiesDialogAction);
			menu.add(new Separator(EMPTY_PROPERTY_GROUP));
		}
		
		menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
	}
	
	private int getPageSizeInUnits()
	{
		return fPageSize * getAddressableUnitPerLine();
	}
	
	private void getPageSizeFromPreference()
	{
		fPageSize = DebugUIPlugin.getDefault().getPreferenceStore().getInt(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PAGE_SIZE);
	}
	
	private void getPreBufferSizeFromPreference()
	{
		fPreBufferSize = DebugUIPlugin.getDefault().getPreferenceStore().getInt(IDebugPreferenceConstants.PREF_TABLE_RENDERING_PRE_BUFFER_SIZE);
	}
	
	private void getPostBufferSizeFromPreference()
	{
		fPostBufferSize = DebugUIPlugin.getDefault().getPreferenceStore().getInt(IDebugPreferenceConstants.PREF_TABLE_RENDERING_POST_BUFFER_SIZE);
	}
	
	private void updateDynamicLoadProperty() {
		
		boolean value = DebugUIPlugin
				.getDefault()
				.getPreferenceStore()
				.getBoolean(IDebugPreferenceConstants.PREF_DYNAMIC_LOAD_MEM);
		
		if (value != isDynamicLoad())
		{
			setDynamicLoad(value);
		
			if (!fIsDisposed) {
				if (isDynamicLoad()) {
					fContentDescriptor.setPostBuffer(getPostBufferSize());
					fContentDescriptor.setPreBuffer(getPreBufferSize());
					fContentDescriptor.setNumLines(getNumberOfVisibleLines());
	
				} else {
					fContentDescriptor.setPostBuffer(0);
					fContentDescriptor.setPreBuffer(0);
					fContentDescriptor.setNumLines(fPageSize);
				}	
			}
		}
	}
	
	private void getDynamicLoadFromPreference()
	{
		setDynamicLoad(DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugPreferenceConstants.PREF_DYNAMIC_LOAD_MEM));
	}
	
	private boolean isDynamicLoad()
	{
		return fContentDescriptor.isDynamicLoad();
	}
	
	private int getPageSize()
	{
		return fPageSize;
	}
	
	private int getNumLinesToLoad() {
		int numberOfLines = -1;
		
		if (isDynamicLoad())
			numberOfLines = getNumberOfVisibleLines();
		else
			numberOfLines = getPageSize();
		
		return numberOfLines;
	}
	
	private void setDynamicLoad(boolean load)
	{
		fContentDescriptor.setDynamicLoad(load);
	}
	
	private void handlePageStartAddressChanged(BigInteger address)
	{
		// do not handle if in dynamic mode
		if (isDynamicLoad())
			return;
		
		if (!(getMemoryBlock() instanceof IMemoryBlockExtension))
			return;
		
		// do not handle event if the base address of the memory
		// block has changed, wait for debug event to update to
		// new location
		if (isMemoryBlockBaseAddressChanged())
			return;

		if(fTableViewer.getKey(0).equals(address))
			return;
	
		BigInteger start = fContentDescriptor.getStartAddress();
		BigInteger end = fContentDescriptor.getEndAddress();
		
		// smaller than start address, load at start address
		if (address.compareTo(start) < 0)
		{
			if (isAtTopLimit())
				return;
			
			address = start;
		}
		
		// bigger than end address, no need to load, already at top
		if (address.compareTo(end) > 0)
		{
			if (isAtBottomLimit())
				return;
			
			address = end.subtract(BigInteger.valueOf(getPageSizeInUnits()));
		}
		
		fContentDescriptor.setLoadAddress(address);
		final BigInteger finaladdress = address;
		Runnable runnable = new Runnable() {
			public void run() {
				if (fTableViewer.getTable().isDisposed())
					return;
				
				fTableViewer.setTopIndex(finaladdress);
				refresh();
			}};
		
		runOnUIThread(runnable);

		updateSyncPageStartAddress(address);
		updateSyncTopAddress(address);
	}
	private void handleDyanicLoadChanged() {
		
		// if currently in dynamic load mode, update page
		// start address
		BigInteger pageStart = getTopVisibleAddress();
		updateSyncPageStartAddress(pageStart);
		
		updateDynamicLoadProperty();
		if (isDynamicLoad())
		{
			refresh();
			fTableViewer.setTopIndex(pageStart);
		}
		else
		{
			handlePageStartAddressChanged(pageStart);
		}
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.debug.ui.memory.IMemoryRendering#becomesHidden()
	 */
	public void becomesHidden() {		
		// creates new object for storing potential changes in sync properties
		fPendingSyncProperties = new PendingPropertyChanges();		
		super.becomesHidden();
		
		if (getMemoryBlock() instanceof IMemoryBlockExtension)
			updateRenderingLabel(false);	
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.ui.memory.IMemoryRendering#becomesVisible()
	 */
	public void becomesVisible() {
		
		if (!fIsCreated)
		{
			// label can still be constructed even though the rendering has not finished being
			// initialized
			updateRenderingLabel(true);
			super.becomesVisible();
			return;
		}
		
		// do not do anything if already visible
		if (isVisible() == true)
		{
			// super should always be called
			super.becomesVisible();
			return;
		}
		
		super.becomesVisible();
		
		if (fPendingSyncProperties != null)
		{
			// deal with format
			boolean format = false;
			int rowSize = getBytesPerLine();
			if (fPendingSyncProperties.getRowSize() > 0)
			{
				format = true;
				rowSize = fPendingSyncProperties.getRowSize();
			}
			
			int colSize = getBytesPerColumn();
			if (fPendingSyncProperties.getColumnSize() > 0)
			{
				format = true;
				colSize = fPendingSyncProperties.getColumnSize();
			}
			
			if (format)
				format(rowSize, colSize);
			
			BigInteger selectedAddress = fPendingSyncProperties.getSelectedAddress();
			if (selectedAddress != null)
				fTableViewer.setSelection(selectedAddress);
			
			updateDynamicLoadProperty();
			
			if (isDynamicLoad())
			{
				BigInteger topVisibleAddress = fPendingSyncProperties.getTopVisibleAddress();
				if (topVisibleAddress != null)
				{
					fContentDescriptor.setLoadAddress(topVisibleAddress);
					fTableViewer.setTopIndex(topVisibleAddress);
				}
			}
			else if (!(getMemoryBlock() instanceof IMemoryBlockExtension))
			{
				BigInteger topVisibleAddress = fPendingSyncProperties.getTopVisibleAddress();
				if (topVisibleAddress != null)
					fTableViewer.setTopIndex(topVisibleAddress);
			}
			else
			{
				if (fPendingSyncProperties.getPageSize() > 0)
				{
					fPageSize = fPendingSyncProperties.getPageSize();
					fContentDescriptor.setNumLines(fPageSize);
				}
				
				BigInteger pageStartAddress = fPendingSyncProperties.getPageStartAddress();
				if (pageStartAddress != null)
					fContentDescriptor.setLoadAddress(pageStartAddress);
				
				fTableViewer.setTopIndex(pageStartAddress);
			}
			
			showTable();
			refresh();
		}

		updateRenderingLabel(true);
		
		Job job = new Job("becomesVisible") //$NON-NLS-1$
		{
			protected IStatus run(IProgressMonitor monitor) {
				if (fIsDisposed)
					return Status.OK_STATUS;
				try {
					fContentDescriptor.updateContentBaseAddress();
				} catch (DebugException e) {
					showMessage(e.getMessage());
				}
				return Status.OK_STATUS;
			}
		};
		job.setSystem(true);
		job.schedule();
		
		// discard these properties
		fPendingSyncProperties = null;
	}
	
	/**
	 * Handle column size changed event from synchronizer
	 * @param newColumnSize
	 */
	private void columnSizeChanged(final int newColumnSize) {
		// ignore event if rendering is not visible
		if (!isVisible())
			return;

		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				int rowSize = getBytesPerLine();
				if (rowSize < newColumnSize)
					rowSize = newColumnSize;
					
				format(rowSize, newColumnSize);
			}
		});
	}
	
	/**
	 * @param newRowSize - new row size in number of bytes
	 */
	private void rowSizeChanged(final int newRowSize)
	{
		// ignore event if rendering is not visible
		if (!isVisible())
			return;
		
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				int colSize = getBytesPerColumn();
				if (newRowSize < colSize)
					colSize = newRowSize;
				
				format(newRowSize, colSize);
			}
		});		
	}
	
	/**
	 * update selected address in synchronizer if update is true.
	 */
	private void updateSyncSelectedAddress(BigInteger address) {
		
		if (!fIsCreated)
			return;
		PropertyChangeEvent event = new PropertyChangeEvent(this, AbstractAsyncTableRendering.PROPERTY_SELECTED_ADDRESS, null, address);
		firePropertyChangedEvent(event);
	}
	
	/**
	 * update column size in synchronizer
	 */
	private void updateSyncColSize() {
		
		if (!fIsCreated)
			return;
		
		PropertyChangeEvent event = new PropertyChangeEvent(this, AbstractAsyncTableRendering.PROPERTY_COL_SIZE, null, new Integer(fColumnSize));
		firePropertyChangedEvent(event);
	}
	
	/**
	 * update column size in synchronizer
	 */
	private void updateSyncRowSize() {
		
		if (!fIsCreated)
			return;
		
		PropertyChangeEvent event = new PropertyChangeEvent(this, AbstractAsyncTableRendering.PROPERTY_ROW_SIZE, null, new Integer(fBytePerLine));
		firePropertyChangedEvent(event);
	}
	
	/**
	 * update top visible address in synchronizer
	 */
	private void updateSyncTopAddress(BigInteger address) {
		
		if (!fIsCreated)
			return;

		PropertyChangeEvent event = new PropertyChangeEvent(this, AbstractAsyncTableRendering.PROPERTY_TOP_ADDRESS, null, address);
		firePropertyChangedEvent(event);
	}
	
	private void updateSyncPageStartAddress(BigInteger address) {
	
		if (!fIsCreated)
			return;
		
		if (isMemoryBlockBaseAddressChanged())
			return;
		
		PropertyChangeEvent event = new PropertyChangeEvent(this, IInternalDebugUIConstants.PROPERTY_PAGE_START_ADDRESS, null, address);
		firePropertyChangedEvent(event);
	}
	
	/**
	 * Returns the color provider for this rendering's memory block or
	 * <code>null</code> if none.
	 * <p>
	 * By default a color provider is obtained by asking this rendering's
	 * memory block for its {@link IColorProvider} adapter. When the color
	 * provider is queried for color information, it is provided with a
	 * {@link MemoryRenderingElement} as an argument. 
	 * </p>
	 * @return the color provider for this rendering's memory block,
	 *  or <code>null</code>
	 */
	protected IColorProvider getColorProviderAdapter()
	{
		return (IColorProvider)getMemoryBlock().getAdapter(IColorProvider.class);
	}
	
	/**
	 * Returns the label provider for this rendering's memory block or
	 * <code>null</code> if none.
	 * <p>
	 * By default a label provider is obtained by asking this rendering's
	 * memory block for its {@link ILabelProvider} adapter. When the label
	 * provider is queried for label information, it is provided with a
	 * {@link MemoryRenderingElement} as an argument. 
	 * </p>
	 * @return the label provider for this rendering's memory block,
	 *  or <code>null</code>
	 */
	protected ILabelProvider getLabelProviderAdapter()
	{
		return (ILabelProvider)getMemoryBlock().getAdapter(ILabelProvider.class);
	}
	
	/**
	 * Returns the font provider for this rendering's memory block or
	 * <code>null</code> if none.
	 * <p>
	 * By default a font provider is obtained by asking this rendering's
	 * memory block for its {@link IFontProvider} adapter. When the font
	 * provider is queried for font information, it is provided with a
	 * {@link MemoryRenderingElement} as an argument. 
	 * </p>
	 * @return the font provider for this rendering's memory block,
	 *  or <code>null</code>
	 */
	protected IFontProvider getFontProviderAdapter()
	{
		return (IFontProvider)getMemoryBlock().getAdapter(IFontProvider.class);
	}
	
	/**
	 * Returns the table presentation for this rendering's memory block or
	 * <code>null</code> if none.
	 * <p>
	 * By default a table presentation is obtained by asking this rendering's
	 * memory block for its {@link IMemoryBlockTablePresentation} adapter.
	 * </p>
	 * @return the table presentation for this rendering's memory block,
	 *  or <code>null</code>
	 */
	protected IMemoryBlockTablePresentation getTablePresentationAdapter()
	{
		return (IMemoryBlockTablePresentation)getMemoryBlock().getAdapter(IMemoryBlockTablePresentation.class);
	}
	
	/**
	 * Setup the viewer so it supports hovers to show the offset of each field
	 */
	private void createToolTip() {
		
		fToolTipShell = new Shell(DebugUIPlugin.getShell(), SWT.ON_TOP | SWT.RESIZE );
		GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 1;
		gridLayout.marginWidth = 2;
		gridLayout.marginHeight = 0;
		fToolTipShell.setLayout(gridLayout);
		fToolTipShell.setBackground(fTableViewer.getTable().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
		
		final Control toolTipControl = createToolTipControl(fToolTipShell);
		
		if (toolTipControl == null)
		{
			// if client decide not to use tooltip support
			fToolTipShell.dispose();
			return;
		}
		
		MouseTrackAdapter listener = new MouseTrackAdapter(){
			
			private TableItem fTooltipItem = null;
			private int fCol = -1;
			
			public void mouseExit(MouseEvent e){
				
				if (!fToolTipShell.isDisposed())
					fToolTipShell.setVisible(false);
				fTooltipItem = null;
			}
			
			public void mouseHover(MouseEvent e){
				
				Point hoverPoint = new Point(e.x, e.y);
				Control control = null;
				
				if (e.widget instanceof Control)
					control = (Control)e.widget;
				
				if (control == null)
					return;
				
				hoverPoint = control.toDisplay(hoverPoint);
				TableItem item = getItem(hoverPoint);
				int column = getColumn(hoverPoint);
				
				//Only if there is a change in hover
				if(this.fTooltipItem != item || fCol != column){
					
					//Keep Track of the latest hover
					fTooltipItem = item;
					fCol = column;
					
					if(item != null){
						toolTipAboutToShow(toolTipControl, fTooltipItem, column);
						
						//Setting location of the tooltip
						Rectangle shellBounds = fToolTipShell.getBounds();
						shellBounds.x = hoverPoint.x;
						shellBounds.y = hoverPoint.y + item.getBounds(0).height;
						
						fToolTipShell.setBounds(shellBounds);
						fToolTipShell.pack();
						
						fToolTipShell.setVisible(true);
					}
					else {
						fToolTipShell.setVisible(false);
					}
				}
			}
		};
		
		fTableViewer.getTable().addMouseTrackListener(listener);
		fTableViewer.getCursor().addMouseTrackListener(listener);
	}
	
	/**
	 * Creates the control used to display tool tips for cells in this table. By default
	 * a label is used to display the address of the cell. Clients may override this
	 * method to create custom tooltip controls.
	 * <p>
	 * Also see the methods <code>getToolTipText(...)</code> and 
	 * <code>toolTipAboutToShow(...)</code>.
	 * </p>
	 * @param composite parent for the tooltip control
	 * @return the tooltip control to be displayed
	 * @since 3.2
	 */
	protected Control createToolTipControl(Composite composite) {
		Control fToolTipLabel = new Label(composite, SWT.NONE);
		fToolTipLabel.setForeground(fTableViewer.getTable().getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
		fToolTipLabel.setBackground(fTableViewer.getTable().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
		fToolTipLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL |
				GridData.VERTICAL_ALIGN_CENTER));
		return fToolTipLabel;
	}
	
	/**
	 * Bug with table widget,BUG 113015, the widget is not able to return the correct
	 * table item if SWT.FULL_SELECTION is not on when the table is created.
	 * Created the following function to work around the problem.
	 * We can remove this method when the bug is fixed.
	 * @param point
	 * @return the table item where the point is located, return null if the item cannot be located.
	 */
	private TableItem getItem(Point point)
	{
		TableItem[] items = fTableViewer.getTable().getItems();
		for (int i=0; i<items.length; i++)
		{
			TableItem item = items[i];
			if (item.getData() != null)
			{
				Point start = new Point(item.getBounds(0).x, item.getBounds(0).y);
				start = fTableViewer.getTable().toDisplay(start);
				Point end = new Point(start.x + item.getBounds(0).width, start.y + item.getBounds(0).height);
				
				if (start.y < point.y && point.y < end.y)
					return item;
			}
		}
		return null;
	}
	
	/**
	 * Method for figuring out which column the point is located.
	 * @param point
	 * @return the column index where the point is located, return -1 if column is not found.
	 */
	private int getColumn(Point point)
	{
		int colCnt = fTableViewer.getTable().getColumnCount();
		
		TableItem item = null;
		for (int i=0; i<fTableViewer.getTable().getItemCount(); i++)
		{
			item = fTableViewer.getTable().getItem(i);
			if (item.getData() != null)
				break;
		}
		
		if (item != null)
		{
			for (int i=0; i<colCnt; i++)
			{
				Point start = new Point(item.getBounds(i).x, item.getBounds(i).y);
				start = fTableViewer.getTable().toDisplay(start);
				Point end = new Point(start.x + item.getBounds(i).width, start.y + item.getBounds(i).height);
				
				if (start.x < point.x && end.x > point.x)
					return i;
			}
		}
		return -1;
	}
	
	/**
	 * Called when the tool tip is about to show in this rendering.
	 * Clients who overrides <code>createTooltipControl</code> may need to
	 * also override this method to ensure that the tooltip shows up properly
	 * in their customized control.
	 * <p>
	 * By default a text tooltip is displayed, and the contents for the tooltip
	 * are generated by the <code>getToolTipText(...)</code> method.
	 * </p>
	 * @param toolTipControl - the control for displaying the tooltip
	 * @param item - the table item where the mouse is pointing.
	 * @param col - the column at which the mouse is pointing.
	 * @since 3.2
	 */
	protected void toolTipAboutToShow(Control toolTipControl, TableItem item,
			int col) {
		if (toolTipControl instanceof Label) {
			Object address = fTableViewer.getKey(fTableViewer.getTable().indexOf(item), col);
			if (address != null  && address instanceof BigInteger) {
				Object data = item.getData();
				if (data instanceof MemorySegment) {
					MemorySegment line = (MemorySegment) data;

					if (col > 0) {
						int start = (col - 1) * getBytesPerColumn();
						int end = start + getBytesPerColumn();
						MemoryByte[] bytes = line.getBytes(start, end);

						String str = getToolTipText((BigInteger)address, bytes);

						if (str != null)
							((Label) toolTipControl).setText(str);
					} else {
						String str = getToolTipText((BigInteger)address,
								new MemoryByte[] {});

						if (str != null)
							((Label) toolTipControl).setText(str);
					}
				}
			}
		}
	}
	
	/**
	 * Returns the text to display in a tool tip at the specified address
	 * for the specified bytes. By default the address of the bytes is displayed.
	 * Subclasses may override.
	 * 
	 * @param address address of cell that tool tip is displayed for 
	 * @param bytes the bytes in the cell
	 * @return the tooltip text for the memory bytes located at the specified
	 *         address
	 * @since 3.2
	 */
	protected String getToolTipText(BigInteger address, MemoryByte[] bytes)
	{
		StringBuffer buf = new StringBuffer("0x"); //$NON-NLS-1$
		buf.append(address.toString(16).toUpperCase());
		
		return buf.toString();
	}
	
	private void setColumnHeadings()
	{
		String[] columnLabels = new String[0];
		
		IMemoryBlockTablePresentation presentation = getTablePresentationAdapter();
		if (presentation != null)
		{
			columnLabels = presentation.getColumnLabels(getMemoryBlock(), getBytesPerLine(), getBytesPerLine()/getBytesPerColumn());
		}
		
		// check that column labels returned are not null
		if (columnLabels == null)
			columnLabels = new String[0];
		
		int numByteColumns = fBytePerLine/fColumnSize;
		
		TableColumn[] columns = fTableViewer.getTable().getColumns();
		
		int j=0;
		for (int i=1; i<columns.length-1; i++)
		{	
			// if the number of column labels returned is correct
			// use supplied column labels
			if (columnLabels.length == numByteColumns)
			{
				columns[i].setText(columnLabels[j]);
				j++;
			}
			else
			{
				// otherwise, use default
				int addressableUnit = getAddressableUnitPerColumn();
				if (addressableUnit >= 4)
				{
					columns[i].setText(Integer.toHexString(j*addressableUnit).toUpperCase() + 
							" - " + Integer.toHexString(j*addressableUnit+addressableUnit-1).toUpperCase()); //$NON-NLS-1$
				}
				else
				{
					columns[i].setText(Integer.toHexString(j*addressableUnit).toUpperCase());
				}
				j++;
			}
		}
	}
	
	/**
	 * 
	 * Return this rendering's viewer
	 * @return this rendering's viewer
	 */
	public StructuredViewer getViewer()
	{
		return fTableViewer;
	}
	
	private boolean isMemoryBlockBaseAddressChanged()
	{
		try {
			BigInteger address = getMemoryBlockBaseAddress();
			BigInteger oldBaseAddress = fContentDescriptor.getContentBaseAddress();
			if (!oldBaseAddress.equals(address))
				return true;
		} catch (DebugException e) {
			// fail silently
		}
		return false;
	}
	
	/**
	 * @param topVisibleAddress
	 */
	private void createContentDescriptor(final BigInteger topVisibleAddress) {
		fContentDescriptor = new TableRenderingContentDescriptor(AbstractAsyncTableRendering.this);
		fContentDescriptor.setPostBuffer(getPostBufferSize());
		fContentDescriptor.setPreBuffer(getPreBufferSize());
		fContentDescriptor.setLoadAddress(topVisibleAddress);
		try {
			fContentDescriptor.updateContentBaseAddress();
			
		} catch (DebugException e) {
			fError = true;
			showMessage(e.getMessage());
		}
		
		fContentDescriptor.setAddressableSize(getAddressableSize());
			
		try {
			int addressSize = 4;
			if (getMemoryBlock() instanceof IMemoryBlockExtension)
			{
				IMemoryBlockExtension extMb = (IMemoryBlockExtension)getMemoryBlock();
				addressSize = extMb.getAddressSize();
				
				if (addressSize <= 0)
				{
					DebugUIPlugin.logErrorMessage("Invalid address Size: " + addressSize); //$NON-NLS-1$
					addressSize = 4;
				}
				fContentDescriptor.setAddressSize(addressSize);
			}
			fContentDescriptor.setAddressSize(addressSize);
		} catch (DebugException e) {
			fError = true;
			showMessage(e.getMessage());
		} finally {
			if (fContentDescriptor.getAddressSize() <= 0)
				fContentDescriptor.setAddressSize(4);
		}
	}
	
	/**
	 * Return the number of lines to be bufferred before the top visible line of the memory rendering
	 * @return number of lines to be buffered before the top visible line in the memory rendering
	 */
	private int getPreBufferSize()
	{
		if (fPreBufferSize < 0)
			getPreBufferSizeFromPreference();
		
		return fPreBufferSize;
	}
	
	/**
	 * Returns the number of lines to be bufferred after the last visible line in the memory rendering
	 * @return the number of lines to be bufferred after the last visible line in the memory rendering
	 */
	private int getPostBufferSize()
	{
		if (fPostBufferSize < 0)
			getPostBufferSizeFromPreference();
		
		return fPostBufferSize;
	}
	
	private TableRenderingContentDescriptor getContentDescriptor()
	{
		return fContentDescriptor;
	}
	
	private void createGoToAddressComposite(Composite parent)
	{
		fGoToAddressComposite = new GoToAddressComposite();
		fGoToAddressComposite.createControl(parent);
		Button button = fGoToAddressComposite.getButton(IDialogConstants.OK_ID);
		if (button != null)
		{
			button.addSelectionListener(new SelectionAdapter() {

				public void widgetSelected(SelectionEvent e) {
					doGoToAddress();
				}
			});
			
			button = fGoToAddressComposite.getButton(IDialogConstants.CANCEL_ID);
			if (button != null)
			{
				button.addSelectionListener(new SelectionAdapter() {
					public void widgetSelected(SelectionEvent e) {
						hideGotoAddressComposite();
					}});
			}
		}
		
		fGoToAddressComposite.getExpressionWidget().addSelectionListener(new SelectionAdapter() {
			public void widgetDefaultSelected(SelectionEvent e) {
				doGoToAddress();
			}});
		
		fGoToAddressComposite.getExpressionWidget().addKeyListener(new KeyAdapter() {

			public void keyPressed(KeyEvent e) {
				if (e.keyCode == SWT.ESC)
					hideGotoAddressComposite();
				super.keyPressed(e);
			}});
	}
	
	private void showGoToAddressComposite() {
		
		String selectedStr = getSelectedAsString();
		Text text = fGoToAddressComposite.getExpressionWidget();
		text.setText(selectedStr);
		text.setSelection(0, text.getCharCount());
	
		double height = fGoToAddressComposite.getHeight();
		double canvasHeight = fSashForm.getParent().getClientArea().height;
		double tableHeight = canvasHeight - height;
		
		double tableWeight = (tableHeight/canvasHeight) * 100;
		double textWeight = (height / canvasHeight) * 100;
		fSashForm.setWeights(new int[]{(int)tableWeight, (int)textWeight});
		fSashForm.setMaximizedControl(null);
		
		fGoToAddressComposite.getExpressionWidget().setFocus();
	}
	
	private void hideGotoAddressComposite()
	{
		fSashForm.setMaximizedControl(fTableViewer.getControl());
		if (isActivated())
			fTableViewer.getControl().setFocus();
	}
	
	/**
	 * 
	 */
	private void doGoToAddress() {
		try {
			BigInteger address = fGoToAddressComposite.getGoToAddress(fContentDescriptor.getContentBaseAddress(), getSelectedAddress());
			fGoToAddressAction.doGoToAddress(address.toString(16));
			hideGotoAddressComposite();
		} catch (DebugException e1) {
			MemoryViewUtil.openError(DebugUIMessages.GoToAddressAction_Go_to_address_failed, 
					DebugUIMessages.GoToAddressAction_Go_to_address_failed, e1);
		} catch (NumberFormatException e1)
		{
			MemoryViewUtil.openError(DebugUIMessages.GoToAddressAction_Go_to_address_failed, 
				DebugUIMessages.GoToAddressAction_Address_is_invalid, e1);
		}
	}
	
	public void activated() {
		super.activated();
		
		fActivated = true;
		IWorkbench workbench = PlatformUI.getWorkbench();
		ICommandService commandSupport = (ICommandService)workbench.getAdapter(ICommandService.class);
		IContextService contextSupport = (IContextService)workbench.getAdapter(IContextService.class);
		
		if (commandSupport != null && contextSupport != null)
		{
			fContext.add(contextSupport.activateContext(ID_ASYNC_TABLE_RENDERING_CONTEXT));
			Command gotoCommand = commandSupport.getCommand(ID_GO_TO_ADDRESS_COMMAND);

			if (fGoToAddressHandler == null)
			{
				fGoToAddressHandler = new AbstractHandler() {
					public Object execute(ExecutionEvent event) throws ExecutionException {
						if (fSashForm.getMaximizedControl() != null)
							fGoToAddressAction.run();
						else
							hideGotoAddressComposite();
						return null;
					}};
			}
			gotoCommand.setHandler(fGoToAddressHandler);
			
			// The page up and page down actions can only be activated if the rendering
			// is in manual scrolling mode.  We are unable to determine the scrolling mode
			// until the content descriptor is created.  When the rendering is activated, the content
			// descriptor may not be created yet.  In that case, we cannot activate the shortcuts here.
			// We will activate the shortcut after the rendering is created.
			if (fContentDescriptor != null && !isDynamicLoad())
			{
				activatePageActions();
			}
		}		
	}

	private void activatePageActions() {
		IWorkbench workbench = PlatformUI.getWorkbench();
		ICommandService commandSupport = (ICommandService)workbench.getAdapter(ICommandService.class);
		if (commandSupport != null)
		{
			Command nextPage = commandSupport.getCommand(ID_NEXT_PAGE_COMMAND);
			if (fNextPageHandler == null)
			{
				fNextPageHandler = new AbstractHandler() {
	
					public Object execute(ExecutionEvent arg0)
							throws ExecutionException {
						fNextAction.run();
						return null;
					}						
				};
			}
			nextPage.setHandler(fNextPageHandler);
			
			Command prevPage = commandSupport.getCommand(ID_PREV_PAGE_COMMAND);
			if (fPrevPageHandler == null)
			{
				fPrevPageHandler = new AbstractHandler() {
	
					public Object execute(ExecutionEvent arg0)
							throws ExecutionException {
						fPrevAction.run();
						return null;
					}						
				};
			}
			prevPage.setHandler(fPrevPageHandler);
		}
	}

	public void deactivated() {
		
		fActivated = false;
    	IWorkbench workbench = PlatformUI.getWorkbench();
		ICommandService commandSupport = (ICommandService)workbench.getAdapter(ICommandService.class);
		IContextService contextSupport = (IContextService)workbench.getAdapter(IContextService.class);
		
		if (commandSupport != null && contextSupport != null)
		{
			// 	remove handler
			Command command = commandSupport.getCommand(ID_GO_TO_ADDRESS_COMMAND);
			command.setHandler(null);
			
			command = commandSupport.getCommand(ID_NEXT_PAGE_COMMAND);
			command.setHandler(null);
			
			command = commandSupport.getCommand(ID_PREV_PAGE_COMMAND);
			command.setHandler(null);

			if (fContext != null)
				contextSupport.deactivateContexts(fContext);
		}
		super.deactivated();
	}
	
	private boolean isActivated()
	{
		return fActivated;
	}
	
	/**
	 * Returns text for the given memory bytes at the specified address for the specified
	 * rendering type. This is called by the label provider for.
	 * Subclasses must override.
	 * 
	 * @param renderingTypeId rendering type identifier
	 * @param address address where the bytes belong to
	 * @param data the bytes
	 * @return a string to represent the memory. Cannot not return <code>null</code>.
	 * 	Returns a string to pad the cell if the memory cannot be converted
	 *  successfully.
	 */
	abstract public String getString(String renderingTypeId, BigInteger address, MemoryByte[] data);
	
	/**
	 * Returns bytes for the given text corresponding to bytes at the given
	 * address for the specified rendering type. This is called by the cell modifier
	 * when modifying bytes in a memory block.
	 * Subclasses must convert the string value to an array of bytes.  The bytes will
	 * be passed to the debug adapter for memory block modification.
	 * Returns <code>null</code> if the bytes cannot be formatted properly.
	 * 
	 * @param renderingTypeId rendering type identifier
	 * @param address address the bytes begin at
	 * @param currentValues current values of the data in bytes format
	 * @param newValue the string to be converted to bytes
	 * @return the bytes converted from a string
	 */
	abstract public byte[] getBytes(String renderingTypeId, BigInteger address, MemoryByte[] currentValues, String newValue);
}

Back to the top