//#preprocess
/*
* Copyright 2012 Monits
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.monits.blackberry.commons.uielements;
import javax.microedition.location.Coordinates;
import net.rim.device.api.lbs.MapField;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.Graphics;
//#ifdef TouchEnabled
import net.rim.device.api.ui.TouchEvent;
import net.rim.device.api.ui.TouchGesture;
//#endif
import net.rim.device.api.ui.XYPoint;
import net.rim.device.api.ui.XYRect;
import net.rim.device.api.util.Arrays;
import net.rim.device.api.util.MathUtilities;
import com.monits.blackberry.commons.service.ServiceLocator;
import com.monits.blackberry.commons.uielements.map.Marker;
/**
* Map field that support Marker object in it.
* @author Rodrigo Pereyra
*/
public class CustomMap extends MapField {
private Marker openLocation;
private Marker focusLocation;
private Marker markers[];
private Bitmap crosshair;
private int _touchX;
private int _touchY;
/**
* Constructor.
* @param crosshair Image that will be displayed in the center of the field.
*/
public CustomMap(Bitmap crosshair) {
super();
markers = new Marker[0];
this.crosshair = crosshair;
}
/**
* Adds a new marker on the map and retrieves it.
*
* @param marker The marker being placed.
* @return The created marker.
*/
public Marker addMarker(Marker marker) {
Arrays.add(markers, marker);
this.invalidate();
return marker;
}
/**
* Removes all markers from the map.
*/
public void removeAllMarkers() {
markers = new Marker[0];
this.invalidate();
}
/**
* Retrieve the focus location.
* @return the focus location or null if there no focus location.
*/
public Marker getFocusLocation() {
return focusLocation;
}
protected void paint(Graphics graphics) {
super.paint(graphics);
XYPoint actualFieldOut = new XYPoint();
Coordinates actualCord = new Coordinates(((double) getLatitude()) / 100000.0, ((double) getLongitude()) / 100000.0, 0);
convertWorldToField(actualCord, actualFieldOut);
focusLocation = null;
for (int i = 0; i < markers.length; i++) {
XYRect rect = null;
Marker loc = markers[i];
if (null != loc) {
XYPoint fieldOut = new XYPoint();
convertWorldToField(loc.getCoor(), fieldOut);
if (fieldOut.x > (-loc.getBitmap().getWidth())
&& fieldOut.x < getWidth() + loc.getBitmap().getWidth()) {
if (fieldOut.y > (-loc.getBitmap().getHeight())
&& fieldOut.y < getHeight()
+ loc.getBitmap().getHeight()) {
int imgW = loc.getBitmap().getWidth();
int imgH = loc.getBitmap().getHeight();
rect = new XYRect(fieldOut.x - imgW / 2,
fieldOut.y - imgH, imgW, imgH);
if (rect.contains(actualFieldOut) && focusLocation == null) {
graphics.drawBitmap(rect, loc.getFocusBitmap(), 0, 0);
focusLocation = loc;
} else {
graphics.drawBitmap(rect, loc.getBitmap(), 0, 0);
}
}
}
}
}
if (openLocation != null) {
drawOpenMarker(graphics, openLocation);
}
// Display the crosshair
if (crosshair != null) {
graphics.drawBitmap(this.getWidth() / 2 - crosshair.getWidth() / 2, this.getHeight() / 2 - crosshair.getHeight() / 2, crosshair.getWidth(), crosshair.getHeight(), crosshair, 0, 0);
}
}
protected void drawOpenMarker(Graphics graphics, Marker location) {
// Implement this if you want to draw a description or whatever.
// By default it doesn't do anything.
}
/**
* Retrieve the marker at the given point.
* @param fieldPoint Position of the marker.
* @return A marker object that correspond with the point,
* or null if there no marker at the given point.
*/
public Marker getMarkerAtPoint(XYPoint fieldPoint) {
for (int i = 0; i < markers.length; i++) {
XYRect rect = null;
Marker loc = markers[i];
if (null != loc) {
XYPoint fieldOut = new XYPoint();
convertWorldToField(loc.getCoor(), fieldOut);
if (fieldOut.x > (-loc.getBitmap().getWidth())
&& fieldOut.x < getWidth() + loc.getBitmap().getWidth()) {
if (fieldOut.y > (-loc.getBitmap().getHeight())
&& fieldOut.y < getHeight() + loc.getBitmap().getHeight()) {
int imgW = loc.getBitmap().getWidth();
int imgH = loc.getBitmap().getHeight();
rect = new XYRect(fieldOut.x - imgW / 2,
fieldOut.y - imgH, imgW, imgH);
if (rect.contains(fieldPoint)) {
return markers[i];
}
}
}
}
}
return null;
}
/**
* @return True if a marker is open, otherwise false
*/
protected boolean isMarkerOpen() {
return openLocation != null;
}
/**
* Open the given marker.
* @param loc Marker to be open.
*/
public void openMarker(Marker loc) {
openLocation = loc;
if (null != loc) {
XYPoint fieldOut = new XYPoint();
Coordinates worldOut = new Coordinates((float) 0.0, (float) 0.0, (float) 0.0);
convertWorldToField(new Coordinates(loc.getCoor().getLatitude(), loc.getCoor().getLongitude(), (float) 0.0), fieldOut);
int newY = fieldOut.y - openLocation.getBitmap().getHeight() - ServiceLocator.getScreenTypeService().getNewSize(15);
convertFieldToWorld(new XYPoint(fieldOut.x, newY), worldOut);
moveTo(worldOut);
} else {
this.invalidate();
}
}
public Marker getOpenLocation() {
return openLocation;
}
//#ifdef TouchEnabled
protected boolean touchEvent(TouchEvent message) {
switch (message.getEvent()) {
//mark that we're starting to interact
case TouchEvent.DOWN:
_touchX = message.getX(1);
_touchY = message.getY(1);
return true;
//user is wanting to move the map
case TouchEvent.MOVE:
int dx = _touchX - message.getX(1);
int dy = _touchY - message.getY(1);
_touchX = message.getX(1);
_touchY = message.getY(1);
//perform checks to make sure we don't move outside of the map's range
int lat = getLatitude() - dy*(int)MathUtilities.pow(2, (double)getZoom());
if(lat < -9000000) {
lat = -9000000;
}
else if (lat > 9000000) {
lat = 9000000;
}
int lon = getLongitude() + dx*(int)MathUtilities.pow(2, (double)getZoom());
if(lon < -18000000) {
lon = -18000000;
}
else if (lon > 18000000) {
lon = 18000000;
}
moveTo(lat, lon);
return true;
case TouchEvent.GESTURE:
TouchGesture gesture = message.getGesture();
if (gesture.getEvent() == TouchGesture.TAP) {
// Handle the double tapping
if (gesture.getTapCount() >= 2) {
// set a minimum quantity of zoom
setZoom(Math.max(getZoom() - 1, getMinZoom()));
return true;
}
Marker m = getMarkerAtPoint(new XYPoint(_touchX, _touchY));
// if a poi, display the popup
if (isMarkerOpen()) {
openMarker(null);
} else {
// Go the point
move(_touchX - getWidth() / 2, _touchY - getHeight() / 2);
if (m != null) {
openMarker(m);
}
}
}
return true;
}
return super.touchEvent(message);
}
//#endif
}