/*******************************************************************************
 *  Copyright (c) 2006, 2018 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
 *     Teodor Madan (Freescale) -  Bug 292360 -  [Memory View] platform renderings do not implement correctly IMemoryRendering#getControl
 *     Teodor Madan (Freescale) -  Bug 292426 -  [Memory View] platform renderings cannot be repositioned from non-UI thread through calls to IRepositionableMemoryRendering#goToAddress
 *     Teodor Madan (Freescale) & Jeremiah Swan (IBM) - Bug 300036 -  [Memory View] NPE in AbstractAsyncTableRendering#getSelectedAddress on rendering creation
 *******************************************************************************/

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.core.IInternalDebugCoreConstants;
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.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.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.debug.ui.memory.MemoryRenderingElement;
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.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.Label;
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.IContextActivation;
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()
		 */
		@Override
		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$
		}

		@Override
		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$
		}

		@Override
		public void run() {
			BigInteger address = fContentDescriptor.getLoadAddress();
			address = address.subtract(BigInteger.valueOf(getPageSizeInUnits()));
			handlePageStartAddressChanged(address);
		}
	}

	private class RenderingGoToAddressAction extends GoToAddressAction {
		public RenderingGoToAddressAction(IMemoryRenderingContainer container, AbstractBaseTableRendering rendering) {
			super(container, rendering);
		}

		@Override
		public void run() {
			showGoToAddressComposite();
		}
	}

	private class SwitchPageJob extends UIJob {
		private Object fLock = new Object();
		private boolean fShowMessagePage = false;
		private String fMessage = IInternalDebugCoreConstants.EMPTY_STRING;

		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;
			}
		}

		@Override
		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)
		 */
		@Override
		public boolean contains(ISchedulingRule rule) {
			return rule == this;
		}

		/*
		 * (non-Javadoc)
		 * @see
		 * org.eclipse.core.runtime.jobs.ISchedulingRule#isConflicting(org.eclipse
		 * .core.runtime.jobs.ISchedulingRule)
		 */
		@Override
		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<IContextActivation> 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<IMenuListener> 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 = event -> {
		updateSyncTopAddress(getTopVisibleAddress());
		updateSyncSelectedAddress(getSelectedAddress());
	};

	private SelectionAdapter fScrollBarSelectionListener = new SelectionAdapter() {
		@Override
		public void widgetSelected(SelectionEvent e) {
			updateSyncTopAddress(getTopVisibleAddress());
		}
	};

	private IModelChangedListener fModelChangedListener = (delta, proxy) -> {
		if (delta.getElement() == getMemoryBlock()) {
			showTable();
			updateRenderingLabel(isVisible());
		}
	};

	private IVirtualContentListener fViewerListener = new IVirtualContentListener() {

		private int startThreshold;
		private int endThreshold;

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

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

		@Override
		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 = (monitor,
			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()
	 */
	@Override
	public void resetRendering() throws DebugException {
		if (!fIsCreated) {
			return;
		}

		BigInteger baseAddress = fContentDescriptor.getContentBaseAddress();

		fTableViewer.setSelection(baseAddress);
		reloadTable(baseAddress);
		fTableViewer.setTopIndex(baseAddress);
		if (!isDynamicLoad()) {
			updateSyncPageStartAddress(baseAddress);
		}

		updateSyncSelectedAddress(baseAddress);
		updateSyncTopAddress(baseAddress);
	}

	@Override
	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 the parent to add the page to
	 */
	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 the parent composite
	 */
	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()) {

			@Override
			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$
					@Override
					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() {
								@Override
								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 = 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, 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);

		if (fMenuListeners != null) {
			Iterator<IMenuListener> iter = fMenuListeners.iterator();
			while (iter.hasNext()) {
				fMenuMgr.removeMenuListener(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()
	 */
	@Override
	public Control getControl() {
		return fPageBook;
	}

	/*
	 * (non-Javadoc)
	 * @see
	 * org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse
	 * .jface.util.PropertyChangeEvent)
	 */
	@Override
	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);
		}
	}

	/**
	 * @param pageSize the new page size
	 */
	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 = () -> {
			if (fTableViewer.getTable().isDisposed()) {
				return;
			}

			doTopVisibleAddressChanged(address);
		};
		runOnUIThread(runnable);
	}

	/**
	 * @param address the changed 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$

				@Override
				public IStatus runInUIThread(IProgressMonitor monitor) {
					runnable.run();
					return Status.OK_STATUS;
				}
			};
			job.setSystem(true);
			job.schedule();
		}
	}

	private void selectedAddressChanged(final BigInteger address) {
		Runnable runnable = () -> {

			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 = 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 = 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
	 */
	@Override
	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 = 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 the {@link String} model id
	 * @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 the {@link String} model id
	 * @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 / 32 / 64/ 128) * addressableSize
	 * @param columnSize - number of bytes per column, possible values: (1 / 2 /
	 *            4 / 8 / 16 / 32/ 64 / 128) * addressableSize
	 * @return true if format is successful, false, otherwise
	 */
	@Override
	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
	 */
	@Override
	public int getAddressableUnitPerLine() {
		return fBytePerLine / getAddressableSize();
	}

	/**
	 * Returns the number of addressable units per column.
	 *
	 * @return number of addressable units per column
	 */
	@Override
	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
	 */
	@Override
	public int getBytesPerColumn() {
		return fColumnSize;
	}

	/**
	 * Returns the number of bytes displayed in a row.
	 *
	 * @return the number of bytes displayed in a row
	 */
	@Override
	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 (DebugUIPlugin.DEBUG_DYNAMIC_LOADING) {
			DebugUIPlugin.trace(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$
			@Override
			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()
	 */
	@Override
	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();
		}

		if (fPresentationContext != null) {
			fPresentationContext.dispose();
		}

		if (fToolTipShell != null && !fToolTipShell.isDisposed()) {
			fToolTipShell.dispose();
			fToolTipShell = null;
		}

		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$
			@Override
			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 = IInternalDebugCoreConstants.EMPTY_STRING;
		if (getMemoryBlock() instanceof IMemoryBlockExtension) {
			label = ((IMemoryBlockExtension) getMemoryBlock()).getExpression();

			if (label == null) {
				label = DebugUIMessages.AbstractTableRendering_8;
			}

			if (label.startsWith("&")) { //$NON-NLS-1$
				label = "&" + label; //$NON-NLS-1$
			}

			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
	 */
	@Override
	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)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public <T> T getAdapter(Class<T> adapter) {

		if (adapter == IColorProvider.class) {
			return (T) getColorProviderAdapter();
		}

		if (adapter == ILabelProvider.class) {
			return (T) getLabelProviderAdapter();
		}

		if (adapter == IFontProvider.class) {
			return (T) getFontProviderAdapter();
		}

		if (adapter == IModelChangedListener.class) {
			return (T) fModelChangedListener;
		}

		if (adapter == IWorkbenchAdapter.class) {
			// needed workbench adapter to fill the title of property page
			if (fWorkbenchAdapter == null) {
				fWorkbenchAdapter = new IWorkbenchAdapter() {
					@Override
					public Object[] getChildren(Object o) {
						return new Object[0];
					}

					@Override
					public ImageDescriptor getImageDescriptor(Object object) {
						return null;
					}

					@Override
					public String getLabel(Object o) {
						return AbstractAsyncTableRendering.this.getLabel();
					}

					@Override
					public Object getParent(Object o) {
						return null;
					}
				};
			}
			return (T) fWorkbenchAdapter;
		}

		if (adapter == TableRenderingContentDescriptor.class) {
			return (T) 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
	 */
	@Override
	public int getNumCharsPerByte() {
		return -1;
	}

	/**
	 * Create actions for this rendering
	 */
	protected void createActions() {

		fCopyToClipboardAction = new AsyncCopyTableRenderingAction(this, fTableViewer);
		fGoToAddressAction = new RenderingGoToAddressAction(getMemoryRenderingContainer(), 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
	 */
	@Override
	public BigInteger getSelectedAddress() {
		if (!fIsCreated) {
			return null;
		}

		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.
	 */
	@Override
	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
	 */
	@Override
	public String getSelectedAsString() {

		if (getSelectedAddress() == null) {
			return IInternalDebugCoreConstants.EMPTY_STRING;
		}

		MemoryByte[] bytes = getSelectedAsBytes();
		if (bytes.length > 0) {
			return getString(this.getRenderingId(), getSelectedAddress(), bytes);
		} else {
			return IInternalDebugCoreConstants.EMPTY_STRING;
		}

	}

	/**
	 * 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
	 */
	@Override
	public void goToAddress(final BigInteger address) throws DebugException {

		if (!fIsCreated || fTableViewer.getVirtualContentModel() == null) {
			return;
		}

		final int keyIndex = fTableViewer.getVirtualContentModel().indexOfKey(address);

		if (keyIndex < 0) {
			// 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;
			}
		}

		Runnable runnable = () -> {
			showTable();
			if (keyIndex >= 0) {
				// address is within range, set cursor and reveal
				fTableViewer.setSelection(address);
				updateSyncTopAddress(getTopVisibleAddress());
				updateSyncSelectedAddress(address);
			} else {
				// load at the address
				fTableViewer.setSelection(address);
				reloadTable(address);

				updateSyncSelectedAddress(address);
				if (!isDynamicLoad()) {
					updateSyncPageStartAddress(address);
				}
				updateSyncTopAddress(address);
			}
		};
		runOnUIThread(runnable);
	}

	/**
	 * Refresh the table viewer with the current top visible address. Update
	 * labels in the memory rendering.
	 */
	@Override
	public void refresh() {
		if (!fIsCreated) {
			return;
		}

		fTableViewer.refresh();
	}

	/**
	 * Resize column to the preferred size.
	 */
	@Override
	public void resizeColumnsToPreferredSize() {
		if (!fIsCreated) {
			return;
		}

		fTableViewer.resizeColumnsToPreferredSize();
		if (!fIsShowAddressColumn) {
			final TableColumn column = fTableViewer.getTable().getColumn(0);
			column.addControlListener(new ControlListener() {

				@Override
				public void controlMoved(ControlEvent e) {
				}

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

	/**
	 * Updates labels of this rendering.
	 */
	@Override
	public void updateLabels() {
		if (!fIsCreated) {
			return;
		}

		UIJob job = new UIJob("updateLabels") { //$NON-NLS-1$

			@Override
			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;
		}

		Object key = fTableViewer.getKey(0);
		if (key != null) {
			if (key.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 = () -> {
			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()
	 */
	@Override
	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()
	 */
	@Override
	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$
		{
			@Override
			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 the new column size
	 */
	private void columnSizeChanged(final int newColumnSize) {
		// ignore event if rendering is not visible
		if (!isVisible()) {
			return;
		}

		Display.getDefault().asyncExec(() -> {
			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(() -> {
			int colSize = getBytesPerColumn();
			if (newRowSize < colSize) {
				colSize = newRowSize;
			}

			format(newRowSize, colSize);
		});
	}

	/**
	 * update selected address in synchronizer if update is true.
	 *
	 * @param address the address to update
	 */
	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, Integer.valueOf(fColumnSize));
		firePropertyChangedEvent(event);
	}

	/**
	 * update column size in synchronizer
	 */
	private void updateSyncRowSize() {

		if (!fIsCreated) {
			return;
		}

		PropertyChangeEvent event = new PropertyChangeEvent(this, AbstractAsyncTableRendering.PROPERTY_ROW_SIZE, null, Integer.valueOf(fBytePerLine));
		firePropertyChangedEvent(event);
	}

	/**
	 * update top visible address in synchronizer
	 *
	 * @param address the address to update
	 */
	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 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 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 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 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;

			@Override
			public void mouseExit(MouseEvent e) {

				if (!fToolTipShell.isDisposed()) {
					fToolTipShell.setVisible(false);
				}
				fTooltipItem = null;
			}

			@Override
			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 the given {@link Point} to find the {@link TableItem} for
	 * @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 the {@link Point} the get the column number for
	 * @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 the address to get the description for
	 */
	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() {

				@Override
				public void widgetSelected(SelectionEvent e) {
					doGoToAddress();
				}
			});

			button = fGoToAddressComposite.getButton(IDialogConstants.CANCEL_ID);
			if (button != null) {
				button.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						hideGotoAddressComposite();
					}
				});
			}
		}

		fGoToAddressComposite.getExpressionWidget().addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				doGoToAddress();
			}
		});

		fGoToAddressComposite.getExpressionWidget().addKeyListener(new KeyAdapter() {

			@Override
			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);
		}
	}

	@Override
	public void activated() {
		super.activated();

		fActivated = true;
		IWorkbench workbench = PlatformUI.getWorkbench();
		ICommandService commandSupport = workbench.getAdapter(ICommandService.class);
		IContextService contextSupport = 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() {
					@Override
					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 = workbench.getAdapter(ICommandService.class);
		if (commandSupport != null) {
			Command nextPage = commandSupport.getCommand(ID_NEXT_PAGE_COMMAND);
			if (fNextPageHandler == null) {
				fNextPageHandler = new AbstractHandler() {

					@Override
					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() {

					@Override
					public Object execute(ExecutionEvent arg0) throws ExecutionException {
						fPrevAction.run();
						return null;
					}
				};
			}
			prevPage.setHandler(fPrevPageHandler);
		}
	}

	@Override
	public void deactivated() {

		fActivated = false;
		IWorkbench workbench = PlatformUI.getWorkbench();
		ICommandService commandSupport = workbench.getAdapter(ICommandService.class);
		IContextService contextSupport = 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.
	 */
	@Override
	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
	 */
	@Override
	abstract public byte[] getBytes(String renderingTypeId, BigInteger address, MemoryByte[] currentValues, String newValue);
}
