FileDocCategorySizeDatePackage
JHexEditor.javaAPI Docmp4parser 1.0-RC-179638Wed Dec 19 20:10:21 GMT 2012com.coremedia.iso.gui.hex

JHexEditor.java

/*
 * Copyright 2008 Germán Laullón
 *
 * Licensed under the Apache License, Version 2.0 (the License);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.coremedia.iso.gui.hex;

import javax.swing.JPanel;
import javax.swing.JScrollBar;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.nio.ByteBuffer;

/**
 * Combines a hex view and an ASCII view to a fully fledged hex editor.
 */
public class JHexEditor extends JPanel implements FocusListener, AdjustmentListener, MouseWheelListener {
    ByteBuffer buff;
    public int cursor;
    protected static Font font = new Font("Monospaced", 0, 12);
    protected int border = 2;
    public boolean DEBUG = false;
    private JScrollBar scrollBar;
    private int inicio = 0;
    private int numberOfVisibleLines = 10;

    public JHexEditor(ByteBuffer buff) {
        super();
        this.buff = buff;

        this.addMouseWheelListener(this);

        scrollBar = new JScrollBar(JScrollBar.VERTICAL);
        scrollBar.addAdjustmentListener(this);
        scrollBar.setMinimum(0);
        scrollBar.setMaximum((int) (buff.limit() / getNumberOfVisibleLines()));

        JPanel p1, p2, p3;
        //centro
        p1 = new JPanel(new BorderLayout(1, 1));
        p1.add(new JHexEditorHEX(this), BorderLayout.CENTER);
        p1.add(new Columnas(), BorderLayout.NORTH);

        // izq.
        p2 = new JPanel(new BorderLayout(1, 1));
        p2.add(new Filas(), BorderLayout.CENTER);
        p2.add(new Caja(), BorderLayout.NORTH);

        // der
        p3 = new JPanel(new BorderLayout(1, 1));
        p3.add(scrollBar, BorderLayout.EAST);
        p3.add(new JHexEditorASCII(this), BorderLayout.CENTER);
        p3.add(new Caja(), BorderLayout.NORTH);

        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout(1, 1));
        panel.add(p1, BorderLayout.CENTER);
        panel.add(p2, BorderLayout.WEST);
        panel.add(p3, BorderLayout.EAST);

        this.setLayout(new BorderLayout(1, 1));
        this.add(panel, BorderLayout.CENTER);
    }

    public void paint(Graphics g) {
        FontMetrics fn = getFontMetrics(font);
        Rectangle rec = this.getBounds();
        numberOfVisibleLines = (rec.height / fn.getHeight()) - 2;
        int n = (int) (buff.limit() / 16);
        if ((buff.limit() % 16) > 0) {
            n++;
        }
        if (numberOfVisibleLines > n) {
            numberOfVisibleLines = n;
            inicio = 0;
        }

        scrollBar.setValues(getInicio(), getNumberOfVisibleLines(), 0, n);
        scrollBar.setValueIsAdjusting(true);
        super.paint(g);
    }

    protected void actualizaCursor() {
        int n = (cursor / 16);
        if ((buff.limit() % 16) > 0) {
            n++;
        }
        if (n < inicio) {
            inicio = n;
        } else if (n >= inicio + numberOfVisibleLines) {
            inicio = n - numberOfVisibleLines + 2;
        }
        repaint();
    }

    protected int getInicio() {
        return inicio;
    }

    protected int getNumberOfVisibleLines() {
        if (DEBUG) {
            System.err.println("numberOfVisibleLines: " + numberOfVisibleLines);
        }
        return numberOfVisibleLines;
    }

    protected void filledCursor(Graphics g, int x, int y, int s) {
        FontMetrics fn = getFontMetrics(font);
        g.fillRect(((fn.stringWidth(" ") + 1) * x) + border, (fn.getHeight() * y) + border, ((fn.stringWidth(" ") + 1) * s), fn.getHeight() + 1);
    }

    protected void cuadro(Graphics g, int x, int y, int s) {
        FontMetrics fn = getFontMetrics(font);
        g.drawRect(((fn.stringWidth(" ") + 1) * x) + border, (fn.getHeight() * y) + border, ((fn.stringWidth(" ") + 1) * s), fn.getHeight() + 1);
    }

    protected void printString(Graphics g, String s, int x, int y) {
        FontMetrics fn = getFontMetrics(font);
        g.drawString(s, ((fn.stringWidth(" ") + 1) * x) + border, ((fn.getHeight() * (y + 1)) - fn.getMaxDescent()) + border);
    }

    public void focusGained(FocusEvent e) {
        this.repaint();
    }

    public void focusLost(FocusEvent e) {
        this.repaint();
    }

    public void adjustmentValueChanged(AdjustmentEvent e) {
        inicio = e.getValue();
        if (inicio < 0) inicio = 0;
        repaint();
    }

    public void mouseWheelMoved(MouseWheelEvent e) {
        inicio += (e.getUnitsToScroll());
        int n = (int) (buff.limit() / 16);
        n += 4;
        if ((inicio + numberOfVisibleLines) >= n) {
            inicio = n - numberOfVisibleLines;
        }
        if (inicio < 0) {
            inicio = 0;
        }
        repaint();
    }

    public void keyPressed(KeyEvent e) {
        switch (e.getKeyCode()) {
            case 33:    // rep
                if (cursor >= (16 * numberOfVisibleLines)) {
                    cursor -= (16 * numberOfVisibleLines);
                }
                actualizaCursor();
                break;
            case 34:    // fin
                if (cursor < (buff.limit() - (16 * numberOfVisibleLines))) {
                    cursor += (16 * numberOfVisibleLines);
                }
                actualizaCursor();
                break;
            case 35:    // fin
                cursor = (int) (buff.limit() - 1);
                actualizaCursor();
                break;
            case 36:    // ini
                cursor = 0;
                actualizaCursor();
                break;
            case 37:    // <--
                if (cursor != 0) cursor--;
                actualizaCursor();
                break;
            case 38:    // <--
                if (cursor > 15) cursor -= 16;
                actualizaCursor();
                break;
            case 39:    // -->
                if (cursor != (buff.limit() - 1)) cursor++;
                actualizaCursor();
                break;
            case 40:    // -->
                if (cursor < (buff.limit() - 16)) cursor += 16;
                actualizaCursor();
                break;

        }
    }

    private class Columnas extends JPanel {
        public Columnas() {
            this.setLayout(new BorderLayout(1, 1));
        }

        public Dimension getPreferredSize() {
            return getMinimumSize();
        }

        public Dimension getMinimumSize() {
            Dimension d = new Dimension();
            FontMetrics fn = getFontMetrics(font);
            int h = fn.getHeight();
            int nl = 1;
            d.setSize(((fn.stringWidth(" ") + 1) * +((16 * 3) - 1)) + (border * 2) + 1, h * nl + (border * 2) + 1);
            return d;
        }

        public void paint(Graphics g) {
            Dimension d = getMinimumSize();
            g.setColor(Color.white);
            g.fillRect(0, 0, d.width, d.height);
            g.setColor(Color.black);
            g.setFont(font);

            for (int n = 0; n < 16; n++) {
                if (n == (cursor % 16)) cuadro(g, n * 3, 0, 2);
                String s = "00" + Integer.toHexString(n);
                s = s.substring(s.length() - 2);
                printString(g, s, n * 3, 0);
            }
        }
    }

    private class Caja extends JPanel {
        public Dimension getPreferredSize() {
            return getMinimumSize();
        }

        public Dimension getMinimumSize() {
            Dimension d = new Dimension();
            FontMetrics fn = getFontMetrics(font);
            int h = fn.getHeight();
            d.setSize((fn.stringWidth(" ") + 1) + (border * 2) + 1, h + (border * 2) + 1);
            return d;
        }

    }

    private class Filas extends JPanel {
        public Filas() {
            this.setLayout(new BorderLayout(1, 1));
        }

        public Dimension getPreferredSize() {
            return getMinimumSize();
        }

        public Dimension getMinimumSize() {
            Dimension d = new Dimension();
            FontMetrics fn = getFontMetrics(font);
            int h = fn.getHeight();
            int nl = getNumberOfVisibleLines();
            d.setSize((fn.stringWidth(" ") + 1) * (8) + (border * 2) + 1, h * nl + (border * 2) + 1);
            return d;
        }

        public void paint(Graphics g) {
            Dimension d = getMinimumSize();
            g.setColor(Color.white);
            g.fillRect(0, 0, d.width, d.height);
            g.setColor(Color.black);
            g.setFont(font);

            int ini = getInicio();
            int fin = ini + getNumberOfVisibleLines();
            int y = 0;
            for (int n = ini; n < fin; n++) {
                if (n == (cursor / 16)) cuadro(g, 0, y, 8);
                String s = "0000000000000" + Integer.toHexString(n);
                s = s.substring(s.length() - 8);
                printString(g, s, 0, y++);
            }
        }
    }

}