www.pudn.com > GMapViewer-src.zip > MapPinManager.java



package org.sreid.j2me.gmapviewer;

import java.util.*;
import javax.microedition.rms.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import org.sreid.j2me.util.*;

// Handles permanent map pins, and temporary search result map pins.
class MapPinManager {

	private static final String RECORD_STORE_NAME = "GMapViewer.mappins";

	private final GMapViewer app;

	private RecordStore rms;

	private final Vector mapPins = new Vector();

	MapPinManager(GMapViewer app) {
		this.app = app;
	}

	void openRMS() {
		try {
			rms = RecordStore.openRecordStore(RECORD_STORE_NAME, true);
			RecordEnumeration re = rms.enumerateRecords(null, null, false);
			mapPins.removeAllElements();
			byte[] buffer = new byte[500];
			while (re.hasNextElement()) {
				int id = re.nextRecordId();
				try {
					int rlen = rms.getRecord(id, buffer, 0);
					MapPin mp = new MapPin(buffer, 0, rlen);
					mp.rmsID = id;
					mapPins.addElement(mp);
				}
				catch (Exception e) {
					app.exception("An error occured while reading a map pin from RMS.", e);
					rms.deleteRecord(id);
				}
			}
		}
		catch (Exception e) {
			app.exception("An error occured while enumerating map pin RMS.", e);
		}
	}

	void closeRMS() {
		try {
			rms.closeRecordStore();
		}
		catch (Exception e) {
			app.exception("An error occured while closing map pin RMS.", e);
		}
	}

	/** Call this whenever a pin changes. */
	void keepPin(MapPin pin) {
		if (!mapPins.contains(pin)) {
			mapPins.addElement(pin);
			sortPinsNearestFirst();
		}
		if (pin.isPermanent) {
			try {
				byte[] buffer = new byte[500];
				int rlen = pin.toBytes(buffer, 0);
				if (pin.rmsID == -1) {
					pin.rmsID = rms.addRecord(buffer, 0, rlen);
				}
				else {
					rms.setRecord(pin.rmsID, buffer, 0, rlen);
				}
			}
			catch (Exception e) {
				app.exception("An error occured while saving a map pin to RMS.", e);
			}
		}
	}

	void deletePin(MapPin pin) {
		mapPins.removeElement(pin);
		if (pin.rmsID != -1) {
			try {
				rms.deleteRecord(pin.rmsID);
			}
			catch (Exception e) {
				app.exception("An error occured while deleting a map pin from RMS.", e);
			}
			finally {
				pin.rmsID = -1;
			}
		}
	}

	void deleteNonPermanentPins() {
		for (int i = mapPins.size() - 1; i >= 0; i--) {
			if (!getMapPin(i).isPermanent) mapPins.removeElementAt(i);
		}
	}

	void sortPinsNearestFirst() {
		final int x = app.canvas.getX();
		final int y = app.canvas.getY();
		// Copy to temporary array
		Object[] array = new Object[mapPins.size()];
		mapPins.copyInto(array);
		// Sort temporary array
		Sort.sort(array, new Comparator() {
			public int compare(Object o1, Object o2) {
				MapPin p1 = (MapPin)o1;
				MapPin p2 = (MapPin)o2;
				if (p1.isPermanent && p2.isPermanent) {
					// Sort permanent pins by distance from current position.
					// Pythagorean theorem. Using longs here because distance^2 may be large.
					long xd1 = Math.abs(p1.x - x);
					long yd1 = Math.abs(p1.y - y);
					long d1 = (xd1 * xd1) + (yd1 * yd1);
					long xd2 = Math.abs(p2.x - x);
					long yd2 = Math.abs(p2.y - y);
					long d2 = (xd2 * xd2) + (yd2 * yd2);
					if (d1 < d2) return -1;
					if (d1 > d2) return 1;
					return 0;
				}
				else {
					// Search pins should not have their order changed.
					if (p1.isPermanent && !p2.isPermanent) return 1;
					if (!p1.isPermanent && p2.isPermanent) return -1;
					return 0; // both non-permanent, preserve order (requires a stable sort)
				}
			}
		});
		// Copy back to Vector
		for (int i = 0; i < array.length; i++) {
			mapPins.setElementAt(array[i], i);
		}		
	}

	Enumeration enumeration() {
		return mapPins.elements();
	}

	MapPin getMapPin(int index) {
		return (MapPin)mapPins.elementAt(index);
	}

	int getMapPinCount() {
		return mapPins.size();
	}

}