Wednesday, July 4, 2012

72. FRACTAL EXPLORER IN JAVA




import java.awt.*;
import java.applet.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;


public class Fractal extends Applet implements ActionListener, MouseListener, MouseMotionListener, 
AdjustmentListener, KeyListener, DocumentListener {
public static final int X = 800, Y = 550, ButX=72, ButY=26;
public static final int Min_Iter=0, Max_Iter=10000, SL_phMAX=200, SL_peMAX=400, Max_Fractal=6;
public static final double STX[]={ -2.7, -2.3, -2.5, -2.2, -5.2, 2.98 };

public static final double STY[]={ -1.43, -1.43, -1.43, -1.25, -4.3, 0.012};
public static final double fGzoom=400.0/140.0, fzoom[]={ 1.0, 1.0, 1.0, 1.0, 3.0, ((double)Y)/(800.0*fGzoom)};
public static final String sFractal[]={ "Mandlebrot", "F(Z)=Z^3", "F(Z)=Z^2-Z", "F(Z)=Z^3-Z^2+Z", 
"Henon Map" ,"Logistic Eq." };
public static BufferedImage pBI=new BufferedImage(X, Y, BufferedImage.TYPE_INT_RGB), 
pBI2=new BufferedImage(X, Y, BufferedImage.TYPE_INT_RGB);
public static int width, height, R[]=new int[SL_peMAX], G[]=new int[SL_peMAX], B[]=new int[SL_peMAX];
public static int r_ph=0, r_pe=45, g_ph=64, g_pe=110, b_ph=165, b_pe=80;
public static int r_ph2, r_pe2, g_ph2, g_pe2, b_ph2, b_pe2;
public static int niter=500, lniter, niter2, fractal=0, lfractal, fractal2, Action, lAct, lAct2, PvNx;
public static double stx, sty, zoom, stx2, sty2, zoom2, Gzoom;
private static JButton Butt_Fractal, Butt_Zoom, Butt_Refresh, Butt_Pal, Butt_PvNx;
private static JScrollBar SBiter;
private static JTextField TFiter;
private static JComboBox CBfractal;
private static JPanel JPbut;
private static FramePal Frame_Pal=null;
private static Font IFont;
public static boolean bMouse=false, bDrag=false, bZoom=false, bPal=false;
public static Point mouse_in, lmouse_in, mouse, lmouse;


public Fractal() {
PalInit();
}

public void init() {
setSize(X, Y);
width = getSize().width;
height = getSize().height;
setBackground( Color.black );
PvNx=0;
stx=STX[fractal];
sty=STY[fractal];
Gzoom=fGzoom;
if(X>Y) Gzoom/=(double)Y;
else Gzoom/=(double)X;
zoom=Gzoom*fzoom[fractal];
Action=1;
mouse_in=new Point(0,0);
lmouse_in=new Point(0,0);
mouse=new Point(0,0);
lmouse=new Point(0,0);
IFont=new Font(null, Font.BOLD, 14);
// Controls
CBfractal=new JComboBox(sFractal);
CBfractal.setSelectedIndex(fractal);
CBfractal.addActionListener(this);
Butt_Fractal=new JButton("Fractal");
Butt_Fractal.setPreferredSize(new Dimension(ButX, ButY));
Butt_Fractal.setMargin(new Insets(5, 5, 5, 5));
Butt_Fractal.setActionCommand("fractal");
Butt_Fractal.setEnabled(true);
Butt_Fractal.addActionListener(this);
Butt_Zoom=new JButton("Zoom");
Butt_Zoom.setPreferredSize(new Dimension(ButX, ButY));
Butt_Zoom.setMargin(new Insets(5, 5, 5, 5));
Butt_Zoom.setActionCommand("zoom");
Butt_Zoom.setEnabled(false);
Butt_Zoom.addActionListener(this);
Butt_Refresh=new JButton("Refresh");
Butt_Refresh.setPreferredSize(new Dimension(ButX, ButY));
Butt_Refresh.setMargin(new Insets(5, 5, 5, 5));
Butt_Refresh.setActionCommand("refresh");
Butt_Refresh.setEnabled(false);
Butt_Refresh.addActionListener(this);
Butt_Pal=new JButton("Palette");
Butt_Pal.setPreferredSize(new Dimension(ButX, ButY));
Butt_Pal.setMargin(new Insets(5, 5, 5, 5));
Butt_Pal.setActionCommand("editpal");
Butt_Pal.setEnabled(true);
Butt_Pal.addActionListener(this);
SBiter=new JScrollBar(JScrollBar.VERTICAL, 1, 1, 0, 3);
SBiter.setPreferredSize(new Dimension(20, ButY));
SBiter.addAdjustmentListener(this);
TFiter=new JTextField(Integer.toString(niter), 4);
TFiter.setFont(new Font(null, Font.BOLD, 14));
TFiter.setHorizontalAlignment(JTextField.CENTER);
TFiter.setPreferredSize(new Dimension(60, 24));
TFiter.addKeyListener(this);
TFiter.getDocument().addDocumentListener(this);
JPbut=new JPanel();
JPbut.add(CBfractal);
JPbut.add(Butt_Fractal);
JPbut.add(Butt_Zoom);
JPbut.add(Butt_Refresh);
JPbut.add(Butt_Pal);
JPbut.add(SBiter);
JPbut.add(TFiter);
this.add(JPbut);
Butt_PvNx=new JButton("Back");
Butt_PvNx.setPreferredSize(new Dimension(45, 21));
Butt_PvNx.setMargin(new Insets(5, 5, 5, 5));
Butt_PvNx.setActionCommand("pvnx");
Butt_PvNx.setEnabled(false);
Butt_PvNx.setLocation(0,0);
this.add(Butt_PvNx);
Butt_PvNx.addActionListener(this);
addMouseListener(this);
addMouseMotionListener(this);
}


public void mouseEntered( MouseEvent e ) {}

public void mouseExited( MouseEvent e ) {}

public void mouseClicked( MouseEvent e ) {}

public void mousePressed( MouseEvent e ) {
int eb=e.getButton();
if(eb==MouseEvent.BUTTON1) {
lmouse_in.setLocation(mouse_in);
mouse.x=mouse_in.x=e.getX();
mouse.y=mouse_in.y=e.getY();
if(mouse_in.x<X && mouse_in.y<Y) {
bMouse=true;
Butt_Zoom.setEnabled(bZoom=false);
}
repaint();
}
if(eb==MouseEvent.BUTTON3) {
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
mouse.x=mouse_in.x=e.getX();
mouse.y=mouse_in.y=e.getY();
if(mouse_in.x<X && mouse_in.y<Y) {
bDrag=true;
Butt_Zoom.setEnabled(bZoom=false);
}
repaint();
}
e.consume();
}

public void mouseReleased( MouseEvent e ) {
int eb=e.getButton();
if(eb==MouseEvent.BUTTON1) {
if(!bMouse) return;
bMouse=false;
mouse.x=e.getX();
if(mouse.x>=X) mouse.x=X-1;
if(mouse.x<0) mouse.x=0;
mouse.y=e.getY();
if(mouse.y>=Y) mouse.y=Y-1;
if(mouse.y<0) mouse.y=0;
if(Math.abs(mouse_in.x-mouse.x)>4 && Math.abs(mouse_in.y-mouse.y)>4) {
Butt_Zoom.setEnabled(true);
bZoom=true;
}
repaint();
}
if(eb==MouseEvent.BUTTON3) {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
if(!bDrag) return;
bDrag=false;
if(fractal!=lfractal) CBfractal.setSelectedIndex(fractal=lfractal);
if(niter!=lniter) TFiter.setText(Integer.toString(niter=lniter));
mouse.x=e.getX();
if(mouse.x>=X) mouse.x=X-1;
if(mouse.x<0) mouse.x=0;
mouse.y=e.getY();
if(mouse.y>=Y) mouse.y=Y-1;
if(mouse.y<0) mouse.y=0;
if(fractal==Max_Fractal-1) { // Log eq.
stx-=zoom*(double)(mouse.x-mouse_in.x);
sty-=zoom*(double)(mouse.y-mouse_in.y);
Action=2;
}
else Action=3;
repaint();
}
e.consume();
}

public void mouseMoved( MouseEvent e ) {}

public void mouseDragged( MouseEvent e ) { 
if(!bMouse && !bDrag) return;
mouse.x=e.getX();
if(mouse.x>=X) mouse.x=X-1;
if(mouse.x<0) mouse.x=0;
mouse.y=e.getY();
if(mouse.y>=Y) mouse.y=Y-1;
if(mouse.y<0) mouse.y=0;
repaint();
e.consume();
}


public void actionPerformed(ActionEvent e) {
double tx, ty, tz, crx, cry, fxy;
int lx, ly;
if("fractal".equals(e.getActionCommand()))  {
if(zoom!=Gzoom*fzoom[fractal] || fractal!=lfractal || stx!=STX[fractal] || sty!=STY[fractal]) {
if(bZoom) Butt_Zoom.setEnabled(bZoom=false);
Butt_PvNx.setEnabled(true);
Store();
stx=STX[fractal];
sty=STY[fractal];
zoom=Gzoom*fzoom[fractal];
if(fractal<Max_Fractal-1) Action=1;
else Action=2;
repaint();
}
}
if("zoom".equals(e.getActionCommand()) && bZoom) {
Butt_Zoom.setEnabled(bZoom=false);
Butt_Refresh.setEnabled(false);
Butt_PvNx.setEnabled(true);
if(fractal!=lfractal) {
fractal=lfractal;
CBfractal.setSelectedIndex(fractal);
}
Store();
if(mouse_in.x>mouse.x) tx=(double)mouse.x;
else tx=(double)mouse_in.x;
if(mouse_in.y>mouse.y) ty=(double)mouse.y;
else ty=(double)mouse_in.y;
lx=Math.abs(mouse_in.x-mouse.x);
ly=Math.abs(mouse_in.y-mouse.y);
if(lx>ly) tz=(double)ly;
else tz=(double)lx;
fxy=tz/(double)Y;
// Center zoomed image
crx=((double)lx-(double)X*fxy)/2.0;
cry=((double)ly-(double)Y*fxy)/2.0;
// New param
stx+=(tx+crx)*zoom;
sty+=(ty+cry)*zoom;
zoom*=tz/(double)Y;
Action=lAct;
repaint();
}
if("refresh".equals(e.getActionCommand())) {
Butt_Refresh.setEnabled(false);
if(bZoom) Butt_Zoom.setEnabled(bZoom=false);
if(fractal!=lfractal) {
fractal=lfractal;
CBfractal.setSelectedIndex(fractal);
}
Action=lAct;
repaint();
}
else if("pvnx".equals(e.getActionCommand())) {
Butt_Refresh.setEnabled(false);
if(bZoom) Butt_Zoom.setEnabled(bZoom=false);
Swap();
Action=0;
repaint();
}
else if("editpal".equals(e.getActionCommand())) {
if(!bPal) {
bPal=true;
Frame_Pal=new FramePal();
Frame_Pal.setSize(600, 365);
        Frame_Pal.setLocation(0, 0);
        Frame_Pal.setResizable(false);        
        Frame_Pal.setVisible(true);
}
else {
if((Frame_Pal.getExtendedState()&Frame.ICONIFIED)!=0)
Frame_Pal.setExtendedState(Frame.NORMAL);
Frame_Pal.setVisible(true);
}
}
// ComboBox Fractal
if(e.getSource()==CBfractal);
fractal=CBfractal.getSelectedIndex();
}


public void adjustmentValueChanged(AdjustmentEvent ae) {
int i=ae.getValue();
if(i==0 && niter<Max_Iter) niter++;
if(i==2 && niter>Min_Iter) niter--;
TFiter.setText(Integer.toString(niter));
SBiter.setValue(1);
}


    public void keyTyped(KeyEvent e) {
    char c=e.getKeyChar();
    String s=TFiter.getText();
    if(c<'0' || c>'9')
    TFiter.setText(Integer.toString(niter));
    else {
    if(Integer.parseInt(TFiter.getText())>Max_Iter)
    niter=Max_Iter;
TFiter.setText(Integer.toString(niter));
    }
    }


    public void keyPressed(KeyEvent e) {}


    public void keyReleased(KeyEvent e) {
    char c=e.getKeyChar();
    if(c<'0' || c>'9')
    TFiter.setText(Integer.toString(niter));
    else {
    if(Integer.parseInt(TFiter.getText())>Max_Iter) 
    niter=Max_Iter;
    TFiter.setText(Integer.toString(niter)); 
    }
    }


public void changedUpdate(DocumentEvent e) {}

public void removeUpdate(DocumentEvent e) {
String s=TFiter.getText();
      if(s.length()>0) {
      niter=Integer.parseInt(s);
      if(niter<Min_Iter) niter=Min_Iter;
      }
        else niter=Min_Iter;
Butt_Refresh.setEnabled(niter!=lniter);



public void insertUpdate(DocumentEvent e) {
String s=TFiter.getText();
boolean b=true;
for(int i=0;i<s.length();i++)
if(s.charAt(i)>'9' || s.charAt(i)<'0') b=false;
if(b) niter=Integer.parseInt(TFiter.getText());
Butt_Refresh.setEnabled(niter!=lniter);


}

public int makeARGB(int a, int r, int g, int b) {
return a << 24 | r << 16 | g << 8 | b;



public float fmod(float a, float b) {
float c=a%b;
if(c<0) c+=b;
return c;
}


public void PalInit() {
for(int i=0;i<SL_peMAX;i++) {
R[i]=Math.round(127.5f+127.5f*(float)Math.sin(Math.PI*(float)r_ph/100.0f+fmod(i, r_pe)*Math.PI*2.0f/(float)r_pe));
G[i]=Math.round(127.5f+127.5f*(float)Math.sin(Math.PI*(float)g_ph/100.0f+fmod(i, g_pe)*Math.PI*2.0f/(float)g_pe));
B[i]=Math.round(127.5f+127.5f*(float)Math.sin(Math.PI*(float)b_ph/100.0f+fmod(i, b_pe)*Math.PI*2.0f/(float)b_pe));
}
}

public int Pal(int n) {
if(n>=niter) return makeARGB(0, 0, 0, 0);
return makeARGB(0, R[(int)fmod(n, r_pe)], G[(int)fmod(n, g_pe)], B[(int)fmod(n, b_pe)]);
}

public Color Pal2(int n, int rph, int rpe, int gph, int gpe, int bph, int bpe) {
int r, g, b;
r=Math.round(127.5f+127.5f*(float)Math.sin(Math.PI*(float)rph/100.0f+fmod(n, rpe)*Math.PI*2.0f/(float)rpe));
g=Math.round(127.5f+127.5f*(float)Math.sin(Math.PI*(float)gph/100.0f+fmod(n, gpe)*Math.PI*2.0f/(float)gpe));
b=Math.round(127.5f+127.5f*(float)Math.sin(Math.PI*(float)bph/100.0f+fmod(n, bpe)*Math.PI*2.0f/(float)bpe));
return new Color(r, g, b);
}


public int Fractal(int type, double re, double im) {
double x=0, y=0, t;
int n=0;
if(type==4 || type==5) { x=re; y=im; }
while(Math.abs(x)<100000 && Math.abs(y)<100000 && n<niter) {
t=x;
switch(type) {
case 0:
x=re+x*x-y*y;
y=im+2*t*y;
break;
case 1:
x=im+x*x*x-3*x*y*y;
y=re+3*t*t*y-y*y*y;
break;
case 2:
x=re+x*x-y*y-x;
y=im+2*t*y-y;
break;
case 3:
x=im+x*x*x-3*x*y*y-x*x+y*y+x;
y=re+3*t*t*y-y*y*y-2*t*y+y;
break;
case 4:
x=1-0.2*x*x+y;
y=1.01*t;
break;
default:
n=niter;
break;
}
n++;
}
return n;
}


public void Store() {
BufferedImage tbi;
PvNx=0;
Butt_PvNx.setText("Back");
lAct2=lAct;
stx2=stx;
sty2=sty;
zoom2=zoom;
niter2=lniter;
fractal2=lfractal;
r_ph2=r_ph; r_pe2=r_pe;
g_ph2=g_ph; g_pe2=g_pe;
b_ph2=b_ph; b_pe2=b_pe;
tbi=pBI;
pBI=pBI2;
pBI2=tbi;
}

public void Swap() {
BufferedImage tbi;
double td;
int ti;
if(PvNx==0) {
PvNx=1;
Butt_PvNx.setText("Next");
}
else {
PvNx=0;
Butt_PvNx.setText("Back");
}
ti=lAct;
lAct=lAct2;
lAct2=ti;
td=stx;
stx=stx2;
stx2=td;
td=sty;
sty=sty2;
sty2=td;
td=zoom;
zoom=zoom2;
zoom2=td;
ti=lniter;
lniter=niter=niter2;
niter2=ti;
TFiter.setText(Integer.toString(niter));
ti=lfractal;
lfractal=fractal=fractal2;
fractal2=ti;
CBfractal.setSelectedIndex(fractal);
ti=r_ph; r_ph=r_ph2; r_ph2=ti;
ti=g_ph; g_ph=g_ph2; g_ph2=ti;
ti=b_ph; b_ph=b_ph2; b_ph2=ti;
ti=r_pe; r_pe=r_pe2; r_pe2=ti;
ti=g_pe; g_pe=g_pe2; g_pe2=ti;
ti=b_pe; b_pe=b_pe2; b_pe2=ti;
PalInit();
tbi=pBI;
pBI=pBI2;
pBI2=tbi;
}


public void paint(Graphics g) {
int x=0, y=0, n=0, smx=0, smy=0, lx=0, ly=0, ti;
int sr1_left, sr1_right, sr1_top, sr1_bottom, sr2_left, sr2_right, sr2_top, sr2_bottom; 
double cx, cy, s1_sx, s1_sy, s2_sx, s2_sy, td;
Point src, dst;
Graphics gi;
BufferedImage tbi;
Raster r;
switch(Action) {
case 0: 
if(!bMouse && !bDrag) g.drawImage(pBI, 0, 0, null);
if(bMouse || bZoom) {
if(bMouse) {
if(lmouse_in.x>lmouse.x) smx=lmouse.x;
else smx=lmouse_in.x;
if(lmouse_in.y>lmouse.y) smy=lmouse.y;
else smy=lmouse_in.y;
lx=smx+Math.abs(lmouse_in.x-lmouse.x)+1;
ly=smy+Math.abs(lmouse_in.y-lmouse.y)+1;
g.drawImage(pBI, smx, smy, lx, ly, smx, smy, lx, ly, null);
lmouse_in.setLocation(mouse_in);
}
lmouse.setLocation(mouse);
if(mouse_in.x>mouse.x) smx=mouse.x;
else smx=mouse_in.x;
if(mouse_in.y>mouse.y) smy=mouse.y;
else smy=mouse_in.y;
g.setColor(Color.red);
g.drawRect(smx, smy, Math.abs(mouse_in.x-mouse.x), Math.abs(mouse_in.y-mouse.y));
}
if(bDrag) {
x=mouse.x-mouse_in.x;
y=mouse.y-mouse_in.y;
lx=width-Math.abs(x);
ly=height-Math.abs(y);
src=new Point(0, 0);
dst=new Point(0, 0);
if(x>=0) {
src.x=x;
dst.x=0;
}
else {
src.x=0;
dst.x=-x;
}
if(y>=0) {
src.y=y;
dst.y=0;
}
else {
src.y=0;
dst.y=-y;
}
g.drawImage(pBI, src.x, src.y, src.x+lx, src.y+ly, dst.x, dst.y, dst.x+lx, dst.y+ly, null);
g.setColor(Color.black);
// BLACKNESS X
if(x>=0) src.x=0;
else src.x=width+x;
g.fillRect(src.x, 0, Math.abs(x), height);
// BLACKNESS Y
if(y>=0) src.y=0;
else src.y=height+y;
g.fillRect( 0, src.y, width, Math.abs(y));
}
break;
case 1: // Fractals
lAct=Action;
lniter=niter;
lfractal=fractal;
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
for(y=0, cy=sty;y<Y;y++, cy+=zoom) {
for(x=0, cx=stx;x<X;x++, cx+=zoom)
pBI.setRGB(x, y, Pal(Fractal(fractal, cx, cy)));
g.drawImage(pBI, 0, y, X, y+1, 0, y, X, y+1, null);
}
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
break;
case 2: //Logistic eq.
lAct=Action;
lniter=niter;
lfractal=fractal;
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
gi=pBI.getGraphics();
gi.setColor(Color.black);
gi.fillRect(0, 0, width, height);
gi.dispose();
for(x=0, cx=stx, cy=0.5;x<X;x++, cx+=zoom) {
for(n=0;n<niter;n++) {
cy=cx*cy*(1-cy); // Logistic eq.
ly=(int)((cy*0.7-sty)/zoom);
if(ly>=0 && ly<height && n>200) 
pBI.setRGB(x, ly, Pal(n));
}
g.drawImage(pBI, x, 0, x+1, Y, x, 0, x+1, Y, null);
}
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
break;
case 3: // Drag update
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
x=mouse.x-mouse_in.x;
y=mouse.y-mouse_in.y;
lx=width-Math.abs(x);
ly=height-Math.abs(y);
src=new Point(0, 0);
dst=new Point(0, 0);
if(x>=0) {
src.x=x;
dst.x=0;
}
else {
src.x=0;
dst.x=-x;
}
if(y>=0) {
src.y=y;
dst.y=0;
}
else {
src.y=0;
dst.y=-y;
}
// Copy main image
gi=pBI.getGraphics();
tbi=new BufferedImage(X, Y, BufferedImage.TYPE_INT_RGB);
r=pBI.getData();
tbi.setData(r);
gi.drawImage(tbi, src.x, src.y, src.x+lx, src.y+ly, dst.x, dst.y, dst.x+lx, dst.y+ly, null);
tbi.flush();
gi.setColor(Color.black);
// BLACKNESS X
if(x>=0) src.x=0;
else src.x=width+x;
gi.fillRect(src.x, 0, Math.abs(x), height);
// BLACKNESS Y
if(y>=0) src.y=0;
else src.y=height+y;
gi.fillRect( 0, src.y, width, Math.abs(y));
g.drawImage(pBI, 0, 0, null);
gi.dispose();
if(x>=0) {
sr1_left=0;
sr1_right=x;
s1_sx=stx-zoom*(double)x;
sr2_left=0;
sr2_right=width;
s2_sx=stx-zoom*(double)x;
}
else {
sr1_left=width+x;
sr1_right=width;
s1_sx=stx+zoom*(double)(width);
sr2_left=0;
sr2_right=width;
s2_sx=stx-zoom*(double)x;
}
if(y>=0) {
sr1_top=y;
sr1_bottom=height;
s1_sy=sty;
sr2_top=0;
sr2_bottom=y;
s2_sy=sty-zoom*(double)y;
}
else {
sr1_top=0;
sr1_bottom=height+y;
s1_sy=sty-zoom*(double)y;
sr2_top=height+y;
sr2_bottom=height;
s2_sy=sty+zoom*(double)height;
}
// Actualização pos origem
stx-=zoom*(double)x;
sty-=zoom*(double)y;
if(sr1_top>sr2_top) {
ti=sr1_top; sr1_top=sr2_top; sr2_top=ti;
ti=sr1_bottom; sr1_bottom=sr2_bottom; sr2_bottom=ti;
ti=sr1_left; sr1_left=sr2_left; sr2_left=ti;
ti=sr1_right; sr1_right=sr2_right; sr2_right=ti;
td=s1_sx; s1_sx=s2_sx; s2_sx=td;
td=s1_sy; s1_sy=s2_sy; s2_sy=td;
}
for(y=sr1_top, cy=s1_sy;y<sr1_bottom;y++, cy+=zoom) 
for(x=sr1_left, cx=s1_sx;x<sr1_right;x++, cx+=zoom) {
pBI.setRGB(x, y, Pal(Fractal(lfractal, cx, cy)));
g.drawImage(pBI, 0, y, X, y+1, 0, y, X, y+1, null);
}
for(y=sr2_top, cy=s2_sy;y<sr2_bottom;y++, cy+=zoom) 
for(x=sr2_left, cx=s2_sx;x<sr2_right;x++, cx+=zoom) {
pBI.setRGB(x, y, Pal(Fractal(lfractal, cx, cy)));
g.drawImage(pBI, 0, y, X, y+1, 0, y, X, y+1, null);
}
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
break;
default: break;
}
Action=0;
Point po=JPbut.getLocation();
g.setFont(IFont);
g.setColor(Color.BLACK);
g.drawString("Iterations", po.x+520, po.y+22);
CBfractal.repaint();
Butt_Fractal.repaint();
Butt_Zoom.repaint();
Butt_Refresh.repaint();
Butt_Pal.repaint();
SBiter.repaint();
TFiter.repaint();
Butt_PvNx.setLocation(0, 0);
Butt_PvNx.repaint();
}

public void update(Graphics g) {
  paint(g);
}

public void rep() {
repaint();
}

class FramePal extends JFrame implements ActionListener, ChangeListener, WindowListener {
private JSlider Rph, Rpe, Gph, Gpe, Bph, Bpe;
private Spectrum spec;


public FramePal() {
super("Edit Palette");
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
JButton BPal_Cancel=new JButton("Cancel");
BPal_Cancel.setPreferredSize(new Dimension(ButX, ButY));
BPal_Cancel.setMargin(new Insets(5, 5, 5, 5));
BPal_Cancel.setActionCommand("pcancel");
BPal_Cancel.addActionListener(this);
JButton BPal_Ok=new JButton("Ok");
BPal_Ok.setPreferredSize(new Dimension(ButX, ButY));
BPal_Ok.setMargin(new Insets(5, 5, 5, 5));
BPal_Ok.setActionCommand("pok");
BPal_Ok.addActionListener(this);
JPanel Panel_But=new JPanel();
Panel_But.add(BPal_Ok, BorderLayout.CENTER);
Panel_But.add(BPal_Cancel, BorderLayout.CENTER);
Rph = new JSlider(JSlider.HORIZONTAL, 0, SL_phMAX, r_ph);
Rph.setToolTipText(""+ r_ph);
Rpe = new JSlider(JSlider.HORIZONTAL, 1, SL_peMAX, r_pe);
Rpe.setToolTipText(""+ r_pe);
Gph = new JSlider(JSlider.HORIZONTAL, 0, SL_phMAX, g_ph);
Gph.setToolTipText(""+ g_ph);
Gpe = new JSlider(JSlider.HORIZONTAL, 1, SL_peMAX, g_pe);
Gpe.setToolTipText(""+ g_pe);
Bph = new JSlider(JSlider.HORIZONTAL, 0, SL_phMAX, b_ph);
Bph.setToolTipText(""+ b_ph);
Bpe = new JSlider(JSlider.HORIZONTAL, 1, SL_peMAX, b_pe);
Bpe.setToolTipText(""+ b_pe);
Rph.addChangeListener(this);
Rpe.addChangeListener(this);
Gph.addChangeListener(this);
Gpe.addChangeListener(this);
Bph.addChangeListener(this);
Bpe.addChangeListener(this);
// Phase
Box box_ph1=Box.createVerticalBox();
box_ph1.add(Rph);
box_ph1.add(Box.createVerticalStrut(25));
box_ph1.add(Gph);
box_ph1.add(Box.createVerticalStrut(25));
box_ph1.add(Bph);
box_ph1.setBorder(BorderFactory.createEmptyBorder(25,10,30,10));
Box box_ph2=Box.createVerticalBox();
Border border_ph=BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
border_ph=BorderFactory.createTitledBorder(border_ph, "Phase", TitledBorder.LEADING , TitledBorder.TOP);
box_ph2.setBorder(border_ph);
box_ph2.add(box_ph1);
Box box_ph=Box.createVerticalBox();
box_ph.setBorder(BorderFactory.createEmptyBorder(20,0,20,0));
box_ph.add(box_ph2);
// Period
Box box_pe1=Box.createVerticalBox();
box_pe1.add(Rpe);
box_pe1.add(Box.createVerticalStrut(25));
box_pe1.add(Gpe);
box_pe1.add(Box.createVerticalStrut(25));
box_pe1.add(Bpe);
box_pe1.setBorder(BorderFactory.createEmptyBorder(25,10,30,10));
Box box_pe2=Box.createVerticalBox();
Border border_pe=BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
border_pe=BorderFactory.createTitledBorder(border_pe, "Period", TitledBorder.LEADING , TitledBorder.TOP);
box_pe2.setBorder(border_pe);
box_pe2.add(box_pe1);
Box box_pe=Box.createVerticalBox();
box_pe.setBorder(BorderFactory.createEmptyBorder(20,0,20,0));
box_pe.add(box_pe2);
// Labels
JLabel L_red=new JLabel("Red");
L_red.setFont(new Font(null, Font.BOLD, 14));
L_red.setForeground(Color.RED);
JLabel L_green=new JLabel("Green");
L_green.setFont(new Font(null, Font.BOLD, 14));
L_green.setForeground(new Color(0, 200, 0));
JLabel L_blue=new JLabel("Blue");
L_blue.setFont(new Font(null, Font.BOLD, 14));
L_blue.setForeground(Color.BLUE);
Box box_cor=Box.createVerticalBox();
box_cor.add(Box.createVerticalStrut(64));
box_cor.add(L_red);
box_cor.add(Box.createVerticalStrut(22));
box_cor.add(L_green);
box_cor.add(Box.createVerticalStrut(22));
box_cor.add(L_blue);
box_cor.add(Box.createVerticalGlue());
// add
Box box_rgb=Box.createHorizontalBox();
box_rgb.add(Box.createHorizontalGlue());
box_rgb.add(Box.createRigidArea(new Dimension(10, 80)));
box_rgb.add(box_cor);
box_rgb.add(Box.createRigidArea(new Dimension(5, 80)));
box_rgb.add(box_ph);
box_rgb.add(Box.createRigidArea(new Dimension(15, 80)));
box_rgb.add(box_pe);
box_rgb.add(Box.createRigidArea(new Dimension(20, 80)));
spec=new Spectrum();
//
Container CPal=getContentPane();
CPal.setLayout(new BorderLayout());
CPal.add(box_rgb, BorderLayout.NORTH);
CPal.add(spec, BorderLayout.CENTER);
CPal.add(Panel_But, BorderLayout.SOUTH);
}

        public void actionPerformed(ActionEvent e) {
        boolean b=false;
        int v;
if("pok".equals(e.getActionCommand())) {
if(r_ph!=(v=Rph.getValue())) {
r_ph=v;
b=true;
}
if(r_pe!=(v=Rpe.getValue())) {
r_pe=v;
b=true;
}
if(g_ph!=(v=Gph.getValue())) {
g_ph=v;
b=true;
}
if(g_pe!=(v=Gpe.getValue())) {
g_pe=v;
b=true;
}
if(b_ph!=(v=Bph.getValue())) {
b_ph=v;
b=true;
}
if(b_pe!=(v=Bpe.getValue())) {
b_pe=v;
b=true;
}
setVisible(false);
dispose();
bPal=false;
if(b) {
PalInit();
Butt_Refresh.setEnabled(false);
if(bZoom) Butt_Zoom.setEnabled(bZoom=false);
if(fractal!=lfractal) CBfractal.setSelectedIndex(fractal=lfractal);
Action=lAct;
rep();

}
if("pcancel".equals(e.getActionCommand())) {
setVisible(false);
dispose();
bPal=false;
}
        }
        
        public void stateChanged(ChangeEvent e) {
JSlider src = (JSlider)e.getSource();
if (!src.getValueIsAdjusting()) return;
    if (e.getSource().equals(Rph)) {
Rph.setToolTipText(""+ Rph.getValue());
spec.refresh(Rph.getValue(), Rpe.getValue(), Gph.getValue(), Gpe.getValue(), Bph.getValue(), Bpe.getValue());
    }
    else if (src.equals(Rpe)) {
Rpe.setToolTipText(""+ Rpe.getValue());
spec.refresh(Rph.getValue(), Rpe.getValue(), Gph.getValue(), Gpe.getValue(), Bph.getValue(), Bpe.getValue());
    }
    else if (src.equals(Gph)) {
Gph.setToolTipText(""+ Gph.getValue());
spec.refresh(Rph.getValue(), Rpe.getValue(), Gph.getValue(), Gpe.getValue(), Bph.getValue(), Bpe.getValue());
    }
    else if (src.equals(Gpe)) {
Gpe.setToolTipText(""+ Gpe.getValue());
spec.refresh(Rph.getValue(), Rpe.getValue(), Gph.getValue(), Gpe.getValue(), Bph.getValue(), Bpe.getValue());
    }
    else if (src.equals(Bph)) {
Bph.setToolTipText(""+ Bph.getValue());
spec.refresh(Rph.getValue(), Rpe.getValue(), Gph.getValue(), Gpe.getValue(), Bph.getValue(), Bpe.getValue());
    }
    else if (src.equals(Bpe)) {
Bpe.setToolTipText(""+ Bpe.getValue());
spec.refresh(Rph.getValue(), Rpe.getValue(), Gph.getValue(), Gpe.getValue(), Bph.getValue(), Bpe.getValue());
    }    
        }
        
        public void windowActivated(WindowEvent e) {}
        
        public void windowClosed(WindowEvent e) {}
        
        public void windowClosing(WindowEvent e) {
bPal=false;
        }
        
        public void windowDeactivated(WindowEvent e) {}
        
        public void windowDeiconified(WindowEvent e) {}
        
        public void windowIconified(WindowEvent e) {}
        
        public void windowOpened(WindowEvent e) {}
        
        public class Spectrum extends JPanel {
private int rph, rpe, gph, gpe, bph, bpe;
        public Spectrum() {
        rph=r_ph; rpe=r_pe;
        gph=g_ph; gpe=g_pe;
        bph=b_ph; bpe=b_pe;
        }
       
        public void refresh(int rh, int re, int gh, int ge, int bh, int be) {
        rph=rh; rpe=re;
        gph=gh; gpe=ge;
        bph=bh; bpe=be;
        repaint();
        }
       
        public void paint(Graphics g) {
        super.paint(g);
        for(int i=0;i<500;i++) {
        g.setColor(Pal2(i, rph, rpe, gph, gpe, bph, bpe));
        g.drawLine(i+50, 0, i+50, 50);
        }
        }
        }
}
}


SAMPLE OUTPUT: