25 Years of Programming
An open source source for C, C++, OWL, BASIC, MDB, XLS, DOT, and more...
Home   Projects   Up   Sitemap   Search   Blog   Forum+Chat   About Us   Privacy   Terms of Use   Feedback   FAQ   Images   Services   Ads   Donate   Humor

Mandelbrot set area. Click to view full size.

JBrot (Java Mandelbrot Set)

In order to learn something about Java, I spent a month creating this conversion of the Winbrot project. The program is functional, and it is nice to finally have a version that runs on Windows XP, but not all of Winbrot's features are implemented. The source files still contain some commented out C++ code that hasn't yet been converted. Work on this project is not likely to continue because the downside of Java's cross-platform versatility is that it runs too slowly to be practical for this type of program.

This program preserves Winbrot's Auto-run mode and random area selection and "boring area" filtering methods, which could easily be incorporated into any Java Mandelbrot program.

The project was built with Borland's JBuilderX IDE. Java is verbose, and using an IDE to work with it can save a huge amount of typing. Plus there are help files and other reference materials. JBuilder is available for free at http://www.borland.com/downloads/download_jbuilder.html.

The source code for JBrot is included in the Winbrot zip file.

Mandelbrot set area. Click to view full size.

JBrot (Java)

MandelbrotGenerator.java

package jbrot;

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.io.*;
import javax.swing.*;
import java.util.*;

/**
 * <p>Title: This file is part of the JBrot project.</p>
 * <p>Description: Java version of the Winbrot Mandelbrot generator program.</p>
 * <p>Copyright: Copyright (C)1993-2004 Steven Whitney.</p>
 * <p>Published under GNU GPL (General Public License) Version 2,
 * with ABSOLUTELY NO WARRANTY.</p>
 * <p>Initially published by http://25yearsofprogramming.com.</p>
 * <p>This program (the JBrot project) is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License (GPL)
 * Version 2 as published by the Free Software Foundation.
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.</p>
 * @version 1.0
 */

//When I create a new class or a new JavaBean based on Object,
//it is not given anything more than what this class already has, so I assume
//that this class (and all classes) is inherently based on Object,
//and is probably also a valid JavaBean until you do something that violates
//the JavaBean rules.
///////////////////////////////////////////////////////////////////////////////
public class MandelbrotGenerator
{
static Random RandomGenerator = new Random();       // a random # generating machine
Rectangle2D.Double WholeMbrot = new Rectangle2D.Double(-2.0, 1.25, 2.5, 2.5);
Rectangle2D.Double curr = new Rectangle2D.Double(); // currently-displayed region
protected Stack prev = new Stack();                 // poppable list of previous curr's

int PixelWidth = 0, PixelHeight = 0;// image is scaled to this window size
double AspectRatio = 0;             // PixelWidth / PixelHeight

private int zpower = 2;				// the power to which z is raised (normally 2)
private double dx;                  // increment of curr in x, y dimensions for each pixel.
private double dy;

public boolean allowzoom = false;	// whether current display is a calculated Mandelbrot area
boolean isotropicxy = true;			// whether to keep dx == dy

byte[] Reds = new byte[256];        // for palette rotation, rotate these arrays in place
byte[] Greens = new byte[256];
byte[] Blues = new byte[256];
byte[] Alphas = new byte[256];
int bitMasks[] = new int[] {0xff};  // all 8 bits are significant (used)
SampleModel samplemodel;

byte[] EscapeTimeArray;             //a contiguous buffer holding the escape times

// note that the image wound up here instead of the JPanel!
BufferedImage image = null;                             // Holds the generated image
//IndexColorModel colormodel = ColorModelRandom256();   //more visible during testing
IndexColorModel colormodel = ColorModelGrayScale256();  // default startup mode
//IndexColorModel colormodel = ColorModelFromFile("blues.map");

//I did this the same as Winbrot - an ordinary array of string file names.
public String[] MapFiles;	        // list of all available .MAP files
private int MapFileIndex = -1;      //index, and used to retrieve the file name.
boolean MapFileIsModified = false;  // =old SDib::palettechanged

public String[] FileList;           // command line arguments and/or user-selected files

//----------------------------------------------------------------------------
//constructors
public MandelbrotGenerator()    //unused default ctor with arbitrary size
{
	this(100,100);
}
public MandelbrotGenerator(int width, int height)
{
	try
	{
		jbInit();
	}
	catch(Exception ex)
	{
		ex.printStackTrace();
	}
	//do this in all ctors so Prev[0] is always WholeMbrot as a start point.
	//it actually isn't yet, but it will be when the next one is created.
	curr = WholeMbrot;
	SetWindowSize(width, height);
}
private void jbInit() throws Exception
{
}
//----------------------------------------------------------------------------
public void SetWindowSize(int width, int height)
{
PixelWidth = width;
PixelHeight = height;
AspectRatio = (double)PixelWidth / (double)PixelHeight;
//a sample model with 8-bits of data stored in an 8-bit data element.
//The bitmask is anded with the data.  The confusing thing here is that the
//SampleModel names and methods (banding, banking, etc.) are geared toward color
//or color plane usage.  In this case, the actual data is not true pixel
//data at all, packed or otherwise.
//This is here because it only changes when the window size changes.
samplemodel = new SinglePixelPackedSampleModel(DataBuffer.TYPE_BYTE, PixelWidth,
											   PixelHeight, bitMasks);
calcmbrot();
}
//----------------------------------------------------------------------------
public void draw(Graphics g, int x, int y)
{
	if(image != null)
		g.drawImage(image, x, y, null);
}
//----------------------------------------------------------------------------
public int  getZPower() { return zpower; }
public void setZPower(int z)
{
if((z >= 2) && (z <= 16))	// I tested 16: ok, but uninteresting
{
	zpower = z;
	prev.clear();
	curr = WholeMbrot;
	calcmbrot();
}
}
//----------------------------------------------------------------------------
public void setIsotropicXY(boolean b)
{
	isotropicxy = b;
	calcmbrot();
}
//----------------------------------------------------------------------------
// save the current curr as previous, then set it to the new one.
public void setcurr(Rectangle2D.Double newmandelrectangle)
{
prev.push(curr);
curr = newmandelrectangle;
calcmbrot();
}
//----------------------------------------------------------------------------
// display the previous area (the one before the currently displayed one).
// As you back up over entries, they are deleted from the list.
// The last prev entry will always be the one currently being calculated or displayed.
public void GoBack()
{
if(prev.isEmpty())
	return;
curr = (Rectangle2D.Double)prev.pop();
calcmbrot();
//	SetParentCaption(string(GetApplication()->GetName()) + " - Previous (#" +
//					tostring(prev.GetItemsInContainer()) + ")");
}                       	//CmFilePrevious
//----------------------------------------------------------------------------
// zoom into a specified quadrant:
//0=ZoomOut, 1=TopLeft, 2=TopRight, 3=BottomLeft, 4=BottomRight, 5=CenterQuad
void quadrantzoom(int quadrant)
{
if(allowzoom)
{
//	SetParentCaption(string(GetApplication()->GetName()) + " - New Quadrant Zoom");
	Rectangle2D.Double m = null;
	double Left = curr.getX();
	double Top = curr.getY();
	double Height = curr.getHeight();
	double Width = curr.getWidth();
	double MidHeight = Top - Height / 2.;//getCenterY() uses Top + Height/2 = wrong!
	double MidWidth = Left + Width / 2.;
	switch(quadrant)
	{
		case 0:// zooms out
			m = new Rectangle2D.Double(Left - Width / 2., Top + Height / 2.,
										   Width * 2., Height * 2.);
			break;
		case 1:    // the rest zoom in
			m = new Rectangle2D.Double(Left, Top, Width / 2., Height / 2.);
			break;
		case 2:
			m = new Rectangle2D.Double(MidWidth, Top, Width / 2., Height / 2.);
			break;
		case 3:
			m = new Rectangle2D.Double(Left, MidHeight, Width / 2., Height / 2.);
			break;
		case 4:
			m = new Rectangle2D.Double(MidWidth, MidHeight, Width / 2., Height / 2.);
			break;
		case 5:
			m = new Rectangle2D.Double(Left + Width / 4., Top - Height / 4.,
										   Width / 2., Height / 2.);
			break;
	}
	if(m != null)
		setcurr(m);
}
else	// for now, for BMP, you must use mouse drag to define area
{
	// method (but not worth doing):
	// copy dib->Rect() to a DoubleRect; calc its quadrant, according to cmd;
	// make a TRect from the DoubleRect, and WriteFilePIC() using it.
//	MessageBox("Use mouse to select area of PIC.","Cannot Quadrant-Select a PIC/BMP",MB_OK);
}
}                    		//quadrantzoom
//----------------------------------------------------------------------------
// RELEASED left mouse button after defining a selection area.
public void MouseZoom(int DragLeft, int DragTop, int DragWidth, int DragHeight)
{
// prevent zero-area selection
if(((DragWidth) <= 0) || ((DragHeight) <= 0))
	return;
if(allowzoom)			// IF CURRENT DISPLAY IS A CALCULATED MANDELBROT REGION
{
//	SetParentCaption(string(GetApplication()->GetName()) + " - New Zoom View");

	//Keep this as a reminder that you can't use this method.
	//The window into which you are zooming may be showing more area than is
	//defined by curr (if extra was dragged in to fit the aspect ratio),
	//so you might be zooming in an area that isn't even within curr.
//	double Left = curr.x + (LeftPct * curr.width);
//	double Top = curr.y - (TopPct * curr.height);
//	double Width = WidthPct * curr.getWidth();
//	double Height = HeightPct * curr.getHeight();

	// In this method,
	// everything is relative to left and top, which are always valid and known.
	// if user dragged outside curr's actual defined region,
	// the new region will simply include an area that wasn't in the previous design.
	double Left = curr.getX() + (dx * DragLeft);
	double Top = curr.getY() - (dy * DragTop);
	double width = Math.abs(dx * (double)DragWidth);
	double height = Math.abs(dy * (double)DragHeight);

	Rectangle2D.Double r = new Rectangle2D.Double(Left, Top, width, height);
	setcurr(r);
}
}       	            	//MouseZoom
//----------------------------------------------------------------------------
//sets curr to be a random non-boring area within the m-set, then calculates the
//image for it.
public void randomarea()
{
Rectangle2D.Double m;								// function's return value
double Left, Top, Right, Bottom, Height, Width, MidHeight, MidWidth;
while(true)
{
	// CALCULATE A RANDOM TOP LEFT POINT WITHIN THE "MBROT" AREA
	// THIS VERSION WORKED WELL FOR ZPOWER == 2 (STANDARD)
	// tleft = ((double)random(25001) - 20000.) / 10000.;	// -2.0 to +0.50
	// ttop = ((double)random(25001) - 12500.) / 10000.;	// -1.25 to +1.25
	// THIS VERSION IS TO ACCOMODATE ANY ZPOWER
	Left = ((double)RandomGenerator.nextInt(40001) - 20000.) / 10000.;	// -2.0 to +2.0
	Top =  ((double)RandomGenerator.nextInt(40001) - 20000.) / 10000.;	// -2.0 to +2.0
	do
	{
		// THE FOLLOWING GIVES A RANDOM HEIGHT 0. TO +2.5, PROBABLY TOO BIG
		// Height = ((double)lrandom(2500000L)) / 1000000.;
		// THE NUMBERS USED HERE DETERMINE HOW CLOSE A ZOOM IS POSSIBLE
		// GIVEN A/B BELOW, HEIGHT WILL BE BETWEEN 1/B AND (A-1)/B.
		// next line was used for a long time, but many designs are similar at this scale.
		// Height = ((double)random(10001)) / 100000.;	// .00001 to .1	good
		// Height = ((double)lrandom(10000001L)) / 1e9;	// 1e-9 to .01	better
		Height = ((double)RandomGenerator.nextInt(1000000001)) / 1e11;	// 1e-11 to .01	great!
	}
	while(Height == 0.);
	Width = AspectRatio * Height;		// set the Width
	m = new Rectangle2D.Double(Left, Top, Width, Height);// create the proposed area
	Right = Left + Width;	//do not trust the Rectangle2D.Double built-in fns.
	Bottom = Top - Height;
	MidWidth = Left + Width / 2.;
	MidHeight = Top - Height / 2.;
	// but reject it if a sampling of its points all have very similar escape times
	int r = calcescapetime(MidWidth, MidHeight);			// a reference point
	// minimum required escape time variation
	//12 seemed to produce a higher percentage of interesting designs.
	//try even higher numbers.
	int minimum = 8;
	if( (Math.abs(r - calcescapetime(Left, Top)) 		< minimum)	&&
		(Math.abs(r - calcescapetime(Right, Top)) 		< minimum) 	&&
		(Math.abs(r - calcescapetime(Left, Bottom))	    < minimum) 	&&
		(Math.abs(r - calcescapetime(Right, Bottom))	< minimum)	&&
		(Math.abs(r - calcescapetime(Left, MidHeight)) 	< minimum) 	&&
		(Math.abs(r - calcescapetime(Right, MidHeight)) < minimum)	&&
		(Math.abs(r - calcescapetime(MidWidth, Top))    < minimum) 	&&
		(Math.abs(r - calcescapetime(MidWidth, Bottom))	< minimum) )
			continue;
	break;							// if you made it to end, you can exit loop
}
//SetParentCaption(string(GetApplication()->GetName()) + " - Random Area");
setcurr(m);
}							//randomarea
//----------------------------------------------------------------------------
// calculates the escape time for a single point (d).
// Repeatedly calculate Z = Z * Z + C until the iteration count reaches
// the maximum or until we can be certain it is heading to infinity.
// remember that escape times get stored as uchars, and (uchar)255 + 1 = 0.
// if the loop completes, you must return 255 upon exit, not 256.
//
// since z starts at (0,0), an actual iteration count of 0 is impossible
// (it can never actually abort "after" 0 iterations because at that time z IS 0),
// so it tests for > 2 AFTER each iteration, to get an extra "elevation" in the .PIC file.
//
// the test you use to break loop *will* affect the shapes of the colored bands.
// (e.g. if you use Manhattan distance, corners will be squared off)
//
// Testing prior z values to detect cycles (and thus abort loop early) did work, but
// randomarea() effectively screens out all the areas where the cycle tests are any use.
//
// To calculate Julia sets or even other non-Mandelbrot variations, you probably
// have only to provide alternate versions of calcescapetime().
//
int calcescapetime(double creal, double cimag) //  = complex& d
{
double zreal = 0., zimag = 0.;         //complex z(0,0)
double oldzreal = 0., oldzimag = 0.;   //complex oldz(0,0)
double temp;
int i, j;
for(i = 0 ; i < 255 ; i++)
{
	oldzreal = zreal;  //oldz = z;
	oldzimag = zimag;  //oldz = z;
	for(j = 1 ; j < zpower ; j++) 	// multiply once less than zpower
	{
		temp = (zreal * oldzreal) - (zimag * oldzimag); //z *= oldz;
		zimag = (zreal * oldzimag) + (zimag * oldzreal);
		zreal = temp;//you can't set the new zreal until you're through calculating with it (line above)
	}
	zreal = zreal + creal;
	zimag = zimag + cimag;
	if(((zreal * zreal) + (zimag * zimag)) > 4.0)
		break;
}
return(i);
}							//calcescapetime
//----------------------------------------------------------------------------
//Generate the escape times for curr. These are the bytes, each 0-255.
//This is called by the ctors, but it can be called at any time, by anyone,
//to recalculate curr to a new window size.
//I run this Java version on a 3.2GHz computer rather than the 90MHz computer
//that Winbrot ran on. Thus, I abandoned the use of IdleAction() or its Java equivalent,
//since a design can now be calculated in its entirety fast enough to not hang up Windows.
//That having been said, Java is too slow in other respects to be practical for this type
//of application.
public void calcmbrot()
{
// x and y (absolute) intervals each horiz. and vertical pixel
dx = curr.getWidth()  / (double)(PixelWidth - 1);
dy = curr.getHeight() / (double)(PixelHeight - 1);

//if(false)
if(isotropicxy)
{
	// this forces dx:dy to be 1:1, by setting both to be the larger of the two,
	// which will ensure that *at least* the entire selected area is displayed.
	// Not only that, but since the loops count PIXELS, you'll always fill the screen.
	// If isotropicxy is OFF, you'll fill it by calculating more pixels in the
	// smaller dimension, which will, for example, squeeze circles out of round.
	// If isotropicxy is ON, you'll fill it by pulling in more of the "mbrot" area
	// than curr actually specifies, but circles will stay round.
	// It is good to save curr BEFORE forcing dx == dy.		<-- ?
	// It should make it possible to switch between a distorted and nondistorted view.
	if(dx >= dy)//	dx = dy = Math.max(dx,dy);
		dy = dx;
	else
		dx = dy;

}
// This buffer is used by the DataBuffer, which is used by the Raster.
EscapeTimeArray = new byte[PixelWidth * PixelHeight];
int index = 0;
double creal = curr.x;// the complex constant c of z = z * z + c
double cimag = curr.y;
int row, column;
for(row = 0; row < PixelHeight ; row++)	// the next dib row to be calculated
{
	creal = curr.x;                     // x-axis back to zero (left side)
	for(column = 0 ; column < PixelWidth ; column++) 	// calculates a row
	{
		EscapeTimeArray[index++] = (byte)calcescapetime(creal, cimag);
		creal += dx;					// increment x axis (move right)
	}
	cimag -= dy;         // decrement y axis (move down)
}
allowzoom = true;
//calculation is complete.  the rest is image creation.
CreateImage();
}								//calcmbrot
//----------------------------------------------------------------------------
//creates the BufferedImage.  You must call it whenever the escape time data
//or window size changes.  If only the colormodel changes, you can simply
//recreate image without calling this (see various fns for examples).
private void CreateImage()
{
//Having only indexes 0-255 (no actual color info), it does not need to be banked.
DataBuffer dbuf = new DataBufferByte(EscapeTimeArray, PixelWidth * PixelHeight, 0);
WritableRaster raster = Raster.createWritableRaster(samplemodel, dbuf, null);
image = new BufferedImage(colormodel, raster, false, null);
}
//----------------------------------------------------------------------------
//this will be the startup color model, the only fn that returns nonvoid.
private IndexColorModel ColorModelGrayScale256()
{
	// Generate 256-color grayscale model
	for(int i = 0 ; i < 256 ; i++)
	{
		Reds[i] = Greens[i] = Blues[i] = (byte)i;
		Alphas[i] = (byte)255;
	}
	return new IndexColorModel(8, 256, Reds, Greens, Blues, Alphas);
}
//----------------------------------------------------------------------------
//to do: disallow duplicates, and change this to void.
//
private IndexColorModel ColorModelRandom256()
{
	for(int i = 0 ; i < 256 ; i++)
	{
		Reds[i] = (byte)RandomGenerator.nextInt(256);
		Greens[i] = (byte)RandomGenerator.nextInt(256);
		Blues[i] = (byte)RandomGenerator.nextInt(256);
		Alphas[i] = (byte)255;
	}
	return new IndexColorModel(8, 256, Reds, Greens, Blues, Alphas);
}
//----------------------------------------------------------------------------
public void ColorModelRandomWalk256()
{
	//3 methods because I can't figure out which to use.
	switch(2)
//	switch(RandomGenerator.nextInt(3))
	{
	 case 0:
		//method 1: all start the same
		Reds[0] = Greens[0] = Blues[0] = (byte)127;
		break;
	 case 1:
		 //method 2: all start the same random
		 Reds[0] = Greens[0] = Blues[0] = (byte)RandomGenerator.nextInt(256);
		 break;
	 case 2:
		 //method 3 (my preferred): each starts independently random
		 Reds[0] = (byte)RandomGenerator.nextInt(256);
		 Greens[0] = (byte)RandomGenerator.nextInt(256);
		 Blues[0] = (byte)RandomGenerator.nextInt(256);
		 break;
	 }
	Alphas[0] = (byte)255;

	// if all colors have the same std dev, the average gradation of all colors is
	// the same, so while a palette may have some unequal color jumps in it,
	// the average color range is always the same, and the palette has no
	// characteristic hue - it eventually covers the full possible range of
	// all the color planes -- which is too much to pack into one palette.
//	double stddev = 4.;

	//if each color has a different std dev, colors jump by individually different
	//average amounts, so some colors cover a wide portion of their possible
	//range, and others traverse less, to give each palette a different overall hue.
	//maxincrement determines how fine the gradations will be - a small number
	//creates a palette with fine gradations so you can hardly tell one band
	//from the next.  a large number makes the color jumps more abrupt and wild.
	//In general, a palette works best if at least one large section of it has
	//very fine gradations.  This still doesn't work as well as the designed
	//palettes, but it's a lot easier than trying to design your own.
	int maxincrement = 1 + RandomGenerator.nextInt(8);//zero crashes nextInt(n)

	double stddevRed = RandomGenerator.nextInt(maxincrement);
	double stddevGreen = RandomGenerator.nextInt(maxincrement);
	double stddevBlue = RandomGenerator.nextInt(maxincrement);

	for(int i = 1 ; i < 256 ; i++)
	{
		//note: you are setting this color relative to the one BEFORE it!
		Reds[i] = GetNextRandomColor(Reds[i-1],stddevRed);
		Greens[i] = GetNextRandomColor(Greens[i-1],stddevGreen);
		Blues[i] = GetNextRandomColor(Blues[i-1],stddevBlue);
		Alphas[i] = (byte)255;
	}
	colormodel = new IndexColorModel(8, 256, Reds, Greens, Blues, Alphas);
	image = new BufferedImage(colormodel, image.getRaster(), false, null);
}
//----------------------------------------------------------------------------
//Randomly choose (from a file) or (occasionally) create a random color map,
//possibly reversing it, and rotating it a bit.  To add variety to randomly
//generated images.
public void SelectColorMapAtRandom()
{
boolean gotone = false;
int N = MapFiles.length;
if(N > 0)
{
	switch(RandomGenerator.nextInt(10))
	{
		case 0:// 1 in 10 is a non-file random walk palette
			break;
		default:
			// choose a .MAP file at random, for variety
			if(ColorModelFromFile(MapFiles[RandomGenerator.nextInt(N)]))
				gotone = true;
			break;
	}
}
if(!gotone)
	ColorModelRandomWalk256();
if(RandomGenerator.nextInt(2) == 0)		// doubles the available palettes
	ReverseColormodel();
// whichever palette you have, rotate it a bit
for(int i = RandomGenerator.nextInt(256) ; i > 0 ; i--)
	RotateColormodel(1);
}
//----------------------------------------------------------------------------
//file line format is 3 ints, then discard the rest:
//   0   0   0  this is a comment
// Loads color palette from a Fractint .MAP file, Format: r g b possiblecomment\n
// (Reminder: non-color-related ".MAP" files do exist: TLINK)
// If file is a valid .map file, but too short, colors are reused in order.
// If file isn't a valid .map file, colors aren't changed.
public boolean ColorModelFromFile(String filename)
{
//if(!QuerySavePalette())
//	return false;
MapFileIsModified = false;

byte[] reds = new byte[256];   //you don't change the real arrays until
byte[] greens = new byte[256]; //all has succeeded.
byte[] blues = new byte[256];
byte[] alphas = new byte[256];

BufferedReader infile = null;
//	read exception handling.  I think these can all go in one Try block,
//	with all the catches at the end.
try
{
	infile = new BufferedReader(new FileReader(filename));
}
catch(FileNotFoundException ex)
{
	JOptionPane.showMessageDialog(null,
								  "Palette is unchanged.",
								  "File " + filename + " not found",
								  JOptionPane.INFORMATION_MESSAGE);
//	ex.printStackTrace();
	return false;
}
String s = new String();
int colorcounter = 0;
try
{
	for (int i = 0; i < 256; i++, colorcounter++)
	{
		s = infile.readLine();
		if((s == null) || (s.length() == 0))
			break;
		//you MUST trim it.  The parser cannot deal with leading whitespace.
		//if present, it results in t[0] as a non-null, zero-length string.
		//"\\s+" should be "1 or more whitespace", if I got it right.
		String t[] = s.trim().split("\\s+");
		reds[i] = (byte)Integer.parseInt(t[0].trim());
		greens[i] = (byte)Integer.parseInt(t[1].trim());
		blues[i] = (byte)Integer.parseInt(t[2].trim());
		//any comment would be t[3] and above, and we just discard them.
		alphas[i] = (byte)255;
	}
}
catch(IOException ex1)
{
	//this exception should only occur if a line fails to contain 3 items.
	//if it's just a short file (< 256 colors), that's ok, handled later.
	JOptionPane.showMessageDialog(null,        //Java Messagebox equivalent
								  "Palette is unchanged.",
								  "Unexpected end of Color Map file " + filename,
								  JOptionPane.WARNING_MESSAGE);
//	ex1.printStackTrace();
return false;
}
catch(NumberFormatException nfe)
{
	JOptionPane.showMessageDialog(null,
								  ".MAP File " + filename + " is corrupt, unparsable.  Palette is unchanged.",
								  "NumberFormatException.",
								  JOptionPane.ERROR_MESSAGE);
//	nfe.printStackTrace();
return false;
}
try
{
	infile.close();
}
catch(IOException ex2)
{
	JOptionPane.showMessageDialog(null,
								  "Unexpected error.  Shouldn't ever happen.",
								  "Error closing file " + filename + " .",
								  JOptionPane.WARNING_MESSAGE);
//	ex2.printStackTrace();
}
//if the file had at least 1, but less than 256 colors,
// fill in any missing colors,copying from colors[0] forward
if((colorcounter > 0) && (colorcounter < 256))
{
//	JOptionPane.showMessageDialog(null,   //useful during testing or if problems
//								  "Will reuse colors in order as necessary.",
//								  ".MAP file " + filename + " has < 256 colors",
//								  JOptionPane.INFORMATION_MESSAGE);

	for(int j = colorcounter ; j < 256 ; j++)
	{
		reds[j] = reds[j - colorcounter];
		greens[j] = greens[j - colorcounter];
		blues[j] = blues[j - colorcounter];
		alphas[j] = (byte)255;
	}
}
Reds = reds;
Greens = greens;
Blues = blues;
Alphas = alphas;
colormodel = new IndexColorModel(8, 256, Reds, Greens, Blues, Alphas);
image = new BufferedImage(colormodel, image.getRaster(), false, null);
return true;
}
//----------------------------------------------------------------------------
// loads the next MapFile as the current one.
public boolean NextMapFile()
{
int N = MapFiles.length;
if(N > 0)
{
	if(++MapFileIndex >= N)
		MapFileIndex = 0;
	ColorModelFromFile(MapFiles[MapFileIndex]);
	return(true);
}
return false;
}
//----------------------------------------------------------------------------
// loads the previous MapFile as the current one.
public boolean PreviousMapFile()
{
int N = MapFiles.length;
if(N > 0)
{
	if(--MapFileIndex < 0)
		MapFileIndex = N - 1;
	ColorModelFromFile(MapFiles[MapFileIndex]);
	return(true);
}
return false;
}
//----------------------------------------------------------------------------
public void RotateColormodel(int direction)
{
if(direction == 0)
	return;
if(direction > 0)
{
	RotateByteArrayForward(Reds);
	RotateByteArrayForward(Greens);
	RotateByteArrayForward(Blues);
	RotateByteArrayForward(Alphas);
}
else
{
	RotateByteArrayBackward(Reds);
	RotateByteArrayBackward(Greens);
	RotateByteArrayBackward(Blues);
	RotateByteArrayBackward(Alphas);
}
colormodel = new IndexColorModel(8, 256, Reds, Greens, Blues, Alphas);
image = new BufferedImage(colormodel, image.getRaster(), false, null);
}
//----------------------------------------------------------------------------
public void ReverseColormodel()
{
ReverseByteArray(Reds);
ReverseByteArray(Greens);
ReverseByteArray(Blues);
ReverseByteArray(Alphas);
colormodel = new IndexColorModel(8, 256, Reds, Greens, Blues, Alphas);
image = new BufferedImage(colormodel, image.getRaster(), false, null);
}
public void ComplementColormodel()
{
ComplementByteArray(Reds);
ComplementByteArray(Greens);
ComplementByteArray(Blues);
//ComplementByteArray(Alphas);   //no!!
colormodel = new IndexColorModel(8, 256, Reds, Greens, Blues, Alphas);
image = new BufferedImage(colormodel, image.getRaster(), false, null);
}
public void LightenColormodel()
{
LightenByteArray(Reds);
LightenByteArray(Greens);
LightenByteArray(Blues);
//LightenByteArray(Alphas);   //no!!
colormodel = new IndexColorModel(8, 256, Reds, Greens, Blues, Alphas);
image = new BufferedImage(colormodel, image.getRaster(), false, null);
}
public void DarkenColormodel()
{
DarkenByteArray(Reds);
DarkenByteArray(Greens);
DarkenByteArray(Blues);
//DarkenByteArray(Alphas);   //no!!
colormodel = new IndexColorModel(8, 256, Reds, Greens, Blues, Alphas);
image = new BufferedImage(colormodel, image.getRaster(), false, null);
}


//----------------------------------------------------------------------------
//this is for rotating the color plane arrays.  "Forward" means the original
//[0] element moves forward in the array (and normal color palettes will be
//seen to cycle in toward the mandelbrot region's center (higher regions)).
private static void RotateByteArrayForward(byte c[])
{
if(c.length == 0)
	return;
byte temp = c[c.length - 1];
for (int i = c.length - 1; i > 0 ; i--) //every array has a public .length
	c[i] = c[i-1];
c[0] = temp;
}
private static void RotateByteArrayBackward(byte c[])
{
if(c.length == 0)
	return;
byte temp = c[0];
for (int i = 0; i < (c.length - 1) ; i++) //every array has a public .length
	c[i] = c[i+1];
c[c.length - 1] = temp;
}
//----------------------------------------------------------------------------
// reverse the order of the colors in the palette
private void ReverseByteArray(byte[] c)
{
if(c.length == 0)
	return;
int top = c.length - 1;
int midpoint = c.length / 2;
byte temp;
for(int i = 0 ; i < midpoint ; i++)
{
	temp = c[i];
	c[i] = c[top - i];
	c[top - i] = temp;
}
}                  			// ReverseByteArray
//----------------------------------------------------------------------------
// change each color to its complementary color
private void ComplementByteArray(byte[] c)
{
if(c.length == 0)
	return;
for(int i = 0 ; i < c.length ; i++)
	c[i] = (byte)(255 - c[i]);
}                   	  	// ComplementColors
//----------------------------------------------------------------------------
// increase each rgb component by 1
private void LightenByteArray(byte c[])
{
if(c.length == 0)
	return;
for(int i = 0 ; i < c.length ; i++)
{
	// after 256 calls, you do get back where you started
	c[i] = (byte)(c[i] + 1);
}
}                     	// LightenColors
//----------------------------------------------------------------------------
// increase each rgb component by 1
private void DarkenByteArray(byte c[])
{
if(c.length == 0)
	return;
for(int i = 0 ; i < c.length ; i++)
{
	// after 256 calls, you do get back where you started
	c[i] = (byte)(c[i] - 1);
}
}                     	// LightenColors


//----------------------------------------------------------------------------
//returns a random color component (0-255) that is normally displaced from the
//given one, using the provided standard deviation.  When used to create colors
//for a color table, the result is a palette whose colors have a fractal
//distribution, which seems appropriate for a fractal display.
//Method is copied from music.cpp.
//It would be even more interesting to make all the various parameters
//variables, then time how long each set is allowed to run, and evolve the
//combinations that users like best.
byte GetNextRandomColor(byte b, double StdDev)
{
int c = b;	                    // need int to allow negatives and out of range

// better: always increases, for a smooth gradation
c += Math.abs(RandomGenerator.nextGaussian()) * StdDev;

//this winds up with more banding due to colors sliding in both directions,
//and flipping back and forth between 0 and 255.
//c += RandomGenerator.nextGaussian() * StdDev;

if(c < 0) c += 256;    // regular method: wrap
if(c > 255) c -= 256;

//if(c < 0) c = 0;        // alternate method: bottom out or top out.
//if(c > 255) c = 255;    // colors generally stay dark; boring.

return (byte)c;
}          						//GetNextRandomColor
//----------------------------------------------------------------------------
// usage: int x = 5; x = round(speed * sine(30) * x);
// not used here, but leave it in as a reminder that my round() still works
// differently from the C++ AND Java library round().
// For library: 2.5 rounds to 3, but -2.5 rounds to -2.
// For mine   : 2.5 rounds to 3, and -2.5 rounds to -3.
// Eventually collect my fns into, I think, ...\My Java\Mylib.
// Then import mylib.*
// And invoke fn with Mylib.round(n);
// See Math.rint() -- it might do it correctly.
int round(double d)
{
if(d > 0)    		// if positive, make more positive before rounding
	d += .5;
else
	if(d < 0)    	// if negative, make more negative before rounding
		d -= .5;
return (int)d;			// java also truncates decimal portion
}

//----------------------------------------------------------------------------
}//end class MandelbrotGenerator
///////////////////////////////////////////////////////////////////////////////

JDibPanel.java

package jbrot;

import javax.swing.*;
import javax.swing.JPanel;
import java.awt.*;
import javax.swing.BorderFactory;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;


/**
 * <p>Title: This file is part of the JBrot Mandelbrot generator project.</p>
 * <p>Description: A JPanel JavaBean containing a JDib, and that will contain all
*  the functionality of my SDibWindow class.  Putting the functionality into a
* custom panel instead of the Frame should allow using it in either an app
* or an applet (I hope).</p>
 * <p>Copyright: Copyright (C)1993-2004 Steven Whitney.</p>
 * <p>Published under GNU GPL (General Public License) Version 2,
 * with ABSOLUTELY NO WARRANTY.</p>
 * <p>Initially published by http://25yearsofprogramming.com.</p>
 * @version 1.0
 */

/*
I am assuming for now that a JavaBean is the same as a Custom Component.
The only way I could make it "droppable" onto the App's Content Panel was
to create it as a New JavaBean that extends JPanel
rather than merely as a New Class that extends JPanel, which allowed creating it,
but didn't seem to allow any way to use it.

Because IndexColorModel and BufferedImage are incapable of modifying themselves,
and also can't be modified externally, it is no use to try to extend them
(except to add additional members).
All the methods for palette creation, rotation, modification, reading and writing,
must go here. (8/29/2006 - I guess I decided that wasn't the case, since I wound up
putting them elsewhere!)

However, once I've developed the methods here, I could create classes with
members of these types rather than extending them.  For example, a
JPalette class that has a ColorModel member.  The various manipulation functions
would do the manipulation, create a new ColorModel based on it,
set the member to point to it, and then return it:
ColorModel Rotate(int i)  {}   This would at least be more modular.

You can leave the name as JDibPanel, even though it's now really a
JMandelbrotPanel.  You could create a superclass for MandelbrotGenerator
that defines a more general image creator and use refs to it here.
Then you could implement subclasses MandelbrotGenerator, BifGenerator, etc.
with the same methods.
*/
///////////////////////////////////////////////////////////////////////////////
public class JDibPanel extends JPanel
{
protected MandelbrotGenerator mandelgenerator =
	   new MandelbrotGenerator(this.WIDTH, this.HEIGHT);

private boolean Dragging = false;
private Point DragStart = new Point(0,0);	// corners of region being selected with box
private Point DragEnd = new Point(0,0);
private int DragLeft, DragTop, DragWidth, DragHeight;//defines dragged rectangle

private Rectangle DragRect = new Rectangle(0,0,0,0);// dragged area in window coordinates
private Rectangle2D.Double DragPct = new Rectangle2D.Double(0.,0.,0.,0.); // dragged area as % of screen dimensions

//----------------------------------------------------------------------------
public JDibPanel()
{
try
{
	jbInit();
}
catch(Exception ex)
{
	ex.printStackTrace();
}

}

//----------------------------------------------------------------------------
private void jbInit() throws Exception
{
this.setBackground(Color.black);
this.setForeground(Color.white);
this.setBorder(BorderFactory.createLineBorder(Color.black));
	this.addMouseMotionListener(new JDibPanel_this_mouseMotionAdapter(this));
	this.addMouseListener(new JDibPanel_this_mouseAdapter(this));
this.addComponentListener(new JDibPanel_this_componentAdapter(this));
this.setLayout(null);
}
//----------------------------------------------------------------------------
//#error what is the difference between paint() and paintComponent()?
public void paint(Graphics g)
{
mandelgenerator.draw(g, 0, 0);
}
//----------------------------------------------------------------------------
void this_componentResized(ComponentEvent event)
{
//unsure why we need the source if THIS is being resized
Component source = (Component)event.getSource();
Dimension newsize = source.getSize();
mandelgenerator.SetWindowSize(newsize.width, newsize.height);
source.repaint();
//	repaint(); //mine, seems to work the same.
}

//----------------------------------------------------------------------------
//Event handlers: most of these are just pass-throughs from the frame to the
//Mandelgenerator, on the assumption that if this application becomes an applet,
//it will have a JDibPanel, but it won't have a Frame,
//so you'll have to provide some other way to invoke them.
//----------------------------------------------------------------------------
// originally, and usually, selects and displays a random region.
// but if there are any files in FileList, loads the next one.
// (a feature currently undocumented, but useful at startup),
void CmFileNew()
{
boolean gotone = false;
//while(FileList.GetItemsInContainer())	// If a file fails, go on to the next one
//{
//	// copy a name from the list, delete it from list, try to use it to initialize
//	gotone = OpenFile(FileList.GetNext());
//	if(gotone)
//		break;
//}
if(!gotone)		// last resort is a new random one
	mandelgenerator.randomarea();//uses existing color map, not a new random one
repaint();
}        					// CmFileNew
//----------------------------------------------------------------------------
// this is called by the PauseTimer. It randomizes the area AND the palette.
void CmFileNewRandom()
{
	mandelgenerator.SelectColorMapAtRandom();
	mandelgenerator.randomarea();
	repaint();
}        					// CmFileNewRandom
//-----------------------------------------------------------------------------
public void CmFilePrevious()
{
	mandelgenerator.GoBack();
	repaint();
}
//-----------------------------------------------------------------------------
public void CmColorsRotate(int direction)
{
	if(!Dragging)//if autorot was on before drag, it'll resume when done.
	{
		mandelgenerator.RotateColormodel(direction);
		repaint();
	}
}
public void CmColorsReverse()
{
	mandelgenerator.ReverseColormodel();
	repaint();
}
public void CmColorsComplement()
{
	mandelgenerator.ComplementColormodel();
	repaint();
}
public void CmColorsLighten()
{
	mandelgenerator.LightenColormodel();
	repaint();
}
public void CmColorsDarken()
{
	mandelgenerator.DarkenColormodel();
	repaint();
}
public void CmColorsRandomize()
{
	//note this uses the new RandomWalk, not the old uniform random, method.
	mandelgenerator.ColorModelRandomWalk256();
	repaint();
}
public void CmColorsNextMap()
{
	mandelgenerator.NextMapFile();
	repaint();
}
public void CmColorsPreviousMap()
{
	mandelgenerator.PreviousMapFile();
	repaint();
}
public void LoadColors(String filename)
{
	mandelgenerator.ColorModelFromFile(filename);
	repaint();
}
public void setZPower(int z)
{
mandelgenerator.setZPower(z);
repaint();
}
public void quadrantzoom(int quadrant)
{
	mandelgenerator.quadrantzoom(quadrant);
	repaint();
}
//----------------------------------------------------------------------------
public void CmSetIsotropicXY(boolean b)
{
	mandelgenerator.setIsotropicXY(b);
	repaint();
}

//----------------------------------------------------------------------------
void this_mousePressed(MouseEvent e)
{
// begin defining a new area to calculate
if(e.getButton() == MouseEvent.BUTTON1)
{
	Dragging = true;
	DragStart.setLocation(e.getPoint());
	DragEnd.setLocation(e.getPoint());
}
}
//----------------------------------------------------------------------------
void this_mouseDragged(MouseEvent e)
{
// drag cursor to define a new calculation area
if(Dragging)//only BUTTON1 turns on Dragging
{
	Graphics g = getGraphics();
	g.setColor(new Color(0,0,0,255));
	g.setXORMode(new Color(255,255,255,255));

	if(!DragStart.equals(DragEnd))//prevents 1 missing pixel at DragTop DragLeft
	{
	   //erase the old rectangle, using the dimensions previously calculated (below)
	   //works for dragging in any direction, and correctly draws the focusrect.
	   g.drawRect(DragLeft, DragTop, DragWidth, DragHeight);
   }
   //now define and draw the new rectangle.
   //I think the key to why this finally worked is that you DON'T mess with
   //DragStart and DragEnd during the drag: they are what they are: e.getPoint,
   //but you choose the appropriate parameters to give to drawRect().
   DragEnd.setLocation(e.getPoint());//the new DragEnd is set here

   DragLeft = Math.min(DragStart.x, DragEnd.x);
   DragTop = Math.min(DragStart.y, DragEnd.y);// min: y axis is upside down
   DragWidth = Math.abs(DragEnd.x - DragStart.x);
   DragHeight = Math.abs(DragEnd.y - DragStart.y);

   g.drawRect(DragLeft, DragTop, DragWidth, DragHeight);
   g.dispose();
}
}
//----------------------------------------------------------------------------
// RELEASED left mouse button after defining a selection area.
void this_mouseReleased(MouseEvent e)
{
if(Dragging && (e.getButton() == MouseEvent.BUTTON1))
{
	//DragLeft, etc. are still valid from their final calc. in MouseMove.

	//this block was for testing, but is helpful to see when dragging is finished.
	Graphics g = getGraphics();
	g.setColor(new Color(255,255,255,255));
	g.setXORMode(new Color(255,255,255,255));
	g.drawRect(DragLeft, DragTop, DragWidth, DragHeight);
	g.dispose();

//	DragRect = new Rectangle(DragLeft,
//							 DragTop,
//							 DragLeft + DragWidth,
//							 DragTop + DragHeight);
	// calculate what percent the point coordinates and size of the drag region
	//are of the screen dimensions.
	// ex: if DragWidth is 800, rightmost point of 799 translates to 1.0.
//	double cWidth = Math.abs((double)getWidth());//this Component's Width
//	double cHeight = Math.abs((double)getHeight());
//	double LeftPct =   (double)DragLeft     / (cWidth - 1.);
//	double TopPct =    (double)DragTop      / (cHeight - 1.);
//	double WidthPct =  (double)(DragWidth)  / (cWidth - 1.);
//	double HeightPct = (double)(DragHeight) / (cHeight - 1.);
//	DragPct.setRect(LeftPct, TopPct, WidthPct, HeightPct);

	mandelgenerator.MouseZoom(DragLeft, DragTop, DragWidth, DragHeight);

	Dragging = false;
	repaint();
}
}
//EvLButtonUp
//-----------------------------------------------------------------------------
}//end JDibPanel class
///////////////////////////////////////////////////////////////////////////////
class JDibPanel_this_componentAdapter extends java.awt.event.ComponentAdapter
{
JDibPanel adaptee;
JDibPanel_this_componentAdapter(JDibPanel adaptee)
{
this.adaptee = adaptee;
}

public void componentResized(ComponentEvent e)
{
adaptee.this_componentResized(e);
}
}

class JDibPanel_this_mouseAdapter extends java.awt.event.MouseAdapter
{
	JDibPanel adaptee;

JDibPanel_this_mouseAdapter(JDibPanel adaptee)
	{
	this.adaptee = adaptee;
	}
	public void mousePressed(MouseEvent e)
	{
	adaptee.this_mousePressed(e);
	}
	public void mouseReleased(MouseEvent e)
	{
	adaptee.this_mouseReleased(e);
	}
}

class JDibPanel_this_mouseMotionAdapter extends java.awt.event.MouseMotionAdapter
{
	JDibPanel adaptee;
	JDibPanel_this_mouseMotionAdapter(JDibPanel adaptee)
	{
	this.adaptee = adaptee;
	}
	public void mouseDragged(MouseEvent e)
	{
	adaptee.this_mouseDragged(e);
	}
}

JBrotFrame.java

package jbrot;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
import java.awt.geom.*;
import java.io.File;
import java.io.FilenameFilter;


/**
 * <p>Title: This file is part of the JBrot Mandelbrot generator project.</p>
 * <p>Description: Java version of Winbrot</p>
 * <p>Copyright: Copyright (C)2004 Steven Whitney.</p>
 * <p>Published under GNU GPL (General Public License) Version 2,
 * with ABSOLUTELY NO WARRANTY.</p>
 * <p>Initially published by http://25yearsofprogramming.com.</p>
 * @version 1.0
 */
///////////////////////////////////////////////////////////////////////////////
public class JBrotFrame extends JFrame
{
int displaysecs = 65535;	// period that a completed design remains on screen
String MAPDir;				// last-used directories for MAP files and app-specific DATA
String DATADir;				// (without trailing backslashes)

int FirstFreeColor = 0;     // first palette index that can be freely randomized or changed


//	-----------------------------------------------------------------------
JPanel contentPane;
JMenuBar jMenuBar1 = new JMenuBar();
JMenu jMenuFile = new JMenu();
JMenuItem jMenuFileExit = new JMenuItem();
JMenu jMenuHelp = new JMenu();
JMenuItem jMenuHelpAbout = new JMenuItem();
JToolBar jToolBar = new JToolBar();
JButton jButton1 = new JButton();
JButton jButton2 = new JButton();
JButton jButton3 = new JButton();
ImageIcon image1;
ImageIcon image2;
ImageIcon image3;
JLabel statusBar = new JLabel();
BorderLayout borderLayout1 = new BorderLayout();
JDibPanel jDibPanel1 = new JDibPanel();
JMenu jMenuColors = new JMenu();
JMenuItem jMenuItemColorsLoad = new JMenuItem();
JMenuItem jMenuItemFileEditList = new JMenuItem();
JMenuItem jMenuItemFileFlip = new JMenuItem();
JMenuItem jMenuItemFilePrevious = new JMenuItem();
JMenuItem jMenuItemFileRestart = new JMenuItem();
JMenuItem jMenuItemFileSaveAs = new JMenuItem();
JMenuItem jMenuItemFileOpen = new JMenuItem();
JMenuItem jMenuItemFileNew = new JMenuItem();
JMenuItem jMenuItemColorsSaveAs = new JMenuItem();
JMenuItem jMenuItemColorsNextMap = new JMenuItem();
JMenuItem jMenuItemColorsPreviousMap = new JMenuItem();
JMenuItem jMenuItemColorsEditList = new JMenuItem();
JMenuItem jMenuItemColorsRandomize = new JMenuItem();
JMenuItem jMenuItemColorsReverse = new JMenuItem();
JMenuItem jMenuItemColorsComplement = new JMenuItem();
JMenuItem jMenuItemColorsLighten = new JMenuItem();
JMenuItem jMenuItemColorsDarken = new JMenuItem();
JMenuItem jMenuItemColorsRotateForward = new JMenuItem();
JMenuItem jMenuItemColorsRotateBackward = new JMenuItem();
JMenu jMenuView = new JMenu();
JMenuItem jMenuItemViewFitToWindow = new JMenuItem();
JCheckBoxMenuItem jCheckBoxMenuItemIsotropicXY = new JCheckBoxMenuItem();
JMenuItem jMenuItemViewZPower = new JMenuItem();
JMenuItem jMenuItemViewDisplaySecs = new JMenuItem();
JMenuItem jMenuItemViewZoomOut = new JMenuItem();
JMenuItem jMenuItemViewZoomTopLeft = new JMenuItem();
JMenuItem jMenuItemViewZoomTopRight = new JMenuItem();
JMenuItem jMenuItemViewZoomBottomLeft = new JMenuItem();
JMenuItem jMenuItemViewZoomBottomRight = new JMenuItem();
JMenuItem jMenuItemViewZoomCenter = new JMenuItem();
JMenu jMenuEffects = new JMenu();
JMenuItem jMenuItemEffectsAverage = new JMenuItem();
JMenuItem jMenuItemEffectsRandomizePixels = new JMenuItem();
JMenuItem jMenuItemEffectsRandomizeHeights = new JMenuItem();
JMenuItem jMenuItemEffectsInvertHeights = new JMenuItem();
JMenuItem jMenuItemEffectsFlipVertical = new JMenuItem();
JMenuItem jMenuItemEffectsFlipHorizontal = new JMenuItem();
JMenuItem jMenuItemHelpIndex = new JMenuItem();
JCheckBoxMenuItem jCheckBoxMenuItemAutoRotateColors = new JCheckBoxMenuItem();

//To get a timing value, you are really supposed to do the action a few
//times and get an actual time value to use.  50ms worked ok here.
javax.swing.Timer ColorRotTimer = new javax.swing.Timer(100,null);
//the initial delay must be short, because even if you reset the delay later,
//this will be its *first* interval before firing at all.
javax.swing.Timer PauseTimer = new javax.swing.Timer(10000,null);

//Construct the frame
public JBrotFrame()
{
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try
{
	jbInit();
}
catch(Exception e)
{
	e.printStackTrace();
}
//create the list of .MAP color files in the startup directory.
//does this code belong in ctor? or maybe as a response to the windowOpened event?
File currentdir = new File(".");
String[] dirlist = currentdir.list(new DirFilter(".+\\.[Mm][Aa][Pp]"));
Arrays.sort(dirlist);   // get a predictable order
jDibPanel1.mandelgenerator.MapFiles = dirlist;

//String[] dirlist = currentdir.list();
//JOptionPane.showMessageDialog(null,
//							  String.valueOf(dirlist.length),
//							  "list length",
//							  JOptionPane.PLAIN_MESSAGE);


}

//Component initialization
private void jbInit() throws Exception
{
image1 = new ImageIcon(jbrot.JBrotFrame.class.getResource("openFile.png"));
image2 = new ImageIcon(jbrot.JBrotFrame.class.getResource("closeFile.png"));
image3 = new ImageIcon(jbrot.JBrotFrame.class.getResource("help.png"));
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(borderLayout1);
this.setLocale(java.util.Locale.getDefault());
this.setResizable(true);
this.setSize(new Dimension(470, 460));
this.setState(Frame.NORMAL);
this.setTitle("JBrot");
jMenuFile.setMnemonic('F');
jMenuFile.setText("File");
jMenuFileExit.setMnemonic('X');
jMenuFileExit.setText("Exit");
jMenuFileExit.addActionListener(new JBrotFrame_jMenuFileExit_ActionAdapter(this));
jMenuHelp.setMnemonic('H');
jMenuHelp.setText("Help");
jMenuHelpAbout.setMinimumSize(new Dimension(0, 0));
jMenuHelpAbout.setMnemonic('A');
jMenuHelpAbout.setText("About");
jMenuHelpAbout.addActionListener(new JBrotFrame_jMenuHelpAbout_ActionAdapter(this));
jButton1.setIcon(image1);
jButton1.setToolTipText("Open File");
jButton2.setIcon(image2);
jButton2.setToolTipText("Close File");
jButton3.setIcon(image3);
jButton3.setToolTipText("Help");
jMenuColors.setMnemonic('C');
jMenuColors.setText("Colors");
jMenuItemColorsLoad.setMnemonic('M');
jMenuItemColorsLoad.setText("Load .MAP...");
jMenuItemColorsLoad.setAccelerator(javax.swing.KeyStroke.getKeyStroke('M', 0, false));
jMenuItemColorsLoad.addActionListener(new JBrotFrame_jMenuItemColorsLoad_actionAdapter(this));
jMenuItemFileEditList.setMnemonic('L');
jMenuItemFileEditList.setText("Edit List...");
jMenuItemFileFlip.setToolTipText("Invert the region so it is upside down, and recalculate it.");
jMenuItemFileFlip.setMnemonic('F');
jMenuItemFileFlip.setText("Flip Vertical");
jMenuItemFileFlip.setAccelerator(javax.swing.KeyStroke.getKeyStroke('F', 0, false));
jMenuItemFilePrevious.setMnemonic('P');
jMenuItemFilePrevious.setText("Previous Area");
jMenuItemFilePrevious.setAccelerator(javax.swing.KeyStroke.getKeyStroke('P', 0, false));
jMenuItemFilePrevious.addActionListener(new JBrotFrame_jMenuItemFilePrevious_actionAdapter(this));
jMenuItemFileRestart.setMnemonic('R');
jMenuItemFileRestart.setText("Restart (whole MBrot area)");
jMenuItemFileRestart.addActionListener(new JBrotFrame_jMenuItemFileRestart_actionAdapter(this));
jMenuItemFileSaveAs.setMnemonic('S');
jMenuItemFileSaveAs.setText("Save As...");
jMenuItemFileSaveAs.setAccelerator(javax.swing.KeyStroke.getKeyStroke('S', java.awt.event.KeyEvent.CTRL_MASK, false));
jMenuItemFileOpen.setToolTipText("Display a design from an .INF or .PIC file.");
jMenuItemFileOpen.setMnemonic('O');
jMenuItemFileOpen.setText("Open...");
jMenuItemFileOpen.setAccelerator(javax.swing.KeyStroke.getKeyStroke('O', java.awt.event.KeyEvent.CTRL_MASK, false));
jMenuItemFileNew.setMnemonic('N');
jMenuItemFileNew.setText("New (Random Area)");
jMenuItemFileNew.setAccelerator(javax.swing.KeyStroke.getKeyStroke('N', 0, false));
jMenuItemFileNew.addActionListener(new JBrotFrame_jMenuItemFileNew_actionAdapter(this));
jMenuItemColorsSaveAs.setMnemonic('S');
jMenuItemColorsSaveAs.setText("Save As .MAP...");
jMenuItemColorsNextMap.setMnemonic('N');
jMenuItemColorsNextMap.setText("Next .MAP File");
jMenuItemColorsNextMap.setAccelerator(javax.swing.KeyStroke.getKeyStroke(']', 0, false));
jMenuItemColorsNextMap.addActionListener(new JBrotFrame_jMenuItemColorsNextMap_actionAdapter(this));
jMenuItemColorsPreviousMap.setMnemonic('P');
jMenuItemColorsPreviousMap.setText("Previous .MAP File");
jMenuItemColorsPreviousMap.setAccelerator(javax.swing.KeyStroke.getKeyStroke('[', 0, false));
jMenuItemColorsPreviousMap.addActionListener(new JBrotFrame_jMenuItemColorsPreviousMap_actionAdapter(this));
jMenuItemColorsEditList.setMnemonic('E');
jMenuItemColorsEditList.setText("Edit .MAP File List...");
jMenuItemColorsRandomize.setMnemonic('R');
jMenuItemColorsRandomize.setText("Randomize");
jMenuItemColorsRandomize.setAccelerator(javax.swing.KeyStroke.getKeyStroke('R', 0, false));
	jMenuItemColorsRandomize.addActionListener(new JBrotFrame_jMenuItemColorsRandomize_actionAdapter(this));
jMenuItemColorsReverse.setMnemonic('V');
jMenuItemColorsReverse.setText("Reverse");
jMenuItemColorsReverse.setAccelerator(javax.swing.KeyStroke.getKeyStroke('V', 0, false));
	jMenuItemColorsReverse.addActionListener(new JBrotFrame_jMenuItemColorsReverse_actionAdapter(this));
jMenuItemColorsComplement.setMnemonic('C');
jMenuItemColorsComplement.setText("Complement");
jMenuItemColorsComplement.setAccelerator(javax.swing.KeyStroke.getKeyStroke('C', 0, false));
	jMenuItemColorsComplement.addActionListener(new JBrotFrame_jMenuItemColorsComplement_actionAdapter(this));
jMenuItemColorsLighten.setMnemonic('L');
jMenuItemColorsLighten.setText("Lighten");
jMenuItemColorsLighten.setAccelerator(javax.swing.KeyStroke.getKeyStroke('L', 0, false));
	jMenuItemColorsLighten.addActionListener(new JBrotFrame_jMenuItemColorsLighten_actionAdapter(this));
jMenuItemColorsDarken.setMnemonic('D');
jMenuItemColorsDarken.setText("Darken");
jMenuItemColorsDarken.setAccelerator(javax.swing.KeyStroke.getKeyStroke('D', 0, false));
	jMenuItemColorsDarken.addActionListener(new JBrotFrame_jMenuItemColorsDarken_actionAdapter(this));
jMenuItemColorsRotateForward.setMnemonic('.');
jMenuItemColorsRotateForward.setText("Rotate Forward (. or >)");
jMenuItemColorsRotateForward.setAccelerator(javax.swing.KeyStroke.getKeyStroke('.', 0, false));
	jMenuItemColorsRotateForward.addActionListener(new JBrotFrame_jMenuItemColorsRotateForward_actionAdapter(this));
jMenuItemColorsRotateBackward.setMnemonic(',');
jMenuItemColorsRotateBackward.setText("Rotate Backward (, or <)");
jMenuItemColorsRotateBackward.setAccelerator(javax.swing.KeyStroke.getKeyStroke(',', 0, false));
	jMenuItemColorsRotateBackward.addActionListener(new JBrotFrame_jMenuItemColorsRotateBackward_actionAdapter(this));
jMenuView.setMnemonic('V');
jMenuView.setText("View");
jMenuItemViewFitToWindow.setMnemonic('F');
jMenuItemViewFitToWindow.setText("Fit to Window");
jMenuItemViewFitToWindow.setAccelerator(javax.swing.KeyStroke.getKeyStroke('W', 0, false));
jCheckBoxMenuItemIsotropicXY.setMnemonic('I');
jCheckBoxMenuItemIsotropicXY.setText("IsotropicXY");
jCheckBoxMenuItemIsotropicXY.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.
											event.KeyEvent.VK_I, 0, false));
jCheckBoxMenuItemIsotropicXY.setState(true);
jCheckBoxMenuItemIsotropicXY.addActionListener(new
JBrotFrame_jCheckBoxMenuItemIsotropicXY_actionAdapter(this));
jMenuItemViewZPower.setToolTipText("Set the desired power of Z to use.");
jMenuItemViewZPower.setMnemonic('Z');
jMenuItemViewZPower.setText("Set Z Power...");
jMenuItemViewZPower.setAccelerator(javax.swing.KeyStroke.getKeyStroke('Z', 0, false));
	jMenuItemViewZPower.addActionListener(new JBrotFrame_jMenuItemViewZPower_actionAdapter(this));
jMenuItemViewDisplaySecs.setToolTipText("Set number of seconds pause before automatic File | New command.");
jMenuItemViewDisplaySecs.setMnemonic('T');
jMenuItemViewDisplaySecs.setText("Set Display Time Interval...");
jMenuItemViewDisplaySecs.setAccelerator(javax.swing.KeyStroke.getKeyStroke('T', 0, false));
	jMenuItemViewDisplaySecs.addActionListener(new JBrotFrame_jMenuItemViewDisplaySecs_actionAdapter(this));
jMenuItemViewZoomOut.setMnemonic('0');
jMenuItemViewZoomOut.setText("0-ZoomOut");
jMenuItemViewZoomOut.setAccelerator(javax.swing.KeyStroke.getKeyStroke('0', 0, false));
	jMenuItemViewZoomOut.addActionListener(new JBrotFrame_jMenuItemViewZoomOut_actionAdapter(this));
jMenuItemViewZoomTopLeft.setMnemonic('1');
jMenuItemViewZoomTopLeft.setText("1-ZoomTopLeft");
jMenuItemViewZoomTopLeft.setAccelerator(javax.swing.KeyStroke.getKeyStroke('1', 0, false));
	jMenuItemViewZoomTopLeft.addActionListener(new JBrotFrame_jMenuItemViewZoomTopLeft_actionAdapter(this));
jMenuItemViewZoomTopRight.setMnemonic('2');
jMenuItemViewZoomTopRight.setText("2-ZoomTopRight");
jMenuItemViewZoomTopRight.setAccelerator(javax.swing.KeyStroke.getKeyStroke('2', 0, false));
	jMenuItemViewZoomTopRight.addActionListener(new JBrotFrame_jMenuItemViewZoomTopRight_actionAdapter(this));
jMenuItemViewZoomBottomLeft.setMnemonic('3');
jMenuItemViewZoomBottomLeft.setText("3-ZoomBottomLeft");
jMenuItemViewZoomBottomLeft.setAccelerator(javax.swing.KeyStroke.getKeyStroke('3', 0, false));
	jMenuItemViewZoomBottomLeft.addActionListener(new JBrotFrame_jMenuItemViewZoomBottomLeft_actionAdapter(this));
jMenuItemViewZoomBottomRight.setMnemonic('4');
jMenuItemViewZoomBottomRight.setText("4-ZoomBottomRight");
jMenuItemViewZoomBottomRight.setAccelerator(javax.swing.KeyStroke.getKeyStroke('4', 0, false));
	jMenuItemViewZoomBottomRight.addActionListener(new JBrotFrame_jMenuItemViewZoomBottomRight_actionAdapter(this));
jMenuItemViewZoomCenter.setMnemonic('5');
jMenuItemViewZoomCenter.setText("5-ZoomCenter");
jMenuItemViewZoomCenter.setAccelerator(javax.swing.KeyStroke.getKeyStroke('5', 0, false));
	jMenuItemViewZoomCenter.addActionListener(new JBrotFrame_jMenuItemViewZoomCenter_actionAdapter(this));
jMenuEffects.setMnemonic('E');
jMenuEffects.setText("Effects");
jMenuItemEffectsAverage.setMnemonic('A');
jMenuItemEffectsAverage.setText("Average Pixels");
jMenuItemEffectsAverage.setAccelerator(javax.swing.KeyStroke.getKeyStroke('G', 0, false));
jMenuItemEffectsRandomizePixels.setMnemonic('P');
jMenuItemEffectsRandomizePixels.setText("Randomize Pixels");
jMenuItemEffectsRandomizeHeights.setMnemonic('R');
jMenuItemEffectsRandomizeHeights.setText("Rearrange Heights");
jMenuItemEffectsRandomizeHeights.setAccelerator(javax.swing.KeyStroke.getKeyStroke('H', 0, false));
jMenuItemEffectsInvertHeights.setMnemonic('I');
jMenuItemEffectsInvertHeights.setText("Invert Heights");
jMenuItemEffectsFlipVertical.setMnemonic('V');
jMenuItemEffectsFlipVertical.setText("Flip Vertical");
jMenuItemEffectsFlipHorizontal.setMnemonic('H');
jMenuItemEffectsFlipHorizontal.setText("Flip Horizontal");
jMenuItemHelpIndex.setMnemonic('I');
jMenuItemHelpIndex.setText("Index");
//	you must enter manually the VK keys (any keys that result in 2 chars inside the ' ')
//	- the JBuilder Menu Designer does it wrong.
jMenuItemHelpIndex.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F1, 0, false));
jCheckBoxMenuItemAutoRotateColors.setText("AutoRotate Colors");
jCheckBoxMenuItemAutoRotateColors.setAccelerator(javax.swing.KeyStroke.getKeyStroke('=', 0, false));
jCheckBoxMenuItemAutoRotateColors.addActionListener(new JBrotFrame_jCheckBoxMenuItemAutoRotateColors_actionAdapter(this));
statusBar.setToolTipText("");
statusBar.setText(" ");
ColorRotTimer.addActionListener(new JBrotFrame_ColorRotTimer_actionAdapter(this));
PauseTimer.addActionListener(new JBrotFrame_PauseTimer_actionAdapter(this));
jToolBar.add(jButton1);
jToolBar.add(jButton2);
jToolBar.add(jButton3);
jMenuFile.add(jMenuItemFileNew);
jMenuFile.add(jMenuItemFileOpen);
jMenuFile.add(jMenuItemFileSaveAs);
jMenuFile.add(jMenuItemFileRestart);
jMenuFile.addSeparator();
jMenuFile.add(jMenuItemFilePrevious);
jMenuFile.add(jMenuItemFileFlip);
jMenuFile.addSeparator();
jMenuFile.add(jMenuItemFileEditList);
jMenuFile.addSeparator();
jMenuFile.add(jMenuFileExit);
jMenuHelp.add(jMenuItemHelpIndex);
jMenuHelp.add(jMenuHelpAbout);
jMenuBar1.add(jMenuFile);
jMenuBar1.add(jMenuColors);
jMenuBar1.add(jMenuView);
jMenuBar1.add(jMenuEffects);
jMenuBar1.add(jMenuHelp);
this.setJMenuBar(jMenuBar1);
contentPane.add(jToolBar, BorderLayout.NORTH);
contentPane.add(statusBar, BorderLayout.SOUTH);
contentPane.add(jDibPanel1, BorderLayout.CENTER);
jMenuColors.add(jMenuItemColorsLoad);
jMenuColors.add(jMenuItemColorsSaveAs);
jMenuColors.addSeparator();
jMenuColors.add(jMenuItemColorsNextMap);
jMenuColors.add(jMenuItemColorsPreviousMap);
jMenuColors.add(jMenuItemColorsEditList);
jMenuColors.addSeparator();
jMenuColors.add(jMenuItemColorsRandomize);
jMenuColors.add(jMenuItemColorsReverse);
jMenuColors.add(jMenuItemColorsComplement);
jMenuColors.add(jMenuItemColorsLighten);
jMenuColors.add(jMenuItemColorsDarken);
jMenuColors.addSeparator();
jMenuColors.add(jMenuItemColorsRotateForward);
jMenuColors.add(jMenuItemColorsRotateBackward);
jMenuView.add(jMenuItemViewFitToWindow);
jMenuView.add(jCheckBoxMenuItemIsotropicXY);
jMenuView.add(jMenuItemViewZPower);
jMenuView.add(jMenuItemViewDisplaySecs);
jMenuView.addSeparator();
jMenuView.add(jCheckBoxMenuItemAutoRotateColors);
jMenuView.addSeparator();
jMenuView.add(jMenuItemViewZoomOut);
jMenuView.add(jMenuItemViewZoomTopLeft);
jMenuView.add(jMenuItemViewZoomTopRight);
jMenuView.add(jMenuItemViewZoomBottomLeft);
jMenuView.add(jMenuItemViewZoomBottomRight);
jMenuView.add(jMenuItemViewZoomCenter);
jMenuEffects.add(jMenuItemEffectsAverage);
jMenuEffects.add(jMenuItemEffectsRandomizePixels);
jMenuEffects.addSeparator();
jMenuEffects.add(jMenuItemEffectsRandomizeHeights);
jMenuEffects.add(jMenuItemEffectsInvertHeights);
jMenuEffects.addSeparator();
jMenuEffects.add(jMenuItemEffectsFlipVertical);
jMenuEffects.add(jMenuItemEffectsFlipHorizontal);
}

//----------------------------------------------------------------------------
//File | Exit action performed
public void jMenuFileExit_actionPerformed(ActionEvent e)
{
System.exit(0);
}

//----------------------------------------------------------------------------
//Help | About action performed
public void jMenuHelpAbout_actionPerformed(ActionEvent e)
{
JBrotFrame_AboutBox dlg = new JBrotFrame_AboutBox(this);
Dimension dlgSize = dlg.getPreferredSize();
Dimension frmSize = getSize();
Point loc = getLocation();
dlg.setLocation((frmSize.width - dlgSize.width) / 2 + loc.x, (frmSize.height - dlgSize.height) / 2 + loc.y);
dlg.setModal(true);
dlg.pack();
dlg.setVisible(true);
}

//----------------------------------------------------------------------------
//Overridden so we can exit when window is closed
protected void processWindowEvent(WindowEvent e)
{
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING)
{
	jMenuFileExit_actionPerformed(null);
}
}
//----------------------------------------------------------------------------
void jMenuItemFileNew_actionPerformed(ActionEvent e)
{
	jDibPanel1.CmFileNew();
}
//----------------------------------------------------------------------------
void jMenuItemFilePrevious_actionPerformed(ActionEvent e)
{
jDibPanel1.CmFilePrevious();
}
//----------------------------------------------------------------------------
	void jMenuItemColorsRotateForward_actionPerformed(ActionEvent e)
	{
		jCheckBoxMenuItemAutoRotateColors.setState(false);
		jDibPanel1.CmColorsRotate(1);
	}
	//----------------------------------------------------------------------------
	void jMenuItemColorsRotateBackward_actionPerformed(ActionEvent e)
	{
		jCheckBoxMenuItemAutoRotateColors.setState(false);
		jDibPanel1.CmColorsRotate(-1);
	}
	//----------------------------------------------------------------------------
	void ColorRotTimer_actionPerformed(ActionEvent e)
	{
		if(jCheckBoxMenuItemAutoRotateColors.getState() == true)
			jDibPanel1.CmColorsRotate(1);
	}

//----------------------------------------------------------------------------
	void jCheckBoxMenuItemAutoRotateColors_actionPerformed(ActionEvent e)
	{
		//Note that the checking and unchecking of the menu item is handled
		//automatically, and since this works correctly, it apparently occurs
		//before this function is called.  This gets its new state.
		if(jCheckBoxMenuItemAutoRotateColors.getState() == true)
			ColorRotTimer.start();
		else
			ColorRotTimer.stop();
	}

void jMenuItemColorsReverse_actionPerformed(ActionEvent e)
	{
		jDibPanel1.CmColorsReverse();
	}

void jMenuItemColorsComplement_actionPerformed(ActionEvent e)
{
	jDibPanel1.CmColorsComplement();
}

void jMenuItemColorsLighten_actionPerformed(ActionEvent e)
{
	jDibPanel1.CmColorsLighten();
}

void jMenuItemColorsDarken_actionPerformed(ActionEvent e)
{
	jDibPanel1.CmColorsDarken();
}

void jMenuItemColorsLoad_actionPerformed(ActionEvent e)
{
//		To make this useful, you must add a file chooser
	jDibPanel1.LoadColors("GRAYSCAL.MAP");
}

void jMenuItemColorsRandomize_actionPerformed(ActionEvent e)
{
	//note this uses the new RandomWalk, not the old uniform random, method.
	jDibPanel1.CmColorsRandomize();
}

void jMenuItemColorsNextMap_actionPerformed(ActionEvent e)
{
	jDibPanel1.CmColorsNextMap();
}

//----------------------------------------------------------------------------
void jMenuItemColorsPreviousMap_actionPerformed(ActionEvent e)
{
	jDibPanel1.CmColorsPreviousMap();
}

//----------------------------------------------------------------------------
void jMenuItemViewZPower_actionPerformed(ActionEvent e)
{
String msg = "Power of z (n) To Use in (z = z^n + c). (Minimum 2, Maximum 16): ";
String val = JOptionPane.showInputDialog(this, msg,
						 new Integer(jDibPanel1.mandelgenerator.getZPower()));
if((val != null) && (val.length() > 0))
{
	int i = Integer.parseInt(val);
	jDibPanel1.setZPower(i);
}
}
//----------------------------------------------------------------------------
void jMenuItemFileRestart_actionPerformed(ActionEvent e)
{
	//set zpower to itself: this empties the stack, etc., for a fresh start
	jDibPanel1.setZPower(jDibPanel1.mandelgenerator.getZPower());
}
//----------------------------------------------------------------------------
void jMenuItemViewDisplaySecs_actionPerformed(ActionEvent e)
{
String msg = "Time Delay Before Automatic File|New.\nNumber of seconds (1 to 65535):";
String val = JOptionPane.showInputDialog(this, msg, new Integer(displaysecs));
if((val != null) && (val.length() > 0))
{
	int i = Integer.parseInt(val);
	if(i > 0)
	{
		displaysecs = i;
		PauseTimer.stop();
		PauseTimer.setDelay(displaysecs * 1000);
		PauseTimer.start();
	}
}
}
//----------------------------------------------------------------------------

void PauseTimer_actionPerformed(ActionEvent e)
{
	jDibPanel1.CmFileNewRandom();
}

//----------------------------------------------------------------------------
void jMenuItemViewZoomOut_actionPerformed(ActionEvent e)
{
	jDibPanel1.quadrantzoom(0);
}

//----------------------------------------------------------------------------
void jMenuItemViewZoomTopLeft_actionPerformed(ActionEvent e)
{
	jDibPanel1.quadrantzoom(1);
}

//----------------------------------------------------------------------------
void jMenuItemViewZoomTopRight_actionPerformed(ActionEvent e)
{
	jDibPanel1.quadrantzoom(2);
}

void jMenuItemViewZoomBottomLeft_actionPerformed(ActionEvent e)
{
	jDibPanel1.quadrantzoom(3);
}

void jMenuItemViewZoomBottomRight_actionPerformed(ActionEvent e)
{
	jDibPanel1.quadrantzoom(4);
}

void jMenuItemViewZoomCenter_actionPerformed(ActionEvent e)
{
	jDibPanel1.quadrantzoom(5);
}

//----------------------------------------------------------------------------
	public void jCheckBoxMenuItemIsotropicXY_actionPerformed(ActionEvent e)
	{
		jDibPanel1.CmSetIsotropicXY(jCheckBoxMenuItemIsotropicXY.getState());
	}
//-----------------------------------------------------------------------------
}//end class JBrotFrame

///////////////////////////////////////////////////////////////////////////////


class JBrotFrame_jCheckBoxMenuItemIsotropicXY_actionAdapter implements ActionListener
{
	private JBrotFrame adaptee;
	JBrotFrame_jCheckBoxMenuItemIsotropicXY_actionAdapter(JBrotFrame adaptee)
	{
		this.adaptee = adaptee;
	}

	public void actionPerformed(ActionEvent e)
	{
		adaptee.jCheckBoxMenuItemIsotropicXY_actionPerformed(e);
	}
}
///////////////////////////////////////////////////////////////////////////////

class JBrotFrame_jMenuFileExit_ActionAdapter implements ActionListener
{
JBrotFrame adaptee;
JBrotFrame_jMenuFileExit_ActionAdapter(JBrotFrame adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.jMenuFileExit_actionPerformed(e);
}
}

///////////////////////////////////////////////////////////////////////////////
class JBrotFrame_jMenuHelpAbout_ActionAdapter implements ActionListener
{
JBrotFrame adaptee;
JBrotFrame_jMenuHelpAbout_ActionAdapter(JBrotFrame adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.jMenuHelpAbout_actionPerformed(e);
}
}

///////////////////////////////////////////////////////////////////////////////
class JBrotFrame_jMenuItemFileNew_actionAdapter implements java.awt.event.ActionListener
{
JBrotFrame adaptee;

JBrotFrame_jMenuItemFileNew_actionAdapter(JBrotFrame adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.jMenuItemFileNew_actionPerformed(e);
}
}

class JBrotFrame_jMenuItemFilePrevious_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;

	JBrotFrame_jMenuItemFilePrevious_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.jMenuItemFilePrevious_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemColorsRotateForward_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;
	JBrotFrame_jMenuItemColorsRotateForward_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.jMenuItemColorsRotateForward_actionPerformed(e);
	}
}

class JBrotFrame_ColorRotTimer_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;
	JBrotFrame_ColorRotTimer_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.ColorRotTimer_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemColorsRotateBackward_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;
	JBrotFrame_jMenuItemColorsRotateBackward_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.jMenuItemColorsRotateBackward_actionPerformed(e);
	}
}

class JBrotFrame_jCheckBoxMenuItemAutoRotateColors_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;
	JBrotFrame_jCheckBoxMenuItemAutoRotateColors_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.jCheckBoxMenuItemAutoRotateColors_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemColorsReverse_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;
	JBrotFrame_jMenuItemColorsReverse_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.jMenuItemColorsReverse_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemColorsComplement_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;
	JBrotFrame_jMenuItemColorsComplement_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.jMenuItemColorsComplement_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemColorsLighten_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;
	JBrotFrame_jMenuItemColorsLighten_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.jMenuItemColorsLighten_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemColorsDarken_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;
	JBrotFrame_jMenuItemColorsDarken_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.jMenuItemColorsDarken_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemColorsLoad_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;
	JBrotFrame_jMenuItemColorsLoad_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.jMenuItemColorsLoad_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemColorsRandomize_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;
	JBrotFrame_jMenuItemColorsRandomize_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.jMenuItemColorsRandomize_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemColorsNextMap_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;

	JBrotFrame_jMenuItemColorsNextMap_actionAdapter(JBrotFrame adaptee)
	{
		this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
		adaptee.jMenuItemColorsNextMap_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemColorsPreviousMap_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;

	JBrotFrame_jMenuItemColorsPreviousMap_actionAdapter(JBrotFrame adaptee)
	{
		this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
		adaptee.jMenuItemColorsPreviousMap_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemViewZPower_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;

	JBrotFrame_jMenuItemViewZPower_actionAdapter(JBrotFrame adaptee)
	{
		this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
		adaptee.jMenuItemViewZPower_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemFileRestart_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;

	JBrotFrame_jMenuItemFileRestart_actionAdapter(JBrotFrame adaptee)
	{
		this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
		adaptee.jMenuItemFileRestart_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemViewDisplaySecs_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;

	JBrotFrame_jMenuItemViewDisplaySecs_actionAdapter(JBrotFrame adaptee)
	{
		this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
		adaptee.jMenuItemViewDisplaySecs_actionPerformed(e);
	}
}

class JBrotFrame_PauseTimer_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;

	JBrotFrame_PauseTimer_actionAdapter(JBrotFrame adaptee)
	{
		this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
		adaptee.PauseTimer_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemViewZoomOut_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;

	JBrotFrame_jMenuItemViewZoomOut_actionAdapter(JBrotFrame adaptee)
	{
		this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
		adaptee.jMenuItemViewZoomOut_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemViewZoomTopLeft_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;

JBrotFrame_jMenuItemViewZoomTopLeft_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.jMenuItemViewZoomTopLeft_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemViewZoomTopRight_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;

JBrotFrame_jMenuItemViewZoomTopRight_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.jMenuItemViewZoomTopRight_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemViewZoomBottomLeft_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;

JBrotFrame_jMenuItemViewZoomBottomLeft_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.jMenuItemViewZoomBottomLeft_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemViewZoomBottomRight_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;

JBrotFrame_jMenuItemViewZoomBottomRight_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.jMenuItemViewZoomBottomRight_actionPerformed(e);
	}
}

class JBrotFrame_jMenuItemViewZoomCenter_actionAdapter implements java.awt.event.ActionListener
{
	JBrotFrame adaptee;

JBrotFrame_jMenuItemViewZoomCenter_actionAdapter(JBrotFrame adaptee)
	{
	this.adaptee = adaptee;
	}
	public void actionPerformed(ActionEvent e)
	{
	adaptee.jMenuItemViewZoomCenter_actionPerformed(e);
	}
}

JBrotClass.java

package jbrot;

import javax.swing.UIManager;
import java.awt.*;

/**
 * <p>Title: This file is part of the JBrot project.</p>
 * <p>Description: Java version of Winbrot</p>
 * <p>Copyright: Copyright (C)2004 Steven Whitney.</p>
 * @version 1.0
 */

public class JBrotClass
{
    boolean packFrame = false;

	//Construct the application
    public JBrotClass()
    {
	JBrotFrame frame = new JBrotFrame();
	//Validate frames that have preset sizes
	//Pack frames that have useful preferred size info, e.g. from their layout
	if (packFrame)
	{
	    frame.pack();
	}
	else
	{
	    frame.validate();
	}
	//Center the window
	Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
	Dimension frameSize = frame.getSize();
	if (frameSize.height > screenSize.height)
	{
	    frameSize.height = screenSize.height;
	}
	if (frameSize.width > screenSize.width)
	{
	    frameSize.width = screenSize.width;
	}
	frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
	frame.setVisible(true);
    }

	//Main method
    public static void main(String[] args)
    {
	try
	{
	    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
	}
	catch(Exception e)
	{
	    e.printStackTrace();
	}
	new JBrotClass();
    }
}

DirFilter.java

package jbrot;

import java.io.FilenameFilter;
import java.io.File;
import java.util.regex.*;

/**
 * <p>Title: JBrot</p>
 * <p>Description: A class that filters filenames for File.list() </p>
 * <p>Copyright: This file uses unmodified code for the class DirFilter from the
 * excellent book "Thinking in Java, 3rd Ed. Revision 4.0" by Bruce Eckel.
 * The book is available free at http://www.mindview.net/Books/TIJ/.
 * In this JBrot distribution, that code is not included because of
 * caution about the copyright. JBrot is distributed under the
 * GNU GPL, and the book is definitely not. You will need to locate and
 * insert the code yourself, and must not include it in any subsequent
 * distribution of JBrot unless you obtain permission from the author.</p>
 */

Insert required code here. It's only a few lines.

 

 

Valid HTML 4.01 Transitional Valid CSS
View content labeling at ICRA.
Copyright ©2008 Steven Whitney. Last modified 02/27/2008.