Merge pull request #4147 from osmandapp/ruler_improvements

Ruler improvements
This commit is contained in:
vshcherb 2017-07-19 17:25:01 +02:00 committed by GitHub
commit ea15c68527
3 changed files with 328 additions and 297 deletions

View file

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<dimen name="acceptable_touch_radius">48dp</dimen>
<dimen name="dialog_button_height">36dp</dimen> <dimen name="dialog_button_height">36dp</dimen>
<dimen name="undo_bottom_offset">15dp</dimen> <dimen name="undo_bottom_offset">15dp</dimen>
<dimen name="touch_slop">32dp</dimen> <dimen name="touch_slop">32dp</dimen>
@ -10,7 +12,7 @@
<dimen name="dashboard_land_width">360dp</dimen> <dimen name="dashboard_land_width">360dp</dimen>
<dimen name="dashboard_map_toolbar">56dp</dimen> <dimen name="dashboard_map_toolbar">56dp</dimen>
<dimen name="dash_parking_height">78dp</dimen> <dimen name="dash_parking_height">78dp</dimen>
<dimen name="subHeaderPadding">2dp</dimen> <dimen name="subHeaderPadding">2dp</dimen>
<dimen name="subHeaderMarginLeft">15dp</dimen> <dimen name="subHeaderMarginLeft">15dp</dimen>
<dimen name="showAllButtonMarginRight">14dp</dimen> <dimen name="showAllButtonMarginRight">14dp</dimen>
@ -30,15 +32,15 @@
<dimen name="dashCardMargin">4dp</dimen> <dimen name="dashCardMargin">4dp</dimen>
<dimen name="abp__shadow_height">4dp</dimen> <dimen name="abp__shadow_height">4dp</dimen>
<dimen name="dashFABMargin">0dp</dimen> <dimen name="dashFABMargin">0dp</dimen>
<dimen name="list_content_padding">16dp</dimen> <dimen name="list_content_padding">16dp</dimen>
<dimen name="list_header_padding">8dp</dimen> <dimen name="list_header_padding">8dp</dimen>
<dimen name="list_header_top_margin">16dp</dimen> <dimen name="list_header_top_margin">16dp</dimen>
<dimen name="list_header_settings_top_margin">10dp</dimen> <dimen name="list_header_settings_top_margin">10dp</dimen>
<dimen name="list_header_text_left_margin">12dp</dimen> <dimen name="list_header_text_left_margin">12dp</dimen>
<dimen name="list_header_bottom_margin">8dp</dimen> <dimen name="list_header_bottom_margin">8dp</dimen>
<dimen name="favorites_icon_right_margin">24dp</dimen> <dimen name="favorites_icon_right_margin">24dp</dimen>
<dimen name="local_index_check_right_margin">10dp</dimen> <dimen name="local_index_check_right_margin">10dp</dimen>
<dimen name="favorites_icon_top_margin">13dp</dimen> <dimen name="favorites_icon_top_margin">13dp</dimen>
@ -50,8 +52,8 @@
<dimen name="gpx_small_icon_margin">3dp</dimen> <dimen name="gpx_small_icon_margin">3dp</dimen>
<dimen name="gpx_small_text_margin">14dp</dimen> <dimen name="gpx_small_text_margin">14dp</dimen>
<dimen name="gpx_text_top_margin">6dp</dimen> <dimen name="gpx_text_top_margin">6dp</dimen>
<dimen name="dashboard_parking_left_margin">16dp</dimen> <dimen name="dashboard_parking_left_margin">16dp</dimen>
<dimen name="dashboard_parking_icon_size">48dp</dimen> <dimen name="dashboard_parking_icon_size">48dp</dimen>
<!-- map buttons --> <!-- map buttons -->
@ -69,8 +71,8 @@
<dimen name="map_ruler_width">120dp</dimen> <dimen name="map_ruler_width">120dp</dimen>
<dimen name="map_ruler_bottom_margin">9dp</dimen> <dimen name="map_ruler_bottom_margin">9dp</dimen>
<dimen name="map_alarm_size">78dp</dimen> <dimen name="map_alarm_size">78dp</dimen>
<dimen name="map_alarm_bottom_margin">87dp</dimen> <dimen name="map_alarm_bottom_margin">87dp</dimen>
<dimen name="map_alarm_bottom_margin_land">57dp</dimen> <dimen name="map_alarm_bottom_margin_land">57dp</dimen>
<dimen name="map_button_shadow_height">85dp</dimen> <dimen name="map_button_shadow_height">85dp</dimen>
@ -83,8 +85,8 @@
<dimen name="map_button_spacing_land">6dp</dimen> <dimen name="map_button_spacing_land">6dp</dimen>
<dimen name="map_button_margin">6dp</dimen> <dimen name="map_button_margin">6dp</dimen>
<dimen name="map_routing_progress_width">100dp</dimen> <dimen name="map_routing_progress_width">100dp</dimen>
<dimen name="map_button_inset_shadow">2dp</dimen> <dimen name="map_button_inset_shadow">2dp</dimen>
<dimen name="map_button_inset">2dp</dimen> <dimen name="map_button_inset">2dp</dimen>
<dimen name="map_button_rect_rad">3dp</dimen> <dimen name="map_button_rect_rad">3dp</dimen>
@ -94,9 +96,9 @@
<dimen name="map_route_planning_land_width_minus_shadow">306dp</dimen> <dimen name="map_route_planning_land_width_minus_shadow">306dp</dimen>
<dimen name="map_route_planning_max_height">330dp</dimen> <dimen name="map_route_planning_max_height">330dp</dimen>
<dimen name="map_minwidth_widget">100dp</dimen> <dimen name="map_minwidth_widget">100dp</dimen>
<dimen name="map_widget_text_size">23sp</dimen> <dimen name="map_widget_text_size">23sp</dimen>
<dimen name="map_widget_text_size_small">15sp</dimen> <dimen name="map_widget_text_size_small">15sp</dimen>
<dimen name="map_button_text_size">18sp</dimen> <dimen name="map_button_text_size">18sp</dimen>
@ -104,7 +106,7 @@
<dimen name="map_widget_text_bottom_margin">1sp</dimen> <dimen name="map_widget_text_bottom_margin">1sp</dimen>
<dimen name="map_widget_text_small_bottom_margin">3sp</dimen> <dimen name="map_widget_text_small_bottom_margin">3sp</dimen>
<dimen name="map_widget_icon_margin">2dp</dimen> <dimen name="map_widget_icon_margin">2dp</dimen>
<dimen name="dash_margin">2dp</dimen> <dimen name="dash_margin">2dp</dimen>
<dimen name="dash_margin_h">6dp</dimen> <dimen name="dash_margin_h">6dp</dimen>

View file

@ -6,6 +6,7 @@ import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
@ -28,330 +29,358 @@ import gnu.trove.list.array.TIntArrayList;
public class RulerControlLayer extends OsmandMapLayer { public class RulerControlLayer extends OsmandMapLayer {
public static final long DELAY = 2000; private static final long DRAW_TIME = 2000;
private static final int TEXT_SIZE = 14; private static final long DELAY_BEFORE_DRAW = 500;
private static final int TEXT_SIZE = 14;
private final MapActivity mapActivity; private final MapActivity mapActivity;
private OsmandApplication app; private OsmandApplication app;
private OsmandMapTileView view; private OsmandMapTileView view;
private View rightWidgetsPanel; private View rightWidgetsPanel;
private TextSide textSide; private TextSide textSide;
private int maxRadiusInDp; private int maxRadiusInDp;
private float maxRadius; private float maxRadius;
private int radius; private int radius;
private double roundedDist; private double roundedDist;
private boolean showTwoFingersDistance; private boolean showTwoFingersDistance;
private boolean showDistBetweenFingerAndLocation; private boolean showDistBetweenFingerAndLocation;
private boolean touchOutside;
private int acceptableTouchRadius;
private QuadPoint cacheCenter; private QuadPoint cacheCenter;
private int cacheIntZoom; private int cacheIntZoom;
private double cacheTileX; private double cacheTileX;
private double cacheTileY; private double cacheTileY;
private long cacheMultiTouchEndTime; private long cacheMultiTouchEndTime;
private ArrayList<String> cacheDistances; private ArrayList<String> cacheDistances;
private Path distancePath; private Path distancePath;
private TIntArrayList tx; private TIntArrayList tx;
private TIntArrayList ty; private TIntArrayList ty;
private LatLon singleTouchPointLatLon; private LatLon touchPointLatLon;
private PointF touchPoint;
private PointF firstTouchPoint;
private long touchTime;
private Bitmap centerIconDay; private Bitmap centerIconDay;
private Bitmap centerIconNight; private Bitmap centerIconNight;
private Paint bitmapPaint; private Paint bitmapPaint;
private RenderingLineAttributes lineAttrs; private RenderingLineAttributes lineAttrs;
private RenderingLineAttributes circleAttrs; private RenderingLineAttributes circleAttrs;
private RenderingLineAttributes circleAttrsAlt; private RenderingLineAttributes circleAttrsAlt;
private Handler handler; private Handler handler;
public RulerControlLayer(MapActivity mapActivity) { public RulerControlLayer(MapActivity mapActivity) {
this.mapActivity = mapActivity; this.mapActivity = mapActivity;
} }
public boolean isShowTwoFingersDistance() { public boolean isShowTwoFingersDistance() {
return showTwoFingersDistance; return showTwoFingersDistance;
} }
public boolean isShowDistBetweenFingerAndLocation() { public boolean isShowDistBetweenFingerAndLocation() {
return showDistBetweenFingerAndLocation; return showDistBetweenFingerAndLocation;
} }
public LatLon getSingleTouchPointLatLon() { public LatLon getTouchPointLatLon() {
return singleTouchPointLatLon; return touchPointLatLon;
} }
@Override @Override
public void initLayer(final OsmandMapTileView view) { public void initLayer(final OsmandMapTileView view) {
app = mapActivity.getMyApplication(); app = mapActivity.getMyApplication();
this.view = view; this.view = view;
cacheDistances = new ArrayList<>(); cacheDistances = new ArrayList<>();
cacheCenter = new QuadPoint(); cacheCenter = new QuadPoint();
maxRadiusInDp = mapActivity.getResources().getDimensionPixelSize(R.dimen.map_ruler_width); maxRadiusInDp = mapActivity.getResources().getDimensionPixelSize(R.dimen.map_ruler_width);
rightWidgetsPanel = mapActivity.findViewById(R.id.map_right_widgets_panel); rightWidgetsPanel = mapActivity.findViewById(R.id.map_right_widgets_panel);
distancePath = new Path(); distancePath = new Path();
tx = new TIntArrayList(); tx = new TIntArrayList();
ty = new TIntArrayList(); ty = new TIntArrayList();
firstTouchPoint = new PointF();
touchPoint = new PointF();
acceptableTouchRadius = mapActivity.getResources().getDimensionPixelSize(R.dimen.acceptable_touch_radius);
centerIconDay = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_ruler_center_day); centerIconDay = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_ruler_center_day);
centerIconNight = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_ruler_center_night); centerIconNight = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_ruler_center_night);
bitmapPaint = new Paint(); bitmapPaint = new Paint();
bitmapPaint.setAntiAlias(true); bitmapPaint.setAntiAlias(true);
bitmapPaint.setDither(true); bitmapPaint.setDither(true);
bitmapPaint.setFilterBitmap(true); bitmapPaint.setFilterBitmap(true);
lineAttrs = new RenderingLineAttributes("rulerLine"); lineAttrs = new RenderingLineAttributes("rulerLine");
float textSize = TEXT_SIZE * mapActivity.getResources().getDisplayMetrics().density; float textSize = TEXT_SIZE * mapActivity.getResources().getDisplayMetrics().density;
circleAttrs = new RenderingLineAttributes("rulerCircle"); circleAttrs = new RenderingLineAttributes("rulerCircle");
circleAttrs.paint2.setTextSize(textSize); circleAttrs.paint2.setTextSize(textSize);
circleAttrs.paint3.setTextSize(textSize); circleAttrs.paint3.setTextSize(textSize);
circleAttrsAlt = new RenderingLineAttributes("rulerCircleAlt"); circleAttrsAlt = new RenderingLineAttributes("rulerCircleAlt");
circleAttrsAlt.paint2.setTextSize(textSize); circleAttrsAlt.paint2.setTextSize(textSize);
circleAttrsAlt.paint3.setTextSize(textSize); circleAttrsAlt.paint3.setTextSize(textSize);
handler = new Handler() { handler = new Handler() {
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
view.refreshMap(); view.refreshMap();
} }
}; };
} }
@Override @Override
public boolean isMapGestureAllowed(MapGestureType type) { public boolean isMapGestureAllowed(MapGestureType type) {
if (rulerModeOn() && type == MapGestureType.TWO_POINTERS_ZOOM_OUT) { if (rulerModeOn() && type == MapGestureType.TWO_POINTERS_ZOOM_OUT) {
return false; return false;
} else { } else {
return true; return true;
} }
} }
@Override @Override
public boolean onTouchEvent(MotionEvent event, RotatedTileBox tileBox) { public boolean onTouchEvent(MotionEvent event, RotatedTileBox tileBox) {
if (event.getAction() == MotionEvent.ACTION_DOWN) { if (rulerModeOn()) {
showDistBetweenFingerAndLocation = true; if (event.getAction() == MotionEvent.ACTION_DOWN) {
singleTouchPointLatLon = tileBox.getLatLonFromPixel(event.getX(), event.getY()); touchOutside = false;
} else if (event.getAction() == MotionEvent.ACTION_UP) { firstTouchPoint.set(event.getX(), event.getY());
showDistBetweenFingerAndLocation = false; setSingleTouch(event.getX(), event.getY(), tileBox);
} } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
return false; double d = Math.sqrt(Math.pow(event.getX() - firstTouchPoint.x, 2) + Math.pow(event.getY() - firstTouchPoint.y, 2));
} if (d < acceptableTouchRadius) {
setSingleTouch(event.getX(), event.getY(), tileBox);
touchOutside = false;
} else {
touchOutside = true;
}
} else if (event.getAction() == MotionEvent.ACTION_UP) {
refreshMapDelayed();
}
}
return false;
}
@Override private void setSingleTouch(float x, float y, RotatedTileBox tb) {
public void onDraw(Canvas canvas, RotatedTileBox tb, DrawSettings settings) { touchTime = System.currentTimeMillis();
if (rulerModeOn()) { touchPoint.set(x, y);
lineAttrs.updatePaints(view, settings, tb); touchPointLatLon = tb.getLatLonFromPixel(x, y);
circleAttrs.updatePaints(view, settings, tb); }
circleAttrs.paint2.setStyle(Style.FILL);
circleAttrsAlt.updatePaints(view, settings, tb);
circleAttrsAlt.paint2.setStyle(Style.FILL);
final QuadPoint center = tb.getCenterPixelPoint();
final RulerMode mode = app.getSettings().RULER_MODE.get();
if (view.isMultiTouch()) { @Override
showDistBetweenFingerAndLocation = false; public void onDraw(Canvas canvas, RotatedTileBox tb, DrawSettings settings) {
} else if (cacheMultiTouchEndTime != view.getMultiTouchEndTime()) { if (rulerModeOn()) {
cacheMultiTouchEndTime = view.getMultiTouchEndTime(); lineAttrs.updatePaints(view, settings, tb);
refreshMapDelayed(); circleAttrs.updatePaints(view, settings, tb);
} circleAttrs.paint2.setStyle(Style.FILL);
showTwoFingersDistance = !view.isWasZoomInMultiTouch() && !tb.isZoomAnimated() && circleAttrsAlt.updatePaints(view, settings, tb);
(view.isMultiTouch() || System.currentTimeMillis() - cacheMultiTouchEndTime < DELAY); circleAttrsAlt.paint2.setStyle(Style.FILL);
final QuadPoint center = tb.getCenterPixelPoint();
final RulerMode mode = app.getSettings().RULER_MODE.get();
drawCenterIcon(canvas, tb, center, settings.isNightMode(), mode); if (cacheMultiTouchEndTime != view.getMultiTouchEndTime()) {
Location currentLoc = app.getLocationProvider().getLastKnownLocation(); cacheMultiTouchEndTime = view.getMultiTouchEndTime();
if (showDistBetweenFingerAndLocation && currentLoc != null) { refreshMapDelayed();
float x = tb.getPixXFromLonNoRot(singleTouchPointLatLon.getLongitude()); }
float y = tb.getPixYFromLatNoRot(singleTouchPointLatLon.getLatitude()); boolean wasNotZoom = !view.isWasZoomInMultiTouch() && !tb.isZoomAnimated();
drawDistBetweenFingerAndLocation(canvas, tb, x, y, currentLoc, settings.isNightMode()); showTwoFingersDistance = wasNotZoom &&
} else if (showTwoFingersDistance) { (view.isMultiTouch() || System.currentTimeMillis() - cacheMultiTouchEndTime < DRAW_TIME);
LatLon firstTouchPoint = view.getFirstTouchPointLatLon(); showDistBetweenFingerAndLocation = !showTwoFingersDistance && wasNotZoom && !view.isMultiTouch() &&
LatLon secondTouchPoint = view.getSecondTouchPointLatLon(); !touchOutside && System.currentTimeMillis() - touchTime > DELAY_BEFORE_DRAW &&
float x1 = tb.getPixXFromLonNoRot(firstTouchPoint.getLongitude()); System.currentTimeMillis() - touchTime < DRAW_TIME;
float y1 = tb.getPixYFromLatNoRot(firstTouchPoint.getLatitude());
float x2 = tb.getPixXFromLonNoRot(secondTouchPoint.getLongitude());
float y2 = tb.getPixYFromLatNoRot(secondTouchPoint.getLatitude());
drawFingerDistance(canvas, x1, y1, x2, y2, settings.isNightMode());
}
if (mode == RulerMode.FIRST || mode == RulerMode.SECOND) {
updateData(tb, center);
RenderingLineAttributes attrs;
if (mode == RulerMode.FIRST) {
attrs = circleAttrs;
} else {
attrs = circleAttrsAlt;
}
for (int i = 1; i <= cacheDistances.size(); i++) {
drawCircle(canvas, tb, i, center, attrs);
}
}
}
}
private boolean rulerModeOn() { drawCenterIcon(canvas, tb, center, settings.isNightMode(), mode);
return mapActivity.getMapLayers().getMapWidgetRegistry().isVisible("ruler") && Location currentLoc = app.getLocationProvider().getLastKnownLocation();
rightWidgetsPanel.getVisibility() == View.VISIBLE; if (showDistBetweenFingerAndLocation && currentLoc != null) {
} float x = tb.getPixXFromLonNoRot(touchPointLatLon.getLongitude());
float y = tb.getPixYFromLatNoRot(touchPointLatLon.getLatitude());
drawDistBetweenFingerAndLocation(canvas, tb, x, y, currentLoc, settings.isNightMode());
} else if (showTwoFingersDistance) {
LatLon firstTouchPoint = view.getFirstTouchPointLatLon();
LatLon secondTouchPoint = view.getSecondTouchPointLatLon();
float x1 = tb.getPixXFromLonNoRot(firstTouchPoint.getLongitude());
float y1 = tb.getPixYFromLatNoRot(firstTouchPoint.getLatitude());
float x2 = tb.getPixXFromLonNoRot(secondTouchPoint.getLongitude());
float y2 = tb.getPixYFromLatNoRot(secondTouchPoint.getLatitude());
drawFingerDistance(canvas, x1, y1, x2, y2, settings.isNightMode());
}
if (mode == RulerMode.FIRST || mode == RulerMode.SECOND) {
updateData(tb, center);
RenderingLineAttributes attrs;
if (mode == RulerMode.FIRST) {
attrs = circleAttrs;
} else {
attrs = circleAttrsAlt;
}
for (int i = 1; i <= cacheDistances.size(); i++) {
drawCircle(canvas, tb, i, center, attrs);
}
}
}
}
public void refreshMapDelayed() { private boolean rulerModeOn() {
handler.sendEmptyMessageDelayed(0, DELAY + 50); return mapActivity.getMapLayers().getMapWidgetRegistry().isVisible("ruler") &&
} rightWidgetsPanel.getVisibility() == View.VISIBLE;
}
private void drawFingerDistance(Canvas canvas, float x1, float y1, float x2, float y2, boolean nightMode) { private void refreshMapDelayed() {
canvas.drawLine(x1, y1, x2, y2, lineAttrs.paint); handler.sendEmptyMessageDelayed(0, DRAW_TIME + 50);
drawFingerTouchIcon(canvas, x1, y1, nightMode); }
drawFingerTouchIcon(canvas, x2, y2, nightMode);
}
private void drawFingerTouchIcon(Canvas canvas, float x, float y, boolean nightMode) { private void drawFingerDistance(Canvas canvas, float x1, float y1, float x2, float y2, boolean nightMode) {
if (nightMode) { canvas.drawLine(x1, y1, x2, y2, lineAttrs.paint);
canvas.drawBitmap(centerIconNight, x - centerIconNight.getWidth() / 2, drawFingerTouchIcon(canvas, x1, y1, nightMode);
y - centerIconNight.getHeight() / 2, bitmapPaint); drawFingerTouchIcon(canvas, x2, y2, nightMode);
} else { }
canvas.drawBitmap(centerIconDay, x - centerIconDay.getWidth() / 2,
y - centerIconDay.getHeight() / 2, bitmapPaint);
}
}
private void drawCenterIcon(Canvas canvas, RotatedTileBox tb, QuadPoint center, boolean nightMode, private void drawFingerTouchIcon(Canvas canvas, float x, float y, boolean nightMode) {
RulerMode mode) { if (nightMode) {
canvas.rotate(-tb.getRotate(), center.x, center.y); canvas.drawBitmap(centerIconNight, x - centerIconNight.getWidth() / 2,
if (nightMode || mode == RulerMode.SECOND) { y - centerIconNight.getHeight() / 2, bitmapPaint);
canvas.drawBitmap(centerIconNight, center.x - centerIconNight.getWidth() / 2, } else {
center.y - centerIconNight.getHeight() / 2, bitmapPaint); canvas.drawBitmap(centerIconDay, x - centerIconDay.getWidth() / 2,
} else { y - centerIconDay.getHeight() / 2, bitmapPaint);
canvas.drawBitmap(centerIconDay, center.x - centerIconDay.getWidth() / 2, }
center.y - centerIconDay.getHeight() / 2, bitmapPaint); }
}
canvas.rotate(tb.getRotate(), center.x, center.y);
}
private void drawDistBetweenFingerAndLocation(Canvas canvas, RotatedTileBox tb, float x, float y, private void drawCenterIcon(Canvas canvas, RotatedTileBox tb, QuadPoint center, boolean nightMode,
Location currentLoc, boolean nightMode) { RulerMode mode) {
int currX = tb.getPixXFromLonNoRot(currentLoc.getLongitude()); canvas.rotate(-tb.getRotate(), center.x, center.y);
int currY = tb.getPixYFromLatNoRot(currentLoc.getLatitude()); if (nightMode || mode == RulerMode.SECOND) {
distancePath.reset(); canvas.drawBitmap(centerIconNight, center.x - centerIconNight.getWidth() / 2,
tx.clear(); center.y - centerIconNight.getHeight() / 2, bitmapPaint);
ty.clear(); } else {
canvas.drawBitmap(centerIconDay, center.x - centerIconDay.getWidth() / 2,
center.y - centerIconDay.getHeight() / 2, bitmapPaint);
}
canvas.rotate(tb.getRotate(), center.x, center.y);
}
tx.add(currX); private void drawDistBetweenFingerAndLocation(Canvas canvas, RotatedTileBox tb, float x, float y,
ty.add(currY); Location currentLoc, boolean nightMode) {
tx.add((int) x); int currX = tb.getPixXFromLonNoRot(currentLoc.getLongitude());
ty.add((int) y); int currY = tb.getPixYFromLatNoRot(currentLoc.getLatitude());
distancePath.reset();
tx.clear();
ty.clear();
calculatePath(tb, tx, ty, distancePath); tx.add(currX);
canvas.drawPath(distancePath, lineAttrs.paint); ty.add(currY);
drawFingerTouchIcon(canvas, x, y, nightMode); tx.add((int) x);
} ty.add((int) y);
private void updateData(RotatedTileBox tb, QuadPoint center) { calculatePath(tb, tx, ty, distancePath);
if (tb.getPixHeight() > 0 && tb.getPixWidth() > 0 && maxRadiusInDp > 0) { canvas.drawPath(distancePath, lineAttrs.paint);
if (cacheCenter.y != center.y || cacheCenter.x != center.x) { drawFingerTouchIcon(canvas, x, y, nightMode);
cacheCenter = center; }
updateCenter(tb, center);
}
boolean move = tb.getZoom() != cacheIntZoom || Math.abs(tb.getCenterTileX() - cacheTileX) > 1 || private void updateData(RotatedTileBox tb, QuadPoint center) {
Math.abs(tb.getCenterTileY() - cacheTileY) > 1; if (tb.getPixHeight() > 0 && tb.getPixWidth() > 0 && maxRadiusInDp > 0) {
if (cacheCenter.y != center.y || cacheCenter.x != center.x) {
cacheCenter = center;
updateCenter(tb, center);
}
if (!tb.isZoomAnimated() && move) { boolean move = tb.getZoom() != cacheIntZoom || Math.abs(tb.getCenterTileX() - cacheTileX) > 1 ||
cacheIntZoom = tb.getZoom(); Math.abs(tb.getCenterTileY() - cacheTileY) > 1;
cacheTileX = tb.getCenterTileX();
cacheTileY = tb.getCenterTileY();
cacheDistances.clear();
updateDistance(tb);
}
}
}
private void updateCenter(RotatedTileBox tb, QuadPoint center) { if (!tb.isZoomAnimated() && move) {
float topDist = center.y; cacheIntZoom = tb.getZoom();
float bottomDist = tb.getPixHeight() - center.y; cacheTileX = tb.getCenterTileX();
float leftDist = center.x; cacheTileY = tb.getCenterTileY();
float rightDist = tb.getPixWidth() - center.x; cacheDistances.clear();
float maxVertical = topDist >= bottomDist ? topDist : bottomDist; updateDistance(tb);
float maxHorizontal = rightDist >= leftDist ? rightDist : leftDist; }
}
}
if (maxVertical >= maxHorizontal) { private void updateCenter(RotatedTileBox tb, QuadPoint center) {
maxRadius = maxVertical; float topDist = center.y;
textSide = TextSide.VERTICAL; float bottomDist = tb.getPixHeight() - center.y;
} else { float leftDist = center.x;
maxRadius = maxHorizontal; float rightDist = tb.getPixWidth() - center.x;
textSide = TextSide.HORIZONTAL; float maxVertical = topDist >= bottomDist ? topDist : bottomDist;
} float maxHorizontal = rightDist >= leftDist ? rightDist : leftDist;
if (radius != 0) {
updateText();
}
}
private void updateDistance(RotatedTileBox tb) { if (maxVertical >= maxHorizontal) {
final double dist = tb.getDistance(0, tb.getPixHeight() / 2, tb.getPixWidth(), tb.getPixHeight() / 2); maxRadius = maxVertical;
double pixDensity = tb.getPixWidth() / dist; textSide = TextSide.VERTICAL;
roundedDist = OsmAndFormatter.calculateRoundedDist(maxRadiusInDp / pixDensity, app); } else {
radius = (int) (pixDensity * roundedDist); maxRadius = maxHorizontal;
updateText(); textSide = TextSide.HORIZONTAL;
} }
if (radius != 0) {
updateText();
}
}
private void updateText() { private void updateDistance(RotatedTileBox tb) {
double maxCircleRadius = maxRadius; final double dist = tb.getDistance(0, tb.getPixHeight() / 2, tb.getPixWidth(), tb.getPixHeight() / 2);
int i = 1; double pixDensity = tb.getPixWidth() / dist;
while ((maxCircleRadius -= radius) > 0) { roundedDist = OsmAndFormatter.calculateRoundedDist(maxRadiusInDp / pixDensity, app);
cacheDistances.add(OsmAndFormatter radius = (int) (pixDensity * roundedDist);
.getFormattedDistance((float) roundedDist * i++, app, false).replaceAll(" ", "")); updateText();
} }
}
private void drawCircle(Canvas canvas, RotatedTileBox tb, int circleNumber, QuadPoint center, private void updateText() {
RenderingLineAttributes attrs) { double maxCircleRadius = maxRadius;
if (!tb.isZoomAnimated()) { int i = 1;
Rect bounds = new Rect(); while ((maxCircleRadius -= radius) > 0) {
String text = cacheDistances.get(circleNumber - 1); cacheDistances.add(OsmAndFormatter
attrs.paint2.getTextBounds(text, 0, text.length(), bounds); .getFormattedDistance((float) roundedDist * i++, app, false).replaceAll(" ", ""));
}
}
// coords of left or top text private void drawCircle(Canvas canvas, RotatedTileBox tb, int circleNumber, QuadPoint center,
float x1 = 0; RenderingLineAttributes attrs) {
float y1 = 0; if (!tb.isZoomAnimated()) {
// coords of right or bottom text Rect bounds = new Rect();
float x2 = 0; String text = cacheDistances.get(circleNumber - 1);
float y2 = 0; attrs.paint2.getTextBounds(text, 0, text.length(), bounds);
if (textSide == TextSide.VERTICAL) { // coords of left or top text
x1 = center.x - bounds.width() / 2; float x1 = 0;
y1 = center.y - radius * circleNumber + bounds.height() / 2; float y1 = 0;
x2 = center.x - bounds.width() / 2; // coords of right or bottom text
y2 = center.y + radius * circleNumber + bounds.height() / 2; float x2 = 0;
} else if (textSide == TextSide.HORIZONTAL) { float y2 = 0;
x1 = center.x - radius * circleNumber - bounds.width() / 2;
y1 = center.y + bounds.height() / 2;
x2 = center.x + radius * circleNumber - bounds.width() / 2;
y2 = center.y + bounds.height() / 2;
}
canvas.rotate(-tb.getRotate(), center.x, center.y); if (textSide == TextSide.VERTICAL) {
canvas.drawCircle(center.x, center.y, radius * circleNumber, attrs.shadowPaint); x1 = center.x - bounds.width() / 2;
canvas.drawCircle(center.x, center.y, radius * circleNumber, attrs.paint); y1 = center.y - radius * circleNumber + bounds.height() / 2;
canvas.drawText(text, x1, y1, attrs.paint3); x2 = center.x - bounds.width() / 2;
canvas.drawText(text, x1, y1, attrs.paint2); y2 = center.y + radius * circleNumber + bounds.height() / 2;
canvas.drawText(text, x2, y2, attrs.paint3); } else if (textSide == TextSide.HORIZONTAL) {
canvas.drawText(text, x2, y2, attrs.paint2); x1 = center.x - radius * circleNumber - bounds.width() / 2;
canvas.rotate(tb.getRotate(), center.x, center.y); y1 = center.y + bounds.height() / 2;
} x2 = center.x + radius * circleNumber - bounds.width() / 2;
} y2 = center.y + bounds.height() / 2;
}
private enum TextSide { canvas.rotate(-tb.getRotate(), center.x, center.y);
VERTICAL, canvas.drawCircle(center.x, center.y, radius * circleNumber, attrs.shadowPaint);
HORIZONTAL canvas.drawCircle(center.x, center.y, radius * circleNumber, attrs.paint);
} canvas.drawText(text, x1, y1, attrs.paint3);
canvas.drawText(text, x1, y1, attrs.paint2);
canvas.drawText(text, x2, y2, attrs.paint3);
canvas.drawText(text, x2, y2, attrs.paint2);
canvas.rotate(tb.getRotate(), center.x, center.y);
}
}
@Override private enum TextSide {
public void destroyLayer() { VERTICAL,
HORIZONTAL
}
} @Override
public void destroyLayer() {
@Override }
public boolean drawInScreenPixels() {
return false; @Override
} public boolean drawInScreenPixels() {
return false;
}
} }

View file

@ -127,8 +127,8 @@ public class MapInfoWidgetsFactory {
Location currentLoc = map.getMyApplication().getLocationProvider().getLastKnownLocation(); Location currentLoc = map.getMyApplication().getLocationProvider().getLastKnownLocation();
if (rulerLayer.isShowDistBetweenFingerAndLocation() && currentLoc != null) { if (rulerLayer.isShowDistBetweenFingerAndLocation() && currentLoc != null) {
if (!cacheSingleTouchPoint.equals(rulerLayer.getSingleTouchPointLatLon())) { if (!cacheSingleTouchPoint.equals(rulerLayer.getTouchPointLatLon())) {
cacheSingleTouchPoint = rulerLayer.getSingleTouchPointLatLon(); cacheSingleTouchPoint = rulerLayer.getTouchPointLatLon();
setDistanceText(cacheSingleTouchPoint.getLatitude(), cacheSingleTouchPoint.getLongitude(), setDistanceText(cacheSingleTouchPoint.getLatitude(), cacheSingleTouchPoint.getLongitude(),
currentLoc.getLatitude(), currentLoc.getLongitude()); currentLoc.getLatitude(), currentLoc.getLongitude());
fingerAndLocDistWasShown = true; fingerAndLocDistWasShown = true;