protected void processMouseDragged(MouseEvent e) {
		super.processMouseDragged(e);
		model.runMouseScript(MouseEvent.MOUSE_DRAGGED, e.getX(), e.getY());
		int x = e.getX();
		int y = e.getY();
		switch (actionID) {
		case DEFA_ID:
			model.setRotationMatrix(viewer.getRotationMatrix());
			break;
		case PANN_ID:
			int dx = x - dragPoint.x;
			int dy = y - dragPoint.y;
			dragPoint.setLocation(x, y);
			viewer.translateBy(dx, dy);
			break;
		case ROTA_ID:
			if (selectedComponent != null) {
				BitSet bs = getSelectionSet();
				if (bs.cardinality() > 0) {
					dx = x - dragPoint.x;
					dy = y - dragPoint.y;
					dragPoint.setLocation(x, y);
					model.rotateSelectedAtomsXYBy(viewer.getRotationMatrix(), bs, dx, dy);
					if (shouldRejectMoving(bs)) { // roll back rotation
						model.rotateSelectedAtomsXYBy(viewer.getRotationMatrix(), bs, -dx, -dy);
					}
					else {
						refresh();
						model.notifyChange();
					}
				}
			}
			break;
		case TRAN_ID:
			if (selectedComponent != null) {
				BitSet bs = getSelectionSet();
				if (bs.cardinality() > 0) {
					dx = x - dragPoint.x;
					dy = y - dragPoint.y;
					dragPoint.setLocation(x, y);
					model.translateSelectedAtomsXYBy(viewer.getRotationMatrix(), bs, dx, dy);
					if (shouldRejectMoving(bs)) { // roll back translation
						model.translateSelectedAtomsXYBy(viewer.getRotationMatrix(), bs, -dx, -dy);
					}
					else {
						refresh();
						model.notifyChange();
					}
				}
			}
			break;
		case DUPL_ID:
			if (selectedComponent != null) {
				BitSet bs = getSelectionSet();
				if (bs.cardinality() > 0 && selectedComponent instanceof Molecule) {
					if (newMolecule == null) {
						duplicateMolecule();
					}
					dx = x - dragPoint.x;
					dy = y - dragPoint.y;
					dragPoint.setLocation(x, y);
					model.translateSelectedAtomsXYBy(viewer.getRotationMatrix(), bs, dx, dy);
					model.notifyChange();
					refresh();
				}
			}
			break;
		case SLRT_ID:
		case SLOV_ID:
		case DELR_ID:
		case DELC_ID:
		case FIXR_ID:
		case FIXC_ID:
		case XIFR_ID:
		case XIFC_ID:
		case TSLC_ID:
		case CLST_ID:
		case HIDE_ID:
		case EDIH_ID:
			dragRect(x, y);
			break;
		case XADD_ID:
			if (selectedComponent instanceof Atom) {
				dragAtom((Atom) selectedComponent, 'x', x - clickPoint.x, y - clickPoint.y, false);
			}
			break;
		case YADD_ID:
			if (selectedComponent instanceof Atom) {
				dragAtom((Atom) selectedComponent, 'y', x - clickPoint.x, y - clickPoint.y, false);
			}
			break;
		case ZADD_ID:
			if (selectedComponent instanceof Atom) {
				dragAtom((Atom) selectedComponent, 'z', x - clickPoint.x, y - clickPoint.y, false);
			}
			break;
		case XREC_ID:
			if (shapeWithinBounds) {
				Point3f p = viewer.findPointOnDropPlane('x', x, y);
				p.y = Math.abs(2 * p.y) < model.getWidth() ? p.y : model.getWidth() * (p.y < 0 ? -0.5f : 0.5f);
				p.z = Math.abs(2 * p.z) < model.getHeight() ? p.z : model.getHeight() * (p.z < 0 ? -0.5f : 0.5f);
				dragPoint3D.set(p);
				viewer.setRectangle('x', clickPoint3D, dragPoint3D);
			}
			break;
		case YREC_ID:
			if (shapeWithinBounds) {
				Point3f p = viewer.findPointOnDropPlane('y', x, y);
				p.x = Math.abs(2 * p.x) < model.getLength() ? p.x : model.getLength() * (p.x < 0 ? -0.5f : 0.5f);
				p.z = Math.abs(2 * p.z) < model.getHeight() ? p.z : model.getHeight() * (p.z < 0 ? -0.5f : 0.5f);
				dragPoint3D.set(p);
				viewer.setRectangle('y', clickPoint3D, dragPoint3D);
			}
			break;
		case ZREC_ID:
			if (shapeWithinBounds) {
				Point3f p = viewer.findPointOnDropPlane('z', x, y);
				p.x = Math.abs(2 * p.x) < model.getLength() ? p.x : model.getLength() * (p.x < 0 ? -0.5f : 0.5f);
				p.y = Math.abs(2 * p.y) < model.getWidth() ? p.y : model.getWidth() * (p.y < 0 ? -0.5f : 0.5f);
				dragPoint3D.set(p);
				viewer.setRectangle('z', clickPoint3D, dragPoint3D);
			}
			break;
		case XOVL_ID:
			if (shapeWithinBounds) {
				Point3f p = viewer.findPointOnDropPlane('x', x, y);
				p.y = Math.abs(2 * p.y) < model.getWidth() ? p.y : model.getWidth() * (p.y < 0 ? -0.5f : 0.5f);
				p.z = Math.abs(2 * p.z) < model.getHeight() ? p.z : model.getHeight() * (p.z < 0 ? -0.5f : 0.5f);
				dragPoint3D.set(p);
				viewer.setEllipse('x', clickPoint3D, dragPoint3D);
			}
			break;
		case YOVL_ID:
			if (shapeWithinBounds) {
				Point3f p = viewer.findPointOnDropPlane('y', x, y);
				p.x = Math.abs(2 * p.x) < model.getLength() ? p.x : model.getLength() * (p.x < 0 ? -0.5f : 0.5f);
				p.z = Math.abs(2 * p.z) < model.getHeight() ? p.z : model.getHeight() * (p.z < 0 ? -0.5f : 0.5f);
				dragPoint3D.set(p);
				viewer.setEllipse('y', clickPoint3D, dragPoint3D);
			}
			break;
		case ZOVL_ID:
			if (shapeWithinBounds) {
				Point3f p = viewer.findPointOnDropPlane('z', x, y);
				p.x = Math.abs(2 * p.x) < model.getLength() ? p.x : model.getLength() * (p.x < 0 ? -0.5f : 0.5f);
				p.y = Math.abs(2 * p.y) < model.getWidth() ? p.y : model.getWidth() * (p.y < 0 ? -0.5f : 0.5f);
				dragPoint3D.set(p);
				viewer.setEllipse('z', clickPoint3D, dragPoint3D);
			}
			break;
		case SBOX_ID:
			if (selectedFace != -1) {
				moveSimulationBoxFace(selectedFace, x, y);
				model.notifyChange();
			}
			break;
		case EXOB_ID:
			moveObstacleFace(x, y, false);
			break;
		case VVEL_ID:
			if (selectedFace != -1) {
				moveVectorBoxFace(selectedFace, x, y);
			}
			break;
		}
		repaint();
	}