/* * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.max.ins.gui; import java.awt.datatransfer.*; import java.awt.event.*; import com.sun.max.ins.*; import com.sun.max.tele.*; import com.sun.max.unsafe.*; /** * A selectable, lightweight label for displaying memory * locations in the VM with different interpretations. */ public abstract class LocationLabel extends InspectorLabel { protected int value; protected Address origin; private MaxVMState lastRefreshedState = null; /** * @return a menu containing actions suitable for a generic memory location. */ protected InspectorPopupMenu createLocationMenu() { final InspectorPopupMenu menu = new InspectorPopupMenu("Location"); final Address address = origin.plus(value); menu.add(inspection().actions().copyWord(address, null)); menu.add(views().memory().makeViewAction(address, null)); return menu; } /** * Resets the text associated with the label. */ protected abstract void updateText(); protected LocationLabel(Inspection inspection, int value, Address origin) { super(inspection, null); this.value = value; this.origin = origin; if (origin != null) { addMouseListener(new InspectorMouseClickAdapter(inspection) { @Override public void procedure(final MouseEvent mouseEvent) { switch (inspection().gui().getButton(mouseEvent)) { case MouseEvent.BUTTON3: { createLocationMenu().show(mouseEvent.getComponent(), mouseEvent.getX(), mouseEvent.getY()); break; } default: { break; } } } }); } enableDragSource(); } public final void refresh(boolean force) { if (vm().state().newerThan(lastRefreshedState) || force) { lastRefreshedState = vm().state(); updateText(); } } @Override public Transferable getTransferable() { if (origin == null) { return null; } final Address address = origin.plus(value); return new InspectorTransferable.AddressTransferable(inspection(), address); } public final void setValue(int value) { this.value = value; updateText(); } public void setValue(int value, Address origin) { this.value = value; this.origin = origin; updateText(); } /** * A label that displays, in hex, an address relative to an origin. * A right-button menu is available with some useful commands. */ public static class AsAddressWithByteOffset extends LocationLabel { public AsAddressWithByteOffset(Inspection inspection, int offset, Address origin) { super(inspection, offset, origin); redisplay(); } public AsAddressWithByteOffset(Inspection inspection) { this(inspection, 0, Address.zero()); } public final void redisplay() { setFont(preference().style().hexDataFont()); updateText(); } @Override protected final void updateText() { final Address address = origin.plus(value); setText(address.toHexString()); setWrappedToolTipHtmlText(address.to0xHexString() + "<br>" + intToPlusMinusDecimalAndHex(value) + " bytes from origin"); } } /** * A label that displays, in hex, an address with non-negative position relative to an origin. * A right-button menu is available with some useful commands. * VM positions are non-negative and displayed without a '+' prefix. * The address does not update if contents at location get moved. */ public static class AsAddressWithPosition extends LocationLabel { public AsAddressWithPosition(Inspection inspection, int value, Address origin) { super(inspection, value, origin); assert value >= 0; redisplay(); } public final void redisplay() { setFont(preference().style().hexDataFont()); updateText(); } @Override protected final void updateText() { final Address address = origin.plus(value); setText(address.toHexString()); setWrappedToolTipHtmlText(address.to0xHexString() + " (position " + intToDecimalAndHex(value) + " bytes from start)"); } } /** * A label that displays, in decimal, a non-negative position relative to some (optionally specified) origin. * If an origin is specified, then a ToolTip shows that actual address and a right-button * menu is available with some useful commands. * VM positions are non-negative and displayed without a '+' prefix. * The address does not update if contents at location get moved. */ public static class AsPosition extends LocationLabel { public AsPosition(Inspection inspection, int value) { this(inspection, value, null); } public AsPosition(Inspection inspection, int value, Address origin) { super(inspection, value, origin); redisplay(); } public final void redisplay() { setFont(preference().style().decimalDataFont()); updateText(); } @Override protected final void updateText() { setText(Integer.toString(value)); if (origin != null) { setWrappedToolTipHtmlText(origin.plus(value).to0xHexString() + "<br>Position " + intToDecimalAndHex(value) + " bytes from start"); } else { setWrappedToolTipHtmlText("Position " + intToDecimalAndHex(value)); } } } /** * A label that displays, in decimal, an offset in bytes from some origin; * if an origin is specified, then a ToolTip shows that actual address and a right-button * menu is available with some useful commands. * The address does not update if contents at location get moved. */ public static class AsOffset extends LocationLabel { private int indexScalingFactor; public AsOffset(Inspection inspection, int indexScalingFactor) { super(inspection, 0, Address.zero()); this.indexScalingFactor = indexScalingFactor; redisplay(); } public AsOffset(Inspection inspection) { super(inspection, 0, Address.zero()); this.indexScalingFactor = 0; redisplay(); } public void redisplay() { setFont(preference().style().decimalDataFont()); updateText(); } @Override protected void updateText() { String toolTip = origin.plus(value).to0xHexString(); if (indexScalingFactor != 0) { toolTip += "<br>index=" + Integer.toString(value / indexScalingFactor); } toolTip += "<br>" + intToPlusMinusDecimalAndHex(value) + " bytes from origin"; setWrappedToolTipHtmlText(toolTip); setText(intToPlusMinusDecimal(value)); } } /** * A label that displays, in decimal, an offset in words from some origin; * if an origin is specified, then a ToolTip shows that actual address and a right-button * menu is available with some useful commands. * Note that the offset is set as bytes, but displayed as words. * The address does not update if contents at location get moved. */ public static class AsWordOffset extends LocationLabel { /** * Creates a label that displays an offset from an origin as words. * * @param offset offset in bytes from the origin * @param origin the base address for display */ public AsWordOffset(Inspection inspection, int offset, Address origin) { super(inspection, offset, origin); redisplay(); } public AsWordOffset(Inspection inspection, int offset) { this(inspection, offset, Address.zero()); } public AsWordOffset(Inspection inspection) { this(inspection, 0, Address.zero()); } public void redisplay() { setFont(preference().style().decimalDataFont()); updateText(); } @Override protected void updateText() { final int wordOffset = value / vm().platform().nBytesInWord(); setWrappedToolTipHtmlText(origin.plus(value).to0xHexString() + "<br>offset= " + intToPlusMinusDecimalAndHex(wordOffset) + " words from origin)"); setText(intToPlusMinusDecimal(wordOffset)); } } /** * A label that displays a memory location in decimal indexed form (" <prefix>[<index>]"); * A ToolTip shows that actual address and a right-button * menus is available with some useful commands. * The address does not update if contents at location get moved. */ public static class AsIndex extends LocationLabel { private final String prefix; private int index; /** * A label that displays a memory location <origin> + <offset> as "<prefix>[<index>]", * with a ToolTip giving more detail. * * @param prefix optional textual prefix to the value display * @param index the logical index of the value being displayed * @param offset the offset in bytes from origin of the value being displayed * @param origin the base location in VM memory from which the location of the value is computed */ public AsIndex(Inspection inspection, String prefix, int index, int offset, Address origin) { super(inspection, offset, origin); this.prefix = prefix; this.index = index; redisplay(); } public void redisplay() { setFont(preference().style().decimalDataFont()); updateText(); } /** * Sets the value of the label to a new location in VM memory. * * @param index the logical index of the value being displayed * @param offset the offset in bytes from origin of the value being displayed * @param origin the base location in VM memory from which the location of the value is computed */ public void setValue(int index, int offset, Address origin) { this.index = index; this.value = offset; this.origin = origin; updateText(); } @Override protected void updateText() { setText(prefix + "[" + index + "]"); if (origin != null) { setWrappedToolTipHtmlText(origin.plus(value).to0xHexString() + "<br>" + intToPlusMinusDecimalAndHex(value) + " bytes from origin"); } else { setWrappedToolTipHtmlText(intToPlusMinusDecimalAndHex(value) + " bytes from origin"); } } } /** * A label that displays a textual label, * with associated memory location information (origin * and position) displayed in the ToolTip text. * Displays nothing if the label is null. */ public static class AsTextLabel extends LocationLabel { private String labelText; public AsTextLabel(Inspection inspection, Address origin) { super(inspection, 0, origin); redisplay(); } public final void setLocation(String labelText, int value) { this.labelText = labelText; setValue(value); } public final void redisplay() { setFont(preference().style().defaultFont()); updateText(); } @Override protected final void updateText() { setText(labelText); if (labelText != null && !labelText.equals("")) { setWrappedToolTipHtmlText(origin.plus(value).to0xHexString() + " (position " + intToDecimalAndHex(value) + " bytes from start)"); } else { setToolTipText(null); } } } }