⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gmapcanvas.java

📁 基于J2ME的手机地图客户端源码
💻 JAVA
字号:
package org.sreid.j2me.gmapviewer;import java.util.*;import javax.microedition.lcdui.*;import javax.microedition.midlet.*;import org.sreid.j2me.util.*;class GMapCanvas extends Canvas implements CommandListener {	private static final String MAIN_MENU = "Back";	private static final String ZOOM_IN = "Zoom in";	private static final String ZOOM_OUT = "Zoom out";	private static final String CREATE_MAP_PIN = "New map pin";	private static final String MAP_PIN_MENU = "Map pin menu";	private static final String SEARCH_MENU = "Search menu";	private final GMapViewer app;	// Font for map pin text	private final Font font = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_SMALL);	// Absolute position.	private int x, y;	// Zoom level. 0-14. Smaller is more zoomed in.	private int zoom;	private long lastMoveTime = 0;	int requestID = 0; // used by MapTileManager.getMapTile	GMapCanvas(GMapViewer app) {		this.app = app;		setCommandListener(this);		addCommand(new Command(MAIN_MENU, Command.BACK, 1));		addCommand(new Command(ZOOM_IN, Command.SCREEN, 1));		addCommand(new Command(ZOOM_OUT, Command.SCREEN, 1));		addCommand(new Command(CREATE_MAP_PIN, Command.SCREEN, 2));		addCommand(new Command(MAP_PIN_MENU, Command.SCREEN, 2));		addCommand(new Command(SEARCH_MENU, Command.SCREEN, 2));	}	void setXY(int x, int y) {		this.x = x;		this.y = y;		app.mpm.sortPinsNearestFirst();		repaint();	}	int getX() { return x; }	int getY() { return y; }	int getZ() { return zoom; }	// Move view position (relative, 0 = no change)	private void moveView(int movx, int movy) {		long t = System.currentTimeMillis();		boolean fast = (t < (lastMoveTime + app.prefs.getInt("moveSpeedTimeout", 800)));		int speed = (fast ? app.prefs.getInt("moveSpeed2", 20) : app.prefs.getInt("moveSpeed1", 8));		movx *= speed;		movy *= speed;		setXY(x + (movx << zoom), y + (movy << zoom));		lastMoveTime = t;	}	private void zoomIn() {		if (zoom > 0) zoom--;		repaint();	}	private void zoomOut() {		if (zoom < 14) zoom++;		repaint();	}	public void paint(Graphics g) {		// Convert x,y to screen coordinates		final int w = getWidth();		final int h = getHeight();		final int sx = (x >> zoom) - (w / 2); // screen x position		final int sy = (y >> zoom) - (h / 2); // screen y position		final int xpos = sx >> 7;		final int xoff = sx & 0x7f;		final int ypos = sy >> 7;		final int yoff = sy & 0x7f;		//if (app.debug) app.debug("Position: " + x + " " + y + " -> " + xpos + " " + xoff + " " + ypos + " " + yoff + " " + zoom);		// Number of tiles wide/high. Round up, and add 1 to handle overlap.		final int tw = ((w + MapTile.WIDTH - 1) / MapTile.WIDTH) + 1;		final int th = ((h + MapTile.HEIGHT - 1) / MapTile.HEIGHT) + 1;		// Make sure image cache size is large enough that we don't		// have to re-decode tiles on every refresh.		app.cache.imageCacheSize = tw * th + 1;		// Identify visible tiles		XYZ[] visible = new XYZ[tw * th];		int nVisible = 0;		for (int ty = 0; ty < th; ty++) {			for (int tx = 0; tx < tw; tx++) {				XYZ xyz = new XYZ(xpos + tx, ypos + ty, zoom);				if (computeTileVisiblePixels(xyz, sx, sy, w, h) > 0) {					visible[nVisible++] = xyz;				}			}		}		// Sort tiles by how much space in the on-screen area it affects, 		// so that we will request the most visible tiles first.		Sort.sort(visible, 0, nVisible, new Comparator() {			public int compare(Object o1, Object o2) {				int v1, v2;				// First, compare by visible pixels				v1 = computeTileVisiblePixels((XYZ)o1, sx, sy, w, h);				v2 = computeTileVisiblePixels((XYZ)o2, sx, sy, w, h);				if (v1 != v2) return v2 - v1;				// If visible pixels the same (probably fully visible), then compare by distance from center				v1 = computeTileDistance((XYZ)o1, sx, sy, w, h);				v2 = computeTileDistance((XYZ)o2, sx, sy, w, h);				return v1 - v2;			}		});		// Request/draw the tiles		requestID++;		for (int i = 0; i < nVisible; i++) {			XYZ xyz = visible[i];			MapTile mt = app.mtm.getMapTile(xyz);			int tx = (xyz.x * MapTile.WIDTH) - ((xpos * MapTile.WIDTH) + xoff);			int ty =  (xyz.y * MapTile.HEIGHT) - ((ypos * MapTile.HEIGHT) + yoff);			Image image = mt.image; // take a reference now, in case background thread nulls out the field			if (image != null) {				// Got the image. Draw it.				g.drawImage(image, tx, ty, Graphics.TOP|Graphics.LEFT);			}			else if (mt.bytes == null && mt.rmsID == -1) {				if (mt.downloading) {					// yellow to indicate downloading					drawEmptyTile(g, 0xffff00, tx, ty);				}				else  {					// orange to indicate waiting for download					drawEmptyTile(g, 0xff8000, tx, ty);				}			}			else { // Image is null, but does not need to be downloaded. That means we're waiting for decode.				if (mt.decoding) {					// green to indicate decoding					drawEmptyTile(g, 0x00ff00, tx, ty);				}				else {					// blue to indicate waiting for decode					drawEmptyTile(g, 0x0000ff, tx, ty);				}			}		}		// Draw the map pins over top of the tiles.		g.setFont(font);		final int fudge = 100;		final int PW = 16, PH = 16; // pin size		final long mapPinTextRadius = app.prefs.getInt("mapPinTextRadius", 600);		final long mapPinTextRadiusSquared = mapPinTextRadius * mapPinTextRadius;		for (int i = app.mpm.getMapPinCount() - 1; i >= 0; i--) { // reverse order, so closer map pins will overwrite more distant ones			MapPin pin = app.mpm.getMapPin(i);			if (pin == null) continue;			int px = (pin.x >> zoom) - sx;			int py = (pin.y >> zoom) - sy;			if (px >= (-fudge) && px <= (w + fudge) && py >= (-fudge) && py <= (h + fudge)) {				// The pin is on-screen, or close enough. Draw it.				g.setColor(pin.isPermanent ? 0xff0000 : 0x0000ff);				g.fillArc(px - PW, py - PH, PW*2, PH*2, 90, 15);				g.drawLine(px, py - PH, px, py); // draw a line too, so it always goes right to the point.				// Draw text? (pythagorean theorem)				int hdist = Math.abs(x - pin.x);				int vdist = Math.abs(y - pin.y);				if ( (hdist * hdist) + (vdist * vdist) < mapPinTextRadiusSquared) {					g.setColor(0xffffff);					g.fillRect(px + 1, py - PH, font.stringWidth(pin.text), font.getHeight());					g.setColor(0x000000);					g.drawString(pin.text, px + 1, py - PH, Graphics.TOP|Graphics.LEFT);				}			}		}		// Draw crosshairs		g.setColor(0x808080);		final int cs = 3; // crosshair size		g.drawLine(w/2 - cs, h/2, w/2 + cs, h/2);		g.drawLine(w/2, h/2 - cs, w/2, h/2 + cs);		if (app.prefs.getInt("callgc", 0) >= 3) System.gc();	}	// Returns the number of pixels currently visible from the specified tile.	// Return value ranges from 0 (completely off-screen) to 	// MapTile.WIDTH*MapTile.HEIGHT (completely on-screen).	private int computeTileVisiblePixels(XYZ tile, int sx, int sy, int w, int h) {		// convert to pixels		int tx = tile.x * MapTile.WIDTH;		int ty = tile.y * MapTile.HEIGHT;		// figure visible width, visible height		int vw = Math.max(0, (		 Math.min(tx + MapTile.WIDTH, sx + w) -		 Math.max(tx, sx) ));		int vh = Math.max(0, (		  Math.min(ty + MapTile.HEIGHT, sy + h) -		  Math.max(ty, sy) ));		// area		return vw * vh;	}	// Returns the distance (squared actually) of the center of the specified	// tile from the center of the screen.	private int computeTileDistance(XYZ tile, int sx, int sy, int w, int h) {		// convert to pixels		int tx = tile.x * MapTile.WIDTH;		int ty = tile.y * MapTile.HEIGHT;		// Compute horizontal and vertical distances		int hdist = Math.abs( (sx + (w / 2)) - (tx + (MapTile.WIDTH  / 2)) );		int vdist = Math.abs( (sy + (h / 2)) - (ty + (MapTile.HEIGHT / 2)) );		// Pythagorean theorem		return (hdist * hdist) + (vdist * vdist); // don't need longs here, as distance will always be small	}	private void drawEmptyTile(Graphics g, int color, int x, int y) {		// Solid color		g.setColor(color);		g.fillRect(x, y, MapTile.WIDTH, MapTile.HEIGHT);		// ...with a thin black border		g.setColor(0x000000);		g.drawRect(x, y, MapTile.WIDTH, MapTile.HEIGHT);	}	protected void keyPressed(int keyCode) {		doKey(keyCode);	}	protected void keyRepeated(int keyCode) {		doKey(keyCode);	}	private void doKey(int keyCode) {		//app.debug("Key pressed: " + keyCode + "/" + getGameAction(keyCode) + "/" + getKeyName(keyCode));		switch (getGameAction(keyCode)) {			case UP:				moveView(0, -1);				break;			case DOWN:				moveView(0, 1);				break;			case LEFT:				moveView(-1, 0);				break;			case RIGHT:				moveView(1, 0);				break;		}	}	public void commandAction(Command c, Displayable d) {		String cmd = c.getLabel();		if (cmd.equals(ZOOM_IN)) {			zoomIn();		}		if (cmd.equals(ZOOM_OUT)) {			zoomOut();		}		if (cmd.equals(CREATE_MAP_PIN)) {			createMapPin();		}		if (cmd.equals(MAP_PIN_MENU)) {			app.mapPinMenu.cameFrom = this;			app.mapPinMenu.loadList();			app.display.setCurrent(app.mapPinMenu);		}		if (cmd.equals(SEARCH_MENU)) {			app.searchMenu.cameFrom = this;			app.searchMenu.loadList();			app.display.setCurrent(app.searchMenu);		}		if (cmd.equals(MAIN_MENU)) {			app.display.setCurrent(app.mainMenu);		}	}	private void createMapPin() {		final Dialog dlg = Dialog.createTextDialog("New map pin", "Map pin text", "", 40, TextField.ANY);		dlg.setCallback(new Runnable() { public void run() {			String userResponse = (String)dlg.getUserResponse();			if (userResponse != null) {				MapPin pin = new MapPin(x, y);				pin.text = (String)userResponse;				app.mpm.keepPin(pin);			}		}});		dlg.showOn(app);	}	/** Loads position from preferences. */	void loadPosition() {		x = app.prefs.getInt("canvas.x", -2505728);		y = app.prefs.getInt("canvas.y", -1282048);		zoom = app.prefs.getInt("canvas.zoom", 6);	}	/** Saves position to preferences. */	void savePosition() {		app.prefs.put("canvas.x", Integer.toString(x));		app.prefs.put("canvas.y", Integer.toString(y));		app.prefs.put("canvas.zoom", Integer.toString(zoom));	}		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -