alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (MemoryPanel.java)

This example Java source code file (MemoryPanel.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

actionwrapper, awt, biginteger, courier, datatransfer, debugger, event, gui, highprecisionjscrollbar, jtable, listselectionmodel, memorypanel, numberformatexception, object, rectangle, runtimeexception, string, stringbuffer, swing, transferable

The MemoryPanel.java Java example source code

/*
 * Copyright (c) 2001, 2002, 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 sun.jvm.hotspot.ui;

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.io.IOException;
import java.math.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.ui.*;

public class MemoryPanel extends JPanel {
  private boolean is64Bit;
  private Debugger debugger;
  private int addressSize;
  private String unmappedAddrString;
  private HighPrecisionJScrollBar scrollBar;
  private AbstractTableModel model;
  private JTable table;
  private BigInteger startVal;
  // Includes any partially-visible row at the bottom
  private int numVisibleRows;
  // Frequently-used subexpression
  private int numUsableRows;
  // Multi-row (and multi-column) selection. Have to duplicate state
  // from UI so this can work as we scroll off the screen.
  private boolean haveAnchor;
  private int     rowAnchorIndex;
  private int     colAnchorIndex;
  private boolean haveLead;
  private int     rowLeadIndex;
  private int     colLeadIndex;

  abstract class ActionWrapper extends AbstractAction {
    private Action parent;
    ActionWrapper() {
    }

    void setParent(Action parent) {
      this.parent = parent;
    }

    Action getParent() {
      return parent;
    }

    public void actionPerformed(ActionEvent e) {
      if (getParent() != null) {
        getParent().actionPerformed(e);
      }
    }
  }

  public MemoryPanel(final Debugger debugger, boolean is64Bit) {
    super();
    this.debugger = debugger;
    this.is64Bit = is64Bit;
    if (is64Bit) {
      addressSize = 8;
      unmappedAddrString = "??????????????????";
    } else {
      addressSize = 4;
      unmappedAddrString = "??????????";
    }
    setLayout(new BorderLayout());
    setupScrollBar();
    add(scrollBar, BorderLayout.EAST);

    model = new AbstractTableModel() {
        public int getRowCount() {
          return numVisibleRows;
        }
        public int getColumnCount() {
          return 2;
        }
        public Object getValueAt(int row, int column) {
          switch (column) {
          case 0:  return bigIntToHexString(startVal.add(new BigInteger(Integer.toString((row * addressSize)))));
          case 1: {
            try {
              Address addr = bigIntToAddress(startVal.add(new BigInteger(Integer.toString((row * addressSize)))));
              if (addr != null) {
                return addressToString(addr.getAddressAt(0));
              }
              return unmappedAddrString;
            } catch (UnmappedAddressException e) {
              return unmappedAddrString;
            }
          }
          default: throw new RuntimeException("Column " + column + " out of bounds");
          }
        }
        public boolean isCellEditable(int row, int col) {
          return false;
        }
      };

    // View with JTable with no header
    table = new JTable(model);
    table.setTableHeader(null);
    table.setShowGrid(false);
    table.setIntercellSpacing(new Dimension(0, 0));
    table.setCellSelectionEnabled(true);
    table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
    table.setDragEnabled(true);
    Font font = GraphicsUtilities.lookupFont("Courier");
    if (font == null) {
      throw new RuntimeException("Error looking up monospace font Courier");
    }
    table.setFont(font);

    // Export proper data.
    // We need to keep our own notion of the selection in order to
    // properly export data, since the selection can go beyond the
    // visible area on the screen (and since the table's model doesn't
    // back all of those slots).
    // Code thanks to Shannon.Hickey@sfbay
    table.setTransferHandler(new TransferHandler() {
        protected Transferable createTransferable(JComponent c) {
          JTable table = (JTable)c;
          if (haveSelection()) {
            StringBuffer buf = new StringBuffer();
            int iDir = (getRowAnchor() < getRowLead() ? 1 : -1);
            int jDir = (getColAnchor() < getColLead() ? 1 : -1);

            for (int i = getRowAnchor(); i != getRowLead() + iDir; i += iDir) {
              for (int j = getColAnchor(); j != getColLead() + jDir; j += jDir) {
                Object val = model.getValueAt(i, j);
                buf.append(val == null ? "" : val.toString());
                if (j != getColLead()) {
                  buf.append("\t");
                }
              }
              if (i != getRowLead()) {
                buf.append("\n");
              }
            }

            return new StringTransferable(buf.toString());
          }
          return null;
        }

        public int getSourceActions(JComponent c) {
          return COPY;
        }

        public boolean importData(JComponent c, Transferable t) {
          if (canImport(c, t.getTransferDataFlavors())) {
            try {
              String str = (String)t.getTransferData(DataFlavor.stringFlavor);
              handleImport(c, str);
              return true;
            } catch (UnsupportedFlavorException ufe) {
            } catch (IOException ioe) {
            }
          }

          return false;
        }

        public boolean canImport(JComponent c, DataFlavor[] flavors) {
          for (int i = 0; i < flavors.length; i++) {
            if (DataFlavor.stringFlavor.equals(flavors[i])) {
              return true;
            }
          }
          return false;
        }

        private void handleImport(JComponent c, String str) {
          // do whatever you want with the string here
          try {
            makeVisible(debugger.parseAddress(str));
            clearSelection();
            table.clearSelection();
          } catch (NumberFormatException e) {
            System.err.println("Unable to parse address \"" + str + "\"");
          }
        }
      });

    // Supporting keyboard scrolling
    // See src/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java,
    // search for Table.AncestorInputMap

    // Actions to override:
    // selectPreviousRow, selectNextRow,
    // scrollUpChangeSelection, scrollDownChangeSelection,
    // selectPreviousRowExtendSelection, selectNextRowExtendSelection,
    // scrollDownExtendSelection, scrollUpExtendSelection (Shift-PgDn/PgUp)

    ActionMap map = table.getActionMap();

    // Up arrow
    installActionWrapper(map, "selectPreviousRow", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          clearSelection();
          if (table.getSelectedRow() == 0) {
            scrollBar.scrollUpOrLeft();
            table.setRowSelectionInterval(0, 0);
          } else {
            super.actionPerformed(e);
          }
          maybeGrabSelection();
          endUpdate();
        }
      });
    // Down arrow
    installActionWrapper(map, "selectNextRow", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          clearSelection();
          int row = table.getSelectedRow();
          if (row >= numUsableRows) {
            scrollBar.scrollDownOrRight();
            table.setRowSelectionInterval(row, row);
          } else {
            super.actionPerformed(e);
          }
          maybeGrabSelection();
          endUpdate();
        }
      });
    // Page up
    installActionWrapper(map, "scrollUpChangeSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          clearSelection();
          int row = table.getSelectedRow();
          scrollBar.pageUpOrLeft();
          if (row >= 0) {
            table.setRowSelectionInterval(row, row);
          }
          maybeGrabSelection();
          endUpdate();
        }
      });
    // Page down
    installActionWrapper(map, "scrollDownChangeSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          clearSelection();
          int row = table.getSelectedRow();
          scrollBar.pageDownOrRight();
          if (row >= 0) {
            table.setRowSelectionInterval(row, row);
          }
          maybeGrabSelection();
          endUpdate();
        }
      });
    // Shift + Up arrow
    installActionWrapper(map, "selectPreviousRowExtendSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          if (!haveAnchor()) {
            setAnchorFromTable();
            setLeadFromTable();
            //            setAnchor(table.getSelectedRow());
            //            setLead(table.getSelectedRow());
          }
          int newLead = getRowLead() - 1;
          int newAnchor = getRowAnchor();
          if (newLead < 0) {
            scrollBar.scrollUpOrLeft();
            ++newLead;
            ++newAnchor;
          }
          setSelection(newAnchor, newLead, getColAnchor(), getColLead());
          //          printSelection();
          endUpdate();
        }
      });
    // Shift + Left arrow
    installActionWrapper(map, "selectPreviousColumnExtendSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          if (!haveAnchor()) {
            setAnchorFromTable();
            setLeadFromTable();
          }
          int newLead = Math.max(0, getColLead() - 1);
          setSelection(getRowAnchor(), getRowLead(), getColAnchor(), newLead);
          //          printSelection();
          endUpdate();
        }
      });
    // Shift + Down arrow
    installActionWrapper(map, "selectNextRowExtendSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          if (!haveAnchor()) {
            setAnchorFromTable();
            setLeadFromTable();
            //            setAnchor(table.getSelectedRow());
            //            setLead(table.getSelectedRow());
          }
          int newLead = getRowLead() + 1;
          int newAnchor = getRowAnchor();
          if (newLead > numUsableRows) {
            scrollBar.scrollDownOrRight();
            --newLead;
            --newAnchor;
          }
          setSelection(newAnchor, newLead, getColAnchor(), getColLead());
          //          printSelection();
          endUpdate();
        }
      });
    // Shift + Right arrow
    installActionWrapper(map, "selectNextColumnExtendSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          if (!haveAnchor()) {
            setAnchorFromTable();
            setLeadFromTable();
          }
          int newLead = Math.min(model.getColumnCount() - 1, getColLead() + 1);
          setSelection(getRowAnchor(), getRowLead(), getColAnchor(), newLead);
          //          printSelection();
          endUpdate();
        }
      });
    // Shift + Page up
    installActionWrapper(map, "scrollUpExtendSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          if (!haveAnchor()) {
            setAnchorFromTable();
            setLeadFromTable();
            //            setAnchor(table.getSelectedRow());
            //            setLead(table.getSelectedRow());
          }
          int newLead = getRowLead() - numUsableRows;
          int newAnchor = getRowAnchor();
          if (newLead < 0) {
            scrollBar.pageUpOrLeft();
            newLead += numUsableRows;
            newAnchor += numUsableRows;
          }
          setSelection(newAnchor, newLead, getColAnchor(), getColLead());
          //          printSelection();
          endUpdate();
        }
      });
    // Shift + Page down
    installActionWrapper(map, "scrollDownExtendSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          if (!haveAnchor()) {
            setAnchorFromTable();
            setLeadFromTable();
            //            setAnchor(table.getSelectedRow());
            //            setLead(table.getSelectedRow());
          }
          int newLead = getRowLead() + numUsableRows;
          int newAnchor = getRowAnchor();
          if (newLead > numUsableRows) {
            scrollBar.pageDownOrRight();
            newLead -= numUsableRows;
            newAnchor -= numUsableRows;
          }
          setSelection(newAnchor, newLead, getColAnchor(), getColLead());
          //          printSelection();
          endUpdate();
        }
      });

    // Clear our notion of selection upon mouse press
    table.addMouseListener(new MouseAdapter() {
        public void mousePressed(MouseEvent e) {
          if (shouldIgnore(e)) {
            return;
          }
          // Make shift-clicking work properly
          if (e.isShiftDown()) {
            maybeGrabSelection();
            return;
          }
          //          System.err.println("  Clearing selection on mouse press");
          clearSelection();
        }
      });

    // Watch for mouse going out of bounds
    table.addMouseMotionListener(new MouseMotionAdapter() {
        public void mouseDragged(MouseEvent e) {
          if (shouldIgnore(e)) {
            //            System.err.println("  (Ignoring consumed mouse event)");
            return;
          }

          // Look for drag events outside table and scroll if necessary
          Point p = e.getPoint();
          if (table.rowAtPoint(p) == -1) {
            // See whether we are above or below the table
            Rectangle rect = new Rectangle();
            getBounds(rect);
            beginUpdate();
            if (p.y < rect.y) {
              //              System.err.println("  Scrolling up due to mouse event");
              // Scroll up
              scrollBar.scrollUpOrLeft();
              setSelection(getRowAnchor(), 0, getColAnchor(), getColLead());
            } else {
              //              System.err.println("  Scrolling down due to mouse event");
              // Scroll down
              scrollBar.scrollDownOrRight();
              setSelection(getRowAnchor(), numUsableRows, getColAnchor(), getColLead());
            }
            //            printSelection();
            endUpdate();
          } else {
            maybeGrabSelection();
          }
        }
      });


    add(table, BorderLayout.CENTER);

    // Make sure we recompute number of visible rows
    addComponentListener(new ComponentAdapter() {
        public void componentResized(ComponentEvent e) {
          recomputeNumVisibleRows();
          constrain();
        }
      });
    addHierarchyListener(new HierarchyListener() {
        public void hierarchyChanged(HierarchyEvent e) {
          recomputeNumVisibleRows();
          constrain();
        }
      });
    updateFromScrollBar();
  }

  /** Makes the given address visible somewhere in the window */
  public void makeVisible(Address addr) {
    BigInteger bi = addressToBigInt(addr);
    scrollBar.setValueHP(bi);
  }

  //----------------------------------------------------------------------
  // Internals only below this point
  //

  private void setupScrollBar() {
    if (is64Bit) {
      // 64-bit mode
      scrollBar =
        new HighPrecisionJScrollBar(
          Scrollbar.VERTICAL,
          new BigInteger(1, new byte[] {
            (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00,
            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
          new BigInteger(1, new byte[] {
            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
          new BigInteger(1, new byte[] {
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFC}));
      scrollBar.setUnitIncrementHP(new BigInteger(1, new byte[] {
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x08}));
      scrollBar.setBlockIncrementHP(new BigInteger(1, new byte[] {
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40}));
    } else {
      // 32-bit mode
      scrollBar=
        new HighPrecisionJScrollBar(
          Scrollbar.VERTICAL,
          new BigInteger(1, new byte[] {
            (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
          new BigInteger(1, new byte[] {
            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
          new BigInteger(1, new byte[] {
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFC}));
      scrollBar.setUnitIncrementHP(new BigInteger(1, new byte[] {
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x04}));
      scrollBar.setBlockIncrementHP(new BigInteger(1, new byte[] {
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x20}));
    }
    scrollBar.addChangeListener(new ChangeListener() {
        public void stateChanged(ChangeEvent e) {
          updateFromScrollBar();
        }
      });
  }

  private void updateFromScrollBar() {
    beginUpdate();
    BigInteger oldStartVal = startVal;
    startVal = scrollBar.getValueHP();
    constrain();
    model.fireTableDataChanged();
    if (oldStartVal != null) {
      modifySelection(oldStartVal.subtract(startVal).intValue() / addressSize);
    }
    endUpdate();
  }

  private void constrain() {
    BigInteger offset = new BigInteger(Integer.toString(addressSize * (numUsableRows)));
    BigInteger endVal = startVal.add(offset);
    if (endVal.compareTo(scrollBar.getMaximumHP()) > 0) {
      startVal = scrollBar.getMaximumHP().subtract(offset);
      endVal   = scrollBar.getMaximumHP();
      scrollBar.setValueHP(startVal);
      model.fireTableDataChanged();
    }
  }

  private void recomputeNumVisibleRows() {
    Rectangle rect = new Rectangle();
    getBounds(rect);
    int h = table.getRowHeight();
    numVisibleRows = (rect.height + (h - 1)) / h;
    numUsableRows  = numVisibleRows - 2;
    scrollBar.setBlockIncrementHP(new BigInteger(Integer.toString(addressSize * (numUsableRows))));
    model.fireTableDataChanged();
    // FIXME: refresh selection
  }

  private String bigIntToHexString(BigInteger bi) {
    StringBuffer buf = new StringBuffer();
    buf.append("0x");
    String val = bi.toString(16);
    for (int i = 0; i < ((2 * addressSize) - val.length()); i++) {
      buf.append('0');
    }
    buf.append(val);
    return buf.toString();
  }

  private Address bigIntToAddress(BigInteger i) {
    String s = bigIntToHexString(i);
    return debugger.parseAddress(s);
  }

  private BigInteger addressToBigInt(Address a) {
    String s = addressToString(a);
    if (!s.startsWith("0x")) {
      throw new NumberFormatException(s);
    }
    return new BigInteger(s.substring(2), 16);
  }

  private String addressToString(Address a) {
    if (a == null) {
      if (is64Bit) {
        return "0x0000000000000000";
      } else {
        return "0x00000000";
      }
    }
    return a.toString();
  }

  private static void installActionWrapper(ActionMap map,
                                           String actionName,
                                           ActionWrapper wrapper) {
    wrapper.setParent(map.get(actionName));
    map.put(actionName, wrapper);
  }

  private boolean shouldIgnore(MouseEvent e) {
    return e.isConsumed() || (!(SwingUtilities.isLeftMouseButton(e) && table.isEnabled()));
  }

  private void clearSelection() {
    haveAnchor = false;
    haveLead = false;
  }

  private int updateLevel;
  private boolean updating()         { return updateLevel > 0; }
  private void    beginUpdate()      { ++updateLevel;          }
  private void    endUpdate()        { --updateLevel;          }

  private boolean haveAnchor()       { return haveAnchor;  }
  private boolean haveLead()         { return haveLead;    }
  private boolean haveSelection()    { return haveAnchor() && haveLead(); }
  private int     getRowAnchor()     { return rowAnchorIndex; }
  private int     getColAnchor()     { return colAnchorIndex; }
  private int     getRowLead()       { return rowLeadIndex;   }
  private int     getColLead()       { return colLeadIndex;   }

  private void setAnchorFromTable() {
    setAnchor(table.getSelectionModel().getAnchorSelectionIndex(),
              table.getColumnModel().getSelectionModel().getAnchorSelectionIndex());
  }
  private void setLeadFromTable() {
    setLead(table.getSelectionModel().getAnchorSelectionIndex(),
            table.getColumnModel().getSelectionModel().getAnchorSelectionIndex());
  }
  private void setAnchor(int row, int col) {
    rowAnchorIndex = row;
    colAnchorIndex = col;
    haveAnchor = true;
  }
  private void setLead(int row, int col) {
    rowLeadIndex = row;
    colLeadIndex = col;
    haveLead = true;
  }
  private int clamp(int val, int min, int max) {
    return Math.max(Math.min(val, max), min);
  }
  private void maybeGrabSelection() {
    if (table.getSelectedRow() != -1) {
      // Grab selection
      ListSelectionModel rowSel = table.getSelectionModel();
      ListSelectionModel colSel = table.getColumnModel().getSelectionModel();
      if (!haveAnchor()) {
        //        System.err.println("Updating from table's selection");
        setSelection(rowSel.getAnchorSelectionIndex(), rowSel.getLeadSelectionIndex(),
                     colSel.getAnchorSelectionIndex(), colSel.getLeadSelectionIndex());
      } else {
        //        System.err.println("Updating lead from table's selection");
        setSelection(getRowAnchor(), rowSel.getLeadSelectionIndex(),
                     getColAnchor(), colSel.getLeadSelectionIndex());
      }
      //      printSelection();
    }
  }
  private void setSelection(int rowAnchor, int rowLead, int colAnchor, int colLead) {
    setAnchor(rowAnchor, colAnchor);
    setLead(rowLead, colLead);
    table.setRowSelectionInterval(clamp(rowAnchor, 0, numUsableRows),
                                  clamp(rowLead, 0, numUsableRows));
    table.setColumnSelectionInterval(colAnchor, colLead);
  }
  private void modifySelection(int amount) {
    if (haveSelection()) {
      setSelection(getRowAnchor() + amount, getRowLead() + amount,
                   getColAnchor(), getColLead());
    }
  }
  private void printSelection() {
    System.err.println("Selection updated to (" +
                       model.getValueAt(getRowAnchor(), getColAnchor()) +
                       ", " +
                       model.getValueAt(getRowLead(), getColLead()) + ") [(" +
                       getRowAnchor() + ", " + getColAnchor() + "), (" +
                       getRowLead() + ", " + getColLead() + ")]");
  }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java MemoryPanel.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.