|
/*
* @(#)MoleculeEditor_1_0.java 96/05/28 Denis M. BAYADA
*
* Copyright (c) 1996 Denis M. BAYADA, University of Leeds, Leeds, U.K.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and
* without fee is hereby granted.
* Please email denis@mi.leeds.ac.uk for any questions or comments included
* questions on commercial availability.
*
* This software is given "as is". I do not accept responsibility
* for any damage to software or hardware that it may cause.
*/
import java.awt.*;
import java.applet.*;
import java.lang.Math;
/*
* The main class. This class is static. It contains all the interface.
*/
public class MoleculeEditor_1_0 extends java.applet.Applet {
// These static final byte constants are used to check what
// is the current mode
static final byte SINGLE = 1; // Single bond drawing
static final byte DOUBLE = 2; // Double bond drawing
static final byte SELECT = 3; // Selection
static final byte LASSO = 5; // Lasso
static final byte CYCLO6 = 4; // cyclohexane drawing
static final byte CHANGEAT = 6; // Changing Atom Type
static final byte ZOOM = 7; // Zoom
static final byte ARO6 = 8; // Aromatic 6
static final byte TRIPLE = 9; // Triple bond drawing
static final byte UNKNOWN = 10; // unknown selection (should never happen)
static final byte ARO5 = 11; // Aromatic 5
static final byte CYCLO5 = 12; // cyclopentane
// Different GUI components
Panel drawing_area; // Where the molecule is drawn
Button draw_single_button, change_atom_type_button; // The buttons
Button draw_double_button, lasso_button, select_button;
Button delete_selected_button, zoom_button, draw_triple_button;
Button merge_button;
Panel button_panel; // Panel that contains the buttons
Label global_name; // The Molecule Editor label
Label version_name; // The version label
Label atom_type; // The atom type changing label
Choice choice; // The atom type menu
ImageLinesButton_1_0 cyclo6, aro6, cyclo5, aro5; // The drawn buttons
static String cyclo6Name = new String("Cyclo6"); // name of drawn buttons
static String aro6Name = new String("Aro6");
static String cyclo5Name = new String("Cyclo5");
static String aro5Name = new String("Aro5");
TextField message_window = new TextField(17); // The message window
GridBagLayout gridbag = new GridBagLayout(); // The container layout
// The rest
Molecule_1_0 aMolecule; // The molecule itself
static int current_selected = SELECT; // The variable that is set when
// a button is clicked.
// It is a static!
int x,y,oldx,oldy,start_atom; // variables that store the mouse position
// when a button is clicked, the previous
// mouse position, the atom on which
// the mouse was clicked.
int atom_highlighted = -1; // The atom id that is covered by the mouse
int bond_highlighted = -1; // the bond id that is covered by the mouse
Polygon lasso_pol; // The polygon that stores the lasso
int temp_int=0; // temporary variables
int temp_x[] = new int[20]; // temporary variables
int temp_y[] = new int[20]; // temporary variables
int spare_x[] = new int[100]; // variables used for the ZOOM
int spare_y[] = new int[100]; // variables used for the ZOOM
int gravity_x, gravity_y; // variables used for the ZOOM
int runner; // variables used for the ZOOM
int last_selected = -1; // variables used for the Selection
boolean inside_drawing_area = false; // true if mouse in drawing area
// init function is called once. It draws the whole interface
public void init() {
Polygon pol;
// Creation of the cyclo6 drawn button:
int angle = 0;
for (int i=0; i<6; i++)
{
temp_x[i] =
(int)(15.0*Math.cos(60.0*(double)angle/180.0*Math.PI))+15;
temp_y[i] =
(int)(15.0*Math.sin(60.0*(double)angle/180.0*Math.PI))+15;
angle++;
}
pol = new Polygon(temp_x,temp_y,6);
cyclo6 = new ImageLinesButton_1_0(pol,cyclo6Name);
// Creation of the aro6 drawn button:
temp_x[0] = 30;
temp_y[0] = 15;
temp_x[11] = temp_x[0];
temp_y[11] = temp_y[0];
angle = 1;
for (int i=1; i<11; i+=2)
{
temp_x[i] =
(int)(15.0*Math.cos(60.0*(double)angle/180.0*Math.PI))+15;
temp_y[i] =
(int)(15.0*Math.sin(60.0*(double)angle/180.0*Math.PI))+15;
angle++;
temp_x[i+1] = temp_x[i];
temp_y[i+1] = temp_y[i];
}
angle = 0;
for (int i=12; i<18; i++)
{
temp_x[i] =
(int)(10.0*Math.cos(60.0*(double)angle/180.0*Math.PI))+15;
temp_y[i] =
(int)(10.0*Math.sin(60.0*(double)angle/180.0*Math.PI))+15;
angle++;
}
aro6 = new ImageLinesButton_1_0(18, temp_x, temp_y, aro6Name);
// Creation of the cyclo5 drawn button:
angle = 0;
for (int i=0; i<5; i++)
{
temp_x[i] =
(int)(15.0*Math.cos(72.0*(double)angle/180.0*Math.PI))+15;
temp_y[i] =
(int)(15.0*Math.sin(72.0*(double)angle/180.0*Math.PI))+15;
angle++;
}
pol = new Polygon(temp_x,temp_y,5);
cyclo5 = new ImageLinesButton_1_0(pol,cyclo5Name);
// Creation of the aro5 drawn button:
temp_x[0] = 30;
temp_y[0] = 15;
temp_x[9] = temp_x[0];
temp_y[9] = temp_y[0];
angle = 1;
for (int i=1; i<9; i+=2)
{
temp_x[i] =
(int)(15.0*Math.cos(72.0*(double)angle/180.0*Math.PI))+15;
temp_y[i] =
(int)(15.0*Math.sin(72.0*(double)angle/180.0*Math.PI))+15;
angle++;
temp_x[i+1] = temp_x[i];
temp_y[i+1] = temp_y[i];
}
angle = 0;
for (int i=10; i<14; i++)
{
temp_x[i] =
(int)(10.0*Math.cos(72.0*(double)angle/180.0*Math.PI))+15;
temp_y[i] =
(int)(10.0*Math.sin(72.0*(double)angle/180.0*Math.PI))+15;
angle++;
}
aro5 = new ImageLinesButton_1_0(14, temp_x, temp_y, aro5Name);
// simple text buttons
draw_single_button = new Button("Single Bond");
draw_double_button = new Button("Double Bond");
draw_triple_button = new Button("Triple Bond");
change_atom_type_button = new Button("Atom Type");
lasso_button = new Button("Lasso");
select_button = new Button("Select");
zoom_button = new Button("Zoom");
merge_button = new Button("Merge Selected");
delete_selected_button = new Button("Delete Selected");
// Molecule Editor Label, drawn in Helvetica, bold, 26
Font font = new Font("Helvetica",Font.BOLD,26);
global_name = new Label("Molecule Editor",Label.CENTER);
global_name.setFont(font);
// Version Label, drawn in Helvetica, plain, 12
font = new Font("Helvetica",Font.PLAIN,12);
version_name = new Label("1.0",Label.CENTER);
version_name.setFont(font);
// atom type label
atom_type = new Label("Change Selected to:",Label.CENTER);
// Atom type menu
choice = new Choice();
choice.addItem("C");
choice.addItem("B");
choice.addItem("N");
choice.addItem("O");
choice.addItem("F");
choice.addItem("Na");
choice.addItem("Mg");
choice.addItem("Si");
choice.addItem("P");
choice.addItem("S");
choice.addItem("Cl");
choice.addItem("K");
choice.addItem("Ca");
choice.addItem("Mn");
choice.addItem("Fe");
choice.addItem("Br");
choice.addItem("I");
choice.addItem("?");
// The storage panel for buttons
// It is stored in a matrix of two columns and 10 rows
// All the text buttons span 2 rows whereas drawn buttons are in on row
button_panel = new Panel();
button_panel.setLayout(gridbag);
constrain(button_panel, draw_single_button, 0,0,2,1,
GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER,
0.0,0.0, 5,5,0,5);
constrain(button_panel, draw_double_button, 0,1,2,1,
GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER,
0.0,0.0, 5,5,0,5);
constrain(button_panel, draw_triple_button, 0,2,2,1,
GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER,
0.0,0.0, 5,5,0,5);
constrain(button_panel, lasso_button, 0,3,2,1,
GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER,
0.0,0.0, 5,5,0,5);
constrain(button_panel, select_button, 0,4,2,1,
GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER,
0.0,0.0, 5,5,5,5);
constrain(button_panel, zoom_button, 0,5,2,1,
GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER,
0.0,0.0, 5,5,5,5);
constrain(button_panel, delete_selected_button, 0,6,2,1,
GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER,
0.0,0.0, 5,5,5,5);
constrain(button_panel, merge_button, 0,7,2,1,
GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER,
0.0,0.0, 5,5,5,5);
constrain(button_panel, cyclo6, 0,8,1,1,
GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER,
0.0,0.0, 5,5,5,5);
constrain(button_panel, aro6, 1,8,1,1,
GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER,
0.0,0.0, 5,5,5,5);
constrain(button_panel, cyclo5, 0,9,1,1,
GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER,
0.0,0.0, 5,5,5,5);
constrain(button_panel, aro5, 1,9,1,1,
GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER,
0.0,0.0, 5,5,5,5);
// The rest of the interface
drawing_area = new Panel(); // The molecule drawing area
drawing_area.setLayout(new BorderLayout());
aMolecule = new Molecule_1_0(); // Creation of the molecule instance
drawing_area.add("Center",aMolecule); // The molecule is put in its
this.setLayout(gridbag); // drawing area
message_window.setEditable(false); // Message window is set not editable
// The interface is set up. It is a variable width/height grid of
// 3 rows and 4 columns. It is used like this:
// ___1___||____2____||___3___||____4____||
// 1| molecule_editor_label version
// 2| msg_window at_label menu
// 3| buttons molecule_drawing_area
//
constrain(this, global_name, 0,0,3,1,GridBagConstraints.HORIZONTAL,
GridBagConstraints.CENTER,1.0,0.0, 5,5,5,5);
constrain(this, version_name, 3,0,1,1,GridBagConstraints.HORIZONTAL,
GridBagConstraints.CENTER,1.0,0.0, 5,5,5,5);
constrain(this, message_window, 0,1,2,1,GridBagConstraints.NONE,
GridBagConstraints.WEST,0.0,0.0, 5,5,5,5);
constrain(this, atom_type, 2,1,1,1,GridBagConstraints.NONE,
GridBagConstraints.EAST,0.0,0.0, 5,5,5,5);
constrain(this, choice, 3,1,1,1,GridBagConstraints.NONE,
GridBagConstraints.WEST,0.0,0.0, 5,5,5,5);
constrain(this, button_panel, 0,2,1,1,GridBagConstraints.NONE,
GridBagConstraints.NORTHEAST,0.0,0.0, 5,5,5,5);
constrain(this, drawing_area, 1,2,3,1,GridBagConstraints.BOTH,
GridBagConstraints.CENTER,1.0,1.0, 5,5,5,5);
show();
}
// static function called by the ImageLinesButton_1_0 class instances
// the clicked on
public static void buttonMouseUp(String buttonName)
{
if (buttonName.compareTo(cyclo6Name) == 0)
{
current_selected = CYCLO6;
}
else if (buttonName.compareTo(aro6Name) == 0)
{
current_selected = ARO6;
}
else if (buttonName.compareTo(aro5Name) == 0)
{
current_selected = ARO5;
}
else if (buttonName.compareTo(cyclo5Name) == 0)
{
current_selected = CYCLO5;
}
}
// The Event Handling function. This function acts according to the user
// inputs. It calls LocalmouseDown/Up/Move/Drag functions when it detects
// a mouse event and calls the apropriate functions when a button is clicked.
public boolean handleEvent(Event e)
{
switch (e.id)
{
case Event.ACTION_EVENT:
if (e.target == draw_single_button)
{
current_selected = SINGLE;
message_window.setText("Single Bond Drawing");
}
else if (e.target == draw_double_button)
{
current_selected = DOUBLE;
message_window.setText("Double Bond Drawing");
}
else if (e.target == draw_triple_button)
{
current_selected = TRIPLE;
message_window.setText("Triple Bond Drawing");
}
else if (e.target == select_button)
{
current_selected = SELECT;
message_window.setText("Selection Mode");
}
else if (e.target == lasso_button)
{
current_selected = LASSO;
message_window.setText("Lasso Mode");
}
else if (e.target == choice)
{
current_selected = CHANGEAT;
message_window.setText("Changing Atom Type");
aMolecule.ChangeAtomTypes((String)e.arg);
aMolecule.paint(aMolecule.getGraphics());
}
else if (e.target == zoom_button)
{
current_selected = ZOOM;
message_window.setText("Zoom Mode");
}
else if (e.target == delete_selected_button)
{
aMolecule.DeleteSelected();
current_selected = SELECT;
message_window.setText("Selection Mode");
}
else if (e.target == merge_button)
{
aMolecule.MergeSelected();
aMolecule.paint(aMolecule.getGraphics());
current_selected = SELECT;
message_window.setText("Selection Mode");
}
else
current_selected = UNKNOWN;
break;
case Event.MOUSE_DOWN:
LocalmouseDown(e,e.x,e.y);
return false;
case Event.MOUSE_MOVE:
LocalmouseMove(e,e.x,e.y);
return false;
case Event.MOUSE_UP:
LocalmouseUp(e,e.x,e.y);
return false;
case Event.MOUSE_DRAG:
LocalmouseDrag(e,e.x,e.y);
return false;
default: break;
}
return true;
}
// Function called by handleEvent, that acts when the mouse is dragged
public boolean LocalmouseDrag(Event e, int x, int y)
{
Rectangle r = drawing_area.bounds(); // Checks if the mouse is in
if (x>r.x && xr.y && y -1)
{
aMolecule.redrawAtom(atom_highlighted);
}
if (id > -1)
{
aMolecule.redrawAtom(id,Color.blue);
}
}
atom_highlighted = id;
if (this.x < 0 || this.y < 0)
break;
if (temp_int1 < 0 || temp_int2 < 0)
{
g.setColor(Color.lightGray);
g.drawLine(this.x,this.y,oldx,oldy);
g.setColor(Color.black);
break;
}
if (oldx > -1)
{
g.setColor(Color.lightGray);
g.drawLine(this.x,this.y,oldx,oldy);
g.setColor(Color.black);
}
if (id > -1)
{
if (start_atom > -1 &&
aMolecule.BondExist(start_atom,id) != -1)
oldx = -1;
else
{
oldx = aMolecule.atoms_x[id];
oldy = aMolecule.atoms_y[id];
g.drawLine(this.x,this.y,
aMolecule.atoms_x[id],
aMolecule.atoms_y[id]);
}
}
else
{
oldx = temp_int1;
oldy = temp_int2;
g.drawLine(this.x,this.y,oldx,oldy);
}
break;
case LASSO: // add the new point to the lasso and draw the
// the latest line
g.setColor(Color.yellow);
g.drawLine(oldx,oldy,temp_int1,temp_int2);
lasso_pol.addPoint(temp_int1,temp_int2);
oldx = temp_int1;
oldy = temp_int2; break;
case ZOOM: // if first lasso drag, find the gravity centre.
// Otherwise scale the whole thing.
if (oldy == -1)
{
oldy = temp_int2;
gravity_x = 0;
gravity_y = 0;
for (int i=0; i= r.width ||
tempo_int2 <= 0 || tempo_int2 >= r.width)
break;
}
if (runner == aMolecule.nbAtoms)
{
for (runner=0; runner -1 && this.y > -1 && // if mouse outside the
(current_selected == SINGLE || // the drawing area erase
current_selected == DOUBLE)) // the line drawn previously
{
Graphics g = aMolecule.getGraphics();
g.setColor(Color.lightGray);
g.drawLine(this.x,this.y,oldx,oldy);
g.setColor(Color.black);
}
return true;
}// end mouseDrag
// Function called by handleEvent, that acts when the mouse is moved
public boolean LocalmouseMove(Event e, int x, int y)
{
Rectangle r = drawing_area.bounds();
if (x>r.x && xr.y && y -1)
aMolecule.redrawAtom(atom_highlighted);
if (id > -1)
aMolecule.redrawAtom(id,Color.blue);
atom_highlighted = id;
id = aMolecule.cursor_on_bond(temp_int1,temp_int2);
if (bond_highlighted != -1)
aMolecule.redrawBond(bond_highlighted);
if (id != -1)
aMolecule.redrawBond(id,Color.blue);
bond_highlighted = id;
}
}
else if (inside_drawing_area) // if outside drawing area for the first
{ // time, redraw molecule
inside_drawing_area = false;
aMolecule.paint(aMolecule.getGraphics());
}
return true;
}// end mouseMove
// Function called by handleEvent, that acts when the mouse is clicked
public boolean LocalmouseDown(Event e, int x, int y)
{
Rectangle r = drawing_area.bounds();
if (x>r.x && xr.y && y -1) // an atom was selected/deselected
{
this.x = aMolecule.atoms_x[id];
this.y = aMolecule.atoms_y[id];
aMolecule.select_deselect_atom(id);
if (aMolecule.atoms_selected[id])
last_selected = id;
else
last_selected = -1;
aMolecule.redrawAtom(id);
}
else
{
last_selected = -1;
id = aMolecule.cursor_on_bond(temp_int1,temp_int2);
if (id > -1) // a bond is selected/deselected
{
aMolecule.select_deselect_bond(id);
aMolecule.redrawBond(id);
}
}
break;
case SINGLE:
case DOUBLE:
case TRIPLE:
if (id > -1) // if an atom is clicked on, store the
{ // coordinates and its id
this.x = aMolecule.atoms_x[id];
this.y = aMolecule.atoms_y[id];
start_atom = id;
}
else
{
this.x = temp_int1;
this.y = temp_int2;
start_atom = -1;
}
oldx = -1;
oldy = -1;
break;
case LASSO: // initialise the lasso polygon
lasso_pol = new Polygon();
lasso_pol.addPoint(temp_int1,temp_int2);
oldx = temp_int1;
oldy = temp_int2; break;
case ZOOM: // initialise the zoom
oldy = -1;
break;
case CYCLO6: // redraw the polygon from a possible existing
case ARO6: // atom
aMolecule.paint(aMolecule.getGraphics());
Polygon pol = new Polygon();
pol.addPoint(temp_int1, temp_int2);
pol.addPoint(temp_int1, temp_int2+59);
pol.addPoint(temp_int1+51, temp_int2+89);
pol.addPoint(temp_int1+103, temp_int2+59);
pol.addPoint(temp_int1+103, temp_int2);
pol.addPoint(temp_int1+51, temp_int2-30);
pol.addPoint(temp_int1, temp_int2);
aMolecule.getGraphics().drawPolygon(pol);
int id2;
for (int i=0; i<6; i++)
{
id2 = aMolecule.cursor_on_atom(
pol.xpoints[i],pol.ypoints[i]);
if (id2 != -1)
aMolecule.redrawAtom(id2,Color.blue);
}
this.x = temp_int1;
this.y = temp_int2;
break;
case CYCLO5: // redraw the polygon from a possible existing
case ARO5: // atom
aMolecule.paint(aMolecule.getGraphics());
Polygon pol5 = new Polygon();
pol5.addPoint(temp_int1, temp_int2);
pol5.addPoint(temp_int1+16, temp_int2+51);
pol5.addPoint(temp_int1+71, temp_int2+51);
pol5.addPoint(temp_int1+88, temp_int2);
pol5.addPoint(temp_int1+44, temp_int2-32);
pol5.addPoint(temp_int1, temp_int2);
aMolecule.getGraphics().drawPolygon(pol5);
int id5;
for (int i=0; i<5; i++)
{
id5 = aMolecule.cursor_on_atom(
pol5.xpoints[i],pol5.ypoints[i]);
if (id5 != -1)
aMolecule.redrawAtom(id5,Color.blue);
}
this.x = temp_int1;
this.y = temp_int2;
break;
default:break;
}// end switch
}
else
{
this.x = -1;
this.y = -1;
}
return true;
}
// Function called by handleEvent, that acts when the mouse button is released
public boolean LocalmouseUp(Event e, int x, int y)
{
Rectangle r = drawing_area.bounds();
int temp_int1 = x - r.x;
int temp_int2 = y - r.y;
if (x>r.x && xr.y && y= r.width ||
polygon_arrayy[i] >= r.height)
must_exit = true;
if (must_exit)
{
this.x = -1;
this.y = -1;
break;
}
int indices[] = new int[6];
for (int i=0; i<6; i++)
{
indices[i] = aMolecule.cursor_on_atom(
polygon_arrayx[i], polygon_arrayy[i]);
if (indices[i] == -1)
indices[i] = aMolecule.AddAtom(
polygon_arrayx[i], polygon_arrayy[i], 6);
}
if (current_selected == ARO6)
{
aMolecule.AddBond(indices[0],indices[1],4);
aMolecule.AddBond(indices[1],indices[2],4);
aMolecule.AddBond(indices[2],indices[3],4);
aMolecule.AddBond(indices[3],indices[4],4);
aMolecule.AddBond(indices[4],indices[5],4);
aMolecule.AddBond(indices[5],indices[0],4);
}
else
{
aMolecule.AddBond(indices[0],indices[1],1);
aMolecule.AddBond(indices[1],indices[2],1);
aMolecule.AddBond(indices[2],indices[3],1);
aMolecule.AddBond(indices[3],indices[4],1);
aMolecule.AddBond(indices[4],indices[5],1);
aMolecule.AddBond(indices[5],indices[0],1);
}
aMolecule.paint(aMolecule.getGraphics());
this.x = -1;
this.y = -1;
break;
case ARO5: // See comments for 6 membered ring, above.
case CYCLO5:
double scale_fac5 = 1.0+(double)(temp_int2 - this.y)/100.0;
int polygon5_arrayx[] = new int[6];
int polygon5_arrayy[] = new int[6];
polygon5_arrayx[0] = 0;
polygon5_arrayy[0] = 0;
polygon5_arrayx[1] = (int)(scale_fac5*16.0);
polygon5_arrayy[1] = (int)(scale_fac5*51.0);
polygon5_arrayx[2] = (int)(scale_fac5*71.0);
polygon5_arrayy[2] = (int)(scale_fac5*51.0);
polygon5_arrayx[3] = (int)(scale_fac5*88.0);
polygon5_arrayy[3] = 0;
polygon5_arrayx[4] = (int)(scale_fac5*44.0);
polygon5_arrayy[4] = (int)(scale_fac5*(-32.0));
polygon5_arrayx[5] = 0;
polygon5_arrayy[5] = 0;
double theta5 = Math.PI * ((double)(temp_int1-this.x)/100.0);
double cost5 = Math.cos(theta5);
double sint5 = Math.sin(theta5);
int tempx5, tempy5;
for (int i=0; i<6; i++)
{
tempx5 = polygon5_arrayx[i];
tempy5 = polygon5_arrayy[i];
polygon5_arrayx[i] = (int)((double)tempx5*cost5) -
(int)((double)tempy5*sint5) + this.x;
polygon5_arrayy[i] = (int)((double)tempx5*sint5) +
(int)((double)tempy5*cost5) + this.y;
}
for (int i=0; i<6; i++)
{
tempx5 = aMolecule.cursor_on_atom(
polygon5_arrayx[i], polygon5_arrayy[i]);
if (tempx5 != -1)
{
polygon5_arrayx[i] = aMolecule.atoms_x[tempx5];
polygon5_arrayy[i] = aMolecule.atoms_y[tempx5];
aMolecule.redrawAtom(tempx5,Color.blue);
}
}
boolean must_exit5 = false;
for (int i=0; i<5; i++)
if (polygon5_arrayx[i] <= 0 ||
polygon5_arrayy[i] <= 0 ||
polygon5_arrayx[i] >= r.width ||
polygon5_arrayy[i] >= r.height)
must_exit5 = true;
if (must_exit5)
{
this.x = -1;
this.y = -1;
break;
}
int indices5[] = new int[5];
for (int i=0; i<5; i++)
{
indices5[i] = aMolecule.cursor_on_atom(
polygon5_arrayx[i], polygon5_arrayy[i]);
if (indices5[i] == -1)
indices5[i] = aMolecule.AddAtom(
polygon5_arrayx[i], polygon5_arrayy[i], 6);
}
if (current_selected == ARO5)
{
aMolecule.AddBond(indices5[0],indices5[1],4);
aMolecule.AddBond(indices5[1],indices5[2],4);
aMolecule.AddBond(indices5[2],indices5[3],4);
aMolecule.AddBond(indices5[3],indices5[4],4);
aMolecule.AddBond(indices5[4],indices5[0],4);
}
else
{
aMolecule.AddBond(indices5[0],indices5[1],1);
aMolecule.AddBond(indices5[1],indices5[2],1);
aMolecule.AddBond(indices5[2],indices5[3],1);
aMolecule.AddBond(indices5[3],indices5[4],1);
aMolecule.AddBond(indices5[4],indices5[0],1);
}
aMolecule.paint(aMolecule.getGraphics());
this.x = -1;
this.y = -1;
break;
default:break;
}// end switch
}
// If mouse button released outside the drawing area,
// cancel ring drawing
else if ((current_selected == ARO6 || current_selected == CYCLO6 ||
current_selected == ARO5 || current_selected == CYCLO5) &&
this.x > -1 && this.y > -1)
{
aMolecule.paint(aMolecule.getGraphics());
this.x = -1;
this.y = -1;
}
return true;
}// End mouseUp
// This function has been ripped off from David Flanagan's
// Java in a Nutshell, O'reilly & associates, Inc.
// It creates the constraints according to the parameters.
public void constrain(Container container, Component component,
int grid_x, int grid_y,
int grid_width, int grid_height,
int fill, int anchor,
double weight_x, double weight_y,
int top, int left, int bottom, int right)
{
GridBagConstraints c = new GridBagConstraints();
c.gridx = grid_x;
c.gridy = grid_y;
c.gridwidth = grid_width;
c.gridheight = grid_height;
c.fill = fill;
c.anchor = anchor;
c.weightx = weight_x;
c.weighty = weight_y;
if (top+bottom+left+right > 0)
c.insets = new Insets(top,left,bottom,right);
((GridBagLayout)container.getLayout()).setConstraints(component,c);
container.add(component);
}
}// End MoleculeEditor_1_0 class
/*
* This is the Molecule_1_0 class. It is used to store and handle all the aspects
* of a molecule creation, modifications, drawing, etc...
* Everything is stored in arrays. The maximum size is 100 atoms and
* 250 bonds. It is never checked if these limits are passed!
*/
class Molecule_1_0 extends Canvas{
private protected static final int MAX_ATOMS = 100;
private protected static final int MAX_BONDS = 250;
protected int atoms_x[];
protected int atoms_y[];
protected int nbAtoms;
protected int nbBonds;
protected int bonds_1[];
protected int bonds_2[];
protected int bonds_type[];
protected int atoms_type[];
protected byte atoms_degree[];
protected boolean atoms_selected[];
protected boolean bonds_selected[];
private protected static final int MAX_RADIUS = 10;
protected Polygon bonds_area[];
protected Font font;
public Molecule_1_0()
{
atoms_x = new int [MAX_ATOMS];
atoms_y = new int [MAX_ATOMS];
atoms_type = new int [MAX_ATOMS];
atoms_degree = new byte [MAX_ATOMS];
bonds_1 = new int [MAX_BONDS];
bonds_2 = new int [MAX_BONDS];
bonds_type = new int [MAX_BONDS];
atoms_selected = new boolean [MAX_ATOMS];
bonds_selected = new boolean [MAX_BONDS];
bonds_area = new Polygon [MAX_BONDS];
nbAtoms = 0;
nbBonds = 0;
font = new Font("Courier",Font.PLAIN,10);
}
public int AddAtom(int a, int b, int at)
{
atoms_x[nbAtoms] = a;
atoms_y[nbAtoms] = b;
atoms_type[nbAtoms] = at;
atoms_degree[nbAtoms] = 0;
atoms_selected[nbAtoms++] = false;
return nbAtoms-1;
}
public boolean AddBond(int id1, int id2, int bt)
{
if (id1 < nbAtoms && id2 < nbAtoms)
{
int id = BondExist(id1, id2);
if (id != -1)
{
if (bonds_type[id] == bt)
return false;
else
{
bonds_type[id] = bt;
return true;
}
}
bonds_1[nbBonds] = id1;
bonds_2[nbBonds] = id2;
bonds_type[nbBonds] = bt;
bonds_area[nbBonds] = find_polygon(id1,id2);
bonds_selected[nbBonds++] = false;
atoms_degree[id1] += 1;
atoms_degree[id2] += 1;
return true;
}
else
{
return false;
}
}
private Polygon find_polygon(int x, int y)
{
Polygon pol = new Polygon();
int x1 = atoms_x[y] - atoms_x[x];
int y1 = atoms_y[y] - atoms_y[x];
int x2 = -1 * y1;
int y2 = x1;
double norm1 = Math.sqrt((double)(x2*x2+y2*y2));
pol.addPoint(atoms_x[x]+(int)(5.0*(double)x2/norm1)+(int)(8.0*(double)x1/norm1),
atoms_y[x]+(int)(5.0*(double)y2/norm1)+(int)(8.0*(double)y1/norm1));
pol.addPoint(atoms_x[x]+(int)(-5.0*(double)x2/norm1)+(int)(8.0*(double)x1/norm1),
atoms_y[x]+(int)(-5.0*(double)y2/norm1)+(int)(8.0*(double)y1/norm1));
pol.addPoint(atoms_x[y]+(int)(-5.0*(double)x2/norm1)+(int)(-8.0*(double)x1/norm1),
atoms_y[y]+(int)(-5.0*(double)y2/norm1)+(int)(-8.0*(double)y1/norm1));
pol.addPoint(atoms_x[y]+(int)(5.0*(double)x2/norm1)+(int)(-8.0*(double)x1/norm1),
atoms_y[y]+(int)(5.0*(double)y2/norm1)+(int)(-8.0*(double)y1/norm1));
return pol;
}
public boolean RemoveBond(int id1, int id2)
{
if (id1 < nbAtoms && id2 < nbAtoms)
{
for (int i=0; i=0; i--)
if (atoms_selected[i])
RemoveAtom(i);
for (int i=nbBonds-1; i>=0; i--)
if (bonds_selected[i])
RemoveBond(i);
paint(this.getGraphics());
}
int BondExist(int id1, int id2)
{
if (id1 != id2 &&
id1 < nbAtoms && id2 < nbAtoms)
{
for (int i=0; i 122 || (int)at.charAt(1) < 65)
return char2type(at.charAt(0));
else if (at.length() == 2 ||
(int)at.charAt(2) > 122 || (int)at.charAt(2) < 65)
return char2type(at.charAt(0), at.charAt(1));
else
return 200;
}
public int cursor_on_atom(int x, int y)
{
for (int i=0; i -1)
for (int i=0; i= nbBonds)
return;
Graphics g = this.getGraphics();
g.setColor(c);
switch (bonds_type[id])
{
case 3:
x1 = atoms_x[bonds_2[id]] - atoms_x[bonds_1[id]];
y1 = atoms_y[bonds_2[id]] - atoms_y[bonds_1[id]];
x2 = -1 * y1;
y2 = x1;
norm1 = Math.sqrt((double)(x2*x2+y2*y2));
g.drawLine(
atoms_x[bonds_1[id]]+(int)(5.0*(double)x2/norm1),
atoms_y[bonds_1[id]]+(int)(5.0*(double)y2/norm1),
atoms_x[bonds_2[id]]+(int)(5.0*(double)x2/norm1),
atoms_y[bonds_2[id]]+(int)(5.0*(double)y2/norm1));
g.drawLine(
atoms_x[bonds_1[id]]+(int)(-5.0*(double)x2/norm1),
atoms_y[bonds_1[id]]+(int)(-5.0*(double)y2/norm1),
atoms_x[bonds_2[id]]+(int)(-5.0*(double)x2/norm1),
atoms_y[bonds_2[id]]+(int)(-5.0*(double)y2/norm1));
g.drawLine(atoms_x[bonds_1[id]], atoms_y[bonds_1[id]],
atoms_x[bonds_2[id]], atoms_y[bonds_2[id]]);
break;
case 2:
x1 = atoms_x[bonds_2[id]] - atoms_x[bonds_1[id]];
y1 = atoms_y[bonds_2[id]] - atoms_y[bonds_1[id]];
x2 = -1 * y1;
y2 = x1;
norm1 = Math.sqrt((double)(x2*x2+y2*y2));
g.drawLine(
atoms_x[bonds_1[id]]+(int)(4.0*(double)x2/norm1),
atoms_y[bonds_1[id]]+(int)(4.0*(double)y2/norm1),
atoms_x[bonds_2[id]]+(int)(4.0*(double)x2/norm1),
atoms_y[bonds_2[id]]+(int)(4.0*(double)y2/norm1));
g.drawLine(
atoms_x[bonds_1[id]]+(int)(-4.0*(double)x2/norm1),
atoms_y[bonds_1[id]]+(int)(-4.0*(double)y2/norm1),
atoms_x[bonds_2[id]]+(int)(-4.0*(double)x2/norm1),
atoms_y[bonds_2[id]]+(int)(-4.0*(double)y2/norm1));
break;
case 4:
x1 = atoms_x[bonds_2[id]] - atoms_x[bonds_1[id]];
y1 = atoms_y[bonds_2[id]] - atoms_y[bonds_1[id]];
norm1 = Math.sqrt((double)(x1*x1+y1*y1));
g.drawLine(atoms_x[bonds_1[id]], atoms_y[bonds_1[id]],
atoms_x[bonds_1[id]] + (int)((double)x1/5.0),
atoms_y[bonds_1[id]] + (int)((double)y1/5.0));
g.drawLine(
atoms_x[bonds_1[id]] + (int)(2.0*(double)x1/5.0),
atoms_y[bonds_1[id]] + (int)(2.0*(double)y1/5.0),
atoms_x[bonds_1[id]] + (int)(3.0*(double)x1/5.0),
atoms_y[bonds_1[id]] + (int)(3.0*(double)y1/5.0));
g.drawLine(
atoms_x[bonds_1[id]] + (int)(4.0*(double)x1/5.0),
atoms_y[bonds_1[id]] + (int)(4.0*(double)y1/5.0),
atoms_x[bonds_2[id]], atoms_y[bonds_2[id]]);
break;
case 1:
default:
g.drawLine(atoms_x[bonds_1[id]], atoms_y[bonds_1[id]],
atoms_x[bonds_2[id]], atoms_y[bonds_2[id]]);
break;
}
}
public void redrawBond(int id, Color c)
{
if (id < 0 || id >= nbBonds)
return;
simpleRedrawBond(id, c);
if (atoms_selected[bonds_1[id]])
redrawAtom(bonds_1[id],Color.red);
else
redrawAtom(bonds_1[id],Color.black);
if (atoms_selected[bonds_2[id]])
redrawAtom(bonds_2[id],Color.red);
else
redrawAtom(bonds_2[id],Color.black);
}// end redraw_atom
public void redrawBond(int id)
{
if (id > -1 && id < nbBonds)
{
redrawAtom(bonds_1[id]);
redrawAtom(bonds_2[id]);
}
}
public void redrawAtom(int id, Color c)
{
Graphics g = this.getGraphics();
g.setColor(Color.lightGray);
g.fillRect(atoms_x[id]-3,atoms_y[id]-7,10,10);
g.setColor(c);
g.drawString(at2string(atoms_type[id]),
atoms_x[id]-2, atoms_y[id]+2);
}// end redraw_atom
public void redrawAtom(int id)
{
Graphics g = this.getGraphics();
g.setColor(Color.lightGray);
if (atoms_type[id] == 6)
g.fillRect(atoms_x[id]-3,atoms_y[id]-7,10,10);
g.setColor(Color.black);
if (atoms_degree[id] == 0)
{
if (atoms_selected[id])
redrawAtom(id,Color.red);
else
redrawAtom(id,Color.black);
}
else
{
for (int i=0; i maxx)
maxx = xpoints[i];
if (xpoints[i] < minx)
minx = xpoints[i];
if (ypoints[i] > maxy)
maxy = ypoints[i];
if (ypoints[i] < miny)
miny = ypoints[i];
}
width = maxx;
height = maxy;
if (width < 20)
width = 20;
if (height < 20)
height = 20;
}
}
public ImageLinesButton_1_0 (String name)
{
npoints=0;
width = 20;
height = 20;
this.name = new String(name);
}
public boolean handleEvent(Event e)
{
Graphics g = this.getGraphics();
switch (e.id)
{
case Event.MOUSE_DOWN:
reverse_paint(g);
return false;
case Event.MOUSE_UP:
this.paint(g);
MoleculeEditor_1_0.buttonMouseUp(new String(this.name));
return false;
default: break;
}
return true;
}
public Dimension preferredSize()
{
return new Dimension(width+2*MARGIN,height+2*MARGIN);
}
public Dimension minimumSize()
{
return new Dimension(width+2*MARGIN,height+2*MARGIN);
}
public void reverse_paint(Graphics g)
{
g.setColor(Color.black);
g.fillRoundRect(0,0,width+2*MARGIN,height+2*MARGIN,10,10);
g.setColor(Color.white);
g.drawRoundRect(0,0,width+2*MARGIN-1,height+2*MARGIN-1,10,10);
for (int i=0; i
|