マイペースなプログラミング日記

DTMやプログラミングにお熱なd-kamiがマイペースに書くブログ

バイナリエディタを目指して その3

前回はとりあえず表示は行ったものの、キャレットの位置が変なところにいったり、スクロールバーがなかったりだったが今回追加した。キャレットの位置はキャレット用のクラスを作り、そこで制御している。そのため、1行に表示する文字数を指定する必要がある。またスクロールバーは今のところテスト用のクラスであるMainクラスでJScrollPaneを使っているだけである。以下ソース、まずはCaretクラスから

public class Caret{
    private int row;
    private int column;
    private int width;
    private boolean isHigh;

    public Caret(int width){
        row = 0;
        column = 0;
        this.width = width;
        isHigh = true;
    }

    public void nextRow(){
        row++;
    }

    public void beforeRow(){
        if(row > 0)
            row--;
    }

    public void nextColumn(){
        column++;
        if(column >= width){
            column = 0;
            nextRow();
        }
    }

    public void beforeColumn(){
        column--;
        if(column < 0){
            if(row == 0)
                column = 0;
            else
                column = width - 1;

            beforeRow();
        }
    }

    public int getRow(){
        return row;
    }

    public void setRow(int row){
        this.row = row;
    }

    public int getColumn(){
        return column;
    }

    public void setColumn(int column){
        this.column = column;
        isHigh = true;
    }

    public boolean isHigh(){
        return isHigh;
    }

    public void setHigh(boolean isHigh){
        isHigh = isHigh;
    }
}
public class BinaryDocument{
    private int size;
    private int capacity;
    private byte[] contents;

    public BinaryDocument(){
        this(0);
    }

    public BinaryDocument(int size){
        this.size = size;
        this.capacity = (size * 13 / 10) + 10;
        this.contents = new byte[capacity];
    }

    public void set(byte data, int index){
        if(index >= capacity)
            reallocate(index);

        if(index > size)
            size = index;

        contents[index] = data;
    }

    public byte get(int index){
        if(index >= size)
            return (byte)0;

        return contents[index];
    }

    public byte[] gets(int index, int length){
         byte[] data = new byte[length];

         for(int i = 0; i < length; i++){
              data[i] = get(index + i);
         }

         return data;
    }

    private void reallocate(int newSize){
         capacity = (newSize * 13 / 10) + 10;
         byte[] newContents = new byte[capacity];

         for(int i = 0; i < size; i++){
             newContents[i] = contents[i];
         }

         contents = newContents;
         size = newSize;
    }

    public int getSize(){
        return size;
    }
}
import javax.swing.JComponent;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Dimension;

import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;

public class HexEditor extends JComponent implements KeyListener{
    private BinaryDocument document;
    private Caret caret;

    private static final String[] DATA_TABLE = new String[]{
        "0", "1", "2", "3", "4", "5", "6", "7",
        "8", "9", "A", "B", "C", "D", "E", "F"
    };

    public HexEditor(){
        this(new BinaryDocument());
    }

    public HexEditor(BinaryDocument document){
        this.document = document;
        caret = new Caret(16);

        int requireColumn = (document.getSize() / 16) + 10;
        setPreferredSize(new Dimension(16 * 26 + 8, requireColumn * 20));

        setFocusable(true);
        addKeyListener(this);
    }

    public void paintComponent(Graphics g){
        g.setFont(new Font("Monospaced", Font.PLAIN, 16));
        g.setColor(Color.BLACK);

        int row = 128;
        int column = 16;

        for(int y = 0; y < row; y++){
            for(int x = 0; x < column; x++){
                int index = (y * column) + x;
                byte data = document.get(index);

                byte high = (byte)((data >> 4) & 0x0F);
                byte low = (byte)(data & 0x0F);

                g.drawString(DATA_TABLE[high], x * 26 + 8, (y + 1) * 20);
                g.drawString(DATA_TABLE[low], (x * 26) + 8 + 8, (y + 1) * 20);
            }
        }

        g.setColor(new Color(0x6080CCFF, true));
        g.fillRect(caret.getColumn() * 26 + 6, caret.getRow() * 20 + 4, 22, 20);
    }

    public void keyPressed(KeyEvent e){
        switch(e.getKeyCode()){
        case KeyEvent.VK_UP:
            caret.beforeRow();
            break;

        case KeyEvent.VK_DOWN:
            caret.nextRow();
            break;

        case KeyEvent.VK_LEFT:
            caret.beforeColumn();
            break;

        case KeyEvent.VK_RIGHT:
            caret.nextColumn();
            break;

        default:
            break;
        }

        repaint();
    }

    public void keyTyped(KeyEvent e){}
    public void keyReleased(KeyEvent e){}
}
import javax.swing.JFrame;
import javax.swing.JScrollPane;

import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;

public class Main{
    public static void main(String[] args) throws IOException{
        BinaryDocument document = new BinaryDocument(10);

        int index = 0;
        int n;
        byte[] data = new byte[1024];
        BufferedInputStream in = new BufferedInputStream(new FileInputStream("./Main.java"));

        while((n = in.read(data, 0, 1024)) > 0){
            for(int i = 0; i < n; i++){
                document.set(data[i], index++);
            }
        }

        HexEditor editor = new HexEditor(document);
        JFrame frame = new JFrame();

        frame.add(new JScrollPane(editor));
        frame.setSize(600, 500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}