// Java版AceDrawのためのステップ
// 「AceDraw プロト2’」AceDrawProto2dash.java
// Copyright(c)2007 A.Hiramatsu
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.filechooser.*;
public class AceDrawProto2dash {
private static final int imgWidth = 320;
private static final int imgByteWidth = imgWidth / 8;
private static final int imgHeight = 240;
private static final int animeFrmSize = 9728;
private static final int animeFrmImgBytes = imgByteWidth * imgHeight;
private static final int animeFrmHeadSize = 128;
private static class AnimeFrame {
boolean mark;
byte[] img;
private AnimeFrame() {
this.mark = false;
this.img = new byte[animeFrmImgBytes];
for(int i=0; i<animeFrmImgBytes; i++) {
this.img[i] = (byte)255;
}
}
private void setMark(boolean b) {
this.mark = b;
}
private boolean getMark() {
return this.mark;
}
private void setImg(byte[] src) {
int n = src.length;
if(n > animeFrmImgBytes) n = animeFrmImgBytes;
for(int i=0; i<n; i++) {
this.img[i] = src[i];
}
}
private byte[] getImg() {
return this.img;
}
private byte[] cloneImg() {
byte[] rImg = new byte[animeFrmImgBytes];
for(int i=0; i<animeFrmImgBytes; i++) {
rImg[i] = this.img[i];
}
return rImg;
}
};
private ArrayList<AnimeFrame> aniFrms = new ArrayList<AnimeFrame>();
private final int paletts[][] = {
// CPN CPn CpN Cpn cPN cPn cpN cpn
{0x000000,0x000000,0x000000,0x000000,0xffffff,0xffffff,0xffffff,0xffffff}, // cur
{0xe00000,0xe00000,0x000000,0x000000,0xffb0b0,0xffb0b0,0xffffff,0xffffff}, // cur,prv
{0x0000e0,0x000000,0x0000e0,0x000000,0xb0c0ff,0xffffff,0xb0c0ff,0xffffff}, // cur,nxt
{0xd000d0,0xe00000,0x0000e0,0x000000,0xffb0ff,0xffb0b0,0xb0c0ff,0xffffff} // all
};
private byte[] fileHeadBuf = new byte[animeFrmSize];
private byte[] frameHeadBuf = new byte[animeFrmHeadSize];
private byte[] frameImgBuf = new byte[animeFrmImgBytes];
private byte[] drawingImg;
private byte[] prvFrmImg;
private byte[] nxtFrmImg;
private int curFrmNo;
private byte[] undoImg;
private byte[] redoImg;
private JLabel grpInfoLbl;
private JToggleButton freeBtn;
private JToggleButton snglBtn;
private JToggleButton polyBtn;
private JButton undoBtn;
private JPopupMenu plMenu;
private boolean plMenuVisible;
private JFrame mainFrm;
private JFileChooser fChoose = new JFileChooser(".");
private JLabel frmInfoLbl;
private JButton frmBMBtn;
private JButton frmBBtn;
private JButton frmFBtn;
private JButton frmFMBtn;
private JToggleButton frmPBtn;
private JToggleButton frmNBtn;
private JMenu fileMenu;
private JMenu grpMenu;
private JMenu frmMenu;
private JMenu playMenu;
private BufferedImage mainImg = new BufferedImage(imgWidth,imgHeight,
BufferedImage.TYPE_INT_RGB);
private boolean drawing = false;
private boolean dragging = false;
private boolean erasing = false;
private boolean tempdraw = false;
private int drawLatX,drawLatY;
private int drawCurX,drawCurY;
private enum DrawMode {none,free,sngl,poly};
private DrawMode drawmode;
private ArrayList<Point> plPoints;
private boolean canundo,canredo;
private boolean fileClean;
private String fileName = "";
private JPanel grpPnl = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(mainImg,0,0,this);
}
};
private void updateView() {
int bc,bp,bn;
int pal,ix;
int srcp = 0;
pal = 0;
if(frmPBtn.isSelected() && (curFrmNo > 0)) pal = pal + 1;
if(frmNBtn.isSelected() && (curFrmNo < aniFrms.size()-1)) pal = pal + 2;
for(int y=0; y<imgHeight; y++) {
for(int x=0; x<imgByteWidth; x++) {
bc = drawingImg[srcp];
bp = prvFrmImg[srcp];
bn = nxtFrmImg[srcp++];
for(int i=0; i<8; i++) {
ix = ((bc >> (7-i)) & 1)*4 + ((bp >> (7-i)) & 1)*2 + ((bn >> (7-i)) & 1);
mainImg.setRGB(x*8+i,y,paletts[pal][ix]);
}
}
}
grpPnl.repaint();
}
private void updateView(int x1,int y1,int x2,int y2) {
int bc,bp,bn;
int pal,ix;
int srcp;
int t;
if(! (((x1 < 0) && (x2 < 0)) ||
((x1 >= imgWidth) && (x2 >= imgWidth)) ||
((y1 < 0) && (y2 < 0)) ||
((y1 >= imgHeight) && (y2 >= imgHeight))) ) {
if(x1>x2) {
t = x1;
x1 = x2;
x2 = t;
}
if(y1>y2) {
t = y1;
y1 = y2;
y2 = t;
}
if(x1 < 0) x1 = 0;
if(x2 >= imgWidth) x2 = imgWidth-1;
if(y1 < 0) y1 = 0;
if(y2 >= imgHeight) y2 = imgHeight-1;
int bx1 = x1 / 8;
int bx2 = x2 / 8;
pal = 0;
if(frmPBtn.isSelected() && (curFrmNo > 0)) pal = pal + 1;
if(frmNBtn.isSelected() && (curFrmNo < aniFrms.size()-1)) pal = pal + 2;
for(int y=y1; y<=y2; y++) {
srcp = y * imgByteWidth + bx1;
for(int x=bx1; x<=bx2; x++) {
bc = drawingImg[srcp];
bp = prvFrmImg[srcp];
bn = nxtFrmImg[srcp++];
for(int i=0; i<8; i++) {
ix = ((bc >> (7-i)) & 1)*4 + ((bp >> (7-i)) & 1)*2 + ((bn >> (7-i)) & 1);
mainImg.setRGB(x*8+i,y,paletts[pal][ix]);
}
}
}
grpPnl.repaint();
}
}
private void updateFrmInfo() {
char c = ' ';
if(aniFrms.get(curFrmNo).getMark()) c = '*';
frmInfoLbl.setText(c + Integer.toString(curFrmNo+1) +
" / "+Integer.toString(aniFrms.size()));
}
private byte[] newImg() {
byte[] img = new byte[animeFrmImgBytes];
for(int i=0; i < animeFrmImgBytes; i++) {
img[i] = (byte)255;
}
return img;
}
private void updateFrm() {
byte[] img =aniFrms.get(curFrmNo).getImg();
for(int i=0; i < animeFrmImgBytes; i++) {
if(drawingImg[i] != img[i]) {
aniFrms.get(curFrmNo).setImg(drawingImg);
fileClean = false;
break;
}
}
canundo = false;
canredo = false;
}
private void enaMenu() {
fileMenu.setEnabled(true);
grpMenu.setEnabled(true);
frmMenu.setEnabled(true);
playMenu.setEnabled(true);
}
private void disMenu() {
fileMenu.setEnabled(false);
grpMenu.setEnabled(false);
frmMenu.setEnabled(false);
playMenu.setEnabled(false);
}
private void enaFrmFBBtns() {
frmBMBtn.setEnabled(true);
frmBBtn.setEnabled(true);
frmFBtn.setEnabled(true);
frmFMBtn.setEnabled(true);
}
private void disFrmFBBtns() {
frmBMBtn.setEnabled(false);
frmBBtn.setEnabled(false);
frmFBtn.setEnabled(false);
frmFMBtn.setEnabled(false);
}
private void enaDrawBtns() {
freeBtn.setEnabled(true);
snglBtn.setEnabled(true);
polyBtn.setEnabled(true);
undoBtn.setEnabled(true);
}
private void disDrawBtns() {
freeBtn.setEnabled(false);
snglBtn.setEnabled(false);
polyBtn.setEnabled(false);
undoBtn.setEnabled(false);
}
private void imgSetPixel(int x,int y,int op) {
int ofs,bitptn;
if((x>=0) && (x<imgWidth) &&
(y>=0) && (y<imgHeight)) {
ofs = x / 8 + y * imgByteWidth;
bitptn = 0x80 >> (x & 0x07);
switch(op) {
case 0: drawingImg[ofs] &= (byte)(~bitptn); break;
case 1: drawingImg[ofs] |= (byte)bitptn; break;
case 2: drawingImg[ofs] ^= (byte)bitptn; break;
default:
}
}
}
private void imgDrawLine(int x1,int y1,int x2,int y2,int op) {
int w,h,dx,dy,accum;
w = x2 - x1;
dx = 1;
if(w < 0) {
w = -w;
dx = -dx;
}
h = y2 - y1;
dy = 1;
if(h < 0) {
h = -h;
dy = -dy;
}
if((w > 0) || (h > 0)) {
accum = 0;
if(w > h) {
do {
imgSetPixel(x1,y1,op);
x1 += dx;
accum += h;
if(accum >= w) {
accum -= w;
y1 += dy;
}
} while(x1 != x2);
} else {
do {
imgSetPixel(x1,y1,op);
y1 += dy;
accum += w;
if(accum >= h) {
accum -= h;
x1 += dx;
}
} while(y1 != y2);
}
}
}
private void imgDrawHLine(int x1,int x2,int y,int op) {
int ofs,endofs,bp1,bp2;
if((y >= 0) && (y < imgHeight)) {
if(! ((x1 < 0) && (x2 < 0)) ||
((x1 >= imgWidth) && (x2 >= imgWidth)) ) {
if(x1 > x2) {
int t = x1;
x1 = x2;
x2 = t;
}
if(x1 < 0) x1 = 0;
if(x2 >=imgWidth) x2 = imgWidth - 1;
ofs = x1 / 8 + y * imgByteWidth;
bp1 = (0x100 >> (x1 & 0x07)) - 1;
endofs = x2 / 8 + y * imgByteWidth;
bp2 = ~((0x80 >> (x2 & 0x07)) - 1);
if(ofs == endofs) {
switch(op) {
case 0: drawingImg[ofs] &= (byte)(~(bp1 & bp2)); break;
case 1: drawingImg[ofs] |= (byte)(bp1 & bp2); break;
case 2: drawingImg[ofs] ^= (byte)(bp1 & bp2); break;
default:
}
} else {
switch(op) {
case 0: drawingImg[ofs] &= (byte)(~bp1); break;
case 1: drawingImg[ofs] |= (byte)bp1; break;
case 2: drawingImg[ofs] ^= (byte)bp1; break;
default:
}
for(int i=ofs+1; i<endofs; i++) {
switch(op) {
case 0: drawingImg[i] =(byte)0; break;
case 1: drawingImg[i] =(byte)0xff; break;
case 2: drawingImg[i] = (byte)(~drawingImg[i]); break;
default:
}
}
switch(op) {
case 0: drawingImg[endofs] &= (byte)(~bp2); break;
case 1: drawingImg[endofs] |= (byte)bp2; break;
case 2: drawingImg[endofs] ^= (byte)bp2; break;
default:
}
}
}
}
}
private void imgFillRect(int x1,int y1,int x2,int y2,int op) {
if(! ((y1 < 0) && (y2 < 0)) ||
((y1 >= imgHeight) && (y2 >= imgHeight)) ) {
if(y1 > y2) {
int t = y1;
y1 = y2;
y2 = t;
}
if(y1 < 0) y1 = 0;
if(y2 >= imgHeight) y2 = imgHeight - 1;
for(int y=y1; y<=y2; y++) {
imgDrawHLine(x1,x2,y,op);
}
}
}
private void setUndo() {
for(int i=0; i<animeFrmImgBytes; i++) { // 画面イメージを
undoImg[i] = drawingImg[i]; // undoバッファに保存
}
canundo=true; // 「undo可能だがまだ一度もundoしてない」
canredo=false; // 状態にする
}
private void drawTempLine(int x,int y) {
if((drawLatX != x) || (drawLatY != y)) { // 長さが0でなければ
imgDrawLine(drawLatX,drawLatY,x,y,2); // 仮描画する
drawCurX=x; // 仮描画位置更新
drawCurY=y;
tempdraw=true; // 仮描画済み
}
}
private void cancelLine() {
if(drawmode.equals(DrawMode.sngl) || // 仮描画するのは単直線かポリ直線のみ
drawmode.equals(DrawMode.poly)) {
if(tempdraw) { // 仮描画線を引いていたら
if((drawLatX != drawCurX) ||
(drawLatY != drawCurY)) {
imgDrawLine(drawLatX,drawLatY, // 仮描画線を消す
drawCurX,drawCurY,2);
}
}
}
tempdraw=false;
}
MouseListener grpMLsn = new MouseAdapter() { // マウスボタンイベント
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
if(e.getButton()==MouseEvent.BUTTON1) { // 左ボタン押された
if(!erasing) { // 消しゴム使用中でなければ
if(drawmode.equals(DrawMode.free)) { // 自由曲線モード
setUndo();
drawing=true;
dragging=false;
drawLatX=x; // 現在位置を最後の位置とする
drawLatY=y;
} else if(drawmode.equals(DrawMode.sngl)) { // 単直線モード
setUndo();
drawing=true;
drawLatX=x; // 現在位置を最後の位置とする
drawLatY=y;
drawCurX=x; // 仮描画用位置
drawCurY=y;
} else if(drawmode.equals(DrawMode.poly)) { // ポリ直線モード
if(drawing) { // すでに描画中なら
if((drawLatX != x) || (drawLatY != y)) {
plPoints.add(new Point(x,y)); // 現在の点を追加
}
} else {
plPoints.clear();
plPoints.add(new Point(x,y));
setUndo();
disMenu();
disFrmFBBtns();
disDrawBtns();
}
drawing=true; // 描画中にする
drawLatX=x; // 最後の位置を更新
drawLatY=y;
drawCurX=x; // 仮描画用位置
drawCurY=y;
} else {
}
}
} else if(e.getButton()==MouseEvent.BUTTON3) { // 右ボタン押された
if(plMenuVisible) {
plMenu.setVisible(false);
plMenuVisible = false;
} else {
if(drawing) { // 描画中で
if(drawmode.equals(DrawMode.poly)) { // なおかつポリ直線モードなら
plMenu.show(grpPnl,x,y);
plMenuVisible = true;
}
} else { // 描画中でなければ
setUndo();
imgDrawHLine(x-1,x+1,y-2,1);
imgFillRect(x-2,y-1,x+2,y+1,1);
imgDrawHLine(x-1,x+1,y+2,1);
updateView();
erasing = true; // 消しゴム使用中にする
}
}
}
}
public void mouseReleased(MouseEvent e) {
int x = e.getX();
int y = e.getY();
if(e.getButton()==MouseEvent.BUTTON1) { // 左ボタン離された
if(drawmode.equals(DrawMode.free)) { // 自由曲線モード
if(drawing && !dragging) {
imgSetPixel(drawLatX,drawLatY,0); // ドラッグしてなければ1点だけ打つ
updateView(drawLatX,drawLatY,drawLatX,drawLatY);
}
drawing=false;
dragging=false;
} else if(drawmode.equals(DrawMode.sngl)) { // 単直線モード
if(drawing) {
cancelLine(); // 仮描画した線を消す
if((drawLatX != x) || (drawLatY != y)) { // 線の長さが0でなければ
imgDrawLine(drawLatX,drawLatY,
drawCurX,drawCurY,0); // 正式に線を引く
}
updateView();
}
drawing=false;
} else {
}
} else if(e.getButton()==MouseEvent.BUTTON3) { // 右ボタン離された
erasing=false; // 消しゴム使用中を解除
} else {
}
}
public void mouseExited(MouseEvent e) { // マウスが描画領域を出た
grpInfoLbl.setText("");
}
};
MouseMotionListener grpMmLsn = new MouseMotionAdapter() { // マウス移動イベント
public void mouseDragged(MouseEvent e) {
int minx,miny,maxx,maxy;
int x = e.getX();
int y = e.getY();
grpInfoLbl.setText( "(" + Integer.toString(x) +
"," + Integer.toString(y) + ")" ); // 座標表示
if(drawing) {
if(drawmode.equals(DrawMode.free)) { // 自由曲線モード
if((drawLatX != x) || (drawLatY != y)) { // カーソルが動いていたら
imgDrawLine(drawLatX,drawLatY,x,y,0); // 線を引く
int x0 = drawLatX;
int y0 = drawLatY;
drawLatX=x; // 最後の位置を更新
drawLatY=y;
dragging=true;
updateView(x0,y0,x,y);
}
} else if(drawmode.equals(DrawMode.sngl) || // 単直線モード または
(drawmode.equals(DrawMode.poly) && // ポリ直線モードで描画中なら
drawing)) {
if(drawCurX < drawLatX) { // 更新領域の計算その1
minx = drawCurX;
maxx = drawLatX;
} else {
minx = drawLatX;
maxx = drawCurX;
}
if(drawCurY < drawLatY) {
miny = drawCurY;
maxy = drawLatY;
} else {
miny = drawLatY;
maxy = drawCurY;
}
cancelLine(); // 仮描画線を消す
drawTempLine(x,y); // 新しい仮描画線を書く
if(x < minx) minx = x; // 更新領域の計算その2
if(x > maxx) maxx = x;
if(y < miny) miny = y;
if(y > maxy) maxy = y;
updateView(minx,miny,maxx,maxy);
} else {
}
} else if(erasing) { // 消しゴム使用中
imgDrawHLine(x-1,x+1,y-2,1);
imgFillRect(x-2,y-1,x+2,y+1,1);
imgDrawHLine(x-1,x+1,y+2,1);
updateView();
}
}
public void mouseMoved(MouseEvent e) {
int minx,miny,maxx,maxy;
int x = e.getX();
int y = e.getY();
grpInfoLbl.setText( "(" + Integer.toString(x) +
"," + Integer.toString(y) + ")" ); // 座標表示
if(drawmode.equals(DrawMode.poly)) { // ポリ直線モードで
if(drawing) { // 描画中なら
if(drawCurX < drawLatX) { // 更新領域の計算その1
minx = drawCurX;
maxx = drawLatX;
} else {
minx = drawLatX;
maxx = drawCurX;
}
if(drawCurY < drawLatY) {
miny = drawCurY;
maxy = drawLatY;
} else {
miny = drawLatY;
maxy = drawCurY;
}
cancelLine(); // 仮描画線を消す
drawTempLine(x,y); // 新しい仮描画線を描く
if(x < minx) minx = x; // 更新領域の計算その2
if(x > maxx) maxx = x;
if(y < miny) miny = y;
if(y > maxy) maxy = y;
updateView(minx,miny,maxx,maxy);
}
}
}
};
MouseListener plEndLsn = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
int x1,y1,x2,y2;
if(e.getButton()==MouseEvent.BUTTON1) {
cancelLine();
if(plPoints.size() > 2) {
x1 = plPoints.get(0).x;
y1 = plPoints.get(0).y;
for(int i=1; i<plPoints.size(); i++) {
x2 = plPoints.get(i).x;
y2 = plPoints.get(i).y;
imgDrawLine(x1,y1,x2,y2,0);
x1 = x2;
y1 = y2;
}
plPoints.clear();
}
updateView();
drawing = false;
enaMenu();
enaFrmFBBtns();
enaDrawBtns();
}
}
};
MouseListener plBackLsn = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
int x1,y1,x2,y2;
if(e.getButton()==MouseEvent.BUTTON1) {
cancelLine();
if(plPoints.size() > 1) {
x1 = plPoints.get(plPoints.size()-2).x;
y1 = plPoints.get(plPoints.size()-2).y;
x2 = plPoints.get(plPoints.size()-1).x;
y2 = plPoints.get(plPoints.size()-1).y;
plPoints.remove(plPoints.size()-1);
imgDrawLine(x1,y1,x2,y2,2);
drawLatX = x1;
drawLatY = y1;
updateView();
}
}
}
};
MouseListener undoBtnLsn = new MouseAdapter() { // undoボタンイベント
public void mousePressed(MouseEvent e) {
cancelLine();
if(canredo) { // redo可(一度undoしている)
if(canundo) { // undo可なら
for(int i=0; i<animeFrmImgBytes; i++) { // undoバッファの内容を
drawingImg[i] = undoImg[i]; // 画面に復帰
}
} else {
for(int i=0; i<animeFrmImgBytes; i++) { // redoバッファの内容を
drawingImg[i] = redoImg[i]; // 画面に復帰
}
}
canundo = !canundo; // undo可をトグル
} else {
if(canundo) { // 描画後最初のundo
for(int i=0; i<animeFrmImgBytes; i++) { // 現在の画面イメージを
redoImg[i] = drawingImg[i]; // redoバッファに保存
drawingImg[i] = undoImg[i]; // undoバッファの内容を
} // 画面に復帰
canundo=false;
canredo=true; // redo可にする
}
}
updateView();
drawing=false;
dragging=false;
erasing=false;
}
};
MouseListener freeBtnLsn = new MouseAdapter() { // freeボタン
public void mousePressed(MouseEvent e) {
drawmode=DrawMode.free;
drawing=false;
dragging=false;
erasing=false;
}
};
MouseListener snglBtnLsn = new MouseAdapter() { // 単直線ボタン
public void mousePressed(MouseEvent e) {
drawmode=DrawMode.sngl;
drawing=false;
dragging=false;
erasing=false;
}
};
MouseListener polyBtnLsn = new MouseAdapter() { // ポリ直線ボタン
public void mousePressed(MouseEvent e) {
drawmode=DrawMode.poly;
drawing=false;
dragging=false;
erasing=false;
}
};
MouseListener frmFBtnLsn = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if(curFrmNo < aniFrms.size()-1) {
updateFrm();
curFrmNo++;
prvFrmImg = drawingImg;
drawingImg = aniFrms.get(curFrmNo).cloneImg();
if(curFrmNo < aniFrms.size()-1) {
nxtFrmImg = aniFrms.get(curFrmNo+1).getImg();
}
updateView();
updateFrmInfo();
} else {
int r = JOptionPane.showConfirmDialog(mainFrm,"新規フレームを作成しますか?",
"AceDraw",JOptionPane.YES_NO_OPTION);
if(r == JOptionPane.YES_OPTION) {
updateFrm();
addNewFrm();
}
}
}
};
MouseListener frmBBtnLsn = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if(curFrmNo > 0) {
updateFrm();
curFrmNo--;
nxtFrmImg = drawingImg;
drawingImg = aniFrms.get(curFrmNo).cloneImg();
if(curFrmNo > 0) {
prvFrmImg = aniFrms.get(curFrmNo-1).getImg();
}
updateView();
updateFrmInfo();
}
}
};
MouseListener frmFMBtnLsn = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
int newcur = curFrmNo;
if((curFrmNo < aniFrms.size()-1) && (aniFrms.get(curFrmNo).getMark())) {
newcur++;
}
while(newcur < aniFrms.size()-1) {
if(! aniFrms.get(newcur).getMark()) newcur++;
else break;
}
if(curFrmNo != newcur) {
updateFrm();
curFrmNo = newcur;
drawingImg = aniFrms.get(curFrmNo).getImg();
if(curFrmNo > 0) {
prvFrmImg = aniFrms.get(curFrmNo-1).getImg();
}
if(curFrmNo < aniFrms.size()-1) {
nxtFrmImg = aniFrms.get(curFrmNo+1).getImg();
}
updateView();
updateFrmInfo();
}
}
};
MouseListener frmBMBtnLsn = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
int newcur = curFrmNo;
if((curFrmNo > 0) && (aniFrms.get(curFrmNo).getMark())) {
newcur--;
}
while(newcur > 0) {
if(! aniFrms.get(newcur).getMark()) newcur--;
else break;
}
if(curFrmNo != newcur) {
updateFrm();
curFrmNo = newcur;
drawingImg = aniFrms.get(curFrmNo).getImg();
if(curFrmNo > 0) {
prvFrmImg = aniFrms.get(curFrmNo-1).getImg();
}
if(curFrmNo < aniFrms.size()-1) {
nxtFrmImg = aniFrms.get(curFrmNo+1).getImg();
}
updateView();
updateFrmInfo();
canundo = false;
canredo = false;
}
}
};
ItemListener frmPBtnLsn = new ItemListener() {
public void itemStateChanged(ItemEvent e) {
updateView();
}
};
ItemListener frmNBtnLsn = new ItemListener() {
public void itemStateChanged(ItemEvent e) {
updateView();
}
};
private boolean checkClean() {
if(! fileClean) {
int r = JOptionPane.showConfirmDialog(mainFrm,"アニメデータが変更されています。保存しますか?",
"AceDraw",JOptionPane.YES_NO_CANCEL_OPTION);
if(r == JOptionPane.YES_OPTION) {
if(! doFileSave()) r = JOptionPane.CANCEL_OPTION;
}
if(r != JOptionPane.CANCEL_OPTION) {
fileClean = true;
return true;
} else {
return false;
}
} else {
return true;
}
}
private void doFileNew() {
if(checkClean()) {
aniFrms.clear();
aniFrms.add(new AnimeFrame());
curFrmNo = 0;
fileName = "";
drawingImg = aniFrms.get(curFrmNo).cloneImg();
updateView();
updateFrmInfo();
}
}
private void doFileOpen() {
File f;
int n,p;
int rlen = 0;
int totalFrms = 0;
long fsize;
String s;
boolean canRead = false;
FileInputStream fi = null;
AnimeFrame aniFrm;
if(checkClean()) {
n = fChoose.showOpenDialog(mainFrm);
if(n==JFileChooser.APPROVE_OPTION ) {
f = fChoose.getSelectedFile();
if(f != null) {
s = fChoose.getName(f);
canRead = true;
if(s.length()>4) {
if(s.substring(s.length()-4).toUpperCase().equals(".ACD")) {
try {
fi = new FileInputStream(f);
} catch(Throwable fe) {
JOptionPane.showMessageDialog(mainFrm,"ファイルのオープンに失敗しました",
"AceDraw",JOptionPane.ERROR_MESSAGE);
canRead = false;
}
if(canRead) {
try {
rlen = fi.read(fileHeadBuf);
} catch(Throwable fe) {
JOptionPane.showMessageDialog(mainFrm,"ファイルの入力中にエラーが発生しました",
"AceDraw",JOptionPane.ERROR_MESSAGE);
canRead = false;
}
}
if(canRead) {
fsize = f.length();
totalFrms = ((int)fileHeadBuf[8] & 0xff) +
(((int)fileHeadBuf[9] & 0xff) << 8) +
(((int)fileHeadBuf[10] & 0xff) << 16);
curFrmNo = 0;
aniFrms.clear();
if((rlen < animeFrmSize) ||
(fileHeadBuf[0] != 0x41) || (fileHeadBuf[1] != 0x43) ||
(fileHeadBuf[2] != 0x44) || (fileHeadBuf[3] != 0x00) ||
(totalFrms < 1) || (fileHeadBuf[11] != 0) ||
(fsize != (long)animeFrmSize * (totalFrms + 1)) ){
JOptionPane.showMessageDialog(mainFrm,"ファイルヘッダが壊れています",
"AceDraw",JOptionPane.ERROR_MESSAGE);
canRead = false;
}
if(canRead) {
fileName = s;
for(int i=0; i < totalFrms; i++) {
try {
fi.read(frameHeadBuf);
fi.read(frameImgBuf);
} catch(Throwable fe) {
JOptionPane.showMessageDialog(mainFrm,"ファイルの入力中にエラーが発生しました",
"AceDraw",JOptionPane.ERROR_MESSAGE);
canRead = false;
}
if(!canRead) break;
aniFrm = new AnimeFrame();
if(frameHeadBuf[0]!=0) aniFrm.setMark(true);
aniFrm.setImg(frameImgBuf);
aniFrms.add(aniFrm);
}
}
}
} else {
JOptionPane.showMessageDialog(mainFrm,"ファイルの拡張子が.ACDではありません",
"AceDraw",JOptionPane.ERROR_MESSAGE);
canRead = false;
}
}
}
}
if(canRead) {
drawingImg = aniFrms.get(curFrmNo).cloneImg();
if(curFrmNo < totalFrms-1) {
nxtFrmImg = aniFrms.get(curFrmNo+1).getImg();
}
updateView();
updateFrmInfo();
}
}
}
private String saveFileName() {
File f = null;
int n;
String s = "";
n = fChoose.showSaveDialog(mainFrm);
if(n == JFileChooser.APPROVE_OPTION) {
f = fChoose.getSelectedFile();
s = f.getAbsolutePath();
}
return s;
}
private boolean fileSave(String fn) {
boolean canOut = false;
File f = null;
FileOutputStream fos = null;
int lc,fc;
int bOfs,eOfs;
if((fn != null) && (fn.length()!=0)) {
if(fn.indexOf('.')<0) {
fn = fn + ".acd";
} else {
if(! fn.substring(fn.indexOf('.')).toUpperCase().equals(".ACD")) {
JOptionPane.showMessageDialog(mainFrm,"ファイルの拡張子が.ACDではありません",
"AceDraw",JOptionPane.ERROR_MESSAGE);
fn = "";
}
}
if(fn.length() > 0) {
f = new File(fn);
if(f.exists()) {
int r = JOptionPane.showConfirmDialog(mainFrm,"同名ファイルが存在します。上書きしますか?",
"AceDraw",JOptionPane.YES_NO_OPTION);
if(r == JOptionPane.YES_OPTION) canOut = true;
} else {
canOut = true;
}
if(canOut) {
try {
fos = new FileOutputStream(f);
} catch(Throwable fe) {
JOptionPane.showMessageDialog(mainFrm,"ファイルの作成に失敗しました",
"AceDraw",JOptionPane.ERROR_MESSAGE);
}
if(canOut) {
for(int i=0; i<animeFrmSize; i++) fileHeadBuf[i]= 0;
fileHeadBuf[0] = (byte)'A'; // ファイルID
fileHeadBuf[1] = (byte)'C';
fileHeadBuf[2] = (byte)'D';
fileHeadBuf[3] = 0;
fileHeadBuf[4] = 0; // バージョン番号
fileHeadBuf[5] = 1;
fileHeadBuf[6] = 0; // リザーブ
fileHeadBuf[7] = 0;
fileHeadBuf[8] = (byte)(aniFrms.size() & 0xff); // フレーム数
fileHeadBuf[9] = (byte)((aniFrms.size() >> 8) & 0xff);
fileHeadBuf[10] = (byte)((aniFrms.size() >> 16) & 0xff);
fileHeadBuf[11] = (byte)((aniFrms.size() >> 24) & 0xff);
try {
fos.write(fileHeadBuf);
} catch(Throwable fe) {
JOptionPane.showMessageDialog(mainFrm,"出力中にエラーが発生しました",
"AceDraw",JOptionPane.ERROR_MESSAGE);
canOut = false;
}
}
for(int fr = 0; fr < aniFrms.size(); fr ++) {
if(! canOut) break;
if(aniFrms.get(fr).getMark()) frameHeadBuf[0] = 1;
else frameHeadBuf[0] = 0;
for(int i=1; i<128; i++) frameHeadBuf[i] = 0;
frameImgBuf = aniFrms.get(fr).getImg();
if(canOut) {
try {
fos.write(frameHeadBuf);
fos.write(frameImgBuf);
} catch(Throwable fe) {
JOptionPane.showMessageDialog(mainFrm,"出力中にエラーが発生しました",
"AceDraw",JOptionPane.ERROR_MESSAGE);
canOut = false;
}
}
} // for
try {
fos.flush();
fos.close();
fileClean = true;
} catch(Throwable fe) {
JOptionPane.showMessageDialog(mainFrm,"出力ファイルのクローズに失敗しました",
"AceDraw",JOptionPane.ERROR_MESSAGE);
canOut = false;
fileClean = false;
}
}
}
}
return canOut;
}
private boolean doFilesaveAs() {
boolean r =false;
String nfn = saveFileName();
if((nfn != null) && (nfn.length() > 0)) {
if(fileSave(nfn)) {
fileName = nfn;
r = true;
}
}
return r;
}
private boolean doFileSave() {
boolean r = false;
if(fileName.length() == 0) {
r = doFilesaveAs();
} else {
r = fileSave(fileName);
}
return r;
}
private ActionListener fileActLsn = new ActionListener() {
public void actionPerformed(ActionEvent e) {
updateFrm();
if(e.getActionCommand().equals("New")) {
doFileNew();
} else if(e.getActionCommand().equals("Open")) {
doFileOpen();
} else if(e.getActionCommand().equals("Save")) {
doFileSave();
} else if(e.getActionCommand().equals("saveAs")) {
doFilesaveAs();
} else if(e.getActionCommand().equals("eXit")) {
if(checkClean()) System.exit(0);
} else {
}
}
};
private void addNewFrm() {
prvFrmImg = drawingImg;
drawingImg = newImg();
AnimeFrame aniFrm = new AnimeFrame();
if(curFrmNo < aniFrms.size() - 1) {
aniFrms.add(curFrmNo+1,aniFrm);
} else {
aniFrms.add(aniFrm);
}
curFrmNo++;
updateView();
updateFrmInfo();
fileClean = false;
}
private void insertFrm() {
nxtFrmImg = drawingImg;
drawingImg = newImg();
AnimeFrame aniFrm = new AnimeFrame();
aniFrms.add(curFrmNo,aniFrm);
updateView();
updateFrmInfo();
fileClean = false;
}
private void deleteFrm() {
if(aniFrms.size() > 1) {
int r = JOptionPane.showConfirmDialog(mainFrm,"このフレームを削除しますか?",
"AceDraw",JOptionPane.YES_NO_OPTION);
if(r == JOptionPane.YES_OPTION) {
aniFrms.remove(curFrmNo);
if(curFrmNo == aniFrms.size()) {
curFrmNo--;
drawingImg = aniFrms.get(curFrmNo).cloneImg();
if(curFrmNo > 0) {
prvFrmImg = aniFrms.get(curFrmNo-1).getImg();
} else {
prvFrmImg = newImg();
}
} else {
drawingImg = nxtFrmImg;
if(curFrmNo < aniFrms.size() - 1) {
nxtFrmImg = aniFrms.get(curFrmNo+1).getImg();
} else {
nxtFrmImg = newImg();
}
}
updateView();
updateFrmInfo();
fileClean = false;
}
}
}
private ActionListener frmActLsn = new ActionListener() {
public void actionPerformed(ActionEvent e) {
updateFrm();
if(e.getActionCommand().equals("New")) {
addNewFrm();
} else if(e.getActionCommand().equals("Insert")) {
insertFrm();
} else if(e.getActionCommand().equals("Delete")) {
deleteFrm();
} else {
}
}
};
private void initProg() {
drawingImg = newImg();
prvFrmImg = newImg();
nxtFrmImg = newImg();
undoImg = newImg();
redoImg = newImg();
plPoints = new ArrayList<Point>();
}
private void doProg() {
AnimeFrame aniFrm = new AnimeFrame();
aniFrms.add(aniFrm);
curFrmNo = 0;
canundo = false;
canredo = false;
fileClean = true;
drawmode = DrawMode.none;
FileNameExtensionFilter fFilt = new FileNameExtensionFilter("ACEdraw data", "acd");
fChoose.addChoosableFileFilter(fFilt);
grpPnl.addMouseListener(grpMLsn);
grpPnl.addMouseMotionListener(grpMmLsn);
undoBtn.addMouseListener(undoBtnLsn);
freeBtn.addMouseListener(freeBtnLsn);
snglBtn.addMouseListener(snglBtnLsn);
polyBtn.addMouseListener(polyBtnLsn);
frmBMBtn.addMouseListener(frmBMBtnLsn);
frmBBtn.addMouseListener(frmBBtnLsn);
frmFBtn.addMouseListener(frmFBtnLsn);
frmFMBtn.addMouseListener(frmFMBtnLsn);
frmPBtn.addItemListener(frmPBtnLsn);
frmNBtn.addItemListener(frmNBtnLsn);
mainFrm.addWindowListener(winLsn);
}
WindowListener winLsn = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
updateFrm();
if(checkClean()) System.exit(0);
}
};
private void makeFrame() {
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
mainFrm = new JFrame("AceDrawプロト2");
mainFrm.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
JPanel toolBtnPnl = new JPanel(new GridLayout(3,1,2,0));
freeBtn =new JToggleButton("free");
snglBtn =new JToggleButton("single");
polyBtn =new JToggleButton("poly");
toolBtnPnl.add(freeBtn);
toolBtnPnl.add(snglBtn);
toolBtnPnl.add(polyBtn);
ButtonGroup toolBtns = new ButtonGroup();
toolBtns.add(freeBtn);
toolBtns.add(snglBtn);
toolBtns.add(polyBtn);
plMenu = new JPopupMenu();
JMenuItem plItemEnd = new JMenuItem("End");
plItemEnd.addMouseListener(plEndLsn);
JMenuItem plItemBack = new JMenuItem("Back");
plItemBack.addMouseListener(plBackLsn);
plMenu.add(plItemEnd);
plMenu.add(plItemBack);
plMenuVisible = false;
JPanel toolPnl = new JPanel(new BorderLayout(0,4));
undoBtn = new JButton("undo draw");
toolPnl.add(undoBtn,BorderLayout.NORTH);
toolPnl.add(toolBtnPnl,BorderLayout.SOUTH);
JPanel drawPnl = new JPanel(new BorderLayout());
grpInfoLbl = new JLabel();
grpInfoLbl.setFont(new Font("Monospaced",Font.PLAIN,10));
drawPnl.add(grpInfoLbl,BorderLayout.NORTH);
drawPnl.add(toolPnl,BorderLayout.SOUTH);
JPanel mainPnl = new JPanel(new BorderLayout(4,4));
JMenuBar mainMenu = new JMenuBar();
JPanel frmFBPnl = new JPanel(new GridLayout(1,6,2,2));
frmBMBtn = new JButton("<<");
frmBBtn = new JButton("<");
frmFBtn = new JButton(">");
frmFMBtn = new JButton(">>");
frmPBtn = new JToggleButton("P");
frmNBtn = new JToggleButton("N");
frmFBPnl.add(frmBMBtn);
frmFBPnl.add(frmBBtn);
frmFBPnl.add(frmFBtn);
frmFBPnl.add(frmFMBtn);
frmFBPnl.add(frmPBtn);
frmFBPnl.add(frmNBtn);
JPanel frmInfoPnl = new JPanel(new BorderLayout(2,2));
frmInfoLbl = new JLabel("1 / 1");
JLabel lblFrmFrame = new JLabel("Frame:");
frmInfoPnl.add(lblFrmFrame,BorderLayout.WEST);
frmInfoPnl.add(frmInfoLbl,BorderLayout.CENTER);
JPanel frmCtrlPnl = new JPanel(new BorderLayout(8,4));
frmCtrlPnl.add(frmInfoPnl,BorderLayout.NORTH);
frmCtrlPnl.add(frmFBPnl,BorderLayout.CENTER);
grpPnl.setPreferredSize(new Dimension(imgWidth,imgHeight));
mainPnl.add(grpPnl,BorderLayout.CENTER);
mainPnl.add(drawPnl,BorderLayout.EAST);
mainPnl.add(frmCtrlPnl,BorderLayout.SOUTH);
mainPnl.setBorder(new EmptyBorder(4,4,4,4));
fileMenu = new JMenu("File");
fileMenu.setMnemonic(KeyEvent.VK_F);
JMenuItem fileNew = new JMenuItem("New",KeyEvent.VK_N);
fileNew.addActionListener(fileActLsn);
JMenuItem fileOpen = new JMenuItem("Open",KeyEvent.VK_O);
fileOpen.addActionListener(fileActLsn);
JMenuItem fileSave = new JMenuItem("Save",KeyEvent.VK_S);
fileSave.addActionListener(fileActLsn);
JMenuItem filesaveAs = new JMenuItem("saveAs",KeyEvent.VK_A);
filesaveAs.addActionListener(fileActLsn);
JMenuItem fileeXit = new JMenuItem("eXit",KeyEvent.VK_X);
fileeXit.addActionListener(fileActLsn);
fileMenu.add(fileNew);
fileMenu.add(fileOpen);
fileMenu.add(fileSave);
fileMenu.add(filesaveAs);
fileMenu.add(fileeXit);
mainMenu.add(fileMenu);
grpMenu = new JMenu("Graphic");
grpMenu.setMnemonic(KeyEvent.VK_G);
JMenuItem grpcuT = new JMenuItem("cuT",KeyEvent.VK_T);
grpcuT.setEnabled(false);
JMenuItem grpCopy = new JMenuItem("Copy",KeyEvent.VK_C);
grpCopy.setEnabled(false);
JMenuItem grpPaste = new JMenuItem("Paste",KeyEvent.VK_P);
grpPaste.setEnabled(false);
grpMenu.add(grpcuT);
grpMenu.add(grpCopy);
grpMenu.add(grpPaste);
mainMenu.add(grpMenu);
frmMenu = new JMenu("fRame");
frmMenu.setMnemonic(KeyEvent.VK_R);
JMenuItem frmNew = new JMenuItem("New",KeyEvent.VK_N);
frmNew.addActionListener(frmActLsn);
JMenuItem frmIns = new JMenuItem("Insert",KeyEvent.VK_I);
frmIns.addActionListener(frmActLsn);
JMenuItem frmDel = new JMenuItem("Delete",KeyEvent.VK_D);
frmDel.addActionListener(frmActLsn);
JMenuItem frmMove = new JMenuItem("Move",KeyEvent.VK_M);
frmMove.setEnabled(false);
JMenuItem frmCopy = new JMenuItem("Copy",KeyEvent.VK_C);
frmCopy.setEnabled(false);
JMenuItem frmSelF = new JMenuItem("Select frames",KeyEvent.VK_S);
frmSelF.setEnabled(false);
frmMenu.add(frmNew);
frmMenu.add(frmIns);
frmMenu.add(frmDel);
frmMenu.add(frmMove);
frmMenu.add(frmCopy);
frmMenu.add(frmSelF);
mainMenu.add(frmMenu);
playMenu = new JMenu("Play");
playMenu.setMnemonic(KeyEvent.VK_P);
JMenuItem playSt = new JMenuItem("Start",KeyEvent.VK_S);
playSt.setEnabled(false);
playMenu.add(playSt);
mainMenu.add(playMenu);
mainFrm.getContentPane().add(mainPnl);
mainFrm.setJMenuBar(mainMenu);
mainFrm.pack();
mainFrm.setVisible(true);
updateView();
}
public static void main(final String[] args) {
AceDrawProto2dash myProg = new AceDrawProto2dash();
myProg.initProg();
myProg.makeFrame();
myProg.doProg();
}
}
|