protected void processMouseReleased(MouseEvent e) {
		super.processMouseReleased(e);
		if (ModelerUtilities.isRightClick(e)) {
			popup(e);
			return;
		}
		model.runMouseScript(MouseEvent.MOUSE_RELEASED, e.getX(), e.getY());
		int x = e.getX();
		int y = e.getY();
		int clickCount = e.getClickCount();
		BitSet bs = null;
		switch (actionID) {
		case SLRT_ID:
			if (Math.abs(selectedArea.width) > 5 && Math.abs(selectedArea.height) > 5) {
				bs = viewer.findAtomsInRectangle(selectedArea);
				viewer.setSelectionSet(bs);
				multiselectionBitSet.clear();
				multiselectionBitSet.or(bs);
				selectedArea.setSize(0, 0);
				if (bs.cardinality() == 0)
					selectedComponent = null;
				else selectedComponent = model.getAtom(bs.nextSetBit(0));
			}
			break;
		case SLOV_ID:
			if (Math.abs(selectedArea.width) > 5 && Math.abs(selectedArea.height) > 5) {
				bs = viewer.findAtomsInOval(selectedArea);
				viewer.setSelectionSet(bs);
				multiselectionBitSet.clear();
				multiselectionBitSet.or(bs);
				selectedArea.setSize(0, 0);
				if (bs.cardinality() == 0)
					selectedComponent = null;
			}
			break;
		case DELR_ID:
			removeAtoms(viewer.findAtomsInRectangle(selectedArea));
			selectedArea.setSize(0, 0);
			model.notifyChange();
			break;
		case DELC_ID:
			removeAtoms(viewer.findAtomsInOval(selectedArea));
			selectedArea.setSize(0, 0);
			model.notifyChange();
			break;
		case FIXR_ID:
			bs = viewer.findAtomsInRectangle(selectedArea);
			if (bs.cardinality() > 0) {
				model.immobilizeAtoms(bs);
				model.notifyChange();
			}
			selectedArea.setSize(0, 0);
			break;
		case FIXC_ID:
			bs = viewer.findAtomsInOval(selectedArea);
			if (bs.cardinality() > 0) {
				model.immobilizeAtoms(bs);
				model.notifyChange();
			}
			selectedArea.setSize(0, 0);
			break;
		case XIFR_ID:
			bs = viewer.findAtomsInRectangle(selectedArea);
			if (bs.cardinality() > 0) {
				model.mobilizeAtoms(bs);
				model.notifyChange();
			}
			selectedArea.setSize(0, 0);
			break;
		case XIFC_ID:
			bs = viewer.findAtomsInOval(selectedArea);
			if (bs.cardinality() > 0) {
				model.mobilizeAtoms(bs);
				model.notifyChange();
			}
			selectedArea.setSize(0, 0);
			break;
		case TSLC_ID:
			bs = viewer.findAtomsInRectangle(selectedArea);
			if (bs.cardinality() > 0) {
				translucentBitSet.or(bs);
				hidenBitSet.andNot(bs);
				model.notifyChange();
			}
			selectedArea.setSize(0, 0);
			break;
		case CLST_ID:
			bs = viewer.findAtomsInRectangle(selectedArea);
			if (bs.cardinality() > 0) {
				translucentBitSet.andNot(bs);
				hidenBitSet.andNot(bs);
				model.notifyChange();
			}
			selectedArea.setSize(0, 0);
			break;
		case HIDE_ID:
			bs = viewer.findAtomsInRectangle(selectedArea);
			if (bs.cardinality() > 0) {
				hidenBitSet.or(bs);
				model.notifyChange();
			}
			selectedArea.setSize(0, 0);
			break;
		case EDIH_ID:
			bs = viewer.findAtomsInRectangle(selectedArea);
			if (bs.cardinality() > 0) {
				hidenBitSet.andNot(bs);
				model.notifyChange();
			}
			selectedArea.setSize(0, 0);
			break;
		case XADD_ID:
			if (clickCount >= 2) {
				addAtom(viewer.findPointOnDropPlane('x', x, y));
			}
			else {
				if (selectedComponent instanceof Atom) {
					dragAtom((Atom) selectedComponent, 'x', x - clickPoint.x, y - clickPoint.y, true);
				}
			}
			break;
		case YADD_ID:
			if (clickCount >= 2) {
				addAtom(viewer.findPointOnDropPlane('y', x, y));
			}
			else {
				if (selectedComponent instanceof Atom) {
					dragAtom((Atom) selectedComponent, 'y', x - clickPoint.x, y - clickPoint.y, true);
				}
			}
			break;
		case ZADD_ID:
			if (clickCount >= 2) {
				addAtom(viewer.findPointOnDropPlane('z', x, y));
			}
			else {
				if (selectedComponent instanceof Atom) {
					dragAtom((Atom) selectedComponent, 'z', x - clickPoint.x, y - clickPoint.y, true);
				}
			}
			break;
		case XMOL_ID:
			if (clickCount >= 2) {
				addMolecule(viewer.findPointOnDropPlane('x', x, y));
			}
			break;
		case YMOL_ID:
			if (clickCount >= 2) {
				addMolecule(viewer.findPointOnDropPlane('y', x, y));
			}
			break;
		case ZMOL_ID:
			if (clickCount >= 2) {
				addMolecule(viewer.findPointOnDropPlane('z', x, y));
			}
			break;
		case XFIL_ID:
			if (e.getClickCount() >= 2) {
				importModelPopupMenu.setPosition(viewer.findPointOnDropPlane('x', x, y));
				importModelPopupMenu.show(this, x, y);
			}
			break;
		case YFIL_ID:
			if (e.getClickCount() >= 2) {
				importModelPopupMenu.setPosition(viewer.findPointOnDropPlane('y', x, y));
				importModelPopupMenu.show(this, x, y);
			}
			break;
		case ZFIL_ID:
			if (e.getClickCount() >= 2) {
				importModelPopupMenu.setPosition(viewer.findPointOnDropPlane('z', x, y));
				importModelPopupMenu.show(this, x, y);
			}
			break;
		case XREC_ID:
			if (shapeWithinBounds) {
				float yc = (clickPoint3D.y + dragPoint3D.y) * 0.5f;
				float zc = (clickPoint3D.z + dragPoint3D.z) * 0.5f;
				float ly = Math.abs(clickPoint3D.y - dragPoint3D.y) * 0.5f;
				float lz = Math.abs(clickPoint3D.z - dragPoint3D.z) * 0.5f;
				if (ly >= Obstacle.MIN_THICKNESS && lz >= Obstacle.MIN_THICKNESS) {
					addCuboidObstacle(clickPoint3D.x, yc, zc, Obstacle.MIN_THICKNESS, ly, lz);
				}
				dragPoint3D.set(clickPoint3D);
				shapeWithinBounds = false;
			}
			break;
		case YREC_ID:
			if (shapeWithinBounds) {
				float xc = (clickPoint3D.x + dragPoint3D.x) * 0.5f;
				float zc = (clickPoint3D.z + dragPoint3D.z) * 0.5f;
				float lx = Math.abs(clickPoint3D.x - dragPoint3D.x) * 0.5f;
				float lz = Math.abs(clickPoint3D.z - dragPoint3D.z) * 0.5f;
				if (lx >= Obstacle.MIN_THICKNESS && lz >= Obstacle.MIN_THICKNESS) {
					addCuboidObstacle(xc, clickPoint3D.y, zc, lx, Obstacle.MIN_THICKNESS, lz);
				}
				dragPoint3D.set(clickPoint3D);
			}
			break;
		case ZREC_ID:
			if (shapeWithinBounds) {
				float xc = (clickPoint3D.x + dragPoint3D.x) * 0.5f;
				float yc = (clickPoint3D.y + dragPoint3D.y) * 0.5f;
				float lx = Math.abs(clickPoint3D.x - dragPoint3D.x) * 0.5f;
				float ly = Math.abs(clickPoint3D.y - dragPoint3D.y) * 0.5f;
				if (lx >= Obstacle.MIN_THICKNESS && ly >= Obstacle.MIN_THICKNESS) {
					addCuboidObstacle(xc, yc, clickPoint3D.z, lx, ly, Obstacle.MIN_THICKNESS);
				}
				dragPoint3D.set(clickPoint3D);
			}
			break;
		case XOVL_ID:
			if (shapeWithinBounds) {
				float yc = (clickPoint3D.y + dragPoint3D.y) * 0.5f;
				float zc = (clickPoint3D.z + dragPoint3D.z) * 0.5f;
				float ly = Math.abs(clickPoint3D.y - dragPoint3D.y) * 0.5f;
				float lz = Math.abs(clickPoint3D.z - dragPoint3D.z) * 0.5f;
				if (ly >= Obstacle.MIN_THICKNESS && lz >= Obstacle.MIN_THICKNESS) {
					addCylinderObstacle(clickPoint3D.x, yc, zc, 'x', Obstacle.MIN_THICKNESS, ly, lz);
				}
				dragPoint3D.set(clickPoint3D);
			}
			break;
		case YOVL_ID:
			if (shapeWithinBounds) {
				float xc = (clickPoint3D.x + dragPoint3D.x) * 0.5f;
				float zc = (clickPoint3D.z + dragPoint3D.z) * 0.5f;
				float lx = Math.abs(clickPoint3D.x - dragPoint3D.x) * 0.5f;
				float lz = Math.abs(clickPoint3D.z - dragPoint3D.z) * 0.5f;
				if (lx >= Obstacle.MIN_THICKNESS && lz >= Obstacle.MIN_THICKNESS) {
					addCylinderObstacle(xc, clickPoint3D.y, zc, 'y', Obstacle.MIN_THICKNESS, lx, lz);
				}
				dragPoint3D.set(clickPoint3D);
			}
			break;
		case ZOVL_ID:
			if (shapeWithinBounds) {
				float xc = (clickPoint3D.x + dragPoint3D.x) * 0.5f;
				float yc = (clickPoint3D.y + dragPoint3D.y) * 0.5f;
				float lx = Math.abs(clickPoint3D.x - dragPoint3D.x) * 0.5f;
				float ly = Math.abs(clickPoint3D.y - dragPoint3D.y) * 0.5f;
				if (lx >= Obstacle.MIN_THICKNESS && ly >= Obstacle.MIN_THICKNESS) {
					addCylinderObstacle(xc, yc, clickPoint3D.z, 'z', Obstacle.MIN_THICKNESS, lx, ly);
				}
				dragPoint3D.set(clickPoint3D);
			}
			break;
		case EXOB_ID:
			moveObstacleFace(x, y, true);
			model.notifyChange();
			break;
		case DUPL_ID:
			if (newMolecule != null) {
				bs = getSelectionSet();
				if (shouldRejectMoving(bs)) { // roll back duplication
					removeAtoms(bs);
				}
				else {
					refresh();
				}
				newMolecule = null;
			}
			break;
		}
		if (showEnergizer && energizer != null) {
			energizer.buttonPressed = false;
		}
		if (navigator != null)
			navigator.clear();
		repaint();
	}