/*******************************************************************************
 *  Copyright (c) 2006, 2018 IBM Corporation and others.
 *
 *  This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License 2.0
 *  which accompanies this distribution, and is available at
 *  https://www.eclipse.org/legal/epl-2.0/
 *
 *  SPDX-License-Identifier: EPL-2.0
 *
 *  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();
		}

		@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 static class SerialByObjectRule implements ISchedulingRule {
		private Object fObject = null;

		public SerialByObjectRule(Object lock) {
			fObject = lock;
		}

		@Override
		public boolean contains(ISchedulingRule rule) {
			return rule == this;
		}

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

	@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) {
		StringBuilder buffer = new StringBuilder();
		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 = AbstractAsyncTableRendering.this::fillContextMenu;
						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
			StringBuilder msgBuffer = new StringBuilder(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;
	}

	@Override
	public Control getControl() {
		return fPageBook;
	}

	@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 (TableItem item : items) {
				if (item.getData() != null) {
					minHeight = Math.min(item.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;
	}

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

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

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

	@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 (TableItem item : items) {
			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) {
		StringBuilder buf = new StringBuilder("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);
}
