void processMousePressed(MouseEvent e) {

		super.processMousePressed(e);

		if (energizerButtonPressed)
			return;
		if (model.getJob() != null && !model.getJob().isStopped())
			return;

		int clickCount = e.getClickCount();
		if (clickCount >= 2) {
			if (actionID != HEAT_ID && actionID != COOL_ID && actionID != IDMP_ID && actionID != DDMP_ID && actionID != IRES_ID && actionID != DRES_ID && actionID != CPOS_ID && actionID != CNEG_ID && actionID != AACD_ID && actionID != SACD_ID && actionID != ANTD_ID && actionID != SNTD_ID && actionID != SCUR_ID && actionID != RCUR_ID && actionID != SCIR_ID && actionID != RCIR_ID && actionID != SREC_ID && actionID != RREC_ID && actionID != SFRE_ID) {
				resetUndoManager();
				setAction(SELE_ID);
			}
		}

		final int x = e.getX();
		final int y = e.getY();

		if (callOutMousePressed(x, y))
			return;
		if (handleMousePressed(x, y))
			return;

		switch (actionID) {

		case SELE_ID:

			/* FIXME: the special popup menus that do not use right-click. This will be removed in 2010. */
			if (e.isAltDown()) {
				final Atom at = whichAtom(x, y);
				if (at != null) {
					if (at.isAminoAcid()) {
						at.setSelected(true);
						if (acidPopupMenu == null)
							acidPopupMenu = new AminoAcidPopupMenu();
						acidPopupMenu.setAtom(at);
						acidPopupMenu.show(this, x, y);
					} else if (at.isNucleotide() && at.getID() != Element.ID_SP) {
						at.setSelected(true);
						if (nucleotidePopupMenu == null)
							nucleotidePopupMenu = new NucleotidePopupMenu();
						nucleotidePopupMenu.setAtom(at);
						nucleotidePopupMenu.show(this, x, y);
					}
				}
				return;
			}

			if (selectedComponent instanceof RectangularObstacle) {
				obsRectSelected = -1;
				switch (((RectangularObstacle) selectedComponent).getPositionCode(x, y)) {
				case RectangularObstacle.NW:
					obsRectSelected = RectangularObstacle.NW;
					break;
				case RectangularObstacle.NORTH:
					obsRectSelected = RectangularObstacle.NORTH;
					break;
				case RectangularObstacle.NE:
					obsRectSelected = RectangularObstacle.NE;
					break;
				case RectangularObstacle.EAST:
					obsRectSelected = RectangularObstacle.EAST;
					break;
				case RectangularObstacle.SE:
					obsRectSelected = RectangularObstacle.SE;
					break;
				case RectangularObstacle.SOUTH:
					obsRectSelected = RectangularObstacle.SOUTH;
					break;
				case RectangularObstacle.SW:
					obsRectSelected = RectangularObstacle.SW;
					break;
				case RectangularObstacle.WEST:
					obsRectSelected = RectangularObstacle.WEST;
					break;
				case RectangularObstacle.INSIDE:
					obsRectSelected = RectangularObstacle.INSIDE;
					break;
				}
				if (obsRectSelected > RectangularObstacle.INSIDE) {
					((RectangularObstacle) selectedComponent).storeCurrentState();
				} else if (obsRectSelected == -1) {
					selectedComponent.setSelected(false);
					selectedComponent = null;
				}
			} else if (selectedComponent != null) {
				selectedComponent.setSelected(false);
				selectedComponent = null;
			}
			ModelComponent mc = getSelectedComponent(e.getModifiersEx(), x, y);
			if (mc != null) {
				mc.storeCurrentState();
				if (clickCount >= 2) {
					if (isPropertyDialogEnabled() || mc instanceof TextBoxComponent)
						DialogFactory.showDialog(mc);
				}
			}
			repaint();
			break;

		case RCUR_ID:
		case SCUR_ID:
		case SFRE_ID:
			if (clickCount == 1) {
				if (smartPoly == null) {
					smartPoly = new Polygon();
					smartPoly.addPoint(x, y);
				} else {
					addPointToPolygon(smartPoly, x, y);
				}
			}
			break;

		case SCIR_ID:
		case RCIR_ID:
			if (clickCount == 1) {
				if (!(smartShape instanceof Ellipse)) {
					smartShape = new Ellipse(x, y, 10, 10);
				}
			}
			break;

		case SREC_ID:
		case RREC_ID:
			if (clickCount == 1) {
				if (!(smartShape instanceof RoundRectangle)) {
					smartShape = new RoundRectangle(x, y, 10, 10, 20, 20);
				}
			}
			break;

		case COUN_ID:
			showActionTip("Drag the mouse to specify an area within which objects will be counted", x + 10, y + 10);
			if (clickCount == 1)
				selectedArea.setLocation(x, y);
			break;

		case MARK_ID:
			showActionTip("Drag the mouse to specify an area within which objects will be marked", x + 10, y + 10);
			if (clickCount == 1)
				selectedArea.setLocation(x, y);
			break;

		case LINE_ID:
			setSelectedComponent(null);
			break;

		case RECT_ID:
			setSelectedComponent(null);
			showActionTip("Drag the mouse to draw a rectangle", x + 10, y + 10);
			if (clickCount == 1) {
				selectedArea.setLocation(x, y);
				anchorPoint.setLocation(x, y);
			}
			break;

		case TRIA_ID:
			setSelectedComponent(null);
			showActionTip("Drag the mouse to draw a triangle", x + 10, y + 10);
			if (clickCount == 1) {
				selectedArea.setLocation(x, y);
				anchorPoint.setLocation(x, y);
			}
			break;

		case ELLI_ID:
			setSelectedComponent(null);
			showActionTip("Drag the mouse to draw an ellipse", x + 10, y + 10);
			if (clickCount == 1) {
				selectedArea.setLocation(x, y);
				anchorPoint.setLocation(x, y);
			}
			break;

		case FILA_ID:
		case FILB_ID:
		case FILC_ID:
		case FILD_ID:
			showActionTip("Drag the mouse to specify an area which will be filled with atoms", x + 10, y + 10);
			if (clickCount == 1)
				selectedArea.setLocation(x, y);
			break;

		case DELE_ID:
			showActionTip("Drag the mouse to specify an area within which objects will be removed", x + 10, y + 10);
			if (clickCount == 1)
				selectedArea.setLocation(x, y);
			break;

		case ADOB_ID:
			if (clickCount == 1)
				selectedArea.setLocation(x, y);
			showActionTip("Drag your mouse to specify size", x + 10, y + 10);
			break;

		case WHAT_ID:
			mc = getSelectedComponent(e.getModifiersEx(), x, y);
			String str = null;
			if (mc instanceof Obstacle) {
				str = mc.toString();
			} else if (mc instanceof Molecule) {
				if (mc instanceof MolecularObject) {
					if (mc instanceof CurvedSurface)
						str = "Curved Surface #" + molecules.indexOf(mc) + ":" + mc;
					else if (mc instanceof CurvedRibbon)
						str = "Curved Ribbon #" + molecules.indexOf(mc) + ":" + mc;
				} else {
					str = "Molecule #" + molecules.indexOf(mc) + ": " + mc;
				}
			} else if (mc instanceof Atom) {
				str = "Atom #" + mc;
			} else if (mc instanceof RadialBond) {
				str = "#" + bonds.indexOf(mc) + " " + mc.toString();
			} else if (mc instanceof AngularBond) {
				str = "#" + bends.indexOf(mc) + " " + mc.toString();
			} else if (mc instanceof ImageComponent) {
				str = "Image #" + getLayeredComponentIndex((ImageComponent) mc) + ": " + FileUtilities.getFileName(mc.toString());
			} else if (mc instanceof TextBoxComponent) {
				str = "Text box #" + getLayeredComponentIndex((TextBoxComponent) mc);
			} else if (mc instanceof LineComponent) {
				str = "Line #" + getLayeredComponentIndex((LineComponent) mc);
			} else if (mc instanceof RectangleComponent) {
				str = "Rectangle #" + getLayeredComponentIndex((RectangleComponent) mc);
			} else if (mc instanceof TriangleComponent) {
				str = "Triangle #" + getLayeredComponentIndex((TriangleComponent) mc);
			} else if (mc instanceof EllipseComponent) {
				str = "Ellipse #" + getLayeredComponentIndex((EllipseComponent) mc);
			}
			if (str != null) {
				str += " @ (" + ViewAttribute.ANGSTROM_FORMAT.format(x * 0.1) + ", " + ViewAttribute.ANGSTROM_FORMAT.format(y * 0.1) + ")";
			} else {
				str = "(" + ViewAttribute.ANGSTROM_FORMAT.format(x * 0.1) + ", " + ViewAttribute.ANGSTROM_FORMAT.format(y * 0.1) + ")";
			}
			showTip(str, x + 10, y + 10, -1);
			repaint();
			break;

		case ROTA_ID:
			if (selectedComponent instanceof Rotatable) {
				Rotatable r = (Rotatable) selectedComponent;
				rotationHandle = r.getRotationHandle(x, y);
				if (rotationHandle != -1) {
					r.setSelectedToRotate(true);
					setCursor(rotateCursor3);
					selectedComponent.storeCurrentState();
				} else {
					r.setSelectedToRotate(false);
					setCursor(rotateCursor2);
					selectRotatable(x, y);
				}
			} else {
				selectRotatable(x, y);
			}
			repaint();
			break;

		case MEAS_ID:
			if (clickCount == 1) {
				if (!readyToAdjustDistanceVector) {
					Atom at = whichAtom(x, y);
					if (at != null) {
						at.setSelected(true);
						if (e.isShiftDown()) {
							at.addMeasurement(new Point(2 * at.getRx() < getWidth() ? (int) (at.getRx() + 20) : (int) (at.getRx() - 20), (int) at.getRy()));
						} else {
							showActionTip(at.getNumberOfMeasurements() <= 0 ? "Hold down SHIFT and click to add a measurement." : "<html>Drag the green hotspot at the tip to measure, or<br>hold down SHIFT and click to add one more measurement.</html>", x + 10, y + 10);
						}
					}
				} else {
					showActionTip("<html>To remove this measurement, drag the<br>green hotspot out of this window.</html>", x + 10, y + 10);
				}
			}
			break;

		case VELO_ID:
			if (clickCount == 1) {
				if (!readyToAdjustVelocityVector) {
					Atom at = whichAtom(x, y);
					if (at != null) {
						showActionTip("Drag the red hotspot at the tip of the velocity vector", x + 10, y + 10);
						selectVelocity(at);
						at.setSelected(true);
						repaint();
					}
				}
			}
			break;

		case TRAJ_ID:
			Atom at = whichAtom(x, y);
			if (at != null) {
				at.setSelected(true);
				at.setShowRTraj(!at.getShowRTraj());
				if (at.getShowRTraj()) {
					showActionTip("Click the atom to hide its trajectory", x + 20, y + 20);
				} else {
					showActionTip("Click the atom to show its trajectory", x + 20, y + 20);
				}
				repaint();
			}
			break;

		case RAVE_ID:
			at = whichAtom(x, y);
			if (at != null) {
				at.setSelected(true);
				at.setShowRMean(!at.getShowRMean());
				if (at.getShowRMean()) {
					showActionTip("Click the atom to hide its current average position", x + 20, y + 20);
				} else {
					showActionTip("Click the atom to show its current average position", x + 20, y + 20);
				}
				repaint();
			}
			break;

		case DGBD_ID:
			bondAtom1 = whichAtom(x, y);
			if (bondAtom1 == null) {
				RadialBond rb = whichBond(x, y);
				if (rb != null) {
					byte style = rb.getBondStyle();
					switch (style) {
					case RadialBond.DOUBLE_BOND_STYLE:
						style = RadialBond.TRIPLE_BOND_STYLE;
						break;
					case RadialBond.TRIPLE_BOND_STYLE:
						style = RadialBond.STANDARD_STICK_STYLE;
						break;
					default:
						style = RadialBond.DOUBLE_BOND_STYLE;
					}
					rb.setBondStyle(style);
				}
			}
			break;

		case BBON_ID:
			if (e.isAltDown()) {
				if (bondBeingMade)
					createABond(x, y);
			} else {
				at = whichAtom(x, y);
				if (at != null) {
					at.setSelected(true);
					bondBeingMade = true;
					showActionTip("Hold down the ALT key and click another atom", x + 10, y + 10);
					repaint();
				} else {
					bondBeingMade = false;
				}
			}
			break;

		case BBEN_ID:
			if (e.isAltDown()) {
				if (bendBeingMade)
					createABend(x, y);
			} else {
				if (bonds.size() >= 2) {
					RadialBond rBond = whichBond(x, y);
					if (rBond != null) {
						rBond.setSelected(true);
						bendBeingMade = true;
						showActionTip("Hold down the ALT key and click another radial bond", x + 10, y + 10);
						repaint();
					} else {
						bendBeingMade = false;
					}
				}
			}
			break;

		case DUPL_ID:
			if (!ModelerUtilities.isRightClick(e)) {
				mc = getSelectedComponent(e.getModifiersEx(), x, y);
				duplicate(mc, x, y);
				repaint();
			}
			break;

		case ADDA_ID:
			addAtomIndicator.x = addAtomIndicator.y = -1;
			if (clickCount == 1)
				insertAnAtom(x, y, Element.ID_NT);
			break;

		case ADDB_ID:
			addAtomIndicator.x = addAtomIndicator.y = -1;
			if (clickCount == 1)
				insertAnAtom(x, y, Element.ID_PL);
			break;

		case ADDC_ID:
			addAtomIndicator.x = addAtomIndicator.y = -1;
			if (clickCount == 1)
				insertAnAtom(x, y, Element.ID_WS);
			break;

		case ADDD_ID:
			addAtomIndicator.x = addAtomIndicator.y = -1;
			if (clickCount == 1)
				insertAnAtom(x, y, Element.ID_CK);
			break;

		case BENZ_ID:
			if (addObjectIndicator instanceof AddObjectIndicator.AddBenzeneMoleculeIndicator)
				addObjectIndicator.setPainted(false);
			if (clickCount == 1)
				insertAMolecule(x, y, new Benzene());
			break;

		case WATE_ID:
			if (addObjectIndicator instanceof AddObjectIndicator.AddTriatomicMoleculeIndicator)
				addObjectIndicator.setPainted(false);
			if (clickCount == 1)
				insertAMolecule(x, y, new TriatomicMolecule(TriatomicConfigure.typeOfA, TriatomicConfigure.typeOfB, TriatomicConfigure.typeOfC, TriatomicConfigure.d12, TriatomicConfigure.s12, TriatomicConfigure.d23, TriatomicConfigure.s23, TriatomicConfigure.angle, TriatomicConfigure.strength));
			break;

		case ADDI_ID:
			if (addObjectIndicator instanceof AddObjectIndicator.AddDiatomicMoleculeIndicator)
				addObjectIndicator.setPainted(false);
			if (clickCount == 1)
				insertAMolecule(x, y, new DiatomicMolecule(DiatomicConfigure.typeOfA, DiatomicConfigure.typeOfB, DiatomicConfigure.distance, DiatomicConfigure.strength));
			break;

		case ADCH_ID:
			if (addObjectIndicator instanceof AddObjectIndicator.AddChainMoleculeIndicator)
				addObjectIndicator.setPainted(false);
			if (clickCount == 1 && nAtom < atom.length - ChainConfigure.MAXIMUM)
				insertAMolecule(x, y, new ChainMolecule(ChainConfigure.typeOfAtom, ChainConfigure.number, ChainConfigure.growMode, ChainConfigure.distance, ChainConfigure.angle));
			break;

		case IRES_ID:
			at = whichAtom(x, y);
			if (at != null) {
				at.setSelected(true);
				if (at.getRestraint() == null) {
					at.setRestraint(new PointRestraint(10, at.getRx(), at.getRy()));
				} else {
					at.getRestraint().changeK(10);
				}
				repaint();
				model.notifyChange();
			}
			break;

		case DRES_ID:
			at = whichAtom(x, y);
			if (at != null && at.getRestraint() != null) {
				at.setSelected(true);
				if (at.getRestraint().getK() >= 10) {
					at.getRestraint().changeK(-10);
					if (at.getRestraint().getK() <= ZERO)
						at.setRestraint(null);
					repaint();
					model.notifyChange();
				}
			}
			break;

		case IDMP_ID:
			at = whichAtom(x, y);
			if (at != null) {
				at.setSelected(true);
				if (at.addFriction(0.5f)) {
					repaint();
					model.notifyChange();
				}
			}
			break;

		case DDMP_ID:
			at = whichAtom(x, y);
			if (at != null) {
				at.setSelected(true);
				if (at.addFriction(-0.5f)) {
					repaint();
					model.notifyChange();
				}
			}
			break;

		case CPOS_ID:
			at = whichAtom(x, y);
			if (at != null) {
				at.setSelected(true);
				if (at.addCharge(e.isShiftDown() ? -chargeIncrement : chargeIncrement)) {
					repaint();
					model.notifyChange();
				}
			}
			break;

		case CNEG_ID:
			at = whichAtom(x, y);
			if (at != null) {
				at.setSelected(true);
				if (at.addCharge(e.isShiftDown() ? chargeIncrement : -chargeIncrement)) {
					repaint();
					model.notifyChange();
				}
			}
			break;

		case HEAT_ID:
		case COOL_ID:
			pointHeater.setLocation(x, y);
			pointHeater.equiPartitionEnergy(model);
			repaint();
			break;

		case SBOU_ID:
			if (boundary.getType() != RectangularBoundary.DBC_ID) {
				if (!model.isEmpty() && boundary.getHandle() > 0)
					model.getBoundsOfObjects();
			}
			break;

		case AACD_ID:
			mc = getSelectedComponent(e.getModifiersEx(), x, y);
			if (mc instanceof Polypeptide) {
				Atom[] a = ((Polypeptide) mc).getTermini();
				double d1 = (a[0].getRx() - x) * (a[0].getRx() - x) + (a[0].getRy() - y) * (a[0].getRy() - y);
				double d2 = (a[1].getRx() - x) * (a[1].getRx() - x) + (a[1].getRy() - y) * (a[1].getRy() - y);
				((Polypeptide) mc).attachRandomAminoAcidToTerminus(d1 < d2 ? a[0] : a[1]);
				Atom a2 = atom[model.getNumberOfParticles() - 1];
				if (!doNotFireUndoEvent) {
					molecules.getMolecule(model.getAtom(model.getNumberOfAtoms() - 1)).setSelected(true);
					model.getUndoManager().undoableEditHappened(new UndoableEditEvent(model, new UndoableInsertion(AACD_ID, a2.getRx(), a2.getRy())));
					updateUndoUIComponents();
				}
			} else {
				if (mc == null) {
					insertAnAtom(x, y, Math.round(Element.ID_ALA + (float) Math.random() * 19));
				} else if (mc instanceof Atom) {
					((Atom) mc).attachRandomAminoAcid();
					molecules.getMolecule(model.getAtom(model.getNumberOfAtoms() - 1)).setSelected(true);
				}
			}
			break;

		case SACD_ID:
			mc = getSelectedComponent(e.getModifiersEx(), x, y);
			if (mc instanceof Polypeptide) {
				Atom[] a = ((Polypeptide) mc).getTermini();
				double d1 = (a[0].getRx() - x) * (a[0].getRx() - x) + (a[0].getRy() - y) * (a[0].getRy() - y);
				double d2 = (a[1].getRx() - x) * (a[1].getRx() - x) + (a[1].getRy() - y) * (a[1].getRy() - y);
				setSelectedComponent(d1 < d2 ? a[0] : a[1]);
				removeSelectedComponent();
				repaint();
			}
			break;

		case ANTD_ID:
			mc = getSelectedComponent(e.getModifiersEx(), x, y);
			if (mc instanceof DNAStrand) {
				DNAStrand mol = (DNAStrand) mc;
				Atom a1 = null, a2 = null;
				for (Iterator it = mol.iterator(); it.hasNext();) {
					at = (Atom) it.next();
					if (at.getID() == Element.ID_SP) {
						if (bonds.getBondedPartnerCount(at) == 2) {
							if (a1 == null) {
								a1 = at;
							} else {
								a2 = at;
								break;
							}
						}
					}
				}
				if (a1 == null && a2 == null) {
					mol.attachRandomNucleotide(null);
				} else if (a1 != null && a2 != null) {
					boolean b = (a1.getRx() - x) * (a1.getRx() - x) + (a1.getRy() - y) * (a1.getRy() - y) > (a2.getRx() - x) * (a2.getRx() - x) + (a2.getRy() - y) * (a2.getRy() - y);
					mol.attachRandomNucleotide(b ? a2 : a1);
				}
				// WARNING!!! After calling attachRandomNucleotide, molecules will be re-generated.
				// As a result, the mol reference is not valid any more.
				if (!doNotFireUndoEvent) {
					molecules.getMolecule(model.getAtom(model.getNumberOfAtoms() - 1)).setSelected(true);
					model.getUndoManager().undoableEditHappened(new UndoableEditEvent(model, new UndoableInsertion(ANTD_ID)));
					updateUndoUIComponents();
				}
			} else {
				if (mc == null) {
					int id1 = Element.ID_SP;
					int id2 = Math.round(Element.ID_A + (float) Math.random() * 3);
					int d = (int) ((model.getElement(id1).getSigma() + model.getElement(id2).getSigma()) * 0.6);
					boolean b = insertAnAtom(x, y, id1);
					if (b) {
						b = insertAnAtom(x, y + d, id2);
						int noa = model.getNumberOfAtoms();
						if (b) {
							(model).getBonds().add(new RadialBond.Builder(model.getAtom(noa - 2), model.getAtom(noa - 1)).bondLength(d).build());
							MoleculeCollection.sort(model);
							if (!doNotFireUndoEvent) {
								molecules.getMolecule(model.getAtom(noa - 1)).setSelected(true);
								model.getUndoManager().undoableEditHappened(new UndoableEditEvent(model, new UndoableInsertion(ANTD_ID)));
								updateUndoUIComponents();
							}
						} else {
							model.getAtom(noa - 1).setSelected(true);
							removeSelectedComponent();
						}
					}
				}
			}
			break;

		case SNTD_ID:
			mc = getSelectedComponent(e.getModifiersEx(), x, y);
			if (mc instanceof DNAStrand) {
				DNAStrand mol = (DNAStrand) mc;
				Atom a1 = null, a2 = null;
				for (Iterator it = mol.iterator(); it.hasNext();) {
					at = (Atom) it.next();
					if (at.getID() == Element.ID_SP) {
						if (bonds.getBondedPartnerCount(at) == 2) {
							if (a1 == null) {
								a1 = at;
							} else {
								a2 = at;
								break;
							}
						}
					}
				}
				if (a1 != null && a2 != null) {
					int idna = molecules.indexOf(mol);
					List<Integer> list = new ArrayList<Integer>();
					if ((a1.getRx() - x) * (a1.getRx() - x) + (a1.getRy() - y) * (a1.getRy() - y) > (a2.getRx() - x) * (a2.getRx() - x) + (a2.getRy() - y) * (a2.getRy() - y)) {
						list.add(a2.getIndex());
						Atom[] ats = model.getBonds().getBondedPartners(a2, false);
						if (ats != null) {
							for (Atom i : ats) {
								if (i.getID() != Element.ID_SP)
									list.add(i.getIndex());
							}
						}
					} else {
						list.add(a1.getIndex());
						Atom[] ats = model.getBonds().getBondedPartners(a1, false);
						if (ats != null) {
							for (Atom i : ats) {
								if (i.getID() != Element.ID_SP)
									list.add(i.getIndex());
							}
						}
					}
					removeMarkedAtoms(list);
					setSelectedComponent(null);
					repaint();
					model.notifyChange();
					if (!doNotFireUndoEvent) {
						molecules.get(idna).setSelected(true);
						model.getUndoManager().undoableEditHappened(new UndoableEditEvent(model, new UndoableDeletion(SNTD_ID)));
						updateUndoUIComponents();
					}
				}
			}
			break;

		}

		e.consume();

	}