| /******************************************************************************* |
| * Copyright (c) 2006, 2016 Wind River Systems Inc. and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Ted R Williams (Wind River Systems, Inc.) - initial implementation |
| * Randy Rohrbach (Wind River Systems, Inc.) - Copied and modified to create the floating point plugin |
| *******************************************************************************/ |
| |
| package org.eclipse.cdt.debug.ui.memory.floatingpoint; |
| |
| import java.lang.reflect.Method; |
| import java.math.BigInteger; |
| |
| import org.eclipse.cdt.debug.core.model.provisional.IMemoryRenderingViewportProvider; |
| import org.eclipse.cdt.debug.ui.memory.floatingpoint.FPutilities.Endian; |
| import org.eclipse.cdt.debug.ui.memory.floatingpoint.FPutilities.FPDataType; |
| 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.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.debug.core.DebugException; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.model.IMemoryBlock; |
| import org.eclipse.debug.core.model.IMemoryBlockExtension; |
| import org.eclipse.debug.core.model.MemoryByte; |
| import org.eclipse.debug.internal.ui.DebugPluginImages; |
| 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.IMemoryBlockConnection; |
| import org.eclipse.debug.internal.ui.memory.provisional.MemoryViewPresentationContext; |
| import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener; |
| import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; |
| import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy; |
| import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory; |
| import org.eclipse.debug.ui.IDebugUIConstants; |
| import org.eclipse.debug.ui.memory.AbstractMemoryRendering; |
| import org.eclipse.debug.ui.memory.AbstractTableRendering; |
| 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.IRepositionableMemoryRendering; |
| import org.eclipse.debug.ui.memory.IResettableMemoryRendering; |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.action.IAction; |
| 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.IInputValidator; |
| import org.eclipse.jface.dialogs.InputDialog; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.preference.PreferenceConverter; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.jface.viewers.IBasicPropertyConstants; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.dnd.Clipboard; |
| import org.eclipse.swt.dnd.DND; |
| import org.eclipse.swt.dnd.TextTransfer; |
| import org.eclipse.swt.dnd.Transfer; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.RGB; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| 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.model.IWorkbenchAdapter; |
| import org.eclipse.ui.progress.UIJob; |
| |
| |
| /** |
| * A memory rendering displaying memory in a floating point memory view look and |
| * feel, optimized for minimal IO traffic. |
| * <p> |
| * requirements of the debug model implementation: - An IMemoryBlockExtension is |
| * required. |
| * |
| * Since it is not possible to size the memory block to match the size of the |
| * viewport, memory block change notification is not useful. Such events are |
| * ignored by this rendering. |
| */ |
| |
| @SuppressWarnings({ "restriction" }) |
| public class FPRendering extends AbstractMemoryRendering |
| implements IRepositionableMemoryRendering, IResettableMemoryRendering, IMemoryRenderingViewportProvider, IModelChangedListener |
| { |
| protected Rendering fRendering; |
| protected Action actionDisplayBigEndian; |
| protected Action actionDisplayLittleEndian; |
| protected Action actionDisplayFloatingPoint; |
| |
| private IWorkbenchAdapter fWorkbenchAdapter; |
| private IMemoryBlockConnection fConnection; |
| |
| private final static int MAX_MENU_COLUMN_COUNT = 8; |
| |
| Action actionFloatingPoint32 = null; |
| Action actionFloatingPoint64 = null; |
| |
| Action actionDisplay4Digits = null; |
| Action actionDisplay8Digits = null; |
| Action actionDisplay16Digits = null; |
| |
| // Constructor |
| |
| public FPRendering(String id) |
| { |
| super(id); |
| |
| JFaceResources.getFontRegistry().addListener(new IPropertyChangeListener() |
| { |
| @Override |
| public void propertyChange(PropertyChangeEvent event) |
| { |
| if (event.getProperty().equals(IInternalDebugUIConstants.FONT_NAME)) |
| { |
| FPRendering.this.fRendering.handleFontPreferenceChange(JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME)); |
| } |
| } |
| }); |
| |
| this.addPropertyChangeListener(new IPropertyChangeListener() |
| { |
| @Override |
| public void propertyChange(PropertyChangeEvent event) |
| { |
| IMemoryRendering sourceRendering = (IMemoryRendering) event.getSource(); |
| if (!sourceRendering.getMemoryBlock().equals(getMemoryBlock())) |
| return; |
| |
| Object address = event.getNewValue(); |
| |
| if (event.getProperty().equals(AbstractTableRendering.PROPERTY_SELECTED_ADDRESS) && address instanceof BigInteger) |
| { |
| FPRendering.this.fRendering.ensureVisible((BigInteger) address); |
| } |
| } |
| }); |
| |
| FPRenderingPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener() |
| { |
| @Override |
| public void propertyChange(PropertyChangeEvent event) |
| { |
| disposeColors(); |
| allocateColors(); |
| applyPreferences(); |
| } |
| }); |
| |
| DebugUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener() |
| { |
| @Override |
| public void propertyChange(PropertyChangeEvent event) |
| { |
| if (event.getProperty().equals(IDebugUIConstants.PREF_PADDED_STR)) |
| { |
| if (FPRendering.this.fRendering != null) |
| { |
| setRenderingPadding((String) event.getNewValue()); |
| FPRendering.this.fRendering.redrawPanes(); |
| } |
| } |
| } |
| }); |
| } |
| |
| static int paddingCounter = 0; |
| |
| void setRenderingPadding(String padding) |
| { |
| if (padding == null || padding.length() == 0) padding = " "; //$NON-NLS-1$ |
| FPRendering.this.fRendering.setPaddingString(padding); |
| } |
| |
| protected void logError(String message, Exception e) |
| { |
| Status status = new Status(IStatus.ERROR, getRenderingId(), DebugException.INTERNAL_ERROR, message, e); |
| FPRenderingPlugin.getDefault().getLog().log(status); |
| } |
| |
| BigInteger fBigBaseAddress; // Memory base address |
| private BigInteger fStartAddress; // Starting address |
| private BigInteger fEndAddress; // Ending address |
| private int fAddressableSize; // Memory block size |
| private int fAddressSize; // Size of address |
| |
| /* |
| * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener#modelChanged(org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta, org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy) |
| */ |
| @Override |
| public void modelChanged(IModelDelta delta, IModelProxy proxy) |
| { |
| /* |
| * The event model in the traditional renderer is written to expect a suspend first |
| * which will cause it to save its current data set away in an archive. Then when |
| * the state change comes through it will compare and refresh showing a difference. |
| */ |
| int flags = delta.getFlags(); |
| if ( ( flags & IModelDelta.STATE ) != 0 ) { |
| fRendering.handleSuspend(false); |
| } |
| |
| fRendering.handleChange(); |
| } |
| |
| /* |
| * We use the model proxy which is supplied by the TCF implementation to provide the knowledge of memory |
| * change notifications. The older backends ( the reference model, Wind River Systems Inc. ) are written |
| * to generate the Debug Model events. TCF follows the "ModelDelta/IModelProxy" implementation that the |
| * platform renderers use. So this implementation acts as a shim. If the older Debug Events come in then |
| * fine. If the newer model deltas come in fine also. |
| */ |
| IModelProxy fModel; |
| |
| @Override |
| public void dispose() |
| { |
| /* |
| * We use the UI dispatch thread to protect the proxy information. Even though I believe the |
| * dispose routine is always called in the UI dispatch thread. I am going to make sure. |
| */ |
| Display.getDefault().asyncExec(new Runnable() { |
| @Override |
| public void run() { |
| if ( fModel != null ) { |
| fModel.removeModelChangedListener(FPRendering.this); |
| fModel.dispose(); |
| } |
| }}); |
| |
| if(this.fRendering != null) |
| this.fRendering.dispose(); |
| disposeColors(); |
| super.dispose(); |
| } |
| |
| @Override |
| public void init(final IMemoryRenderingContainer container, final IMemoryBlock block) |
| { |
| super.init(container, block); |
| |
| /* |
| * Working with the model proxy must be done on the UI dispatch thread. |
| */ |
| final IModelProxyFactory factory = (IModelProxyFactory) DebugPlugin.getAdapter(block, IModelProxyFactory.class ); |
| if ( factory != null ) { |
| Display.getDefault().asyncExec(new Runnable() { |
| @Override |
| public void run() { |
| |
| /* |
| * The asynchronous model assumes we have an asynchronous viewer that has an IPresentationContext |
| * to represent it. The Platform memory subsystem provides a way to create one without a viewewr. |
| */ |
| IMemoryRenderingSite site = container.getMemoryRenderingSite(); |
| MemoryViewPresentationContext context = new MemoryViewPresentationContext(site, container, FPRendering.this); |
| |
| /* |
| * Get a new proxy and perform the initialization sequence so we are known the |
| * the model provider. |
| */ |
| fModel = factory.createModelProxy(block, context); |
| if (fModel != null) { |
| fModel.installed(null); |
| fModel.addModelChangedListener(FPRendering.this); |
| } |
| |
| }}); |
| } |
| |
| try |
| { |
| fBigBaseAddress = ((IMemoryBlockExtension) block).getBigBaseAddress(); |
| } |
| catch (DebugException de) |
| { |
| logError(FPRenderingMessages.getString("FPRendering.FAILURE_RETRIEVE_BASE_ADDRESS"), de); //$NON-NLS-1$ |
| } |
| |
| try |
| { |
| fAddressableSize = ((IMemoryBlockExtension) block).getAddressableSize(); |
| } |
| catch (DebugException de) |
| { |
| fAddressableSize = 1; |
| } |
| |
| try |
| { |
| fStartAddress = ((IMemoryBlockExtension) block).getMemoryBlockStartAddress(); |
| } |
| catch (DebugException de) |
| { |
| fStartAddress = null; |
| logError(FPRenderingMessages.getString("FPRendering.FAILURE_RETRIEVE_START_ADDRESS"), de); //$NON-NLS-1$ |
| } |
| |
| try |
| { |
| fAddressSize = ((IMemoryBlockExtension) block).getAddressSize(); |
| } |
| catch (DebugException e) |
| { |
| fAddressSize = 0; |
| } |
| |
| BigInteger endAddress; |
| try |
| { |
| endAddress = ((IMemoryBlockExtension) block).getMemoryBlockEndAddress(); |
| if (endAddress != null) |
| fEndAddress = endAddress; |
| } |
| catch (DebugException e) |
| { |
| fEndAddress = null; |
| } |
| |
| if (fEndAddress == null) |
| { |
| int addressSize; |
| try |
| { |
| addressSize = ((IMemoryBlockExtension) block).getAddressSize(); |
| } |
| catch (DebugException e) |
| { |
| addressSize = 4; |
| } |
| |
| endAddress = BigInteger.valueOf(2); |
| endAddress = endAddress.pow(addressSize * 8); |
| endAddress = endAddress.subtract(BigInteger.ONE); |
| fEndAddress = endAddress; |
| } |
| |
| // default to MAX_VALUE if we have trouble getting the end address |
| if (fEndAddress == null) |
| fEndAddress = BigInteger.valueOf(Integer.MAX_VALUE); |
| } |
| |
| public BigInteger getBigBaseAddress() |
| { |
| return fBigBaseAddress; |
| } |
| |
| public BigInteger getMemoryBlockStartAddress() |
| { |
| return fStartAddress; |
| } |
| |
| public BigInteger getMemoryBlockEndAddress() |
| { |
| return fEndAddress; |
| } |
| |
| public int getAddressableSize() |
| { |
| return fAddressableSize; |
| } |
| |
| public int getAddressSize() |
| { |
| return fAddressSize; |
| } |
| |
| @Override |
| public Control createControl(Composite parent) |
| { |
| allocateColors(); |
| |
| this.fRendering = new Rendering(parent, this); |
| |
| applyPreferences(); |
| |
| createMenus(); |
| |
| if (actionFloatingPoint32.isChecked()) |
| actionDisplay16Digits.setEnabled(false); |
| else |
| actionDisplay16Digits.setEnabled(true); |
| |
| return this.fRendering; |
| } |
| |
| /* |
| * We are duplicating the reference to the GoToAddress command because it is private in the platform. |
| * This is not going to change at this point so just live with it. |
| */ |
| private static final String ID_GO_TO_ADDRESS_COMMAND = "org.eclipse.debug.ui.command.gotoaddress"; //$NON-NLS-1$ |
| private AbstractHandler fGoToAddressHandler; |
| |
| @Override |
| public void activated() |
| { |
| super.activated(); |
| |
| IWorkbench workbench = PlatformUI.getWorkbench(); |
| ICommandService commandSupport = workbench.getAdapter(ICommandService.class); |
| |
| if (commandSupport != null) |
| { |
| Command gotoCommand = commandSupport.getCommand(ID_GO_TO_ADDRESS_COMMAND); |
| |
| if (fGoToAddressHandler == null) |
| { |
| fGoToAddressHandler = new AbstractHandler() |
| { |
| @Override |
| public Object execute(ExecutionEvent event) throws ExecutionException |
| { |
| return null; |
| } |
| }; |
| } |
| gotoCommand.setHandler(fGoToAddressHandler); |
| } |
| } |
| |
| @Override |
| public void deactivated() |
| { |
| IWorkbench workbench = PlatformUI.getWorkbench(); |
| ICommandService commandSupport = workbench.getAdapter(ICommandService.class); |
| |
| if (commandSupport != null) |
| { |
| // remove handler |
| Command command = commandSupport.getCommand(ID_GO_TO_ADDRESS_COMMAND); |
| command.setHandler(null); |
| } |
| |
| super.deactivated(); |
| } |
| |
| public void setSelection(BigInteger start, BigInteger end) |
| { |
| fRendering.getSelection().setStart(start, start); |
| fRendering.getSelection().setEnd(end, end); |
| } |
| |
| public void gotoAddress(final BigInteger address) |
| { |
| this.fRendering.gotoAddress(address); |
| } |
| |
| public void updateRenderingLabels() |
| { |
| UIJob job = new UIJob("updateLabels") { //$NON-NLS-1$ |
| @SuppressWarnings("synthetic-access") |
| @Override |
| public IStatus runInUIThread(IProgressMonitor monitor) |
| { |
| |
| // Update tab labels |
| String fLabel = getLabel(); |
| firePropertyChangedEvent(new PropertyChangeEvent(FPRendering.this, IBasicPropertyConstants.P_TEXT, null, fLabel)); |
| return Status.OK_STATUS; |
| } |
| }; |
| job.setSystem(true); |
| job.schedule(); |
| } |
| |
| private Color colorBackground; |
| private Color colorChanged; |
| private Color colorsChanged[] = null; |
| private Color colorEdit; |
| private Color colorSelection; |
| private Color colorText; |
| private Color colorTextAlternate; |
| |
| public void allocateColors() |
| { |
| IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore(); |
| |
| colorBackground = new Color(Display.getDefault(), PreferenceConverter.getColor(store, FPRenderingPreferenceConstants.MEM_COLOR_BACKGROUND)); |
| colorChanged = new Color(Display.getDefault(), PreferenceConverter.getColor(store, FPRenderingPreferenceConstants.MEM_COLOR_CHANGED)); |
| colorEdit = new Color(Display.getDefault(), PreferenceConverter.getColor(store, FPRenderingPreferenceConstants.MEM_COLOR_EDIT)); |
| colorSelection = new Color(Display.getDefault(), PreferenceConverter.getColor(store, FPRenderingPreferenceConstants.MEM_COLOR_SELECTION)); |
| colorText = new Color(Display.getDefault(), PreferenceConverter.getColor(store, FPRenderingPreferenceConstants.MEM_COLOR_TEXT)); |
| |
| // alternate cell color |
| Color textColor = getColorText(); |
| int red = textColor.getRed(); |
| int green = textColor.getGreen(); |
| int blue = textColor.getBlue(); |
| |
| float scale = store.getInt(FPRenderingPreferenceConstants.MEM_LIGHTEN_DARKEN_ALTERNATE_CELLS); |
| |
| red = (int) Math.min(red + ((255 - red) / 10) * scale, 255); |
| green = (int) Math.min(green + ((255 - green) / 10) * scale, 255); |
| blue = (int) Math.min(blue + ((255 - blue) / 10) * scale, 255); |
| |
| colorTextAlternate = new Color(Display.getDefault(), new RGB(red, green, blue)); |
| } |
| |
| public void disposeColors() |
| { |
| if (colorBackground != null) colorBackground.dispose(); |
| colorBackground = null; |
| |
| if (colorChanged != null) colorChanged.dispose(); |
| colorChanged = null; |
| |
| if (colorEdit != null) colorEdit.dispose(); |
| colorEdit = null; |
| |
| if (colorSelection != null) colorSelection.dispose(); |
| colorSelection = null; |
| |
| if (colorText != null) colorText.dispose(); |
| colorText = null; |
| |
| if (colorTextAlternate != null) colorTextAlternate.dispose(); |
| colorTextAlternate = null; |
| |
| disposeChangedColors(); |
| } |
| |
| public void applyPreferences() |
| { |
| if (fRendering != null && !fRendering.isDisposed()) |
| { |
| IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore(); |
| fRendering.setHistoryDepth(store.getInt(FPRenderingPreferenceConstants.MEM_HISTORY_TRAILS_COUNT)); |
| fRendering.setBackground(getColorBackground()); |
| |
| FPAbstractPane panes[] = fRendering.getRenderingPanes(); |
| for (int index = 0; index < panes.length; index++) |
| panes[index].setBackground(getColorBackground()); |
| |
| setRenderingPadding(FPRenderingPlugin.getDefault().getPreferenceStore().getString(IDebugUIConstants.PREF_PADDED_STR)); |
| |
| fRendering.redrawPanes(); |
| } |
| } |
| |
| public Color getColorBackground() |
| { |
| IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore(); |
| |
| if (store.getBoolean(FPRenderingPreferenceConstants.MEM_USE_GLOBAL_BACKGROUND)) |
| return Display.getDefault().getSystemColor(SWT.COLOR_LIST_BACKGROUND); |
| |
| return colorBackground; |
| } |
| |
| public Color getColorChanged() |
| { |
| return colorChanged; |
| } |
| |
| private void disposeChangedColors() |
| { |
| if (colorsChanged != null) |
| for (int index = 0; index < colorsChanged.length; index++) |
| colorsChanged[index].dispose(); |
| colorsChanged = null; |
| } |
| |
| public Color[] getColorsChanged() |
| { |
| if (colorsChanged != null && colorsChanged.length != fRendering.getHistoryDepth()) |
| { |
| disposeChangedColors(); |
| } |
| |
| if (colorsChanged == null) |
| { |
| colorsChanged = new Color[fRendering.getHistoryDepth()]; |
| colorsChanged[0] = colorChanged; |
| int shades = fRendering.getHistoryDepth() + 4; |
| int red = (255 - colorChanged.getRed()) / shades; |
| int green = (255 - colorChanged.getGreen()) / shades; |
| int blue = (255 - colorChanged.getBlue()) / shades; |
| for (int index = 1; index < fRendering.getHistoryDepth(); index++) |
| { |
| colorsChanged[index] = new Color(colorChanged.getDevice(), colorChanged.getRed() + ((shades - index) * red), colorChanged.getGreen() |
| + ((shades - index) * green), colorChanged.getBlue() + ((shades - index) * blue)); |
| } |
| } |
| |
| return colorsChanged; |
| } |
| |
| public Color getColorEdit() |
| { |
| return colorEdit; |
| } |
| |
| public Color getColorSelection() |
| { |
| IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore(); |
| |
| if (store.getBoolean(FPRenderingPreferenceConstants.MEM_USE_GLOBAL_SELECTION)) |
| return Display.getDefault().getSystemColor(SWT.COLOR_LIST_SELECTION); |
| |
| return colorSelection; |
| } |
| |
| public Color getColorText() |
| { |
| IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore(); |
| |
| if (store.getBoolean(FPRenderingPreferenceConstants.MEM_USE_GLOBAL_TEXT)) |
| return Display.getDefault().getSystemColor(SWT.COLOR_LIST_FOREGROUND); |
| |
| return colorText; |
| } |
| |
| public Color getColorTextAlternate() |
| { |
| return colorTextAlternate; |
| } |
| |
| // Menu creation |
| |
| public void createMenus() |
| { |
| // Add the menu to each of the rendering panes |
| |
| Control[] renderingControls = this.fRendering.getRenderingPanes(); |
| |
| for (int index = 0; index < renderingControls.length; index++) |
| super.createPopupMenu(renderingControls[index]); |
| |
| super.createPopupMenu(this.fRendering); |
| |
| // Copy |
| |
| final Action copyAction = new CopyAction(this.fRendering); |
| |
| // Copy address |
| |
| final Action copyAddressAction = new Action(FPRenderingMessages.getString("FPRendering.COPY_ADDRESS")) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| Display.getDefault().asyncExec(new Runnable() |
| { |
| @Override |
| public void run() |
| { |
| FPRendering.this.fRendering.copyAddressToClipboard(); |
| } |
| }); |
| } |
| }; |
| |
| // Reset to base address |
| |
| final Action gotoBaseAddressAction = new Action(FPRenderingMessages.getString("FPRendering.RESET_TO_BASE_ADDRESS")) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| Display.getDefault().asyncExec(new Runnable() |
| { |
| @Override |
| public void run() |
| { |
| FPRendering.this.fRendering.gotoAddress(FPRendering.this.fRendering.fBaseAddress); |
| } |
| }); |
| } |
| }; |
| |
| // Refresh |
| |
| final Action refreshAction = new Action(FPRenderingMessages.getString("FPRendering.REFRESH")) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| Display.getDefault().asyncExec(new Runnable() |
| { |
| @Override |
| public void run() |
| { |
| // For compatibility with DSF update modes (hopefully this will either be replaced |
| // by an enhanced platform interface or the caching will move out of the data layer) |
| |
| try |
| { |
| Method m = fRendering.getMemoryBlock().getClass().getMethod("clearCache", new Class[0]); //$NON-NLS-1$ |
| if (m != null) |
| m.invoke(fRendering.getMemoryBlock(), new Object[0]); |
| } |
| catch (Exception e) |
| { |
| } |
| |
| FPRendering.this.fRendering.refresh(); |
| } |
| }); |
| } |
| }; |
| |
| // Little Endian |
| |
| actionDisplayLittleEndian = new Action(FPRenderingMessages.getString("FPRendering.ENDIAN_LITTLE"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| fRendering.setDisplayLittleEndian(true); |
| setRMCvalue(IFPRConstants.ENDIAN_KEY, Endian.LITTLE.getValue()); |
| } |
| }; |
| |
| // Big Endian |
| |
| actionDisplayBigEndian = new Action(FPRenderingMessages.getString("FPRendering.ENDIAN_BIG"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| fRendering.setDisplayLittleEndian(false); |
| setRMCvalue(IFPRConstants.ENDIAN_KEY, Endian.BIG.getValue()); |
| } |
| }; |
| |
| // Endian settings |
| |
| int endian = getRMCvalue(IFPRConstants.ENDIAN_KEY); |
| |
| endian = endian != -1 ? endian : (fRendering.isDisplayLittleEndian() ? Endian.LITTLE.getValue() : Endian.BIG.getValue()); |
| boolean le = (endian == Endian.LITTLE.getValue()); |
| |
| fRendering.setDisplayLittleEndian(le); |
| actionDisplayLittleEndian.setChecked(le); |
| actionDisplayBigEndian.setChecked(!le); |
| |
| // Float |
| |
| boolean dtFloat = getRMCvalue(IFPRConstants.DATATYPE_KEY) == FPDataType.FLOAT.getValue(); |
| this.fRendering.setFPDataType(dtFloat ? FPDataType.FLOAT : FPDataType.DOUBLE); |
| |
| actionFloatingPoint32 = new Action(FPRenderingMessages.getString("FPRendering.FLOATING_POINT_32"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| fRendering.setDisplayedPrecision(getRMCvalue(IFPRConstants.FLOAT_DISP_KEY)); |
| fRendering.setFPDataType(FPDataType.FLOAT); |
| setRMCvalue(IFPRConstants.DATATYPE_KEY, FPDataType.FLOAT.getValue()); |
| setSelections(); |
| } |
| }; |
| |
| // Double |
| |
| actionFloatingPoint64 = new Action(FPRenderingMessages.getString("FPRendering.FLOATING_POINT_64"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| fRendering.setDisplayedPrecision(getRMCvalue(IFPRConstants.DOUBLE_DISP_KEY)); |
| fRendering.setFPDataType(FPDataType.DOUBLE); |
| setRMCvalue(IFPRConstants.DATATYPE_KEY, FPDataType.DOUBLE.getValue()); |
| setSelections(); |
| } |
| }; |
| |
| // Displayed precision: 4 digits |
| |
| int savedPrecision = getDisplayedPrecision(); |
| |
| actionDisplay4Digits = new Action(FPRenderingMessages.getString("FPRendering.DISPLAYED_PRECISION_4"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| FPRendering.this.fRendering.setDisplayedPrecision(4); |
| setDisplayedPrecision(4); |
| } |
| }; |
| |
| if (savedPrecision == 4) |
| { |
| FPRendering.this.fRendering.setDisplayedPrecision(4); |
| actionDisplay4Digits.setChecked(savedPrecision == 4); |
| } |
| |
| // Displayed precision: 8 digits |
| |
| actionDisplay8Digits = new Action(FPRenderingMessages.getString("FPRendering.DISPLAYED_PRECISION_8"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| FPRendering.this.fRendering.setDisplayedPrecision(8); |
| setDisplayedPrecision(8); |
| } |
| }; |
| |
| if (savedPrecision == 8) |
| { |
| FPRendering.this.fRendering.setDisplayedPrecision(8); |
| actionDisplay8Digits.setChecked(savedPrecision == 8); |
| } |
| |
| // Displayed precision: 16 digits (doubles only) |
| |
| actionDisplay16Digits = new Action(FPRenderingMessages.getString("FPRendering.DISPLAYED_PRECISION_16"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| FPRendering.this.fRendering.setDisplayedPrecision(16); |
| setDisplayedPrecision(16); |
| } |
| }; |
| |
| if (savedPrecision == 16) |
| { |
| FPRendering.this.fRendering.setDisplayedPrecision(16); |
| actionDisplay16Digits.setChecked(savedPrecision == 16); |
| } |
| |
| // Set RMC selections based on datatype and displayed precision settings in effect |
| |
| setSelections(); |
| |
| // Columns |
| |
| int savedColumnCount = getRMCvalue(IFPRConstants.COLUMN_COUNT_KEY); |
| |
| final Action displayColumnCountAuto = new Action(FPRenderingMessages.getString("FPRendering.COLUMN_COUNT_AUTO"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| FPRendering.this.fRendering.setColumnsSetting(Rendering.COLUMNS_AUTO_SIZE_TO_FIT); |
| setRMCvalue(IFPRConstants.COLUMN_COUNT_KEY, Rendering.COLUMNS_AUTO_SIZE_TO_FIT); |
| } |
| }; |
| |
| boolean autoMode = savedColumnCount == Rendering.COLUMNS_AUTO_SIZE_TO_FIT; |
| displayColumnCountAuto.setChecked(autoMode); |
| |
| final Action[] displayColumnCounts = new Action[MAX_MENU_COLUMN_COUNT]; |
| |
| for (int index = 0, j = 1; index < MAX_MENU_COLUMN_COUNT; index++, j *= 2) |
| { |
| final int finali = j; |
| displayColumnCounts[index] = new Action(FPRenderingMessages.getString("FPRendering.COLUMN_COUNT_" + finali), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| FPRendering.this.fRendering.setColumnsSetting(finali); |
| setRMCvalue(IFPRConstants.COLUMN_COUNT_KEY, finali); |
| } |
| }; |
| displayColumnCounts[index].setChecked(fRendering.getColumnsSetting() == finali); |
| } |
| |
| // Set/clear column count selections as appropriate |
| |
| int countValue = getRMCvalue(IFPRConstants.COLUMN_COUNT_KEY); |
| |
| for (int index = 0; index < MAX_MENU_COLUMN_COUNT; index++) |
| displayColumnCounts[index].setChecked(countValue != Rendering.COLUMNS_AUTO_SIZE_TO_FIT && (countValue == (1 << index))); |
| |
| fRendering.setColumnsSetting(getRMCvalue(IFPRConstants.COLUMN_COUNT_KEY)); |
| |
| final Action displayColumnCountCustomValue = new Action("", IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| } |
| }; |
| |
| final Action displayColumnCountCustom = new Action(FPRenderingMessages.getString("FPRendering.COLUMN_COUNT_CUSTOM"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| InputDialog inputDialog = new InputDialog |
| ( |
| fRendering.getShell(), "Set Column Count", "Please enter column count", "", new IInputValidator() //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| { |
| @Override |
| public String isValid(String input) |
| { |
| try |
| { |
| int index = Integer.parseInt(input); |
| |
| if (index <= 0) |
| return "Please enter a positive integer"; //$NON-NLS-1$ |
| |
| if (index > 200) |
| return "Please enter a positive integer not greater than 200"; //$NON-NLS-1$ |
| } |
| catch (NumberFormatException x) |
| { |
| return "Please enter a positive integer"; //$NON-NLS-1$ |
| } |
| |
| return null; |
| } |
| } |
| ); |
| |
| if (inputDialog.open() != Window.OK) |
| { |
| this.setChecked(false); |
| int currentColumnSetting = FPRendering.this.fRendering.getColumnsSetting(); |
| |
| if (currentColumnSetting == Rendering.COLUMNS_AUTO_SIZE_TO_FIT) |
| displayColumnCountAuto.setChecked(true); |
| else |
| { |
| boolean currentCountIsCustom = true; |
| |
| for (int index = 0, j = 1; index < MAX_MENU_COLUMN_COUNT && currentCountIsCustom; index++, j *= 2) |
| { |
| currentCountIsCustom = (j != fRendering.getColumnsSetting()); |
| if (j == fRendering.getColumnsSetting()) |
| displayColumnCounts[index].setChecked(true); |
| } |
| |
| if (currentCountIsCustom) |
| displayColumnCountCustomValue.setChecked(true); |
| } |
| |
| return; |
| } |
| |
| int newColumnCount = -1; |
| |
| try |
| { |
| newColumnCount = Integer.parseInt(inputDialog.getValue()); |
| } |
| catch (NumberFormatException x) |
| { |
| assert false; |
| } |
| |
| boolean customIsOneOfStandardListChoices = false; |
| |
| for (int index = 0, j = 1; index < MAX_MENU_COLUMN_COUNT; index++, j *= 2) |
| { |
| if (newColumnCount == j) |
| { |
| customIsOneOfStandardListChoices = true; |
| FPRendering.this.fRendering.setColumnsSetting(newColumnCount); |
| setRMCvalue(IFPRConstants.COLUMN_COUNT_KEY, newColumnCount); |
| this.setChecked(false); |
| displayColumnCountCustomValue.setChecked(false); |
| displayColumnCounts[index].setChecked(true); |
| break; |
| } |
| } |
| |
| if (!customIsOneOfStandardListChoices) |
| { |
| FPRendering.this.fRendering.setColumnsSetting(newColumnCount); |
| setRMCvalue(IFPRConstants.COLUMN_COUNT_KEY, newColumnCount); |
| this.setChecked(false); |
| |
| displayColumnCountCustomValue.setChecked(true); |
| displayColumnCountCustomValue.setText(Integer.valueOf(fRendering.getColumnsSetting()).toString()); |
| } |
| } |
| }; |
| |
| // Check for a custom value: If we're not in "Auto Fill" mode, check for standard column sizes. |
| // If none of the standard sizes were entered, then it's a custom value; set it and display it. |
| |
| boolean customColumnCountSet = true; |
| countValue = getRMCvalue(IFPRConstants.COLUMN_COUNT_KEY); |
| |
| if (countValue != Rendering.COLUMNS_AUTO_SIZE_TO_FIT) |
| { |
| for (int index = 0; index < MAX_MENU_COLUMN_COUNT; index++) |
| { |
| // If the column count is one of the standard values, set flag to false and exit the loop |
| |
| if (countValue == (1 << index)) |
| { |
| customColumnCountSet = false; |
| break; |
| } |
| } |
| |
| if (customColumnCountSet) |
| { |
| FPRendering.this.fRendering.setColumnsSetting(countValue); |
| displayColumnCountCustomValue.setChecked(true); |
| displayColumnCountCustomValue.setText(Integer.valueOf(fRendering.getColumnsSetting()).toString()); |
| } |
| } |
| |
| // Add the right-mouse-click (RMC) context menu items |
| |
| getPopupMenuManager().addMenuListener(new IMenuListener() |
| { |
| @Override |
| public void menuAboutToShow(IMenuManager manager) |
| { |
| manager.add(new Separator()); |
| |
| MenuManager sub = new MenuManager(FPRenderingMessages.getString("FPRendering.PANES")); //$NON-NLS-1$ |
| |
| sub = new MenuManager(FPRenderingMessages.getString("FPRendering.ENDIAN")); //$NON-NLS-1$ |
| sub.add(actionDisplayBigEndian); |
| sub.add(actionDisplayLittleEndian); |
| manager.add(sub); |
| |
| sub = new MenuManager(FPRenderingMessages.getString("FPRendering.NUMBER_TYPE")); //$NON-NLS-1$ |
| sub.add(actionFloatingPoint32); |
| sub.add(actionFloatingPoint64); |
| manager.add(sub); |
| |
| sub = new MenuManager(FPRenderingMessages.getString("FPRendering.PRECISION")); //$NON-NLS-1$ |
| sub.add(actionDisplay4Digits); |
| sub.add(actionDisplay8Digits); |
| sub.add(actionDisplay16Digits); |
| manager.add(sub); |
| |
| // TODO: Add separator for FP group here: manager.add(new Separator()); |
| |
| sub = new MenuManager(FPRenderingMessages.getString("FPRendering.COLUMN_COUNT")); //$NON-NLS-1$ |
| sub.add(displayColumnCountAuto); |
| |
| for (int index = 0; index < displayColumnCounts.length; index++) |
| sub.add(displayColumnCounts[index]); |
| |
| boolean currentCountIsCustom = fRendering.getColumnsSetting() != 0; |
| |
| for (int index = 0, j = 1; index < MAX_MENU_COLUMN_COUNT && currentCountIsCustom; index++, j *= 2) |
| currentCountIsCustom = (j != fRendering.getColumnsSetting()); |
| |
| if (currentCountIsCustom) |
| sub.add(displayColumnCountCustomValue); |
| |
| sub.add(displayColumnCountCustom); |
| manager.add(sub); |
| |
| // Update modes |
| |
| int updateMode = getRMCvalue(IFPRConstants.UPDATEMODE_KEY); |
| |
| final Action updateAlwaysAction = new Action(FPRenderingMessages.getString("FPRendering.UPDATE_ALWAYS"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| fRendering.setUpdateMode(Rendering.UPDATE_ALWAYS); |
| setRMCvalue(IFPRConstants.UPDATEMODE_KEY, Rendering.UPDATE_ALWAYS); |
| } |
| }; |
| updateAlwaysAction.setChecked(updateMode == Rendering.UPDATE_ALWAYS); |
| |
| final Action updateOnBreakpointAction = new Action(FPRenderingMessages.getString("FPRendering.UPDATE_ON_BREAKPOINT"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| fRendering.setUpdateMode(Rendering.UPDATE_ON_BREAKPOINT); |
| setRMCvalue(IFPRConstants.UPDATEMODE_KEY, Rendering.UPDATE_ON_BREAKPOINT); |
| } |
| }; |
| updateOnBreakpointAction.setChecked(updateMode == Rendering.UPDATE_ON_BREAKPOINT); |
| |
| final Action updateManualAction = new Action(FPRenderingMessages.getString("FPRendering.UPDATE_MANUAL"), IAction.AS_RADIO_BUTTON) //$NON-NLS-1$ |
| { |
| @Override |
| public void run() |
| { |
| fRendering.setUpdateMode(Rendering.UPDATE_MANUAL); |
| setRMCvalue(IFPRConstants.UPDATEMODE_KEY, Rendering.UPDATE_MANUAL); |
| } |
| }; |
| updateManualAction.setChecked(updateMode == Rendering.UPDATE_MANUAL); |
| |
| // Add menu |
| |
| sub = new MenuManager(FPRenderingMessages.getString("FPRendering.UPDATEMODE")); //$NON-NLS-1$ |
| sub.add(updateAlwaysAction); |
| sub.add(updateOnBreakpointAction); |
| sub.add(updateManualAction); |
| manager.add(sub); |
| manager.add(new Separator()); |
| |
| BigInteger start = fRendering.getSelection().getStart(); |
| BigInteger end = fRendering.getSelection().getEnd(); |
| copyAction.setEnabled(start != null && end != null); |
| |
| manager.add(copyAction); |
| manager.add(copyAddressAction); |
| |
| manager.add(gotoBaseAddressAction); |
| manager.add(refreshAction); |
| manager.add(new Separator()); |
| manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); |
| } |
| }); |
| } |
| |
| // Set/clear selections as appropriate |
| |
| public void setSelections() |
| { |
| if (actionDisplay4Digits == null || actionDisplay8Digits == null || actionDisplay16Digits == null) return; |
| |
| // Enable/disable and set/clear menu RMC elements based on currently selected datatype |
| |
| boolean dtFloat = FPRendering.this.fRendering.getFPDataType() == FPDataType.FLOAT; |
| |
| actionDisplay16Digits.setEnabled(!dtFloat); |
| actionFloatingPoint32.setChecked(dtFloat); |
| actionFloatingPoint64.setChecked(!dtFloat); |
| |
| // Set/clear RMC elements based on displayed precision |
| |
| int displayedPrecision = getRMCvalue(dtFloat ? IFPRConstants.FLOAT_DISP_KEY : IFPRConstants.DOUBLE_DISP_KEY); |
| |
| actionDisplay4Digits.setChecked (displayedPrecision == 4); |
| actionDisplay8Digits.setChecked (displayedPrecision == 8); |
| actionDisplay16Digits.setChecked(displayedPrecision == 16); |
| } |
| |
| |
| @Override |
| public Control getControl() |
| { |
| return this.fRendering; |
| } |
| |
| // Selection is terminology for caret position |
| |
| @Override |
| public BigInteger getSelectedAddress() |
| { |
| FPIMemorySelection selection = fRendering.getSelection(); |
| if (selection == null || selection.getStart() == null) |
| return fRendering.getCaretAddress(); |
| |
| return selection.getStartLow(); |
| } |
| |
| @Override |
| public MemoryByte[] getSelectedAsBytes() |
| { |
| try |
| { |
| // default to the caret address and the cell count size |
| BigInteger startAddr = fRendering.getCaretAddress(); |
| int byteCount = fRendering.getCharsPerColumn(); |
| |
| // Now see if there's a selection |
| FPIMemorySelection selection = fRendering.getSelection(); |
| if (selection != null && selection.getStart() != null) |
| { |
| // The implementation is such that just having a caret somewhere (without multiple cells |
| // being selected) constitutes a selection, except for when the rendering is in its initial |
| // state, i.e. just because we get here doesn't mean the user has selected more than one cell. |
| |
| startAddr = getSelectedAddress(); |
| |
| if (selection.getHigh() != null) |
| byteCount = selection.getHigh().subtract(selection.getLow()).intValue() * fRendering.getAddressableSize(); |
| } |
| |
| return fRendering.getViewportCache().getBytes(startAddr, byteCount); |
| |
| } |
| catch (DebugException de) |
| { |
| return new MemoryByte[0]; |
| } |
| } |
| |
| @Override |
| public void goToAddress(final BigInteger address) throws DebugException |
| { |
| Display.getDefault().asyncExec(new Runnable() |
| { |
| @Override |
| public void run() |
| { |
| fRendering.gotoAddress(address); |
| } |
| }); |
| } |
| |
| protected void setTargetMemoryLittleEndian(boolean littleEndian) |
| { |
| // Once we actually read memory we can determine the endianess and need to set these actions accordingly. |
| actionDisplayBigEndian.setChecked(!littleEndian); |
| actionDisplayLittleEndian.setChecked(littleEndian); |
| |
| // When target endian changes, force display endian to track. User can then change display endian if desired. |
| fRendering.setDisplayLittleEndian(littleEndian); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class) |
| */ |
| @Override |
| public Object getAdapter(Class adapter) |
| { |
| if (adapter == IWorkbenchAdapter.class) |
| { |
| if (this.fWorkbenchAdapter == null) |
| { |
| this.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 FPRenderingMessages.getString("FPRendering.RENDERING_NAME"); //$NON-NLS-1$ |
| } |
| |
| @Override |
| public Object getParent(Object o) |
| { |
| return null; |
| } |
| }; |
| } |
| return this.fWorkbenchAdapter; |
| } |
| |
| if (adapter == IMemoryBlockConnection.class) |
| { |
| if (fConnection == null) |
| { |
| fConnection = new IMemoryBlockConnection() |
| { |
| @Override |
| public void update() |
| { |
| // update UI asynchronously |
| Display display = FPRenderingPlugin.getDefault().getWorkbench().getDisplay(); |
| display.asyncExec(new Runnable() |
| { |
| @Override |
| public void run() |
| { |
| try |
| { |
| if (fBigBaseAddress != FPRendering.this.fRendering.getMemoryBlock().getBigBaseAddress()) |
| { |
| fBigBaseAddress = FPRendering.this.fRendering.getMemoryBlock().getBigBaseAddress(); |
| FPRendering.this.fRendering.gotoAddress(fBigBaseAddress); |
| } |
| FPRendering.this.fRendering.refresh(); |
| } |
| catch (DebugException e) |
| { |
| } |
| } |
| }); |
| } |
| }; |
| } |
| |
| return fConnection; |
| } |
| |
| return super.getAdapter(adapter); |
| } |
| |
| @Override |
| public void resetRendering() throws DebugException |
| { |
| fRendering.gotoAddress(fRendering.fBaseAddress); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.cdt.debug.internal.core.model.provisional. |
| * IMemoryRenderingViewportProvider#getViewportAddress() |
| */ |
| @Override |
| public BigInteger getViewportAddress() |
| { |
| return fRendering.getViewportStartAddress(); |
| } |
| |
| // Persistence methods |
| |
| void setDisplayedPrecision(int precision) |
| { |
| // Save the appropriate displayed precision value, based on data type, in the store |
| |
| if (FPRendering.this.fRendering.getFPDataType() == FPDataType.FLOAT) |
| setRMCvalue(IFPRConstants.FLOAT_DISP_KEY, precision); |
| else |
| setRMCvalue(IFPRConstants.DOUBLE_DISP_KEY, precision); |
| } |
| |
| private int getDisplayedPrecision() |
| { |
| // Retrieve the persisted data value from the store |
| |
| IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore(); |
| |
| FPDataType dataType = FPRendering.this.fRendering.getFPDataType(); |
| |
| if (store != null) |
| return store.getInt(dataType == FPDataType.FLOAT ? IFPRConstants.FLOAT_DISP_KEY : IFPRConstants.DOUBLE_DISP_KEY); |
| |
| // If there's nothing persisted, return the default precision for data type |
| |
| return dataType == FPDataType.FLOAT ? FPDataType.FLOAT.getDisplayedPrecision() : FPDataType.DOUBLE.getDisplayedPrecision(); |
| } |
| |
| void setRMCvalue(String key, int value) |
| { |
| // Save the specified key and int value |
| |
| IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore(); |
| if (store != null) store.setValue(key, value); |
| } |
| |
| int getRMCvalue(String key) |
| { |
| // Return the value for the specified key |
| |
| IPreferenceStore store = FPRenderingPlugin.getDefault().getPreferenceStore(); |
| return (store != null) ? store.getInt(key) : 0; |
| } |
| } |
| |
| // Copy class |
| |
| class CopyAction extends Action |
| { |
| // TODO for the sake of large copies, this action should probably read in |
| // blocks on a Job. |
| |
| private Rendering fRendering; |
| private int fType = DND.CLIPBOARD; |
| |
| public CopyAction(Rendering rendering) |
| { |
| this(rendering, DND.CLIPBOARD); |
| } |
| |
| @SuppressWarnings("restriction") // using platform's labels and images; acceptable build risk |
| public CopyAction(Rendering rendering, int clipboardType) |
| { |
| super(); |
| fType = clipboardType; |
| fRendering = rendering; |
| setText(DebugUIMessages.CopyViewToClipboardAction_title); |
| setToolTipText(DebugUIMessages.CopyViewToClipboardAction_tooltip); |
| setImageDescriptor(DebugPluginImages |
| .getImageDescriptor(IInternalDebugUIConstants.IMG_ELCL_COPY_VIEW_TO_CLIPBOARD)); |
| setHoverImageDescriptor(DebugPluginImages |
| .getImageDescriptor(IInternalDebugUIConstants.IMG_LCL_COPY_VIEW_TO_CLIPBOARD)); |
| setDisabledImageDescriptor(DebugPluginImages |
| .getImageDescriptor(IInternalDebugUIConstants.IMG_DLCL_COPY_VIEW_TO_CLIPBOARD)); |
| } |
| |
| @Override |
| public void run() |
| { |
| Clipboard clip = null; |
| final String PANE_SPACING = " "; //$NON-NLS-1$ |
| |
| try |
| { |
| clip = new Clipboard(fRendering.getDisplay()); |
| |
| BigInteger start = fRendering.getSelection().getStart(); |
| BigInteger end = fRendering.getSelection().getEnd(); |
| |
| if (end == null) return; // End will be null when there is nothing selected |
| |
| if (start.compareTo(end) > 0) |
| { |
| // Swap start and end |
| |
| BigInteger bigI = end; |
| end = start; |
| start = bigI; |
| } |
| |
| final FPDataType numberType = fRendering.getFPDataType(); |
| final int bytesPerColumn = numberType.getByteLength(); |
| final boolean isLittleEndian = fRendering.isTargetLittleEndian(); |
| final int columns = fRendering.getColumnCount(); |
| BigInteger lengthToRead = end.subtract(start); |
| |
| int rows = lengthToRead.divide(BigInteger.valueOf(columns * (fRendering.getFPDataType().getByteLength()))).intValue(); |
| |
| if (rows * columns * bytesPerColumn < lengthToRead.intValue()) rows++; |
| |
| StringBuilder buffer = new StringBuilder(); |
| |
| for (int row = 0; row < rows; row++) |
| { |
| BigInteger rowAddress = start.add(BigInteger.valueOf(row * columns * bytesPerColumn)); |
| |
| if (fRendering.getPaneVisible(Rendering.PANE_ADDRESS)) |
| { |
| buffer.append(fRendering.getAddressString(rowAddress)); |
| buffer.append(PANE_SPACING); |
| } |
| |
| if (fRendering.getPaneVisible(Rendering.PANE_DATA)) |
| { |
| for(int col = 0; col < columns; col++) |
| { |
| BigInteger cellAddress = rowAddress.add(BigInteger.valueOf(col * bytesPerColumn)); |
| |
| if (cellAddress.compareTo(end) < 0) |
| { |
| try |
| { |
| FPMemoryByte bytes[] = fRendering.getBytes(cellAddress, bytesPerColumn); |
| buffer.append(fRendering.sciNotationString(bytes, numberType, isLittleEndian)); |
| } |
| catch(DebugException de) |
| { |
| fRendering |
| .logError( |
| FPRenderingMessages |
| .getString("FPRendering.FAILURE_COPY_OPERATION"), de); //$NON-NLS-1$ |
| return; |
| } |
| } |
| else |
| { |
| for(int i = fRendering.getCharsPerColumn(); i > 0; i--) |
| buffer.append(' '); |
| } |
| |
| if (col != columns - 1) |
| buffer.append(' '); |
| } |
| } |
| |
| if (fRendering.getPaneVisible(Rendering.PANE_DATA)) |
| buffer.append(PANE_SPACING); |
| |
| buffer.append("\n"); //$NON-NLS-1$ |
| } |
| |
| if (buffer.length() > 0) |
| { |
| TextTransfer plainTextTransfer = TextTransfer.getInstance(); |
| clip.setContents(new Object[] { buffer.toString() }, new Transfer[] { plainTextTransfer }, fType); |
| } |
| } |
| finally |
| { |
| if (clip != null) |
| { |
| clip.dispose(); |
| } |
| } |
| } |
| } |