Add the ability to keep passed markers on the map

This commit is contained in:
Alex Sytnyk 2018-09-27 16:53:51 +03:00
parent 537396a00c
commit 2ad40bd795
11 changed files with 233 additions and 75 deletions

View file

@ -407,7 +407,6 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/content_padding"
android:layout_marginTop="@dimen/content_padding"
android:background="?attr/bg_card"
android:orientation="vertical">
@ -463,6 +462,65 @@
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/content_padding"
android:layout_marginTop="@dimen/content_padding"
android:background="?attr/bg_card"
android:orientation="vertical">
<LinearLayout
android:id="@+id/keep_passed_row"
android:layout_width="match_parent"
android:layout_height="@dimen/bottom_sheet_title_height"
android:background="?attr/selectableItemBackground"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/keep_passed_markers"
android:textAppearance="@style/TextAppearance.ListItemTitle"/>
<android.support.v7.widget.SwitchCompat
android:id="@+id/keep_passed_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginLeft="@dimen/bottom_sheet_content_margin_small"
android:layout_marginStart="@dimen/bottom_sheet_content_margin_small"
android:background="@null"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginStart="@dimen/content_padding"
android:background="?attr/dashboard_divider"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:paddingTop="@dimen/content_padding_small"
android:text="@string/keep_passed_markers_descr"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"/>
</LinearLayout>
</LinearLayout>
</com.github.ksoichiro.android.observablescrollview.ObservableScrollView>

View file

@ -458,6 +458,65 @@
<include layout="@layout/list_item_divider"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/bg_color"
android:orientation="vertical">
<LinearLayout
android:id="@+id/keep_passed_row"
android:layout_width="match_parent"
android:layout_height="@dimen/bottom_sheet_title_height"
android:background="?attr/selectableItemBackground"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/keep_passed_markers"
android:textAppearance="@style/TextAppearance.ListItemTitle"/>
<android.support.v7.widget.SwitchCompat
android:id="@+id/keep_passed_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginLeft="@dimen/bottom_sheet_content_margin_small"
android:layout_marginStart="@dimen/bottom_sheet_content_margin_small"
android:background="@null"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginStart="@dimen/content_padding"
android:background="?attr/dashboard_divider"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:paddingTop="@dimen/content_padding_small"
android:text="@string/keep_passed_markers_descr"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"/>
</LinearLayout>
<include layout="@layout/list_item_divider"/>
</LinearLayout>
</com.github.ksoichiro.android.observablescrollview.ObservableScrollView>

View file

@ -200,6 +200,7 @@
<color name="gpx_time_span_color">#0080FF</color>
<color name="color_favorite">#eecc22</color>
<color name="color_favorite_gray">#b3b3b3</color>
<!-- Themed color list items -->
<!-- invalid -red, localindex not supported, -->

View file

@ -10,7 +10,9 @@
- For wording and consistency, please note https://osmand.net/help-online?id=technical-articles#Creating_a_Consistent_User_Experience
Thx - Hardy
-->
<string name="shared_string_restore">Restore</string>
<string name="keep_passed_markers_descr">Markers added as a group of Favorites or GPX waypoints marked "Passed" will remain on the map. If the group is not active, the markers will disappear from the map.</string>
<string name="keep_passed_markers">Keep passed markers on the map</string>
<string name="more_transport_on_stop_hint">There is more transport on this stop.</string>
<string name="ask_for_location_permission">Please give OsmAnd permission for location to continue.</string>
<string name="thank_you_for_feedback">Thank you for feedback</string>

View file

@ -580,7 +580,7 @@ public class MapMarkersHelper {
@Nullable
public MapMarker getMapMarker(WptPt wptPt) {
for (MapMarker marker : mapMarkers) {
for (MapMarker marker : getMarkers()) {
if (marker.wptPt == wptPt) {
return marker;
}
@ -590,7 +590,7 @@ public class MapMarkersHelper {
@Nullable
public MapMarker getMapMarker(FavouritePoint favouritePoint) {
for (MapMarker marker : mapMarkers) {
for (MapMarker marker : getMarkers()) {
if (marker.favouritePoint == favouritePoint) {
return marker;
}
@ -600,7 +600,7 @@ public class MapMarkersHelper {
@Nullable
public MapMarker getMapMarker(@NonNull LatLon latLon) {
for (MapMarker marker : mapMarkers) {
for (MapMarker marker : getMarkers()) {
if (marker.point != null && marker.point.equals(latLon)) {
return marker;
}
@ -608,6 +608,14 @@ public class MapMarkersHelper {
return null;
}
private List<MapMarker> getMarkers() {
List<MapMarker> res = new ArrayList<>(mapMarkers);
if (settings.KEEP_PASSED_MARKERS_ON_MAP.get()) {
res.addAll(mapMarkersHistory);
}
return res;
}
@Nullable
public MapMarker getMapMarker(@NonNull String mapObjectName, @NonNull LatLon latLon) {
for (MapMarker marker : mapMarkers) {

View file

@ -723,6 +723,7 @@ public class OsmandSettings {
public final CommonPreference<WikiArticleShowImages> WIKI_ARTICLE_SHOW_IMAGES = new EnumIntPreference<>("wikivoyage_show_imgs", WikiArticleShowImages.OFF, WikiArticleShowImages.values()).makeGlobal();
public final CommonPreference<Boolean> SELECT_MARKER_ON_SINGLE_TAP = new BooleanPreference("select_marker_on_single_tap", false).makeProfile();
public final CommonPreference<Boolean> KEEP_PASSED_MARKERS_ON_MAP = new BooleanPreference("keep_passed_markers_on_map", true).makeProfile();
public final CommonPreference<Boolean> COORDS_INPUT_USE_RIGHT_SIDE = new BooleanPreference("coords_input_use_right_side", true).makeGlobal();
public final OsmandPreference<Format> COORDS_INPUT_FORMAT = new EnumIntPreference<>("coords_input_format", Format.DD_MM_MMM, Format.values()).makeGlobal();

View file

@ -13,64 +13,62 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.v4.content.res.ResourcesCompat;
import net.osmand.plus.R;
import java.util.TreeMap;
public class FavoriteImageDrawable extends Drawable {
private int color;
private Paint paintIcon;
private Paint paintBackground;
private boolean withShadow;
private boolean synced;
private boolean history;
private Bitmap favIcon;
private Bitmap favBackground;
private Bitmap syncedStroke;
private Bitmap syncedColor;
private Bitmap syncedShadow;
private Bitmap syncedIcon;
private Resources resources;
private boolean withShadow;
private boolean synced;
private Paint paintOuter;
private Paint paintInnerCircle;
private Drawable listDrawable;
private Paint paintIcon = new Paint();
private Paint paintBackground = new Paint();
private Paint paintOuter = new Paint();
private Paint paintInnerCircle = new Paint();
private ColorFilter colorFilter;
private ColorFilter grayFilter;
public FavoriteImageDrawable(Context ctx, int color, boolean withShadow, boolean synced) {
this.withShadow = withShadow;
this.synced = synced;
this.resources = ctx.getResources();
this.color = color;
paintBackground = new Paint();
int col = color == 0 || color == Color.BLACK ? getResources().getColor(R.color.color_favorite) : color;
paintBackground.setColorFilter(new PorterDuffColorFilter(col, PorterDuff.Mode.MULTIPLY));
paintIcon = new Paint();
favIcon = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.map_favorite);
favBackground = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.map_white_favorite_shield);
syncedStroke = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.map_shield_marker_point_stroke);
syncedColor = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.map_shield_marker_point_color);
syncedShadow = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.map_shield_marker_point_shadow);
syncedIcon = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.map_marker_point_14dp);
listDrawable = ResourcesCompat.getDrawable(getResources(), R.drawable.ic_action_fav_dark, null).mutate();
paintOuter = new Paint();
paintOuter.setAntiAlias(true);
paintOuter.setStyle(Style.FILL_AND_STROKE);
paintInnerCircle = new Paint();
paintInnerCircle.setStyle(Style.FILL_AND_STROKE);
paintOuter.setColor(color == 0 || color == Color.BLACK ? 0x88555555 : color);
paintInnerCircle.setColor(color == 0 || color == Color.BLACK ? getResources().getColor(R.color.color_favorite)
: color);
paintInnerCircle.setAntiAlias(true);
Resources res = ctx.getResources();
int col = color == 0 || color == Color.BLACK ? res.getColor(R.color.color_favorite) : color;
favIcon = BitmapFactory.decodeResource(res, R.drawable.map_favorite);
favBackground = BitmapFactory.decodeResource(res, R.drawable.map_white_favorite_shield);
syncedStroke = BitmapFactory.decodeResource(res, R.drawable.map_shield_marker_point_stroke);
syncedColor = BitmapFactory.decodeResource(res, R.drawable.map_shield_marker_point_color);
syncedShadow = BitmapFactory.decodeResource(res, R.drawable.map_shield_marker_point_shadow);
syncedIcon = BitmapFactory.decodeResource(res, R.drawable.map_marker_point_14dp);
listDrawable = ResourcesCompat.getDrawable(res, R.drawable.ic_action_fav_dark, null).mutate();
initSimplePaint(paintOuter, color == 0 || color == Color.BLACK ? 0x88555555 : color);
initSimplePaint(paintInnerCircle, col);
colorFilter = new PorterDuffColorFilter(col, PorterDuff.Mode.MULTIPLY);
grayFilter = new PorterDuffColorFilter(res.getColor(R.color.color_favorite_gray), PorterDuff.Mode.MULTIPLY);
}
private void initSimplePaint(Paint paint, int color) {
paint.setAntiAlias(true);
paint.setStyle(Style.FILL_AND_STROKE);
paint.setColor(color);
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
if (!withShadow && !synced) {
Rect bs = new Rect(bounds);
//bs.inset((int) (4 * density), (int) (4 * density));
//bs.inset((int) (4 * density), (int) (4 * density));
bs.inset(bs.width() / 4, bs.height() / 4);
listDrawable.setBounds(bs);
}
@ -86,16 +84,9 @@ public class FavoriteImageDrawable extends Drawable {
return synced ? syncedShadow.getWidth() : favBackground.getWidth();
}
public int getColor() {
return color;
}
public Resources getResources() {
return resources;
}
@Override
public void draw(Canvas canvas) {
public void draw(@NonNull Canvas canvas) {
paintBackground.setColorFilter(history ? grayFilter : colorFilter);
Rect bs = getBounds();
if (synced) {
canvas.drawBitmap(syncedShadow, bs.exactCenterX() - syncedShadow.getWidth() / 2f, bs.exactCenterY() - syncedShadow.getHeight() / 2f, paintBackground);
@ -115,7 +106,8 @@ public class FavoriteImageDrawable extends Drawable {
}
}
public void drawBitmapInCenter(Canvas canvas, float x, float y) {
public void drawBitmapInCenter(Canvas canvas, float x, float y, boolean history) {
this.history = history;
float dx = x - getIntrinsicWidth() / 2f;
float dy = y - getIntrinsicHeight() / 2f;
canvas.translate(dx, dy);

View file

@ -38,35 +38,42 @@ public class MapMarkerMenuController extends MenuController {
MapActivity activity = getMapActivity();
if (activity != null) {
MapMarkersHelper markersHelper = activity.getMyApplication().getMapMarkersHelper();
markersHelper.moveMapMarkerToHistory(getMapMarker());
MapMarker marker = getMapMarker();
if (marker.history) {
markersHelper.restoreMarkerFromHistory(marker, 0);
} else {
markersHelper.moveMapMarkerToHistory(marker);
}
activity.getContextMenu().close();
}
}
};
leftTitleButtonController.caption = mapActivity.getString(R.string.mark_passed);
leftTitleButtonController.caption = mapActivity.getString(mapMarker.history ? R.string.shared_string_restore : R.string.mark_passed);
leftTitleButtonController.leftIcon = useStateList ? createStateListPassedIcon()
: createPassedIcon(getPassedIconBgNormalColorId(), 0);
rightTitleButtonController = new TitleButtonController() {
@Override
public void buttonPressed() {
MapActivity activity = getMapActivity();
if (activity != null) {
OsmandSettings.OsmandPreference<Boolean> indication
= activity.getMyApplication().getSettings().MARKERS_DISTANCE_INDICATION_ENABLED;
if (!indication.get()) {
indication.set(true);
activity.getMapLayers().getMapWidgetRegistry().updateMapMarkersMode(activity);
if (!mapMarker.history) {
rightTitleButtonController = new TitleButtonController() {
@Override
public void buttonPressed() {
MapActivity activity = getMapActivity();
if (activity != null) {
OsmandSettings.OsmandPreference<Boolean> indication
= activity.getMyApplication().getSettings().MARKERS_DISTANCE_INDICATION_ENABLED;
if (!indication.get()) {
indication.set(true);
activity.getMapLayers().getMapWidgetRegistry().updateMapMarkersMode(activity);
}
MapMarkersHelper markersHelper = activity.getMyApplication().getMapMarkersHelper();
markersHelper.moveMarkerToTop(getMapMarker());
activity.getContextMenu().close();
}
MapMarkersHelper markersHelper = activity.getMyApplication().getMapMarkersHelper();
markersHelper.moveMarkerToTop(getMapMarker());
activity.getContextMenu().close();
}
}
};
rightTitleButtonController.caption = mapActivity.getString(R.string.make_active);
rightTitleButtonController.leftIcon = useStateList ? createStateListShowOnTopbarIcon()
: createShowOnTopbarIcon(getDeviceTopNormalColorId(), R.color.dashboard_blue);
};
rightTitleButtonController.caption = mapActivity.getString(R.string.make_active);
rightTitleButtonController.leftIcon = useStateList ? createStateListShowOnTopbarIcon()
: createShowOnTopbarIcon(getDeviceTopNormalColorId(), R.color.dashboard_blue);
}
}
private int getPassedIconBgNormalColorId() {

View file

@ -193,6 +193,15 @@ public class DirectionIndicationDialogFragment extends BaseOsmAndDialogFragment
}
});
final CompoundButton keepPassedToggle = (CompoundButton) mainView.findViewById(R.id.keep_passed_switch);
keepPassedToggle.setChecked(settings.KEEP_PASSED_MARKERS_ON_MAP.get());
mainView.findViewById(R.id.keep_passed_row).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
updateChecked(settings.KEEP_PASSED_MARKERS_ON_MAP, keepPassedToggle);
}
});
return mainView;
}

View file

@ -46,7 +46,10 @@ public class FavouritesLayer extends OsmandMapLayer implements ContextMenuLayer.
private MapTextLayer textLayer;
private Paint paintIcon;
private Bitmap pointSmall;
@ColorInt
private int defaultColor;
@ColorInt
private int grayColor;
private OsmandSettings settings;
@ -70,6 +73,7 @@ public class FavouritesLayer extends OsmandMapLayer implements ContextMenuLayer.
paintIcon = new Paint();
pointSmall = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_white_shield_small);
defaultColor = ContextCompat.getColor(view.getContext(), R.color.color_favorite);
grayColor = ContextCompat.getColor(view.getContext(), R.color.color_favorite_gray);
contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class);
}
@ -135,8 +139,13 @@ public class FavouritesLayer extends OsmandMapLayer implements ContextMenuLayer.
if (intersects(boundIntersections, x, y, iconSize, iconSize)) {
@ColorInt
int col = o.getColor() == 0 || o.getColor() == Color.BLACK ? defaultColor : o.getColor();
paintIcon.setColorFilter(new PorterDuffColorFilter(col, PorterDuff.Mode.MULTIPLY));
int color;
if (marker != null && marker.history) {
color = grayColor;
} else {
color = o.getColor() == 0 || o.getColor() == Color.BLACK ? defaultColor : o.getColor();
}
paintIcon.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY));
canvas.drawBitmap(pointSmall, x - pointSmall.getWidth() / 2, y - pointSmall.getHeight() / 2, paintIcon);
smallObjectsLatLon.add(new LatLon(lat, lon));
} else {
@ -164,12 +173,14 @@ public class FavouritesLayer extends OsmandMapLayer implements ContextMenuLayer.
private void drawBigPoint(Canvas canvas, FavouritePoint o, float x, float y, @Nullable MapMarker marker) {
FavoriteImageDrawable fid;
boolean history = false;
if (marker != null) {
fid = FavoriteImageDrawable.getOrCreateSyncedIcon(view.getContext(), o.getColor());
history = marker.history;
} else {
fid = FavoriteImageDrawable.getOrCreate(view.getContext(), o.getColor(), true);
}
fid.drawBitmapInCenter(canvas, x, y);
fid.drawBitmapInCenter(canvas, x, y, history);
}

View file

@ -106,6 +106,8 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
private int visitedColor;
@ColorInt
private int defPointColor;
@ColorInt
private int grayColor;
@Override
public void initLayer(OsmandMapTileView view) {
@ -174,6 +176,7 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
visitedColor = ContextCompat.getColor(view.getApplication(), R.color.color_ok);
defPointColor = ContextCompat.getColor(view.getApplication(), R.color.gpx_color_point);
grayColor = ContextCompat.getColor(view.getApplication(), R.color.color_favorite_gray);
}
@Override
@ -381,8 +384,13 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
if (intersects(boundIntersections, x, y, iconSize, iconSize)) {
@ColorInt
int pointColor = getPointColor(o, fileColor);
paintIcon.setColorFilter(new PorterDuffColorFilter(pointColor, PorterDuff.Mode.MULTIPLY));
int color;
if (marker != null && marker.history) {
color = grayColor;
} else {
color = getPointColor(o, fileColor);
}
paintIcon.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY));
canvas.drawBitmap(pointSmall, x - pointSmall.getWidth() / 2, y - pointSmall.getHeight() / 2, paintIcon);
smallObjectsLatLon.add(new LatLon(o.lat, o.lon));
} else {
@ -464,12 +472,14 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
private void drawBigPoint(Canvas canvas, WptPt o, int fileColor, float x, float y, @Nullable MapMarker marker) {
int pointColor = getPointColor(o, fileColor);
FavoriteImageDrawable fid;
boolean history = false;
if (marker != null) {
fid = FavoriteImageDrawable.getOrCreateSyncedIcon(view.getContext(), pointColor);
history = marker.history;
} else {
fid = FavoriteImageDrawable.getOrCreate(view.getContext(), pointColor, true);
}
fid.drawBitmapInCenter(canvas, x, y);
fid.drawBitmapInCenter(canvas, x, y, history);
}
@ColorInt