📄 asciidrawpanel.java
字号:
package joeh.asciidraw;
import java.awt.*;
import java.applet.*;
import java.util.*;
import java.io.*;
//We just paint on the Panel directly.
public class AsciiDrawPanel extends Panel {
int columns;
int rows;
//Canvas drawArea; //where the drawing takes place
Image im2;
Dimension im2s;
Graphics im2g;
Graphics ourG;
File destFile;
FileOutputStream destination = null;
Hashtable positions;
Vector keys;
boolean first = true;
Dimension recentSize = new Dimension(0,0);
String THEchar = " ";
Color THEcolor = Color.white;
paletteItem currentColorPaletteSelection;
toolItem currentToolSelection;
AsciiDrawFrame parent;
boolean drawing = true; //yes, drawing (not erasing)
asciiCursor theCursor;
int highlightBorderWidth = 1; //highlight of a sqaure in the main panel
int mode = ToolType.PENCIL;
boolean dirty = true; //tells when to actually loop through all of the data on
//a repaint.
public AsciiDrawPanel(AsciiDrawFrame p, int sqrsize) {
rows = sqrsize;
columns = sqrsize;
parent = p;
theCursor = new asciiCursor(this, rows, columns, 5,5);
positions = new Hashtable();
keys = new Vector();
//System.out.print("LOADING.....");
int x = 0;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
Coordinate key = new Coordinate(i,j);
keys.addElement(key);
Switch dirt = new Switch(false, THEchar, THEcolor); //
positions.put(key,dirt);
}
x++;
}
//System.out.println("DONE LOADING");
}
public void setStatusLabel(String s) {
parent.setStatusLabel(s);
}
public void setCursor() {
Graphics g = this.getGraphics(); //the REAL visible graphics!
//erase old highlight draw new one
//---> Since this flashes off and on if the old loc = current loc,
//we dont do this in that case.
if ( (!(theCursor.getLastLoc().equals(theCursor.getLoc()))) )
unHighlight(g, theCursor.getLastLoc().getX(), theCursor.getLastLoc().getY());
//highlight(buffer, theCursor.getLoc().getX(), theCursor.getLoc().getY());
drawHighlightOnSquare(g, theCursor.getLoc().getX(), theCursor.getLoc().getY());
}
public void setDrawing() {
// System.out.println("drawing");
drawing = true;
}
public void setErasing() {
// System.out.println("erasing");
drawing = false;
}
public boolean isDrawing() {
return drawing;
}
public void setColorAndChar(Color c, String s) {
THEcolor = new Color(c.getRGB());
THEchar = new String(s);
}
public void setColorPaletteSelection(paletteItem newPaletteSelection) {
parent.setColorPaletteSelection(newPaletteSelection);
}
public void setTool(int kind) {
mode = kind;
}
public void setToolSelection(toolItem newToolSelection) {
parent.setToolSelection(newToolSelection);
}
public void setDirty() {
dirty = true;
}
//goes throuugh ALL of the data and paints everything
//Unless we are still waiting on the users desicion to
//undo a clear in which case we only draw the panel boarder
//Note: one annoying case: user clears then resizes then does "undo clear"
//for this I need a HACK (look in code for undo in the event handler and also
// below in the paint method)
public boolean SIZEDCHANGED = false; //means "has sized changed since last undo performed?"
public void paint(Graphics g) {
int oneW = this.size().width/columns;
int oneH = this.size().height/rows;
im2s = new Dimension(this.size().width, this.size().height);
//if size has changed, make new image
if ( !((im2s.width == recentSize.width)&&(im2s.height == recentSize.height)) ) {
SIZEDCHANGED = true;
setDirty();
im2 = null; //garbage collector heaven
//I remember seeing a better way to immediately induce garbage collection... (?)
im2 = createImage(this.size().width, this.size().height);
recentSize = null;
recentSize = new Dimension(im2s.width, im2s.height);
}
if (dirty) {
im2g = im2.getGraphics(); //new image
im2g.setColor(Color.white); //clear it to white
im2g.fillRect(0, 0, im2s.width, im2s.height);
//If we aren't waiting for a user's decision about undo clear
//Or it is that one special HACKy case, then paint the hard way
if ( (!(parent.nextUndo)) ) {
int x = 0;
//set cursor to WATCH -- this next operation is quite lengthy
for (int i = 0; i < rows; i++)
{
// System.out.print(i + " ");
for (int j = 0; j < columns; j++)
{
Switch sw = (Switch)positions.get(keys.elementAt(x));
if ( sw == null )
System.out.print("got null --> ERROR");
else
if (sw.isOn() == true) {
drawSquare(im2g, i, j); //draw the square with data
}
x++;
}
}
dirty = false; //we drew it, so we are now "clean"
SIZEDCHANGED = false; //also we are now at our new size so reset this
//set cursor to NORMAL POINTER CURSOR
}
drawActiveFrame(im2g); //the frame around the entire image
}
//in any case, by now im2 is a "valid" image, so just stick it in g.
//we use dirty, so im2 the old one will be used here. :-)
//System.out.println("drawImage:" + im2);
g.drawImage(im2,0,0,null); //finally, draw it into our real panel graphics
}
public void repaint() {
//System.out.println("repaint...");
paint(this.getGraphics());
//standard textbook remark: "overriding this prevents flashes in some cases"
}
public String getChar() {
return THEchar;
}
//call this before doSave(true)
public void setDestFile(String s) {
System.out.println("filename is " + s);
destFile = new File((new String(s)));
}
public void doSave(boolean fprint, int kind) {
//kind == 1 is ascii normal (like this!)
//kind == 2 also include the Java code that would generate the
//image they drew
//NOTE: the CODEGEN parts below are neccessarily confusing because I'M
//writing out Java code inside of Java code! Also, I've optimized so the
//code will be shorter than the obvious way, so the code is even more obscure.
//Sorry, that's life.
String result = "\n";
//ignore the last few empty rows
int p = 0;
boolean outerBreak = false;
int lastSignificantRow = rows-1;
for (int i = rows-1; i >= 0; i--)
{
for (int j = 0; j < columns; j++)
{
p = j*columns + i;
Switch sw = (Switch)positions.get(keys.elementAt(p));
if ( sw==null )
System.out.print("DATA ERROR");
else
if (sw.isOn() == true) {
lastSignificantRow = i;
outerBreak = true;
break;
}
}
if (outerBreak)
break;
}
if (outerBreak == false) //then there is no data, stop here!
return;
int entries = 0;
//The "code" part here is to generate java code
//that will paint the image one space per pixel
//to a Java Graphics object 'g'.
boolean CODEGEN = false; //don't attach Java code version too
if (kind == 2) //if this was called with kind flag == 2
CODEGEN = true; //then also put the Java code
//at the bottom.
//The java code if run in a Java program
//will paint the image they drew
//using the same colors as they did
//with the scale 1 space = 1 pixel.
//text will be transparent pixels.
Color lastColor = Color.white;
String code = "// Generated by AsciiDraw\n"
+ "// (c) 1996, Joe Heitzeberg. joeh@goldbay.com\n"
+ "// http://www.goldbay.com/joeh\n"
+ "// If you want some picture to be used in a Java\n"
+ "// program, but you don't want to code it up,\n"
+ "// just draw it with AsciiDraw and output the code!\n"
+ "// Because it is hard-coded, it is fast\n";
//draw the image and ignore any empty rows at the start
boolean goAhead = false; //dont write the first few, if any, empty rows
String currentRow = "";
int x = 0;
boolean inRect = false;
int jstart = 0;
for (int i = 0; i <= lastSignificantRow; i++) {
currentRow = ""; //ready for another row
for (int j = 0; j < columns; j++) {
x = j*columns + i;
Switch sw = (Switch)positions.get(keys.elementAt(x));
if ( sw==null )
System.out.print("Uh-oh DATA ERROR. Better restart...");
else {
if (sw.isOn() == true) {
currentRow = currentRow + sw.getChar();
goAhead = true;
if (CODEGEN) {
if (!inRect) {
inRect = true;
jstart = j;
if (!(lastColor.equals(sw.getColor()))) {
lastColor = sw.getColor();
code = code + "g.setColor(new Color("
+ sw.getColor().getRGB() +"));\n";
}
}
else
if (!(lastColor.equals(sw.getColor()))) {
code = code + "g.fillRect("+ jstart + ", "
+ i +", " + (j - jstart) + ", 1); \n";
jstart = j;
lastColor = sw.getColor();
code = code + "g.setColor(new Color("
+ sw.getColor().getRGB() +"));\n";
}
}
}
else { //current cell is off
currentRow = currentRow + " ";
if (CODEGEN) {
//check if a rect to draw has just finished
if (inRect) { //yup we we doing a rect!
inRect = false; //then add code to draw it
code = code + "g.fillRect("+ jstart + ", "
+ i +", " + (j - jstart) + ", 1); \n";
//lastColor = Color.white; //our transparent color
}
}
}
}
}
//done with a row;
if (CODEGEN) {
if (inRect) {
code = code + "g.fillRect("+ jstart +", "
+ i +", " + (columns-jstart) + ", 1); \n";
inRect = false;
}
}
if (goAhead)
result = result + currentRow + "\n";
}
//done, add one blank row for separation
result = result + "\n";
//TEST USE HERE!!!
if (CODEGEN)
result += code + "\n //End of AsciiDraw generated code section." ;
if (fprint) //file out result
{
//message at the top of the output of files
result = "[[ Created with AsciiDraw http://weber.u.washington.edu/~picasso/index.html ]]\n"
+ "[[ Make sure you use a monospace font such as Courier to view your output ]]\n\n" + result;
try {
writeStrToFile(result);
}
catch (SecurityException se)
{
String seStr = " ";
seStr = seStr + "SECURITY VIOLATION - file write attemted\n";
seStr = seStr + "...I guess you are running this from a Browser such as Netscape...\n";
seStr = seStr + "Browsers won't let you write files.\n";
seStr = seStr + "To save your results you'll need to run this as an standalone.\n";
seStr = seStr + " 1. Download the class files.\n";
seStr = seStr + " 2. Run as a standalone (i.e. java AsciiDraw).\n";
seStr = seStr + " --To do this you need the JDK, but you already know that, right?\n";
PreviewFrame pf = new PreviewFrame(400,200, seStr);
pf.show();
}
}
else //standard out result to preview window
{
//System.out.print(result);
PreviewFrame pf = new PreviewFrame(550,450, result);
pf.show();
}
}
//regardless of data, put a highligh on the sqaure
private void drawHighlightOnSquare (Graphics gg, int cooX, int cooY) {
int oneW = this.size().width/columns;
int oneH = this.size().height/rows;
gg.setColor(Color.yellow);
int xxx = cooX*oneW;
int yyy = cooY*oneH;
gg.fillRect(xxx,yyy, oneW, highlightBorderWidth); //top
gg.fillRect(xxx,yyy+oneH-highlightBorderWidth, oneW, highlightBorderWidth); //bottom
gg.fillRect(xxx,yyy,highlightBorderWidth, oneH); //left
gg.fillRect(xxx+oneW-highlightBorderWidth, yyy, highlightBorderWidth, oneH); //right
}
//regardless of data, clear this space
private void clearSquare (Graphics gg, int cooX, int cooY) {
int oneW = this.size().width/columns;
int oneH = this.size().height/rows;
gg.setColor(Color.white);
gg.fillRect(cooX*oneW, cooY*oneH, oneW, oneH);
}
//Draw the square depending on what data is there. Clears first.
private void drawSquare(Graphics gg, int cooX, int cooY) {
int oneW = this.size().width/columns;
int oneH = this.size().height/rows;
//System.out.println("typed " + cooX +","+ cooY);
//uh-oh protection...if location
if ((cooX < columns) && (cooY < rows) && (cooY >= 0) && (cooX >= 0))
{
// gg.setColor(Color.white);
// gg.fillRect(cooX*oneW, cooY*oneH, oneW, oneH);
clearSquare(gg, cooX, cooY);
int arrayNum = (cooX*rows + cooY);
//setDrawing();
Switch sw = ((Switch)positions.get(keys.elementAt(arrayNum)));
if ( sw==null )
System.out.print("got null BAD... drawsquare");
else
if (sw.isOn()) {
//draw the rectangle...and if it is a typed char
gg.setColor(sw.getColor());
gg.fillRect(cooX*oneW, cooY*oneH, oneW, oneH);
if (sw.reallyShowChar()) //then show on the screen too
{
gg.setColor(Color.black);
drawStringWell(gg, sw.getChar(), cooX*oneW, cooY*oneH);
}
}
}
else System.out.println("JOE - FIX ME drawsquare");
drawActiveFrame(gg); //redraw the entire canvas's bounds
}
//private void highlight(Graphics gg, int coordX, int coordY) {
////draw the square with highlight
//if (parent.nextUndo) //then we are still waiting for a user's undo action desicion
// drawHighlightOnSquare(gg,coordX, coordY); //so just show highlight the square only
//else
//{
// drawSquare(gg, coordX, coordY); //draw from the data
// drawHighlightOnSquare(gg, coordX, coordY);
//}
//}
private void unHighlight(Graphics gg, int coordX, int coordY) {
//draw the square with no highlight
if (parent.nextUndo) //then we are still waiting for a user's undo action desicion so just fill white
clearSquare(gg, coordX, coordY);
else
drawSquare(gg, coordX, coordY); //draw from the data
}
private void drawActiveFrame(Graphics g) {
//draw around area we are using
// since the size we have and the size we use can be different
//deping on the window size and the division (since pixels=int)
int oneW = this.size().width/columns;
int oneH = this.size().height/rows;
g.setColor(Color.darkGray);
g.drawLine(0,0,oneW*columns,0);
g.drawLine(0,0,0,oneH*rows);
g.drawLine(oneW*columns,oneH*rows,oneW*columns,0);
g.drawLine(oneW*columns,oneH*rows,0,oneH*rows);
}
public void clearGraphics() {
//fast clear visually the data being displayed, but leave
//the stand-in graphics im2g as is ready to save the day
//quickly in case the user choses undo clear.
Graphics g = this.getGraphics();
Dimension d = this.size();
g.setColor(Color.white);
g.fillRect(0, 0, d.width, d.height);
drawActiveFrame(g);
}
//clears the data only. (use clearGraphics to clear the screen only)
//then if the user misses the chance to undo the clear,
//zap the data
public void doClear() {
//clear the stand-in image that would have been be copied in
//if they had chosen undo.
im2g.setColor(Color.white);
im2g.fillRect(0, 0, im2s.width, im2s.height);
//loop through clearing the data
Enumeration ee = positions.keys(); //get everyone directly
while (ee.hasMoreElements())
{
Switch sw = (Switch)positions.get(ee.nextElement());
if ( sw==null )
System.out.print("DATA ERROR encountered, I suggest restarting this applet");
else
sw.turnOff();
}
}
Dimension dd;
int arrayNumm;
Switch sww;
int ww, hh;
private boolean check4Fill(Graphics g, int cooX, int cooY, Color oc, Color nc) {
arrayNumm = (cooX*rows + cooY);
//im2s == this.size();
ww = im2s.width/columns;
hh = im2s.height/rows;
sww = ((Switch)positions.get(keys.elementAt(arrayNumm)));
if (sww.getColor().equals(oc)) {
sww.setChar(THEchar, false); //these kind don't show on the screen, just in ascii version
sww.setColor(nc);
g.setColor(nc);
g.fillRect(cooX*ww,cooY*hh, ww, hh);
im2g.setColor(nc);
im2g.fillRect(cooX*ww,cooY*hh, ww, hh);
return true;
}
return false;
}
public void areaFill(Graphics g, Color oc, Color nc, int cooX, int cooY) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -