/* * Copyright (C) 2014 James Lawrence. * * This file is part of GrimEdi. * * GrimEdi is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * Created by JFormDesigner on Fri Mar 15 22:45:17 GMT 2013 */ package com.sqrt4.grimedi.ui.editor; import com.sqrt.liblab.io.DataSource; import com.sqrt4.grimedi.ui.MainWindow; import sun.swing.SwingUtilities2; import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.TableModelListener; import javax.swing.table.TableModel; import java.awt.*; import java.awt.event.MouseEvent; import java.io.IOException; /** * @author James Lawrence */ public class HexView extends JPanel { private Font fixedWidth = new Font("Monospaced", Font.PLAIN, 12); private DataSource source; private HexView() { initComponents(); } public HexView(DataSource source) { this(); this.source = source; //hexTable.revalidate(); //JTableHeader rowHeader = new JTableHeader(hexTable.getColumnModel()); //rowHeader.setTable(hexTable); //panel1.setRowHeaderView(rowHeader); } private void createUIComponents() { hexTable = new JTable() { public String getToolTipText(MouseEvent event) { Point p = event.getPoint(); // Locate the renderer under the event location int col = columnAtPoint(p); if (col == 16) return null; if (col > 16) col -= 17; int row = rowAtPoint(p); if (col == -1 || row == -1) return null; int idx = row * 16 + col; int bytes = (int) (source.length() - idx); if (bytes <= 0) return null; StringBuilder sb = new StringBuilder("<html>"); sb.append(String.format("Offset: %06x<br/>", idx)); try { source.position(idx); byte b = source.get(); sb.append(String.format("Byte: hex: %02x, s: %d, u: %d<br/>", b, b, b & 0xff)); if (bytes >= 2) { source.position(idx); int s = source.getShort(); source.position(idx); int sle = source.getShortLE(); sb.append(String.format("Short (BE): hex: %04x, s: %d, u: %d<br/>", s, s, s & 0xffff)); sb.append(String.format("Short (LE): hex: %04x, s: %d, u: %d<br/>", sle, sle, sle & 0xffff)); if (bytes >= 4) { source.position(idx); int i = source.getInt(); source.position(idx); int ile = source.getIntLE(); sb.append(String.format("Int (BE): hex: %08x, s: %d, u: %d<br/>", i, i, i & 0xffffffffL)); sb.append(String.format("Int (LE): hex: %08x, s: %d, u: %d<br/>", ile, ile, ile & 0xffffffffL)); } } source.position(idx); StringBuilder str = new StringBuilder(); int slen = 0; boolean cleanString = false; while (source.remaining() > 0 && slen < 32) { byte o = source.get(); if (o == 0) { cleanString = true; break; } slen++; str.append((char) o); } String string = str.toString(); if (string.length() > 0) { string = string.replace("<", "<").replace(">", ">"); if (slen == 32) string += "..."; sb.append("String: ").append(string); } } catch (IOException e) { MainWindow.getInstance().handleException(e); } sb.append("</html>"); return sb.toString(); } }; hexTable.setRowSelectionAllowed(false); hexTable.setColumnSelectionAllowed(false); hexTable.setCellSelectionEnabled(true); hexTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); // cbf'd with the hassle of selecting the same ascii as selected hex etc. TODO ListSelectionListener listener = new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting()) return; ListSelectionModel colSelModel = hexTable.getColumnModel().getSelectionModel(); int lead = colSelModel.getLeadSelectionIndex(); int anchor = colSelModel.getAnchorSelectionIndex(); for (int col : hexTable.getSelectedColumns()) { for (int row : hexTable.getSelectedRows()) { if (col == 16) continue; if (col > 16) col -= 17; int idx = (row * 16) + col; int linkCol = col + 17; if (!colSelModel.isSelectedIndex(col)) colSelModel.addSelectionInterval(col, col); if (!colSelModel.isSelectedIndex(linkCol)) colSelModel.addSelectionInterval(linkCol, linkCol); } } if (colSelModel.getAnchorSelectionIndex() != anchor || colSelModel.getLeadSelectionIndex() != lead) SwingUtilities2.setLeadAnchorWithoutSelection(colSelModel, anchor, lead); } }; hexTable.getSelectionModel().addListSelectionListener(listener); hexTable.getColumnModel().getSelectionModel().addListSelectionListener(listener); hexTable.getTableHeader().setFont(fixedWidth); hexTable.setFont(fixedWidth); hexTable.setRowMargin(0); hexTable.setRowHeight(hexTable.getFontMetrics(fixedWidth).getHeight()); hexTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); int hexWidth = hexTable.getFontMetrics(fixedWidth).stringWidth("000"); int asciiWidth = hexTable.getFontMetrics(fixedWidth).stringWidth("00"); hexTable.setModel(new TableModel() { public int getRowCount() { return (int) ((source.length() + 15) / 16); } public int getColumnCount() { return 33; } public String getColumnName(int columnIndex) { return columnIndex < 16 ? String.format("%02x", columnIndex) : null; } public Class<?> getColumnClass(int columnIndex) { return String.class; } public boolean isCellEditable(int rowIndex, int columnIndex) { return false; } public Object getValueAt(int rowIndex, int columnIndex) { if (columnIndex == 16) return null; try { boolean ascii = columnIndex > 16; if (ascii) columnIndex -= 17; int pos = rowIndex * 16 + columnIndex; if (pos >= source.length()) return null; source.position(pos); int b = source.getUByte(); return ascii ? new String(new char[]{(char) b}) : String.format("%02x", b); } catch (IOException e) { MainWindow.getInstance().handleException(e); return "xx"; } } public void setValueAt(Object aValue, int rowIndex, int columnIndex) { throw new UnsupportedOperationException(); } public void addTableModelListener(TableModelListener l) { //To change body of implemented methods use File | Settings | File Templates. } public void removeTableModelListener(TableModelListener l) { //To change body of implemented methods use File | Settings | File Templates. } }); for (int i = 0; i < 33; i++) { hexTable.getColumnModel().getColumn(i).setPreferredWidth(i <= 16 ? hexWidth : asciiWidth); } } private void initComponents() { // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents // Generated using JFormDesigner non-commercial license createUIComponents(); panel1 = new JScrollPane(); //======== this ======== setLayout(new BorderLayout()); //======== panel1 ======== { panel1.setViewportView(hexTable); } add(panel1, BorderLayout.CENTER); // JFormDesigner - End of component initialization //GEN-END:initComponents } // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables // Generated using JFormDesigner non-commercial license private JScrollPane panel1; private JTable hexTable; // JFormDesigner - End of variables declaration //GEN-END:variables }