From dd40c4dce61bc8b1e270706343766d3df13cc6e3 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Thu, 30 Jul 2020 21:34:57 +0300 Subject: [PATCH 1/6] Add new track appearance prefs for current recording track --- OsmAnd/res/layout/track_appearance.xml | 11 +- .../plus/settings/backend/OsmandSettings.java | 3 + .../plus/track/TrackAppearanceFragment.java | 44 ++++- .../net/osmand/plus/track/TrackDrawInfo.java | 4 + .../src/net/osmand/plus/views/GPXLayer.java | 175 ++++++++++-------- 5 files changed, 143 insertions(+), 94 deletions(-) diff --git a/OsmAnd/res/layout/track_appearance.xml b/OsmAnd/res/layout/track_appearance.xml index 5060722e54..089e1f174d 100644 --- a/OsmAnd/res/layout/track_appearance.xml +++ b/OsmAnd/res/layout/track_appearance.xml @@ -50,7 +50,7 @@ osmand:typeface="@string/font_roboto_medium" /> + android:layout_gravity="bottom" + tools:visibility="invisible"> + android:layout_marginRight="@dimen/fab_margin_right" /> + android:layout_marginRight="@dimen/fab_margin_right" /> diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java index ea5d75452f..28373853b7 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java @@ -2194,6 +2194,9 @@ public class OsmandSettings { public final OsmandPreference LAST_UPDATES_CARD_REFRESH = new LongPreference("last_updates_card_refresh", 0).makeGlobal(); public final CommonPreference CURRENT_TRACK_COLOR = new IntPreference("current_track_color", 0).makeGlobal().cache(); + public final CommonPreference CURRENT_TRACK_WIDTH = new StringPreference("current_track_width", "").makeGlobal().cache(); + public final CommonPreference CURRENT_TRACK_SHOW_ARROWS = new BooleanPreference("current_track_show_arrows", false).makeGlobal().cache(); + public final CommonPreference CURRENT_TRACK_SHOW_START_FINISH = new BooleanPreference("current_track_show_start_finish", true).makeGlobal().cache(); // this value string is synchronized with settings_pref.xml preference name public final CommonPreference SAVE_TRACK_INTERVAL = new IntPreference("save_track_interval", 5000).makeProfile(); diff --git a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java index b8e375a692..c56311e932 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java @@ -9,9 +9,11 @@ import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.ScrollView; import androidx.annotation.ColorInt; import androidx.annotation.NonNull; @@ -74,7 +76,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement private TrackWidthCard trackWidthCard; private SplitIntervalCard splitIntervalCard; - private ImageView appearanceIcon; + private ImageView trackIcon; @Override public int getMainLayoutId() { @@ -131,6 +133,10 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement } if (currentRecording) { trackDrawInfo = new TrackDrawInfo(true); + trackDrawInfo.setColor(app.getSettings().CURRENT_TRACK_COLOR.get()); + trackDrawInfo.setWidth(app.getSettings().CURRENT_TRACK_WIDTH.get()); + trackDrawInfo.setShowArrows(app.getSettings().CURRENT_TRACK_SHOW_ARROWS.get()); + trackDrawInfo.setShowStartFinish(app.getSettings().CURRENT_TRACK_SHOW_START_FINISH.get()); selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack(); } else { gpxDataItem = app.getGpxDbHelper().getItem(new File(gpxFilePath)); @@ -163,13 +169,14 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); if (view != null) { - appearanceIcon = view.findViewById(R.id.appearance_icon); + trackIcon = view.findViewById(R.id.track_icon); if (isPortrait()) { updateCardsLayout(); } - updateCards(); - updateButtons(view); + setupCards(); + setupButtons(view); + setupScrollShadow(); updateAppearanceIcon(); if (!isPortrait()) { int widthNoShadow = getLandscapeNoShadowWidth(); @@ -327,7 +334,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement private void updateAppearanceIcon() { Drawable icon = getTrackIcon(app, trackDrawInfo.getWidth(), trackDrawInfo.isShowArrows(), trackDrawInfo.getColor()); - appearanceIcon.setImageDrawable(icon); + trackIcon.setImageDrawable(icon); } private void adjustMapPosition(int y) { @@ -387,7 +394,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement } } - private void updateButtons(View view) { + private void setupButtons(View view) { View buttonsContainer = view.findViewById(R.id.buttons_container); buttonsContainer.setBackgroundColor(AndroidUtils.getColorFromAttr(view.getContext(), R.attr.route_info_bg)); View saveButton = view.findViewById(R.id.right_bottom_button); @@ -418,6 +425,26 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement AndroidUiHelper.updateVisibility(view.findViewById(R.id.buttons_divider), true); } + private void setupScrollShadow() { + int shadowIconId = isNightMode() ? R.drawable.bg_contextmenu_shadow : R.drawable.bg_contextmenu_shadow; + final Drawable shadowIcon = app.getUIUtilities().getIcon(shadowIconId); + + final ScrollView scrollView = getBottomScrollView(); + final FrameLayout bottomContainer = getBottomContainer(); + scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() { + + @Override + public void onScrollChanged() { + int scrollY = scrollView.getScrollY(); + if (scrollY <= 0 && bottomContainer.getForeground() != null) { + bottomContainer.setForeground(null); + } else if (scrollY > 0 && bottomContainer.getForeground() == null) { + bottomContainer.setForeground(shadowIcon); + } + } + }); + } + private void saveTrackInfo() { GPXFile gpxFile = selectedGpxFile.getGpxFile(); @@ -440,6 +467,9 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement if (gpxFile.showCurrentTrack) { app.getSettings().CURRENT_TRACK_COLOR.set(trackDrawInfo.getColor()); + app.getSettings().CURRENT_TRACK_WIDTH.set(trackDrawInfo.getWidth()); + app.getSettings().CURRENT_TRACK_SHOW_ARROWS.set(trackDrawInfo.isShowArrows()); + app.getSettings().CURRENT_TRACK_SHOW_START_FINISH.set(trackDrawInfo.isShowStartFinish()); } else { if (gpxDataItem != null) { gpxDataItem = new GpxDataItem(new File(gpxFile.path), gpxFile); @@ -508,7 +538,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } - private void updateCards() { + private void setupCards() { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { ViewGroup cardsContainer = getCardsContainer(); diff --git a/OsmAnd/src/net/osmand/plus/track/TrackDrawInfo.java b/OsmAnd/src/net/osmand/plus/track/TrackDrawInfo.java index 9773ddd329..3dbacb7b56 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackDrawInfo.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackDrawInfo.java @@ -109,6 +109,10 @@ public class TrackDrawInfo { this.showArrows = showArrows; } + public void setShowStartFinish(boolean showStartFinish) { + this.showStartFinish = showStartFinish; + } + public boolean isShowStartFinish() { return showStartFinish; } diff --git a/OsmAnd/src/net/osmand/plus/views/GPXLayer.java b/OsmAnd/src/net/osmand/plus/views/GPXLayer.java index 9e16b28060..8ee950f079 100644 --- a/OsmAnd/src/net/osmand/plus/views/GPXLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/GPXLayer.java @@ -89,9 +89,10 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM private Paint paint; private Paint shadowPaint; private Paint paintIcon; + private int cachedHash; + @ColorInt private int cachedColor; - private int currentTrackColor; private float defaultTrackWidth; private Map cachedTrackWidth = new HashMap<>(); @@ -129,8 +130,13 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM @ColorInt private int grayColor; - private CommonPreference currentTrackColorPref; + private CommonPreference defaultTrackColorPref; + private CommonPreference defaultTrackWidthPref; + + private CommonPreference currentTrackColorPref; private CommonPreference currentTrackWidthPref; + private CommonPreference currentTrackShowArrowsPref; + private CommonPreference currentTrackShowStartFinishPref; @Override public void initLayer(OsmandMapTileView view) { @@ -138,8 +144,14 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM selectedGpxHelper = view.getApplication().getSelectedGpxHelper(); mapMarkersHelper = view.getApplication().getMapMarkersHelper(); osmandRenderer = view.getApplication().getResourceManager().getRenderer().getRenderer(); - currentTrackColorPref = view.getSettings().getCustomRenderProperty(CURRENT_TRACK_COLOR_ATTR); - currentTrackWidthPref = view.getSettings().getCustomRenderProperty(CURRENT_TRACK_WIDTH_ATTR); + + currentTrackColorPref = view.getSettings().CURRENT_TRACK_COLOR; + currentTrackWidthPref = view.getSettings().CURRENT_TRACK_WIDTH; + currentTrackShowArrowsPref = view.getSettings().CURRENT_TRACK_SHOW_ARROWS; + currentTrackShowStartFinishPref = view.getSettings().CURRENT_TRACK_SHOW_START_FINISH; + defaultTrackColorPref = view.getSettings().getCustomRenderProperty(CURRENT_TRACK_COLOR_ATTR).cache(); + defaultTrackWidthPref = view.getSettings().getCustomRenderProperty(CURRENT_TRACK_WIDTH_ATTR).cache(); + initUI(); } @@ -228,7 +240,6 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) { List selectedGPXFiles = selectedGpxHelper.getSelectedGPXFiles(); cache.clear(); - currentTrackColor = view.getSettings().CURRENT_TRACK_COLOR.get(); if (!selectedGPXFiles.isEmpty()) { drawSelectedFilesSegments(canvas, tileBox, selectedGPXFiles, settings); canvas.rotate(-tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY()); @@ -249,7 +260,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM RenderingRulesStorage rrs = view.getApplication().getRendererRegistry().getCurrentSelectedRenderer(); boolean nightMode = drawSettings != null && drawSettings.isNightMode(); int hash = calculateHash(rrs, cachedTrackWidth, routePoints, nightMode, tileBox.getMapDensity(), tileBox.getZoom(), - currentTrackColorPref.get(), currentTrackWidthPref.get()); + defaultTrackColorPref.get(), defaultTrackWidthPref.get()); if (hash != cachedHash) { cachedHash = hash; cachedColor = ContextCompat.getColor(view.getApplication(), R.color.gpx_track); @@ -257,16 +268,16 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM if (rrs != null) { RenderingRuleSearchRequest req = new RenderingRuleSearchRequest(rrs); req.setBooleanFilter(rrs.PROPS.R_NIGHT_MODE, nightMode); - if (currentTrackColorPref != null && currentTrackColorPref.isSet()) { + if (defaultTrackColorPref != null && defaultTrackColorPref.isSet()) { RenderingRuleProperty ctColor = rrs.PROPS.get(CURRENT_TRACK_COLOR_ATTR); if (ctColor != null) { - req.setStringFilter(ctColor, currentTrackColorPref.get()); + req.setStringFilter(ctColor, defaultTrackColorPref.get()); } } - if (currentTrackWidthPref != null && currentTrackWidthPref.isSet()) { + if (defaultTrackWidthPref != null && defaultTrackWidthPref.isSet()) { RenderingRuleProperty ctWidth = rrs.PROPS.get(CURRENT_TRACK_WIDTH_ATTR); if (ctWidth != null) { - req.setStringFilter(ctWidth, currentTrackWidthPref.get()); + req.setStringFilter(ctWidth, defaultTrackWidthPref.get()); } } String additional = ""; @@ -305,10 +316,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } } paint.setColor(color == 0 ? cachedColor : color); - Float strikeWidth = cachedTrackWidth.get(width); - if (strikeWidth != null) { - paint.setStrokeWidth(strikeWidth); - } + paint.setStrokeWidth(getTrackWidth(width, defaultTrackWidth)); } private void acquireTrackWidth(String widthKey, RenderingRulesStorage rrs, RenderingRuleSearchRequest req, RenderingContext rc) { @@ -342,17 +350,10 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM if (tileBox.getZoom() >= START_ZOOM) { // request to load OsmandApplication app = view.getApplication(); - for (SelectedGpxFile g : selectedGPXFiles) { - List groups = g.getDisplayGroups(app); - if (groups != null && !groups.isEmpty()) { - int color = g.getGpxFile().getColor(0); - if (color == 0) { - color = g.getModifiableGpxFile().getColor(0); - } - if (color == 0) { - color = cachedColor; - } - + for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) { + List groups = selectedGpxFile.getDisplayGroups(app); + if (!Algorithms.isEmpty(groups)) { + int color = getTrackColor(selectedGpxFile.getGpxFile(), cachedColor); paintInnerRect.setColor(color); paintInnerRect.setAlpha(179); @@ -416,25 +417,12 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM private void drawDirectionArrows(Canvas canvas, RotatedTileBox tileBox, List selectedGPXFiles) { if (!tileBox.isZoomAnimated()) { for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) { - boolean showArrows = selectedGpxFile.getGpxFile().isShowArrows(); - if (hasTrackDrawInfoForSelectedGpx(selectedGpxFile)) { - showArrows = trackDrawInfo.isShowArrows(); - } + boolean showArrows = isShowArrowsForTrack(selectedGpxFile.getGpxFile()); if (showArrows) { QuadRect correctedQuadRect = getCorrectedQuadRect(tileBox.getLatLonBounds()); - String width = selectedGpxFile.getGpxFile().getWidth(currentTrackWidthPref.get()); - int color = selectedGpxFile.getGpxFile().getColor(cachedColor); - if (selectedGpxFile.isShowCurrentTrack()) { - color = currentTrackColor; - } - if (hasTrackDrawInfoForSelectedGpx(selectedGpxFile)) { - color = trackDrawInfo.getColor(); - width = trackDrawInfo.getWidth(); - } - Float trackWidth = cachedTrackWidth.get(width); - if (trackWidth == null) { - trackWidth = defaultTrackWidth; - } + String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get()); + float trackWidth = getTrackWidth(width, defaultTrackWidth); + int color = getTrackColor(selectedGpxFile.getGpxFile(), cachedColor); int contrastColor = UiUtilities.getContrastColor(view.getApplication(), color, false); GeometryWayStyle arrowsWayStyle = new GeometryArrowsWayStyle(wayContext, arrowBitmap, contrastColor, color, trackWidth); for (TrkSegment segment : selectedGpxFile.getPointsToDisplay()) { @@ -587,10 +575,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM private void drawSelectedFilesStartEndPoints(Canvas canvas, RotatedTileBox tileBox, List selectedGPXFiles) { if (tileBox.getZoom() >= START_ZOOM) { for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) { - boolean showStartFinish = selectedGpxFile.getGpxFile().isShowStartFinish(); - if (hasTrackDrawInfoForSelectedGpx(selectedGpxFile)) { - showStartFinish = trackDrawInfo.isShowStartFinish(); - } + boolean showStartFinish = isShowStartFinishForTrack(selectedGpxFile.getGpxFile()); if (showStartFinish) { List segments = selectedGpxFile.getPointsToDisplay(); for (TrkSegment segment : segments) { @@ -605,11 +590,6 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } } - private boolean hasTrackDrawInfoForSelectedGpx(SelectedGpxFile selectedGpxFile) { - return trackDrawInfo != null && (trackDrawInfo.isCurrentRecording() && selectedGpxFile.isShowCurrentTrack() - || selectedGpxFile.getGpxFile().path.equals(trackDrawInfo.getFilePath())); - } - private void drawStartEndPoints(Canvas canvas, RotatedTileBox tileBox, WptPt start, WptPt end) { int startX = (int) tileBox.getPixXFromLatLon(start.lat, start.lon); int startY = (int) tileBox.getPixYFromLatLon(start.lat, start.lon); @@ -717,13 +697,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM private void drawXAxisPoints(Canvas canvas, RotatedTileBox tileBox) { int color = trackChartPoints.getSegmentColor(); if (color == 0) { - color = trackChartPoints.getGpx().getColor(0); - if (trackChartPoints.getGpx().showCurrentTrack) { - color = currentTrackColor; - } - if (color == 0) { - color = cachedColor; - } + color = getTrackColor(trackChartPoints.getGpx(), cachedColor); trackChartPoints.setSegmentColor(color); } paintGridCircle.setColor(color); @@ -782,21 +756,16 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM private void drawSelectedFilesSegments(Canvas canvas, RotatedTileBox tileBox, List selectedGPXFiles, DrawSettings settings) { + SelectedGpxFile currentTrack = null; for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) { - String width = selectedGpxFile.getGpxFile().getWidth(currentTrackWidthPref.get()); - if (hasTrackDrawInfoForSelectedGpx(selectedGpxFile)) { - width = trackDrawInfo.getWidth(); - } + String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get()); if (!cachedTrackWidth.containsKey(width)) { cachedTrackWidth.put(width, null); } - } - SelectedGpxFile currentTrack = null; - for (SelectedGpxFile g : selectedGPXFiles) { - if (g.isShowCurrentTrack()) { - currentTrack = g; + if (selectedGpxFile.isShowCurrentTrack()) { + currentTrack = selectedGpxFile; } else { - drawSelectedFileSegments(g, false, canvas, tileBox, settings); + drawSelectedFileSegments(selectedGpxFile, false, canvas, tileBox, settings); } } if (currentTrack != null) { @@ -805,21 +774,11 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } private void drawSelectedFileSegments(SelectedGpxFile selectedGpxFile, boolean currentTrack, Canvas canvas, - RotatedTileBox tileBox, DrawSettings settings) { + RotatedTileBox tileBox, DrawSettings settings) { List segments = selectedGpxFile.getPointsToDisplay(); for (TrkSegment ts : segments) { - String width = selectedGpxFile.getGpxFile().getWidth(currentTrackWidthPref.get()); - int color = selectedGpxFile.getGpxFile().getColor(0); - if (currentTrack) { - color = currentTrackColor; - } - if (color == 0) { - color = ts.getColor(cachedColor); - } - if (hasTrackDrawInfoForSelectedGpx(selectedGpxFile)) { - color = trackDrawInfo.getColor(); - width = trackDrawInfo.getWidth(); - } + String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get()); + int color = getTrackColor(selectedGpxFile.getGpxFile(), ts.getColor(cachedColor)); if (ts.renderer == null && !ts.points.isEmpty()) { if (currentTrack) { ts.renderer = new Renderable.CurrentTrack(ts.points); @@ -834,6 +793,60 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } } + private float getTrackWidth(String width, float defaultTrackWidth) { + Float trackWidth = cachedTrackWidth.get(width); + return trackWidth != null ? trackWidth : defaultTrackWidth; + } + + private int getTrackColor(GPXFile gpxFile, int defaultColor) { + int color; + if (hasTrackDrawInfoForTrack(gpxFile)) { + color = trackDrawInfo.getColor(); + } else if (gpxFile.showCurrentTrack) { + color = currentTrackColorPref.get(); + } else { + color = gpxFile.getColor(defaultColor); + } + return color != 0 ? color : defaultColor; + } + + private String getTrackWidthName(GPXFile gpxFile, String defaultWidth) { + String width; + if (hasTrackDrawInfoForTrack(gpxFile)) { + width = trackDrawInfo.getWidth(); + } else if (gpxFile.showCurrentTrack) { + width = currentTrackWidthPref.get(); + } else { + width = gpxFile.getWidth(defaultWidth); + } + return width != null ? width : defaultWidth; + } + + private boolean isShowArrowsForTrack(GPXFile gpxFile) { + if (hasTrackDrawInfoForTrack(gpxFile)) { + return trackDrawInfo.isShowArrows(); + } else if (gpxFile.showCurrentTrack) { + return currentTrackShowArrowsPref.get(); + } else { + return gpxFile.isShowArrows(); + } + } + + private boolean isShowStartFinishForTrack(GPXFile gpxFile) { + if (hasTrackDrawInfoForTrack(gpxFile)) { + return trackDrawInfo.isShowStartFinish(); + } else if (gpxFile.showCurrentTrack) { + return currentTrackShowStartFinishPref.get(); + } else { + return gpxFile.isShowStartFinish(); + } + } + + private boolean hasTrackDrawInfoForTrack(GPXFile gpxFile) { + return trackDrawInfo != null && (trackDrawInfo.isCurrentRecording() && gpxFile.showCurrentTrack + || gpxFile.path.equals(trackDrawInfo.getFilePath())); + } + private boolean isPointVisited(WptPt o) { boolean visit = false; String visited = o.getExtensionsToRead().get("VISITED_KEY"); From 0f89e927e0231df69afa08ad5a8c0d7f502527a0 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Fri, 31 Jul 2020 12:00:46 +0300 Subject: [PATCH 2/6] Fix dancing split interval --- .../src/net/osmand/plus/views/GPXLayer.java | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/views/GPXLayer.java b/OsmAnd/src/net/osmand/plus/views/GPXLayer.java index 8ee950f079..b2a893d6f3 100644 --- a/OsmAnd/src/net/osmand/plus/views/GPXLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/GPXLayer.java @@ -374,15 +374,14 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM int r = (int) (12 * tileBox.getDensity()); paintTextIcon.setTextSize(r); int dr = r * 3 / 2; - int px = -1; - int py = -1; + float px = -1; + float py = -1; for (int k = 0; k < items.size(); k++) { GpxDisplayItem i = items.get(k); - WptPt o = i.locationEnd; - if (o != null && o.lat >= latLonBounds.bottom && o.lat <= latLonBounds.top && o.lon >= latLonBounds.left - && o.lon <= latLonBounds.right) { - int x = (int) tileBox.getPixXFromLatLon(o.lat, o.lon); - int y = (int) tileBox.getPixYFromLatLon(o.lat, o.lon); + WptPt point = i.locationEnd; + if (point != null) { + float x = tileBox.getPixXFromLatLon(point.lat, point.lon); + float y = tileBox.getPixYFromLatLon(point.lat, point.lon); if (px != -1 || py != -1) { if (Math.abs(x - px) <= dr && Math.abs(y - py) <= dr) { continue; @@ -390,25 +389,29 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } px = x; py = y; - String nm = i.splitName; - if (nm != null) { - int ind = nm.indexOf(' '); - if (ind > 0) { - nm = nm.substring(0, ind); + if (point.lat >= latLonBounds.bottom && point.lat <= latLonBounds.top + && point.lon >= latLonBounds.left && point.lon <= latLonBounds.right) { + String name = i.splitName; + if (name != null) { + int ind = name.indexOf(' '); + if (ind > 0) { + name = name.substring(0, ind); + } + Rect bounds = new Rect(); + paintTextIcon.getTextBounds(name, 0, name.length(), bounds); + + float nameHalfWidth = bounds.width() / 2f; + float nameHalfHeight = bounds.height() / 2f; + float density = (float) Math.ceil(tileBox.getDensity()); + RectF rect = new RectF(x - nameHalfWidth - 2 * density, + y + nameHalfHeight + 3 * density, + x + nameHalfWidth + 3 * density, + y - nameHalfHeight - 2 * density); + + canvas.drawRoundRect(rect, 0, 0, paintInnerRect); + canvas.drawRoundRect(rect, 0, 0, paintOuterRect); + canvas.drawText(name, x, y + nameHalfHeight, paintTextIcon); } - Rect bounds = new Rect(); - paintTextIcon.getTextBounds(nm, 0, nm.length(), bounds); - int nmWidth = bounds.width(); - int nmHeight = bounds.height(); - RectF rect = new RectF(x - nmWidth / 2 - 2 * (float) Math.ceil(tileBox.getDensity()), - y + nmHeight / 2 + 3 * (float) Math.ceil(tileBox.getDensity()), - x + nmWidth / 2 + 3 * (float) Math.ceil(tileBox.getDensity()), - y - nmHeight / 2 - 2 * (float) Math.ceil(tileBox.getDensity())); - canvas.drawRoundRect(rect, 0, 0, paintInnerRect); - canvas.drawRoundRect(rect, 0, 0, paintOuterRect); -// canvas.drawRect(rect, paintInnerRect); -// canvas.drawRect(rect, paintOuterRect); - canvas.drawText(nm, x, y + nmHeight / 2, paintTextIcon); } } } @@ -1110,8 +1113,8 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM @Override public void applyNewObjectPosition(@NonNull Object o, - @NonNull LatLon position, - @Nullable final ContextMenuLayer.ApplyMovedObjectCallback callback) { + @NonNull LatLon position, + @Nullable final ContextMenuLayer.ApplyMovedObjectCallback callback) { if (o instanceof WptPt) { final WptPt objectInMotion = (WptPt) o; SelectedGpxFile selectedGpxFile = pointFileMap.get(objectInMotion); From 30a7ebcb305cc52329ff69760d65263afb61a833 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Fri, 31 Jul 2020 12:02:16 +0300 Subject: [PATCH 3/6] Fix split card visibility --- .../plus/track/SplitIntervalBottomSheet.java | 12 +++--------- .../osmand/plus/track/TrackAppearanceFragment.java | 14 +++++++++++++- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/track/SplitIntervalBottomSheet.java b/OsmAnd/src/net/osmand/plus/track/SplitIntervalBottomSheet.java index e102dfffa9..15d94db2cc 100644 --- a/OsmAnd/src/net/osmand/plus/track/SplitIntervalBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/track/SplitIntervalBottomSheet.java @@ -15,7 +15,6 @@ import com.google.android.material.slider.Slider; import net.osmand.PlatformUtil; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; -import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; @@ -30,6 +29,7 @@ import net.osmand.plus.helpers.AndroidUiHelper; import org.apache.commons.logging.Log; import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -310,17 +310,11 @@ public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment { @NonNull public List getDisplayGroups() { - List groups = new ArrayList<>(); Fragment target = getTargetFragment(); if (target instanceof TrackAppearanceFragment) { - List result = ((TrackAppearanceFragment) target).getGpxDisplayGroups(); - for (GpxDisplayGroup group : result) { - if (GpxDisplayItemType.TRACK_SEGMENT == group.getType()) { - groups.add(group); - } - } + return ((TrackAppearanceFragment) target).getDisplaySegmentGroups(); } - return groups; + return Collections.emptyList(); } public static void showInstance(@NonNull FragmentManager fragmentManager, TrackDrawInfo trackDrawInfo, Fragment target) { diff --git a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java index c56311e932..0c2176687c 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java @@ -28,6 +28,7 @@ import net.osmand.data.QuadRect; import net.osmand.data.RotatedTileBox; import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; +import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; @@ -544,7 +545,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement ViewGroup cardsContainer = getCardsContainer(); cardsContainer.removeAllViews(); - if (!selectedGpxFile.isShowCurrentTrack()) { + if (!selectedGpxFile.isShowCurrentTrack() && !Algorithms.isEmpty(getDisplaySegmentGroups())) { splitIntervalCard = new SplitIntervalCard(mapActivity, trackDrawInfo); splitIntervalCard.setListener(this); cardsContainer.addView(splitIntervalCard.build(mapActivity)); @@ -579,6 +580,17 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement return displayGroups; } + @NonNull + public List getDisplaySegmentGroups() { + List groups = new ArrayList<>(); + for (GpxDisplayGroup group : getGpxDisplayGroups()) { + if (GpxDisplayItemType.TRACK_SEGMENT == group.getType()) { + groups.add(group); + } + } + return groups; + } + public void dismissImmediate() { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { From 094bd14c62d4b8e3375972a00348e670b18db24d Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Sat, 1 Aug 2020 13:35:42 +0300 Subject: [PATCH 4/6] Add custom track colors --- OsmAnd/build.gradle | 1 + OsmAnd/res/layout/custom_color_picker.xml | 63 +++++ OsmAnd/res/layout/track_coloring_card.xml | 2 +- .../plus/settings/backend/OsmandSettings.java | 1 + .../plus/track/CustomColorBottomSheet.java | 228 ++++++++++++++++++ .../plus/track/TrackAppearanceFragment.java | 13 +- .../osmand/plus/track/TrackColoringCard.java | 147 +++++++++-- 7 files changed, 437 insertions(+), 18 deletions(-) create mode 100644 OsmAnd/res/layout/custom_color_picker.xml create mode 100644 OsmAnd/src/net/osmand/plus/track/CustomColorBottomSheet.java diff --git a/OsmAnd/build.gradle b/OsmAnd/build.gradle index 714b85eae8..e33b1ca75f 100644 --- a/OsmAnd/build.gradle +++ b/OsmAnd/build.gradle @@ -563,6 +563,7 @@ dependencies { implementation ("com.github.HITGIF:TextFieldBoxes:1.4.5"){ exclude group: 'com.android.support' } + implementation 'com.jaredrummler:colorpicker:1.1.0' huaweiImplementation files('libs/huawei-android-drm_v2.5.2.300.jar') freehuaweiImplementation files('libs/huawei-android-drm_v2.5.2.300.jar') diff --git a/OsmAnd/res/layout/custom_color_picker.xml b/OsmAnd/res/layout/custom_color_picker.xml new file mode 100644 index 0000000000..db6c3a254c --- /dev/null +++ b/OsmAnd/res/layout/custom_color_picker.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/track_coloring_card.xml b/OsmAnd/res/layout/track_coloring_card.xml index 47326a9ad7..5775a98c7d 100644 --- a/OsmAnd/res/layout/track_coloring_card.xml +++ b/OsmAnd/res/layout/track_coloring_card.xml @@ -40,7 +40,7 @@ - CURRENT_TRACK_WIDTH = new StringPreference("current_track_width", "").makeGlobal().cache(); public final CommonPreference CURRENT_TRACK_SHOW_ARROWS = new BooleanPreference("current_track_show_arrows", false).makeGlobal().cache(); public final CommonPreference CURRENT_TRACK_SHOW_START_FINISH = new BooleanPreference("current_track_show_start_finish", true).makeGlobal().cache(); + public final ListStringPreference CUSTOM_TRACK_COLORS = (ListStringPreference) new ListStringPreference("custom_track_colors", null, ",").makeGlobal(); // this value string is synchronized with settings_pref.xml preference name public final CommonPreference SAVE_TRACK_INTERVAL = new IntPreference("save_track_interval", 5000).makeProfile(); diff --git a/OsmAnd/src/net/osmand/plus/track/CustomColorBottomSheet.java b/OsmAnd/src/net/osmand/plus/track/CustomColorBottomSheet.java new file mode 100644 index 0000000000..66029119d5 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/track/CustomColorBottomSheet.java @@ -0,0 +1,228 @@ +package net.osmand.plus.track; + +import android.app.Activity; +import android.graphics.Color; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; + +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; + +import com.jaredrummler.android.colorpicker.ColorPanelView; +import com.jaredrummler.android.colorpicker.ColorPickerView; +import com.jaredrummler.android.colorpicker.ColorPickerView.OnColorChangedListener; + +import net.osmand.AndroidUtils; +import net.osmand.PlatformUtil; +import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.base.MenuBottomSheetDialogFragment; +import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; + +import org.apache.commons.logging.Log; + +public class CustomColorBottomSheet extends MenuBottomSheetDialogFragment implements OnColorChangedListener { + + private static final String TAG = CustomColorBottomSheet.class.getSimpleName(); + + private static final Log log = PlatformUtil.getLog(CustomColorBottomSheet.class); + + private static final String NEW_SELECTED_COLOR = "new_selected_color"; + private static final String PREV_SELECTED_COLOR = "prev_selected_color"; + + private ColorPickerView colorPicker; + private ColorPanelView newColorPanel; + + private EditText hexEditText; + private boolean fromEditText; + + @ColorInt + private int prevColor; + @ColorInt + private int newColor; + + @Override + public void createMenuItems(Bundle savedInstanceState) { + if (savedInstanceState != null) { + newColor = savedInstanceState.getInt(NEW_SELECTED_COLOR); + prevColor = savedInstanceState.getInt(PREV_SELECTED_COLOR); + } else { + Bundle args = getArguments(); + if (args != null) { + prevColor = args.getInt(PREV_SELECTED_COLOR); + newColor = prevColor != -1 ? prevColor : Color.RED; + } + } + + items.add(new TitleItem(getString(R.string.select_color))); + + BaseBottomSheetItem item = new SimpleBottomSheetItem.Builder() + .setCustomView(createPickerView()) + .create(); + items.add(item); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + outState.putInt(NEW_SELECTED_COLOR, newColor); + outState.putInt(PREV_SELECTED_COLOR, prevColor); + super.onSaveInstanceState(outState); + } + + private View createPickerView() { + LayoutInflater themedInflater = UiUtilities.getMaterialInflater(getActivity(), nightMode); + View colorView = themedInflater.inflate(R.layout.custom_color_picker, null); + colorPicker = colorView.findViewById(R.id.color_picker_view); + newColorPanel = colorView.findViewById(R.id.color_panel_new); + hexEditText = colorView.findViewById(R.id.color_hex_edit_text); + + setHex(newColor); + newColorPanel.setColor(newColor); + colorPicker.setColor(newColor, true); + colorPicker.setOnColorChangedListener(this); + hexEditText.addTextChangedListener(new TextWatcher() { + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (hexEditText.isFocused()) { + int color = parseColorString(s.toString()); + if (color != colorPicker.getColor()) { + fromEditText = true; + colorPicker.setColor(color, true); + } + } + } + }); + + return colorView; + } + + @Override + public void onColorChanged(int newColor) { + this.newColor = newColor; + if (newColorPanel != null) { + newColorPanel.setColor(newColor); + } + if (!fromEditText && hexEditText != null) { + setHex(newColor); + Activity activity = getActivity(); + if (activity != null && hexEditText.hasFocus()) { + AndroidUtils.hideSoftKeyboard(activity, hexEditText); + hexEditText.clearFocus(); + } + } + fromEditText = false; + } + + private void setHex(int color) { + hexEditText.setText(String.format("%08X", color)); + } + + @Override + protected int getRightBottomButtonTextId() { + return R.string.shared_string_apply; + } + + @Override + protected void onRightBottomButtonClick() { + Fragment target = getTargetFragment(); + if (target instanceof ColorPickerListener) { + ((ColorPickerListener) target).onColorSelected(prevColor, newColor); + } + dismiss(); + } + + public static void showInstance(@NonNull FragmentManager fragmentManager, Fragment target, int prevColor) { + try { + if (!fragmentManager.isStateSaved() && fragmentManager.findFragmentByTag(CustomColorBottomSheet.TAG) == null) { + Bundle args = new Bundle(); + args.putInt(PREV_SELECTED_COLOR, prevColor); + + CustomColorBottomSheet customColorBottomSheet = new CustomColorBottomSheet(); + customColorBottomSheet.setArguments(args); + customColorBottomSheet.setTargetFragment(target, 0); + customColorBottomSheet.show(fragmentManager, CustomColorBottomSheet.TAG); + } + } catch (RuntimeException e) { + log.error(e); + } + } + + private static int parseColorString(String colorString) throws NumberFormatException { + int a, r, g, b = 0; + if (colorString.startsWith("#")) { + colorString = colorString.substring(1); + } + if (colorString.length() == 0) { + r = 0; + a = 255; + g = 0; + } else if (colorString.length() <= 2) { + a = 255; + r = 0; + b = Integer.parseInt(colorString, 16); + g = 0; + } else if (colorString.length() == 3) { + a = 255; + r = Integer.parseInt(colorString.substring(0, 1), 16); + g = Integer.parseInt(colorString.substring(1, 2), 16); + b = Integer.parseInt(colorString.substring(2, 3), 16); + } else if (colorString.length() == 4) { + a = 255; + r = Integer.parseInt(colorString.substring(0, 2), 16); + g = r; + r = 0; + b = Integer.parseInt(colorString.substring(2, 4), 16); + } else if (colorString.length() == 5) { + a = 255; + r = Integer.parseInt(colorString.substring(0, 1), 16); + g = Integer.parseInt(colorString.substring(1, 3), 16); + b = Integer.parseInt(colorString.substring(3, 5), 16); + } else if (colorString.length() == 6) { + a = 255; + r = Integer.parseInt(colorString.substring(0, 2), 16); + g = Integer.parseInt(colorString.substring(2, 4), 16); + b = Integer.parseInt(colorString.substring(4, 6), 16); + } else if (colorString.length() == 7) { + a = Integer.parseInt(colorString.substring(0, 1), 16); + r = Integer.parseInt(colorString.substring(1, 3), 16); + g = Integer.parseInt(colorString.substring(3, 5), 16); + b = Integer.parseInt(colorString.substring(5, 7), 16); + } else if (colorString.length() == 8) { + a = Integer.parseInt(colorString.substring(0, 2), 16); + r = Integer.parseInt(colorString.substring(2, 4), 16); + g = Integer.parseInt(colorString.substring(4, 6), 16); + b = Integer.parseInt(colorString.substring(6, 8), 16); + } else { + b = -1; + g = -1; + r = -1; + a = -1; + } + return Color.argb(a, r, g, b); + } + + public interface ColorPickerListener { + + void onColorSelected(@ColorInt int prevColor, @ColorInt int newColor); + + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java index 0c2176687c..4834a43b0e 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java @@ -41,6 +41,7 @@ import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener; import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.track.CustomColorBottomSheet.ColorPickerListener; import net.osmand.plus.track.SplitTrackAsyncTask.SplitTrackListener; import net.osmand.render.RenderingRulesStorage; import net.osmand.util.Algorithms; @@ -57,9 +58,9 @@ import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR; import static net.osmand.plus.dialogs.GpxAppearanceAdapter.TRACK_WIDTH_BOLD; import static net.osmand.plus.dialogs.GpxAppearanceAdapter.TRACK_WIDTH_MEDIUM; -public class TrackAppearanceFragment extends ContextMenuScrollFragment implements CardListener { +public class TrackAppearanceFragment extends ContextMenuScrollFragment implements CardListener, ColorPickerListener { - public static final String TAG = TrackAppearanceFragment.class.getSimpleName(); + public static final String TAG = TrackAppearanceFragment.class.getName(); private static final Log log = PlatformUtil.getLog(TrackAppearanceFragment.class); @@ -76,6 +77,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement private TrackWidthCard trackWidthCard; private SplitIntervalCard splitIntervalCard; + private TrackColoringCard trackColoringCard; private ImageView trackIcon; @@ -324,6 +326,11 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement } + @Override + public void onColorSelected(int prevColor, int newColor) { + trackColoringCard.onColorSelected(prevColor, newColor); + } + @Override protected int applyPosY(int currentY, boolean needCloseMenu, boolean needMapAdjust, int previousMenuState, int newMenuState, int dZoom, boolean animated) { int y = super.applyPosY(currentY, needCloseMenu, needMapAdjust, previousMenuState, newMenuState, dZoom, animated); @@ -555,7 +562,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement directionArrowsCard.setListener(this); cardsContainer.addView(directionArrowsCard.build(mapActivity)); - TrackColoringCard trackColoringCard = new TrackColoringCard(mapActivity, trackDrawInfo); + trackColoringCard = new TrackColoringCard(mapActivity, trackDrawInfo, this); trackColoringCard.setListener(this); cardsContainer.addView(trackColoringCard.build(mapActivity)); diff --git a/OsmAnd/src/net/osmand/plus/track/TrackColoringCard.java b/OsmAnd/src/net/osmand/plus/track/TrackColoringCard.java index fbc9eebcdc..7d102c44fa 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackColoringCard.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackColoringCard.java @@ -1,12 +1,13 @@ package net.osmand.plus.track; +import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.os.Build; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.ColorInt; @@ -14,10 +15,14 @@ import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.appcompat.content.res.AppCompatResources; import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import com.google.android.material.internal.FlowLayout; + import net.osmand.AndroidUtils; +import net.osmand.PlatformUtil; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; @@ -25,16 +30,22 @@ import net.osmand.plus.dialogs.GpxAppearanceAdapter.AppearanceListItem; import net.osmand.plus.dialogs.GpxAppearanceAdapter.GpxAppearanceAdapterType; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.routepreparationmenu.cards.BaseCard; -import net.osmand.plus.widgets.FlowLayout; +import net.osmand.plus.track.CustomColorBottomSheet.ColorPickerListener; +import net.osmand.util.Algorithms; + +import org.apache.commons.logging.Log; import java.util.ArrayList; import java.util.List; import static net.osmand.plus.dialogs.GpxAppearanceAdapter.getAppearanceItems; -public class TrackColoringCard extends BaseCard { +public class TrackColoringCard extends BaseCard implements ColorPickerListener { + + public static final int INVALID_VALUE = -1; private final static String SOLID_COLOR = "solid_color"; + private static final Log log = PlatformUtil.getLog(TrackColoringCard.class); private TrackDrawInfo trackDrawInfo; @@ -42,10 +53,15 @@ public class TrackColoringCard extends BaseCard { private TrackAppearanceItem selectedAppearanceItem; private List appearanceItems; - public TrackColoringCard(MapActivity mapActivity, TrackDrawInfo trackDrawInfo) { + private List customColors; + private Fragment target; + + public TrackColoringCard(MapActivity mapActivity, TrackDrawInfo trackDrawInfo, Fragment target) { super(mapActivity); + this.target = target; this.trackDrawInfo = trackDrawInfo; appearanceItems = getGradientAppearanceItems(); + customColors = getCustomColors(); } @Override @@ -67,6 +83,25 @@ public class TrackColoringCard extends BaseCard { AndroidUiHelper.updateVisibility(view.findViewById(R.id.top_divider), isShowDivider()); } + private List getCustomColors() { + List colors = new ArrayList<>(); + List colorNames = app.getSettings().CUSTOM_TRACK_COLORS.getStringsList(); + if (colorNames != null) { + for (String colorHex : colorNames) { + try { + if (!Algorithms.isEmpty(colorHex)) { + int color = Algorithms.parseColor(colorHex); + colors.add(color); + } + } catch (IllegalArgumentException e) { + log.error(e); + } + } + } + + return colors; + } + private List getGradientAppearanceItems() { List items = new ArrayList<>(); items.add(new TrackAppearanceItem(SOLID_COLOR, app.getString(R.string.track_coloring_solid), R.drawable.ic_action_circle)); @@ -80,6 +115,16 @@ public class TrackColoringCard extends BaseCard { private void createColorSelector() { FlowLayout selectColor = view.findViewById(R.id.select_color); + selectColor.removeAllViews(); + + for (int color : customColors) { + selectColor.addView(createColorItemView(color, selectColor, true)); + } + if (customColors.size() < 6) { + selectColor.addView(createAddCustomColorItemView(selectColor)); + } + selectColor.addView(createDividerView(selectColor)); + List colors = new ArrayList<>(); for (AppearanceListItem appearanceListItem : getAppearanceItems(app, GpxAppearanceAdapterType.TRACK_COLOR)) { if (!colors.contains(appearanceListItem.getColor())) { @@ -87,20 +132,13 @@ public class TrackColoringCard extends BaseCard { } } for (int color : colors) { - selectColor.addView(createColorItemView(color, selectColor), new FlowLayout.LayoutParams(0, 0)); + selectColor.addView(createColorItemView(color, selectColor, false)); } updateColorSelector(trackDrawInfo.getColor(), selectColor); } - private View createColorItemView(@ColorInt final int color, final FlowLayout rootView) { - FrameLayout colorItemView = (FrameLayout) UiUtilities.getInflater(rootView.getContext(), nightMode) - .inflate(R.layout.point_editor_button, rootView, false); - ImageView outline = colorItemView.findViewById(R.id.outline); - outline.setImageDrawable( - UiUtilities.tintDrawable(AppCompatResources.getDrawable(app, R.drawable.bg_point_circle_contour), - ContextCompat.getColor(app, - nightMode ? R.color.stroked_buttons_and_links_outline_dark - : R.color.stroked_buttons_and_links_outline_light))); + private View createColorItemView(@ColorInt final int color, final FlowLayout rootView, boolean customColor) { + View colorItemView = createCircleView(rootView); ImageView backgroundCircle = colorItemView.findViewById(R.id.background); backgroundCircle.setImageDrawable(UiUtilities.tintDrawable(AppCompatResources.getDrawable(app, R.drawable.bg_point_circle), color)); backgroundCircle.setOnClickListener(new View.OnClickListener() { @@ -116,10 +154,68 @@ public class TrackColoringCard extends BaseCard { } } }); + if (customColor) { + backgroundCircle.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + CustomColorBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), target, color); + } + return false; + } + }); + } colorItemView.setTag(color); return colorItemView; } + private View createAddCustomColorItemView(FlowLayout rootView) { + View colorItemView = createCircleView(rootView); + ImageView backgroundCircle = colorItemView.findViewById(R.id.background); + + int bgColorId = nightMode ? R.color.activity_background_color_dark : R.color.activity_background_color_light; + Drawable backgroundIcon = app.getUIUtilities().getIcon(R.drawable.bg_point_circle, bgColorId); + + ImageView icon = colorItemView.findViewById(R.id.icon); + icon.setVisibility(View.VISIBLE); + int activeColorResId = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light; + icon.setImageDrawable(app.getUIUtilities().getIcon(R.drawable.ic_action_add, activeColorResId)); + + backgroundCircle.setImageDrawable(backgroundIcon); + backgroundCircle.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + CustomColorBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), target, TrackColoringCard.INVALID_VALUE); + } + } + }); + return colorItemView; + } + + private View createDividerView(FlowLayout rootView) { + LayoutInflater themedInflater = UiUtilities.getInflater(view.getContext(), nightMode); + View divider = themedInflater.inflate(R.layout.simple_divider_item, rootView, false); + + LinearLayout dividerContainer = new LinearLayout(view.getContext()); + dividerContainer.addView(divider); + dividerContainer.setPadding(0, AndroidUtils.dpToPx(app, 1), 0, AndroidUtils.dpToPx(app, 5)); + + return dividerContainer; + } + + private View createCircleView(ViewGroup rootView) { + LayoutInflater themedInflater = UiUtilities.getInflater(view.getContext(), nightMode); + View circleView = themedInflater.inflate(R.layout.point_editor_button, rootView, false); + ImageView outline = circleView.findViewById(R.id.outline); + int colorId = nightMode ? R.color.stroked_buttons_and_links_outline_dark : R.color.stroked_buttons_and_links_outline_light; + Drawable contourIcon = app.getUIUtilities().getIcon(R.drawable.bg_point_circle_contour, colorId); + outline.setImageDrawable(contourIcon); + return circleView; + } + private void updateColorSelector(int color, View rootView) { View oldColor = rootView.findViewWithTag(trackDrawInfo.getColor()); if (oldColor != null) { @@ -175,6 +271,29 @@ public class TrackColoringCard extends BaseCard { updateColorSelector(); } + @Override + public void onColorSelected(int prevColor, int newColor) { + if (prevColor == INVALID_VALUE && customColors.size() < 6) { + customColors.add(newColor); + } else if (!Algorithms.isEmpty(customColors)) { + int index = customColors.indexOf(prevColor); + if (index != INVALID_VALUE) { + customColors.set(index, newColor); + } + } + saveCustomColors(); + updateContent(); + } + + private void saveCustomColors() { + List colorNames = new ArrayList<>(); + for (Integer color : customColors) { + String colorHex = Algorithms.colorToString(color); + colorNames.add(colorHex); + } + app.getSettings().CUSTOM_TRACK_COLORS.setStringsList(colorNames); + } + private class TrackColoringAdapter extends RecyclerView.Adapter { private List items; From df0dc024f8faa2a76f445f5fd57d3fa98455db0b Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Sat, 1 Aug 2020 15:01:34 +0300 Subject: [PATCH 5/6] Fix default track width --- OsmAnd/src/net/osmand/plus/views/GPXLayer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/views/GPXLayer.java b/OsmAnd/src/net/osmand/plus/views/GPXLayer.java index b2a893d6f3..4eb6e3d30d 100644 --- a/OsmAnd/src/net/osmand/plus/views/GPXLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/GPXLayer.java @@ -423,7 +423,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM boolean showArrows = isShowArrowsForTrack(selectedGpxFile.getGpxFile()); if (showArrows) { QuadRect correctedQuadRect = getCorrectedQuadRect(tileBox.getLatLonBounds()); - String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get()); + String width = getTrackWidthName(selectedGpxFile.getGpxFile(), ""); float trackWidth = getTrackWidth(width, defaultTrackWidth); int color = getTrackColor(selectedGpxFile.getGpxFile(), cachedColor); int contrastColor = UiUtilities.getContrastColor(view.getApplication(), color, false); @@ -761,7 +761,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM List selectedGPXFiles, DrawSettings settings) { SelectedGpxFile currentTrack = null; for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) { - String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get()); + String width = getTrackWidthName(selectedGpxFile.getGpxFile(), ""); if (!cachedTrackWidth.containsKey(width)) { cachedTrackWidth.put(width, null); } @@ -780,7 +780,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM RotatedTileBox tileBox, DrawSettings settings) { List segments = selectedGpxFile.getPointsToDisplay(); for (TrkSegment ts : segments) { - String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get()); + String width = getTrackWidthName(selectedGpxFile.getGpxFile(), ""); int color = getTrackColor(selectedGpxFile.getGpxFile(), ts.getColor(cachedColor)); if (ts.renderer == null && !ts.points.isEmpty()) { if (currentTrack) { From c334cfa62e5252eb1114c9a4c21677c7ce9203fd Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Sat, 1 Aug 2020 15:53:41 +0300 Subject: [PATCH 6/6] Remove unnecessary method --- .../main/java/net/osmand/util/Algorithms.java | 4 +- .../net/osmand/plus/GpxSelectionHelper.java | 12 +++- .../plus/track/CustomColorBottomSheet.java | 63 +++---------------- .../src/net/osmand/plus/views/GPXLayer.java | 44 +++++++------ 4 files changed, 40 insertions(+), 83 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/util/Algorithms.java b/OsmAnd-java/src/main/java/net/osmand/util/Algorithms.java index b5a466cb8b..6a3425c05e 100644 --- a/OsmAnd-java/src/main/java/net/osmand/util/Algorithms.java +++ b/OsmAnd-java/src/main/java/net/osmand/util/Algorithms.java @@ -320,10 +320,8 @@ public class Algorithms { * exception. Supported formats are: * #RRGGBB * #AARRGGBB - * 'red', 'blue', 'green', 'black', 'white', 'gray', 'cyan', 'magenta', - * 'yellow', 'lightgray', 'darkgray' */ - public static int parseColor(String colorString) { + public static int parseColor(String colorString) throws IllegalArgumentException { if (colorString.charAt(0) == '#') { // Use a long to avoid rollovers on #ffXXXXXX if (colorString.length() == 4) { diff --git a/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java b/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java index 76425c8e0c..8281a127e4 100644 --- a/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java +++ b/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java @@ -520,12 +520,12 @@ public class GpxSelectionHelper { } GPXFile gpx = GPXUtilities.loadGPXFile(fl); if (obj.has(COLOR)) { - int clr = Algorithms.parseColor(obj.getString(COLOR)); + int clr = parseColor(obj.getString(COLOR)); gpx.setColor(clr); } for (GradientScaleType scaleType : GradientScaleType.values()) { if (obj.has(scaleType.getColorTypeName())) { - int clr = Algorithms.parseColor(obj.getString(scaleType.getColorTypeName())); + int clr = parseColor(obj.getString(scaleType.getColorTypeName())); gpx.setGradientScaleColor(scaleType.getColorTypeName(), clr); } } @@ -567,6 +567,14 @@ public class GpxSelectionHelper { } } + private int parseColor(String color) { + try { + return Algorithms.isEmpty(color) ? 0 : Algorithms.parseColor(color); + } catch (IllegalArgumentException e) { + return 0; + } + } + private void saveCurrentSelections() { JSONArray ar = new JSONArray(); for (SelectedGpxFile s : selectedGPXFiles) { diff --git a/OsmAnd/src/net/osmand/plus/track/CustomColorBottomSheet.java b/OsmAnd/src/net/osmand/plus/track/CustomColorBottomSheet.java index 66029119d5..5096978208 100644 --- a/OsmAnd/src/net/osmand/plus/track/CustomColorBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/track/CustomColorBottomSheet.java @@ -26,6 +26,7 @@ import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; +import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; @@ -103,7 +104,13 @@ public class CustomColorBottomSheet extends MenuBottomSheetDialogFragment implem @Override public void afterTextChanged(Editable s) { if (hexEditText.isFocused()) { - int color = parseColorString(s.toString()); + int color = colorPicker.getColor(); + try { + color = Algorithms.parseColor("#" + s.toString()); + } catch (IllegalArgumentException e) { + hexEditText.setError(getString(R.string.wrong_input)); + log.error(e); + } if (color != colorPicker.getColor()) { fromEditText = true; colorPicker.setColor(color, true); @@ -166,60 +173,6 @@ public class CustomColorBottomSheet extends MenuBottomSheetDialogFragment implem } } - private static int parseColorString(String colorString) throws NumberFormatException { - int a, r, g, b = 0; - if (colorString.startsWith("#")) { - colorString = colorString.substring(1); - } - if (colorString.length() == 0) { - r = 0; - a = 255; - g = 0; - } else if (colorString.length() <= 2) { - a = 255; - r = 0; - b = Integer.parseInt(colorString, 16); - g = 0; - } else if (colorString.length() == 3) { - a = 255; - r = Integer.parseInt(colorString.substring(0, 1), 16); - g = Integer.parseInt(colorString.substring(1, 2), 16); - b = Integer.parseInt(colorString.substring(2, 3), 16); - } else if (colorString.length() == 4) { - a = 255; - r = Integer.parseInt(colorString.substring(0, 2), 16); - g = r; - r = 0; - b = Integer.parseInt(colorString.substring(2, 4), 16); - } else if (colorString.length() == 5) { - a = 255; - r = Integer.parseInt(colorString.substring(0, 1), 16); - g = Integer.parseInt(colorString.substring(1, 3), 16); - b = Integer.parseInt(colorString.substring(3, 5), 16); - } else if (colorString.length() == 6) { - a = 255; - r = Integer.parseInt(colorString.substring(0, 2), 16); - g = Integer.parseInt(colorString.substring(2, 4), 16); - b = Integer.parseInt(colorString.substring(4, 6), 16); - } else if (colorString.length() == 7) { - a = Integer.parseInt(colorString.substring(0, 1), 16); - r = Integer.parseInt(colorString.substring(1, 3), 16); - g = Integer.parseInt(colorString.substring(3, 5), 16); - b = Integer.parseInt(colorString.substring(5, 7), 16); - } else if (colorString.length() == 8) { - a = Integer.parseInt(colorString.substring(0, 2), 16); - r = Integer.parseInt(colorString.substring(2, 4), 16); - g = Integer.parseInt(colorString.substring(4, 6), 16); - b = Integer.parseInt(colorString.substring(6, 8), 16); - } else { - b = -1; - g = -1; - r = -1; - a = -1; - } - return Color.argb(a, r, g, b); - } - public interface ColorPickerListener { void onColorSelected(@ColorInt int prevColor, @ColorInt int newColor); diff --git a/OsmAnd/src/net/osmand/plus/views/GPXLayer.java b/OsmAnd/src/net/osmand/plus/views/GPXLayer.java index 4eb6e3d30d..108c646776 100644 --- a/OsmAnd/src/net/osmand/plus/views/GPXLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/GPXLayer.java @@ -379,7 +379,8 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM for (int k = 0; k < items.size(); k++) { GpxDisplayItem i = items.get(k); WptPt point = i.locationEnd; - if (point != null) { + if (point != null && point.lat >= latLonBounds.bottom && point.lat <= latLonBounds.top + && point.lon >= latLonBounds.left && point.lon <= latLonBounds.right) { float x = tileBox.getPixXFromLatLon(point.lat, point.lon); float y = tileBox.getPixYFromLatLon(point.lat, point.lon); if (px != -1 || py != -1) { @@ -389,29 +390,26 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } px = x; py = y; - if (point.lat >= latLonBounds.bottom && point.lat <= latLonBounds.top - && point.lon >= latLonBounds.left && point.lon <= latLonBounds.right) { - String name = i.splitName; - if (name != null) { - int ind = name.indexOf(' '); - if (ind > 0) { - name = name.substring(0, ind); - } - Rect bounds = new Rect(); - paintTextIcon.getTextBounds(name, 0, name.length(), bounds); - - float nameHalfWidth = bounds.width() / 2f; - float nameHalfHeight = bounds.height() / 2f; - float density = (float) Math.ceil(tileBox.getDensity()); - RectF rect = new RectF(x - nameHalfWidth - 2 * density, - y + nameHalfHeight + 3 * density, - x + nameHalfWidth + 3 * density, - y - nameHalfHeight - 2 * density); - - canvas.drawRoundRect(rect, 0, 0, paintInnerRect); - canvas.drawRoundRect(rect, 0, 0, paintOuterRect); - canvas.drawText(name, x, y + nameHalfHeight, paintTextIcon); + String name = i.splitName; + if (name != null) { + int ind = name.indexOf(' '); + if (ind > 0) { + name = name.substring(0, ind); } + Rect bounds = new Rect(); + paintTextIcon.getTextBounds(name, 0, name.length(), bounds); + + float nameHalfWidth = bounds.width() / 2f; + float nameHalfHeight = bounds.height() / 2f; + float density = (float) Math.ceil(tileBox.getDensity()); + RectF rect = new RectF(x - nameHalfWidth - 2 * density, + y + nameHalfHeight + 3 * density, + x + nameHalfWidth + 3 * density, + y - nameHalfHeight - 2 * density); + + canvas.drawRoundRect(rect, 0, 0, paintInnerRect); + canvas.drawRoundRect(rect, 0, 0, paintOuterRect); + canvas.drawText(name, x, y + nameHalfHeight, paintTextIcon); } } }