Merge pull request #9544 from osmandapp/track_appearance_fixes

Track appearance fixes second part
This commit is contained in:
max-klaus 2020-07-30 17:26:32 +03:00 committed by GitHub
commit 5a05693efb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 1971 additions and 1800 deletions

View file

@ -133,45 +133,7 @@
<!-- RULER --> <!-- RULER -->
<FrameLayout <include layout="@layout/map_ruler" />
android:id="@+id/map_ruler_layout"
android:layout_width="@dimen/map_ruler_width"
android:layout_height="wrap_content"
android:layout_gravity="bottom">
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginBottom="@dimen/map_ruler_bottom_margin">
<TextView
android:id="@+id/map_ruler_text_shadow"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="bottom"
android:gravity="center_horizontal"
android:lineSpacingMultiplier="0.9"
android:textSize="@dimen/map_widget_text_size_small"
tools:text="100 m"/>
<TextView
android:id="@+id/map_ruler_text"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="bottom"
android:gravity="center_horizontal"
android:lineSpacingMultiplier="0.9"
android:textSize="@dimen/map_widget_text_size_small"
tools:text="100 m"/>
</FrameLayout>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/map_ruler_image"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@drawable/ruler"/>
</FrameLayout>
<!-- TRANSPARENCY --> <!-- TRANSPARENCY -->

View file

@ -7,34 +7,6 @@
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:orientation="vertical"> android:orientation="vertical">
<!--<net.osmand.plus.quickaction.QuickActionsWidget
android:id="@+id/quick_action_widget"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:visibility="visible"
android:visibility="gone"/>
<FrameLayout
android:id="@+id/map_quick_actions_button_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="8dp"
android:animateLayoutChanges="true">
<ImageButton
android:id="@+id/map_quick_actions_button"
android:layout_width="@dimen/map_button_size"
android:layout_height="@dimen/map_button_size"
android:background="@drawable/btn_circle_blue"
android:contentDescription="@string/zoomIn"
android:layout_gravity="bottom|right"
android:visibility="gone"
tools:visibility="visible"
tools:src="@drawable/ic_action_remove_dark"/>
</FrameLayout>-->
<FrameLayout <FrameLayout
android:id="@+id/bottom_controls_container" android:id="@+id/bottom_controls_container"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -145,7 +117,12 @@
tools:src="@drawable/ic_action_remove_dark" tools:src="@drawable/ic_action_remove_dark"
android:contentDescription="@string/snap_to_road" /> android:contentDescription="@string/snap_to_road" />
<include layout="@layout/map_ruler" /> <include
layout="@layout/map_ruler"
android:layout_width="@dimen/map_ruler_width"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/map_button_margin"
android:layout_marginLeft="@dimen/map_button_margin" />
</LinearLayout> </LinearLayout>

View file

@ -3,9 +3,7 @@
android:id="@+id/map_ruler_layout" android:id="@+id/map_ruler_layout"
android:layout_width="@dimen/map_ruler_width" android:layout_width="@dimen/map_ruler_width"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom">
android:layout_marginStart="@dimen/map_button_margin"
android:layout_marginLeft="@dimen/map_button_margin">
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -6,7 +6,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/color_transparent"> android:background="@color/color_transparent">
<net.osmand.plus.mapcontextmenu.InterceptorLinearLayout <LinearLayout
android:id="@+id/main_view" android:id="@+id/main_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -88,18 +88,37 @@
</FrameLayout> </FrameLayout>
</net.osmand.plus.mapcontextmenu.InterceptorLinearLayout> </LinearLayout>
<include <FrameLayout
layout="@layout/map_hud_controls" android:id="@+id/map_controls_container"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="end|bottom" android:layout_gravity="bottom">
android:layout_marginStart="@dimen/fab_margin_right"
android:layout_marginLeft="@dimen/fab_margin_right" <include
android:layout_marginEnd="@dimen/fab_margin_right" layout="@layout/map_ruler"
android:layout_marginRight="@dimen/fab_margin_right" android:layout_width="wrap_content"
tools:visibility="invisible" /> android:layout_height="wrap_content"
android:layout_gravity="start|bottom"
android:layout_marginStart="@dimen/fab_margin_right"
android:layout_marginLeft="@dimen/fab_margin_right"
android:layout_marginEnd="@dimen/fab_margin_right"
android:layout_marginRight="@dimen/fab_margin_right"
tools:visibility="invisible" />
<include
layout="@layout/map_hud_controls"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_marginStart="@dimen/fab_margin_right"
android:layout_marginLeft="@dimen/fab_margin_right"
android:layout_marginEnd="@dimen/fab_margin_right"
android:layout_marginRight="@dimen/fab_margin_right"
tools:visibility="invisible" />
</FrameLayout>
<LinearLayout <LinearLayout
android:id="@+id/control_buttons" android:id="@+id/control_buttons"

View file

@ -21,7 +21,7 @@ import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.views.AidlMapLayer; import net.osmand.plus.views.AidlMapLayer;
import net.osmand.plus.views.MapInfoLayer; import net.osmand.plus.views.MapInfoLayer;
import net.osmand.plus.views.OsmandMapLayer; import net.osmand.plus.views.OsmandMapLayer;
import net.osmand.plus.views.mapwidgets.TextInfoWidget; import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import java.util.Map; import java.util.Map;

View file

@ -80,7 +80,7 @@ import net.osmand.plus.views.AidlMapLayer;
import net.osmand.plus.views.MapInfoLayer; import net.osmand.plus.views.MapInfoLayer;
import net.osmand.plus.views.OsmandMapLayer; import net.osmand.plus.views.OsmandMapLayer;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.mapwidgets.TextInfoWidget; import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget;
import net.osmand.router.TurnType; import net.osmand.router.TurnType;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;

View file

@ -536,7 +536,7 @@ public class GpxSelectionHelper {
gpx.setGradientScaleType(obj.optString(GRADIENT_SCALE_TYPE)); gpx.setGradientScaleType(obj.optString(GRADIENT_SCALE_TYPE));
} }
if (obj.has(SHOW_START_FINISH)) { if (obj.has(SHOW_START_FINISH)) {
gpx.setShowStartFinish(obj.optBoolean(SHOW_START_FINISH, false)); gpx.setShowStartFinish(obj.optBoolean(SHOW_START_FINISH, true));
} }
if (obj.has(WIDTH)) { if (obj.has(WIDTH)) {
gpx.setWidth(obj.getString(WIDTH)); gpx.setWidth(obj.getString(WIDTH));

View file

@ -118,7 +118,22 @@ public class OsmAndFormatter {
public static String getFormattedDate(Context context, long milliseconds) { public static String getFormattedDate(Context context, long milliseconds) {
return DateUtils.formatDateTime(context, milliseconds, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL); return DateUtils.formatDateTime(context, milliseconds, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL);
} }
public static String getFormattedTimeInterval(OsmandApplication app, double interval) {
if (interval < 60) {
return interval + " " + app.getString(R.string.int_seconds);
} else if (interval % 60 == 0) {
return (interval / 60) + " " + app.getString(R.string.int_min);
} else {
return (interval / 60f) + " " + app.getString(R.string.int_min);
}
}
public static String getFormattedDistanceInterval(OsmandApplication app, double interval) {
double roundedDist = OsmAndFormatter.calculateRoundedDist(interval, app);
return OsmAndFormatter.getFormattedDistance((float) roundedDist, app);
}
public static double calculateRoundedDist(double distInMeters, OsmandApplication ctx) { public static double calculateRoundedDist(double distInMeters, OsmandApplication ctx) {
OsmandSettings settings = ctx.getSettings(); OsmandSettings settings = ctx.getSettings();
MetricsConstants mc = settings.METRIC_SYSTEM.get(); MetricsConstants mc = settings.METRIC_SYSTEM.get();

View file

@ -175,7 +175,8 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_SETTINGS_ID; import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_SETTINGS_ID;
import static net.osmand.plus.track.TrackDrawInfo.TRACK_FILE_PATH; import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING;
import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME;
public class MapActivity extends OsmandActionBarActivity implements DownloadEvents, public class MapActivity extends OsmandActionBarActivity implements DownloadEvents,
OnRequestPermissionsResultCallback, IRouteInformationListener, AMapPointUpdateListener, OnRequestPermissionsResultCallback, IRouteInformationListener, AMapPointUpdateListener,
@ -1247,7 +1248,8 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
hideContextAndRouteInfoMenues(); hideContextAndRouteInfoMenues();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString(TRACK_FILE_PATH, ((GPXFile) toShow).path); args.putString(TRACK_FILE_NAME, ((GPXFile) toShow).path);
args.putBoolean(CURRENT_RECORDING, ((GPXFile) toShow).showCurrentTrack);
args.putInt(ContextMenuFragment.MENU_STATE_KEY, MenuController.MenuState.HALF_SCREEN); args.putInt(ContextMenuFragment.MENU_STATE_KEY, MenuController.MenuState.HALF_SCREEN);
TrackAppearanceFragment fragment = new TrackAppearanceFragment(); TrackAppearanceFragment fragment = new TrackAppearanceFragment();

View file

@ -70,8 +70,8 @@ import net.osmand.plus.settings.fragments.BaseSettingsFragment;
import net.osmand.plus.views.MapInfoLayer; import net.osmand.plus.views.MapInfoLayer;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.mapwidgets.MapWidgetRegistry; import net.osmand.plus.views.mapwidgets.widgetstates.WidgetState;
import net.osmand.plus.views.mapwidgets.TextInfoWidget; import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import net.osmand.util.GeoPointParserUtil.GeoParsedPoint; import net.osmand.util.GeoPointParserUtil.GeoParsedPoint;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;
@ -2128,7 +2128,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
return DashAudioVideoNotesFragment.FRAGMENT_DATA; return DashAudioVideoNotesFragment.FRAGMENT_DATA;
} }
public class AudioVideoNotesWidgetState extends MapWidgetRegistry.WidgetState { public class AudioVideoNotesWidgetState extends WidgetState {
private static final int AV_WIDGET_STATE_ASK = R.id.av_notes_widget_state_ask; private static final int AV_WIDGET_STATE_ASK = R.id.av_notes_widget_state_ask;
private static final int AV_WIDGET_STATE_AUDIO = R.id.av_notes_widget_state_audio; private static final int AV_WIDGET_STATE_AUDIO = R.id.av_notes_widget_state_audio;

View file

@ -62,7 +62,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment {
public static final int MIDDLE_STATE_MIN_HEIGHT_DP = 520; public static final int MIDDLE_STATE_MIN_HEIGHT_DP = 520;
public static final String MENU_STATE_KEY = "menu_state_key"; public static final String MENU_STATE_KEY = "menu_state_key";
private InterceptorLinearLayout mainView; private LinearLayout mainView;
private View view; private View view;
private OnLayoutChangeListener containerLayoutListener; private OnLayoutChangeListener containerLayoutListener;
private View topShadow; private View topShadow;
@ -163,7 +163,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment {
} }
@Nullable @Nullable
public InterceptorLinearLayout getMainView() { public LinearLayout getMainView() {
return mainView; return mainView;
} }
@ -282,6 +282,9 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment {
bottomContainer = (FrameLayout) view.findViewById(getBottomContainerViewId()); bottomContainer = (FrameLayout) view.findViewById(getBottomContainerViewId());
bottomScrollView = (LockableScrollView) view.findViewById(getBottomScrollViewId()); bottomScrollView = (LockableScrollView) view.findViewById(getBottomScrollViewId());
ViewConfiguration vc = ViewConfiguration.get(context);
final int touchSlop = vc.getScaledTouchSlop();
bottomScrollView.setScrollingEnabled(false); bottomScrollView.setScrollingEnabled(false);
if (getTopViewId() != 0) { if (getTopViewId() != 0) {
View topView = view.findViewById(getTopViewId()); View topView = view.findViewById(getTopViewId());
@ -349,7 +352,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment {
break; break;
case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_MOVE:
if (Math.abs(event.getRawY() - mDownY) > mainView.getTouchSlop()) { if (Math.abs(event.getRawY() - mDownY) > touchSlop) {
moving = true; moving = true;
} }
if (moving) { if (moving) {
@ -435,7 +438,9 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment {
} }
}; };
((InterceptorLinearLayout) mainView).setListener(slideTouchListener); if (mainView instanceof InterceptorLinearLayout) {
((InterceptorLinearLayout) mainView).setListener(slideTouchListener);
}
mainView.setOnTouchListener(slideTouchListener); mainView.setOnTouchListener(slideTouchListener);
containerLayoutListener = new OnLayoutChangeListener() { containerLayoutListener = new OnLayoutChangeListener() {
@ -618,7 +623,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment {
} }
public int getWidth() { public int getWidth() {
InterceptorLinearLayout mainView = getMainView(); LinearLayout mainView = getMainView();
if (mainView != null) { if (mainView != null) {
return mainView.getWidth(); return mainView.getWidth();
} else { } else {

View file

@ -0,0 +1,156 @@
package net.osmand.plus.base;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.MapActivityLayers;
import net.osmand.plus.base.ContextMenuFragment.ContextMenuFragmentListener;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.views.MapControlsLayer;
import net.osmand.plus.views.MapInfoLayer;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.mapwidgets.widgets.RulerWidget;
import java.util.Arrays;
import java.util.Collections;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.BACK_TO_LOC_HUD_ID;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.ZOOM_IN_HUD_ID;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.ZOOM_OUT_HUD_ID;
public abstract class ContextMenuScrollFragment extends ContextMenuFragment implements ContextMenuFragmentListener {
public static final String TAG = ContextMenuScrollFragment.class.getSimpleName();
private static final String ZOOM_IN_BUTTON_ID = ZOOM_IN_HUD_ID + TAG;
private static final String ZOOM_OUT_BUTTON_ID = ZOOM_OUT_HUD_ID + TAG;
private static final String BACK_TO_LOC_BUTTON_ID = BACK_TO_LOC_HUD_ID + TAG;
@Nullable
private View mapBottomHudButtons;
@Nullable
private RulerWidget rulerWidget;
public float getMiddleStateKoef() {
return 0.5f;
}
public boolean isShowMapBottomHudButtons() {
return true;
}
@Override
public int getSupportedMenuStatesPortrait() {
return MenuState.HEADER_ONLY | MenuState.HALF_SCREEN;
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
if (view != null) {
setListener(this);
getBottomScrollView().setScrollingEnabled(true);
mapBottomHudButtons = view.findViewById(R.id.map_controls_container);
if (mapBottomHudButtons != null) {
if (isShowMapBottomHudButtons()) {
setupControlButtons(mapBottomHudButtons);
} else {
AndroidUiHelper.updateVisibility(mapBottomHudButtons, false);
}
}
}
return view;
}
@Override
public void onContextMenuYPosChanged(@NonNull ContextMenuFragment fragment, int y, boolean needMapAdjust, boolean animated) {
updateMapControlsPos(fragment, y, animated);
}
@Override
public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState) {
updateMapControlsVisibility(menuState);
}
@Override
public void onContextMenuDismiss(@NonNull ContextMenuFragment fragment) {
}
@Override
public void onDestroyView() {
super.onDestroyView();
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
MapActivityLayers mapLayers = mapActivity.getMapLayers();
MapControlsLayer mapControlsLayer = mapLayers.getMapControlsLayer();
mapControlsLayer.removeHudButtons(Arrays.asList(ZOOM_IN_BUTTON_ID, ZOOM_OUT_BUTTON_ID, BACK_TO_LOC_BUTTON_ID));
MapInfoLayer mapInfoLayer = mapLayers.getMapInfoLayer();
mapInfoLayer.removeRulerWidgets(Collections.singletonList(rulerWidget));
}
}
private void setupControlButtons(@NonNull View view) {
MapActivity mapActivity = requireMapActivity();
View zoomInButtonView = view.findViewById(R.id.map_zoom_in_button);
View zoomOutButtonView = view.findViewById(R.id.map_zoom_out_button);
View myLocButtonView = view.findViewById(R.id.map_my_location_button);
View mapRulerView = view.findViewById(R.id.map_ruler_layout);
MapActivityLayers mapLayers = mapActivity.getMapLayers();
OsmandMapTileView mapTileView = mapActivity.getMapView();
View.OnLongClickListener longClickListener = MapControlsLayer.getOnClickMagnifierListener(mapTileView);
MapControlsLayer mapControlsLayer = mapLayers.getMapControlsLayer();
mapControlsLayer.setupZoomInButton(zoomInButtonView, longClickListener, ZOOM_IN_BUTTON_ID);
mapControlsLayer.setupZoomOutButton(zoomOutButtonView, longClickListener, ZOOM_OUT_BUTTON_ID);
mapControlsLayer.setupBackToLocationButton(myLocButtonView, BACK_TO_LOC_BUTTON_ID);
MapInfoLayer mapInfoLayer = mapLayers.getMapInfoLayer();
rulerWidget = mapInfoLayer.setupRulerWidget(mapRulerView);
}
public void updateMapControlsPos(@NonNull ContextMenuFragment fragment, int y, boolean animated) {
View mapControlsView = this.mapBottomHudButtons;
if (mapControlsView != null) {
int zoomY = y - getMapControlsHeight();
if (animated) {
fragment.animateView(mapControlsView, zoomY);
} else {
mapControlsView.setY(zoomY);
}
}
}
private int getMapControlsHeight() {
View mapControlsContainer = this.mapBottomHudButtons;
return mapControlsContainer != null ? mapControlsContainer.getHeight() : 0;
}
private void updateMapControlsVisibility(int menuState) {
if (mapBottomHudButtons != null) {
if (menuState == MenuState.HEADER_ONLY) {
if (mapBottomHudButtons.getVisibility() != View.VISIBLE) {
mapBottomHudButtons.setVisibility(View.VISIBLE);
}
} else {
if (mapBottomHudButtons.getVisibility() == View.VISIBLE) {
mapBottomHudButtons.setVisibility(View.INVISIBLE);
}
}
}
}
}

View file

@ -18,7 +18,7 @@ import net.osmand.plus.settings.fragments.BaseSettingsFragment;
import net.osmand.plus.views.MapInfoLayer; import net.osmand.plus.views.MapInfoLayer;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.mapwidgets.TextInfoWidget; import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_BUILDS_ID; import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_BUILDS_ID;

View file

@ -48,8 +48,13 @@ public class SelectedGpxMenuController extends MenuController {
@Override @Override
public void buttonPressed() { public void buttonPressed() {
Intent intent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity()); Intent intent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity());
intent.putExtra(TrackActivity.TRACK_FILE_NAME, selectedGpxPoint.getSelectedGpxFile().getGpxFile().path); SelectedGpxFile selectedGpxFile = selectedGpxPoint.getSelectedGpxFile();
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); if (selectedGpxFile.isShowCurrentTrack()) {
intent.putExtra(TrackActivity.CURRENT_RECORDING, true);
} else {
intent.putExtra(TrackActivity.TRACK_FILE_NAME, selectedGpxFile.getGpxFile().path);
}
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mapActivity.startActivity(intent); mapActivity.startActivity(intent);
} }
}; };

View file

@ -35,7 +35,7 @@ import net.osmand.plus.views.MapInfoLayer;
import net.osmand.plus.views.MapTileLayer; import net.osmand.plus.views.MapTileLayer;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.MapWidgetRegInfo; import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.MapWidgetRegInfo;
import net.osmand.plus.views.mapwidgets.TextInfoWidget; import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import java.text.MessageFormat; import java.text.MessageFormat;

View file

@ -46,7 +46,7 @@ import net.osmand.plus.settings.fragments.BaseSettingsFragment;
import net.osmand.plus.views.MapInfoLayer; import net.osmand.plus.views.MapInfoLayer;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.mapwidgets.TextInfoWidget; import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;

View file

@ -59,7 +59,6 @@ import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener;
import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference; import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
import net.osmand.plus.track.GpxSplitType; import net.osmand.plus.track.GpxSplitType;
import net.osmand.plus.track.SplitIntervalCard;
import net.osmand.plus.track.SplitTrackAsyncTask; import net.osmand.plus.track.SplitTrackAsyncTask;
import net.osmand.plus.track.SplitTrackAsyncTask.SplitTrackListener; import net.osmand.plus.track.SplitTrackAsyncTask.SplitTrackListener;
import net.osmand.plus.widgets.tools.CropCircleTransformation; import net.osmand.plus.widgets.tools.CropCircleTransformation;
@ -830,14 +829,14 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
if (model.size() > 0) { if (model.size() > 0) {
if (distance) { if (distance) {
double dvalue = OsmAndFormatter.calculateRoundedDist(value, app); double dvalue = OsmAndFormatter.calculateRoundedDist(value, app);
options.add(SplitIntervalCard.getFormattedDistanceInterval(app, value)); options.add(OsmAndFormatter.getFormattedDistanceInterval(app, value));
distanceSplit.add(dvalue); distanceSplit.add(dvalue);
timeSplit.add(-1); timeSplit.add(-1);
if (Math.abs(model.get(0).getSplitDistance() - dvalue) < 1) { if (Math.abs(model.get(0).getSplitDistance() - dvalue) < 1) {
selectedSplitInterval = distanceSplit.size() - 1; selectedSplitInterval = distanceSplit.size() - 1;
} }
} else { } else {
options.add(SplitIntervalCard.getFormattedTimeInterval(app, value)); options.add(OsmAndFormatter.getFormattedTimeInterval(app, value));
distanceSplit.add(-1d); distanceSplit.add(-1d);
timeSplit.add(value); timeSplit.add(value);
if (model.get(0).getSplitTime() == value) { if (model.get(0).getSplitTime() == value) {

View file

@ -28,7 +28,7 @@ import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo;
import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.views.TurnPathHelper; import net.osmand.plus.views.TurnPathHelper;
import net.osmand.plus.views.mapwidgets.NextTurnInfoWidget.TurnDrawable; import net.osmand.plus.views.mapwidgets.TurnDrawable;
import net.osmand.router.TurnType; import net.osmand.router.TurnType;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;

View file

@ -40,7 +40,7 @@ import net.osmand.plus.views.AnimateDraggingMapThread;
import net.osmand.plus.views.MapInfoLayer; import net.osmand.plus.views.MapInfoLayer;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.mapwidgets.TextInfoWidget; import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;

View file

@ -1,6 +1,5 @@
package net.osmand.plus.routepreparationmenu; package net.osmand.plus.routepreparationmenu;
import android.Manifest;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import android.content.Context; import android.content.Context;
@ -28,7 +27,6 @@ import androidx.annotation.Nullable;
import androidx.appcompat.view.ContextThemeWrapper; import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.AppCompatImageButton; import androidx.appcompat.widget.AppCompatImageButton;
import androidx.appcompat.widget.AppCompatImageView; import androidx.appcompat.widget.AppCompatImageView;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter; import androidx.fragment.app.FragmentPagerAdapter;
@ -36,15 +34,12 @@ import androidx.viewpager.widget.ViewPager;
import net.osmand.AndroidUtils; import net.osmand.AndroidUtils;
import net.osmand.GPXUtilities; import net.osmand.GPXUtilities;
import net.osmand.Location;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.data.PointDescription; import net.osmand.data.PointDescription;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.LockableViewPager; import net.osmand.plus.LockableViewPager;
import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmAndLocationProvider;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.MapActivityActions; import net.osmand.plus.activities.MapActivityActions;
@ -60,6 +55,8 @@ import net.osmand.plus.routepreparationmenu.cards.PublicTransportCard;
import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.TransportRoutingHelper; import net.osmand.plus.routing.TransportRoutingHelper;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.views.MapControlsLayer;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.router.TransportRoutePlanner.TransportRouteResult; import net.osmand.router.TransportRoutePlanner.TransportRouteResult;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
@ -71,10 +68,15 @@ import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.BACK_TO_LOC_HUD_ID;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.ZOOM_IN_HUD_ID;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.ZOOM_OUT_HUD_ID;
public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMenuFragmentListener, public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMenuFragmentListener,
RouteDetailsFragmentListener { RouteDetailsFragmentListener {
@ -84,18 +86,19 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe
public static final String INITIAL_MENU_STATE_KEY = "initial_menu_state_key"; public static final String INITIAL_MENU_STATE_KEY = "initial_menu_state_key";
public static final String ADJUST_MAP_KEY = "adjust_map_key"; public static final String ADJUST_MAP_KEY = "adjust_map_key";
private static final String ZOOM_IN_BUTTON_ID = ZOOM_IN_HUD_ID + TAG;
private static final String ZOOM_OUT_BUTTON_ID = ZOOM_OUT_HUD_ID + TAG;
private static final String BACK_TO_LOC_BUTTON_ID = BACK_TO_LOC_HUD_ID + TAG;
@Nullable @Nullable
private LockableViewPager viewPager; private LockableViewPager viewPager;
protected List<WeakReference<RouteDetailsFragment>> routeDetailsFragments = new ArrayList<>(); protected List<WeakReference<RouteDetailsFragment>> routeDetailsFragments = new ArrayList<>();
@Nullable @Nullable
private View solidToolbarView; private View solidToolbarView;
private int solidToolbarHeight;
@Nullable @Nullable
private View zoomButtonsView; private View zoomButtonsView;
@Nullable @Nullable
private ImageButton myLocButtonView;
@Nullable
private ViewGroup pagesView; private ViewGroup pagesView;
private boolean portrait; private boolean portrait;
@ -139,7 +142,6 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe
AndroidUtils.addStatusBarPadding21v(mapActivity, view); AndroidUtils.addStatusBarPadding21v(mapActivity, view);
View solidToolbarView = view.findViewById(R.id.toolbar_layout); View solidToolbarView = view.findViewById(R.id.toolbar_layout);
this.solidToolbarView = solidToolbarView; this.solidToolbarView = solidToolbarView;
solidToolbarHeight = getResources().getDimensionPixelSize(R.dimen.dashboard_map_toolbar);
LockableViewPager viewPager = view.findViewById(R.id.pager); LockableViewPager viewPager = view.findViewById(R.id.pager);
this.viewPager = viewPager; this.viewPager = viewPager;
if (!portrait) { if (!portrait) {
@ -241,6 +243,17 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe
} }
} }
@Override
public void onDestroyView() {
super.onDestroyView();
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
MapControlsLayer mapControlsLayer = mapActivity.getMapLayers().getMapControlsLayer();
mapControlsLayer.removeHudButtons(Arrays.asList(ZOOM_IN_BUTTON_ID, ZOOM_OUT_BUTTON_ID, BACK_TO_LOC_BUTTON_ID));
}
}
@Override @Override
public int getStatusBarColorId() { public int getStatusBarColorId() {
View view = getView(); View view = getView();
@ -345,98 +358,27 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe
} }
private void buildZoomButtons(@NonNull View view) { private void buildZoomButtons(@NonNull View view) {
OsmandApplication app = requireMyApplication();
// Zoom buttons
View zoomButtonsView = view.findViewById(R.id.map_hud_controls);
this.zoomButtonsView = zoomButtonsView;
ImageButton zoomInButtonView = (ImageButton) view.findViewById(R.id.map_zoom_in_button);
ImageButton zoomOutButtonView = (ImageButton) view.findViewById(R.id.map_zoom_out_button);
ImageButton myLocButtonView = (ImageButton) view.findViewById(R.id.map_my_location_button);
this.myLocButtonView = myLocButtonView;
AndroidUtils.updateImageButton(app, zoomInButtonView, R.drawable.ic_zoom_in, R.drawable.ic_zoom_in,
R.drawable.btn_circle_trans, R.drawable.btn_circle_night, nightMode);
AndroidUtils.updateImageButton(app, zoomOutButtonView, R.drawable.ic_zoom_out, R.drawable.ic_zoom_out,
R.drawable.btn_circle_trans, R.drawable.btn_circle_night, nightMode);
zoomInButtonView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
doZoomIn();
}
});
zoomOutButtonView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
doZoomOut();
}
});
myLocButtonView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
if (OsmAndLocationProvider.isLocationPermissionAvailable(mapActivity)) {
mapActivity.getMapViewTrackingUtilities().backToLocationImpl();
} else {
ActivityCompat.requestPermissions(mapActivity,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
OsmAndLocationProvider.REQUEST_LOCATION_PERMISSION);
}
}
}
});
updateMyLocation();
zoomButtonsView.setVisibility(View.VISIBLE);
}
private void updateMyLocation() {
MapActivity mapActivity = getMapActivity(); MapActivity mapActivity = getMapActivity();
if (mapActivity == null) { if (mapActivity == null) {
return; return;
} }
OsmandApplication app = mapActivity.getMyApplication(); // Zoom buttons
Location lastKnownLocation = app.getLocationProvider().getLastKnownLocation(); View zoomButtonsView = view.findViewById(R.id.map_hud_controls);
boolean enabled = lastKnownLocation != null; this.zoomButtonsView = zoomButtonsView;
boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation();
ImageButton myLocButtonView = this.myLocButtonView; ImageButton zoomInButton = view.findViewById(R.id.map_zoom_in_button);
if (myLocButtonView != null) { ImageButton zoomOutButton = view.findViewById(R.id.map_zoom_out_button);
if (!enabled) { ImageButton backToLocation = view.findViewById(R.id.map_my_location_button);
myLocButtonView.setImageDrawable(getIcon(R.drawable.ic_my_location, R.color.icon_color_default_light));
AndroidUtils.setBackground(app, myLocButtonView, nightMode, R.drawable.btn_circle, R.drawable.btn_circle_night);
myLocButtonView.setContentDescription(mapActivity.getString(R.string.unknown_location));
} else if (tracked) {
myLocButtonView.setImageDrawable(getIcon(R.drawable.ic_my_location, R.color.color_myloc_distance));
AndroidUtils.setBackground(app, myLocButtonView, nightMode, R.drawable.btn_circle, R.drawable.btn_circle_night);
} else {
myLocButtonView.setImageResource(R.drawable.ic_my_location);
AndroidUtils.setBackground(app, myLocButtonView, nightMode, R.drawable.btn_circle_blue, R.drawable.btn_circle_blue);
myLocButtonView.setContentDescription(mapActivity.getString(R.string.map_widget_back_to_loc));
}
if (app.accessibilityEnabled()) {
myLocButtonView.setClickable(enabled && !tracked && app.getRoutingHelper().isFollowingMode());
}
}
}
public void doZoomIn() { OsmandMapTileView mapTileView = mapActivity.getMapView();
MapActivity mapActivity = getMapActivity(); View.OnLongClickListener longClickListener = MapControlsLayer.getOnClickMagnifierListener(mapTileView);
if (mapActivity != null) { MapControlsLayer mapControlsLayer = mapActivity.getMapLayers().getMapControlsLayer();
OsmandMapTileView map = mapActivity.getMapView();
if (map.isZooming() && map.hasCustomMapRatio()) {
mapActivity.changeZoom(2, System.currentTimeMillis());
} else {
mapActivity.changeZoom(1, System.currentTimeMillis());
}
}
}
public void doZoomOut() { mapControlsLayer.setupZoomInButton(zoomInButton, longClickListener, ZOOM_IN_BUTTON_ID);
MapActivity mapActivity = getMapActivity(); mapControlsLayer.setupZoomOutButton(zoomOutButton, longClickListener, ZOOM_OUT_BUTTON_ID);
if (mapActivity != null) { mapControlsLayer.setupBackToLocationButton(backToLocation, BACK_TO_LOC_BUTTON_ID);
mapActivity.changeZoom(-1, System.currentTimeMillis());
} AndroidUiHelper.updateVisibility(zoomButtonsView, true);
} }
private void updateZoomButtonsVisibility(int menuState) { private void updateZoomButtonsVisibility(int menuState) {

View file

@ -56,7 +56,6 @@ import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.TargetPointsHelper; import net.osmand.plus.TargetPointsHelper;
import net.osmand.plus.TargetPointsHelper.TargetPoint; import net.osmand.plus.TargetPointsHelper.TargetPoint;
@ -67,7 +66,6 @@ import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet; import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet;
import net.osmand.plus.mapcontextmenu.InterceptorLinearLayout;
import net.osmand.plus.mapcontextmenu.CollapsableView; import net.osmand.plus.mapcontextmenu.CollapsableView;
import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu; import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu;
import net.osmand.plus.render.MapRenderRepositories; import net.osmand.plus.render.MapRenderRepositories;
@ -83,6 +81,7 @@ import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.TransportRoutingHelper; import net.osmand.plus.routing.TransportRoutingHelper;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.transport.TransportStopRoute; import net.osmand.plus.transport.TransportStopRoute;
import net.osmand.plus.widgets.TextViewEx; import net.osmand.plus.widgets.TextViewEx;
import net.osmand.plus.widgets.style.CustomTypefaceSpan; import net.osmand.plus.widgets.style.CustomTypefaceSpan;
@ -315,7 +314,7 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT
statisticCard = new RouteStatisticCard(mapActivity, gpx, new OnTouchListener() { statisticCard = new RouteStatisticCard(mapActivity, gpx, new OnTouchListener() {
@Override @Override
public boolean onTouch(View v, MotionEvent ev) { public boolean onTouch(View v, MotionEvent ev) {
InterceptorLinearLayout mainView = getMainView(); LinearLayout mainView = getMainView();
if (mainView != null) { if (mainView != null) {
mainView.requestDisallowInterceptTouchEvent(true); mainView.requestDisallowInterceptTouchEvent(true);
} }

View file

@ -18,7 +18,7 @@ import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.routepreparationmenu.RouteDetailsFragment; import net.osmand.plus.routepreparationmenu.RouteDetailsFragment;
import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.plus.views.TurnPathHelper; import net.osmand.plus.views.TurnPathHelper;
import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory; import net.osmand.plus.views.mapwidgets.LanesDrawable;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import java.util.List; import java.util.List;
@ -80,7 +80,7 @@ public class RouteDirectionsCard extends BaseCard {
int[] lanes = model.getTurnType().getLanes(); int[] lanes = model.getTurnType().getLanes();
if (lanes != null){ if (lanes != null){
RouteInfoWidgetsFactory.LanesDrawable lanesDrawable = new RouteInfoWidgetsFactory.LanesDrawable(mapActivity,1); LanesDrawable lanesDrawable = new LanesDrawable(mapActivity,1);
lanesDrawable.lanes = lanes; lanesDrawable.lanes = lanes;
lanesDrawable.isTurnByTurn = true; lanesDrawable.isTurnByTurn = true;
lanesDrawable.isNightMode = nightMode; lanesDrawable.isNightMode = nightMode;

View file

@ -34,7 +34,7 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static net.osmand.plus.track.TrackDrawInfo.TRACK_FILE_PATH; import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME;
public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment { public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment {
@ -75,7 +75,7 @@ public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment {
} }
Bundle arguments = getArguments(); Bundle arguments = getArguments();
if (savedInstanceState != null) { if (savedInstanceState != null) {
String gpxFilePath = savedInstanceState.getString(TRACK_FILE_PATH); String gpxFilePath = savedInstanceState.getString(TRACK_FILE_NAME);
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath); selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath);
prepareSplitIntervalOptions(); prepareSplitIntervalOptions();
@ -83,7 +83,7 @@ public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment {
selectedDistanceSplitInterval = savedInstanceState.getInt(SELECTED_DISTANCE_SPLIT_INTERVAL); selectedDistanceSplitInterval = savedInstanceState.getInt(SELECTED_DISTANCE_SPLIT_INTERVAL);
selectedSplitType = GpxSplitType.valueOf(savedInstanceState.getString(SELECTED_TRACK_SPLIT_TYPE)); selectedSplitType = GpxSplitType.valueOf(savedInstanceState.getString(SELECTED_TRACK_SPLIT_TYPE));
} else if (arguments != null) { } else if (arguments != null) {
String gpxFilePath = arguments.getString(TRACK_FILE_PATH); String gpxFilePath = arguments.getString(TRACK_FILE_NAME);
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath); selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath);
prepareSplitIntervalOptions(); prepareSplitIntervalOptions();
updateSelectedSplitParams(); updateSelectedSplitParams();
@ -142,7 +142,7 @@ public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment {
outState.putInt(SELECTED_TIME_SPLIT_INTERVAL, selectedTimeSplitInterval); outState.putInt(SELECTED_TIME_SPLIT_INTERVAL, selectedTimeSplitInterval);
outState.putInt(SELECTED_DISTANCE_SPLIT_INTERVAL, selectedDistanceSplitInterval); outState.putInt(SELECTED_DISTANCE_SPLIT_INTERVAL, selectedDistanceSplitInterval);
outState.putString(SELECTED_TRACK_SPLIT_TYPE, selectedSplitType.name()); outState.putString(SELECTED_TRACK_SPLIT_TYPE, selectedSplitType.name());
outState.putString(TRACK_FILE_PATH, selectedGpxFile.getGpxFile().path); outState.putString(TRACK_FILE_NAME, selectedGpxFile.getGpxFile().path);
} }
private void updateSelectedSplitParams() { private void updateSelectedSplitParams() {
@ -188,7 +188,7 @@ public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment {
private void addDistanceOptionSplit(int value, @NonNull List<GpxDisplayGroup> displayGroups) { private void addDistanceOptionSplit(int value, @NonNull List<GpxDisplayGroup> displayGroups) {
if (displayGroups.size() > 0) { if (displayGroups.size() > 0) {
double dvalue = OsmAndFormatter.calculateRoundedDist(value, app); double dvalue = OsmAndFormatter.calculateRoundedDist(value, app);
String formattedDist = SplitIntervalCard.getFormattedDistanceInterval(app, value); String formattedDist = OsmAndFormatter.getFormattedDistanceInterval(app, value);
distanceSplitOptions.put(formattedDist, dvalue); distanceSplitOptions.put(formattedDist, dvalue);
if (Math.abs(displayGroups.get(0).getSplitDistance() - dvalue) < 1) { if (Math.abs(displayGroups.get(0).getSplitDistance() - dvalue) < 1) {
selectedDistanceSplitInterval = distanceSplitOptions.size() - 1; selectedDistanceSplitInterval = distanceSplitOptions.size() - 1;
@ -198,7 +198,7 @@ public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment {
private void addTimeOptionSplit(int value, @NonNull List<GpxDisplayGroup> model) { private void addTimeOptionSplit(int value, @NonNull List<GpxDisplayGroup> model) {
if (model.size() > 0) { if (model.size() > 0) {
String time = SplitIntervalCard.getFormattedTimeInterval(app, value); String time = OsmAndFormatter.getFormattedTimeInterval(app, value);
timeSplitOptions.put(time, value); timeSplitOptions.put(time, value);
if (model.get(0).getSplitTime() == value) { if (model.get(0).getSplitTime() == value) {
selectedTimeSplitInterval = timeSplitOptions.size() - 1; selectedTimeSplitInterval = timeSplitOptions.size() - 1;
@ -327,7 +327,7 @@ public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment {
try { try {
if (fragmentManager.findFragmentByTag(SplitIntervalBottomSheet.TAG) == null) { if (fragmentManager.findFragmentByTag(SplitIntervalBottomSheet.TAG) == null) {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString(TRACK_FILE_PATH, trackDrawInfo.getFilePath()); args.putString(TRACK_FILE_NAME, trackDrawInfo.getFilePath());
SplitIntervalBottomSheet splitIntervalBottomSheet = new SplitIntervalBottomSheet(); SplitIntervalBottomSheet splitIntervalBottomSheet = new SplitIntervalBottomSheet();
splitIntervalBottomSheet.setArguments(args); splitIntervalBottomSheet.setArguments(args);

View file

@ -11,7 +11,6 @@ import androidx.annotation.NonNull;
import net.osmand.AndroidUtils; import net.osmand.AndroidUtils;
import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.AndroidUiHelper;
@ -68,25 +67,10 @@ public class SplitIntervalCard extends BaseCard {
if (splitInterval == 0) { if (splitInterval == 0) {
intervalStr = GpxSplitType.NO_SPLIT.getHumanString(app); intervalStr = GpxSplitType.NO_SPLIT.getHumanString(app);
} else if (trackDrawInfo.getSplitType() == GpxSplitType.DISTANCE.getType()) { } else if (trackDrawInfo.getSplitType() == GpxSplitType.DISTANCE.getType()) {
intervalStr = getFormattedDistanceInterval(app, trackDrawInfo.getSplitInterval()); intervalStr = OsmAndFormatter.getFormattedDistanceInterval(app, trackDrawInfo.getSplitInterval());
} else if (trackDrawInfo.getSplitType() == GpxSplitType.TIME.getType()) { } else if (trackDrawInfo.getSplitType() == GpxSplitType.TIME.getType()) {
intervalStr = getFormattedTimeInterval(app, splitInterval); intervalStr = OsmAndFormatter.getFormattedTimeInterval(app, splitInterval);
} }
return intervalStr; return intervalStr;
} }
public static String getFormattedTimeInterval(OsmandApplication app, double interval) {
if (interval < 60) {
return interval + " " + app.getString(R.string.int_seconds);
} else if (interval % 60 == 0) {
return (interval / 60) + " " + app.getString(R.string.int_min);
} else {
return (interval / 60f) + " " + app.getString(R.string.int_min);
}
}
public static String getFormattedDistanceInterval(OsmandApplication app, double interval) {
double roundedDist = OsmAndFormatter.calculateRoundedDist(interval, app);
return OsmAndFormatter.getFormattedDistance((float) roundedDist, app);
}
} }

View file

@ -1,6 +1,5 @@
package net.osmand.plus.track; package net.osmand.plus.track;
import android.Manifest;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.AsyncTask; import android.os.AsyncTask;
@ -11,41 +10,35 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import androidx.annotation.ColorInt; import androidx.annotation.ColorInt;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils; import net.osmand.AndroidUtils;
import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.GPXFile;
import net.osmand.Location;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.data.QuadRect; import net.osmand.data.QuadRect;
import net.osmand.data.RotatedTileBox; import net.osmand.data.RotatedTileBox;
import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmAndLocationProvider;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.UiUtilities; import net.osmand.plus.UiUtilities;
import net.osmand.plus.UiUtilities.DialogButtonType; import net.osmand.plus.UiUtilities.DialogButtonType;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.ContextMenuFragment; import net.osmand.plus.base.ContextMenuScrollFragment;
import net.osmand.plus.base.ContextMenuFragment.ContextMenuFragmentListener;
import net.osmand.plus.dialogs.GpxAppearanceAdapter; import net.osmand.plus.dialogs.GpxAppearanceAdapter;
import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener; import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener;
import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.track.SplitTrackAsyncTask.SplitTrackListener; import net.osmand.plus.track.SplitTrackAsyncTask.SplitTrackListener;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.render.RenderingRulesStorage; import net.osmand.render.RenderingRulesStorage;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
@ -55,19 +48,21 @@ import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING;
import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME;
import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR; 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_BOLD;
import static net.osmand.plus.dialogs.GpxAppearanceAdapter.TRACK_WIDTH_MEDIUM; import static net.osmand.plus.dialogs.GpxAppearanceAdapter.TRACK_WIDTH_MEDIUM;
import static net.osmand.plus.track.TrackDrawInfo.TRACK_FILE_PATH;
public class TrackAppearanceFragment extends ContextMenuFragment implements CardListener, ContextMenuFragmentListener { public class TrackAppearanceFragment extends ContextMenuScrollFragment implements CardListener {
public static final String TAG = TrackAppearanceFragment.class.getName(); public static final String TAG = TrackAppearanceFragment.class.getSimpleName();
private static final Log log = PlatformUtil.getLog(TrackAppearanceFragment.class); private static final Log log = PlatformUtil.getLog(TrackAppearanceFragment.class);
private OsmandApplication app; private OsmandApplication app;
@Nullable
private GpxDataItem gpxDataItem; private GpxDataItem gpxDataItem;
private TrackDrawInfo trackDrawInfo; private TrackDrawInfo trackDrawInfo;
private SelectedGpxFile selectedGpxFile; private SelectedGpxFile selectedGpxFile;
@ -80,8 +75,6 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card
private SplitIntervalCard splitIntervalCard; private SplitIntervalCard splitIntervalCard;
private ImageView appearanceIcon; private ImageView appearanceIcon;
private View zoomButtonsView;
private ImageButton myLocButtonView;
@Override @Override
public int getMainLayoutId() { public int getMainLayoutId() {
@ -118,16 +111,32 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card
Bundle arguments = getArguments(); Bundle arguments = getArguments();
if (savedInstanceState != null) { if (savedInstanceState != null) {
trackDrawInfo = new TrackDrawInfo(); trackDrawInfo = new TrackDrawInfo(savedInstanceState);
trackDrawInfo.readBundle(savedInstanceState); if (trackDrawInfo.isCurrentRecording()) {
gpxDataItem = app.getGpxDbHelper().getItem(new File(trackDrawInfo.getFilePath())); selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack();
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(trackDrawInfo.getFilePath()); } else {
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(trackDrawInfo.getFilePath());
}
if (!selectedGpxFile.isShowCurrentTrack()) {
gpxDataItem = app.getGpxDbHelper().getItem(new File(trackDrawInfo.getFilePath()));
}
} else if (arguments != null) { } else if (arguments != null) {
String gpxFilePath = arguments.getString(TRACK_FILE_PATH); String gpxFilePath = arguments.getString(TRACK_FILE_NAME);
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath); boolean currentRecording = arguments.getBoolean(CURRENT_RECORDING, false);
File file = new File(selectedGpxFile.getGpxFile().path);
gpxDataItem = app.getGpxDbHelper().getItem(file); if (gpxFilePath == null && !currentRecording) {
trackDrawInfo = new TrackDrawInfo(gpxDataItem); log.error("Required extra '" + TRACK_FILE_NAME + "' is missing");
dismiss();
return;
}
if (currentRecording) {
trackDrawInfo = new TrackDrawInfo(true);
selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack();
} else {
gpxDataItem = app.getGpxDbHelper().getItem(new File(gpxFilePath));
trackDrawInfo = new TrackDrawInfo(gpxDataItem, false);
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath);
}
updateTrackColor(); updateTrackColor();
} }
} }
@ -155,7 +164,6 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card
View view = super.onCreateView(inflater, container, savedInstanceState); View view = super.onCreateView(inflater, container, savedInstanceState);
if (view != null) { if (view != null) {
appearanceIcon = view.findViewById(R.id.appearance_icon); appearanceIcon = view.findViewById(R.id.appearance_icon);
setListener(this);
if (isPortrait()) { if (isPortrait()) {
updateCardsLayout(); updateCardsLayout();
@ -169,7 +177,6 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card
params.gravity = Gravity.BOTTOM | Gravity.START; params.gravity = Gravity.BOTTOM | Gravity.START;
view.findViewById(R.id.control_buttons).setLayoutParams(params); view.findViewById(R.id.control_buttons).setLayoutParams(params);
} }
buildZoomButtons(view);
enterTrackAppearanceMode(); enterTrackAppearanceMode();
runLayoutListener(); runLayoutListener();
} }
@ -196,21 +203,6 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card
updateStatusBarColor(); updateStatusBarColor();
} }
@Override
public void onContextMenuYPosChanged(@NonNull ContextMenuFragment fragment, int y, boolean needMapAdjust, boolean animated) {
updateZoomButtonsPos(fragment, y, animated);
}
@Override
public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState) {
updateZoomButtonsVisibility(menuState);
}
@Override
public void onContextMenuDismiss(@NonNull ContextMenuFragment fragment) {
}
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
@ -333,130 +325,6 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card
return y; return y;
} }
private void buildZoomButtons(@NonNull View view) {
OsmandApplication app = requireMyApplication();
this.zoomButtonsView = view.findViewById(R.id.map_hud_controls);
ImageButton zoomInButtonView = (ImageButton) view.findViewById(R.id.map_zoom_in_button);
ImageButton zoomOutButtonView = (ImageButton) view.findViewById(R.id.map_zoom_out_button);
AndroidUtils.updateImageButton(app, zoomInButtonView, R.drawable.ic_zoom_in, R.drawable.ic_zoom_in,
R.drawable.btn_circle_trans, R.drawable.btn_circle_night, isNightMode());
AndroidUtils.updateImageButton(app, zoomOutButtonView, R.drawable.ic_zoom_out, R.drawable.ic_zoom_out,
R.drawable.btn_circle_trans, R.drawable.btn_circle_night, isNightMode());
zoomInButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doZoomIn();
}
});
zoomOutButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doZoomOut();
}
});
myLocButtonView = (ImageButton) view.findViewById(R.id.map_my_location_button);
myLocButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
if (OsmAndLocationProvider.isLocationPermissionAvailable(mapActivity)) {
mapActivity.getMapViewTrackingUtilities().backToLocationImpl();
} else {
ActivityCompat.requestPermissions(mapActivity,
new String[] {Manifest.permission.ACCESS_FINE_LOCATION},
OsmAndLocationProvider.REQUEST_LOCATION_PERMISSION);
}
}
}
});
updateMyLocation();
zoomButtonsView.setVisibility(View.VISIBLE);
}
private void updateMyLocation() {
MapActivity mapActivity = getMapActivity();
if (mapActivity == null) {
return;
}
OsmandApplication app = mapActivity.getMyApplication();
Location lastKnownLocation = app.getLocationProvider().getLastKnownLocation();
boolean enabled = lastKnownLocation != null;
boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation();
ImageButton myLocButtonView = this.myLocButtonView;
if (myLocButtonView != null) {
if (!enabled) {
myLocButtonView.setImageDrawable(getIcon(R.drawable.ic_my_location, R.color.icon_color_default_light));
AndroidUtils.setBackground(app, myLocButtonView, isNightMode(), R.drawable.btn_circle, R.drawable.btn_circle_night);
myLocButtonView.setContentDescription(mapActivity.getString(R.string.unknown_location));
} else if (tracked) {
myLocButtonView.setImageDrawable(getIcon(R.drawable.ic_my_location, R.color.color_myloc_distance));
AndroidUtils.setBackground(app, myLocButtonView, isNightMode(), R.drawable.btn_circle, R.drawable.btn_circle_night);
} else {
myLocButtonView.setImageResource(R.drawable.ic_my_location);
AndroidUtils.setBackground(app, myLocButtonView, isNightMode(), R.drawable.btn_circle_blue, R.drawable.btn_circle_blue);
myLocButtonView.setContentDescription(mapActivity.getString(R.string.map_widget_back_to_loc));
}
if (app.accessibilityEnabled()) {
myLocButtonView.setClickable(enabled && !tracked && app.getRoutingHelper().isFollowingMode());
}
}
}
public void updateZoomButtonsPos(@NonNull ContextMenuFragment fragment, int y, boolean animated) {
View zoomButtonsView = this.zoomButtonsView;
if (zoomButtonsView != null) {
int zoomY = y - getZoomButtonsHeight();
if (animated) {
fragment.animateView(zoomButtonsView, zoomY);
} else {
zoomButtonsView.setY(zoomY);
}
}
}
private int getZoomButtonsHeight() {
View zoomButtonsView = this.zoomButtonsView;
return zoomButtonsView != null ? zoomButtonsView.getHeight() : 0;
}
public void doZoomIn() {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
OsmandMapTileView map = mapActivity.getMapView();
if (map.isZooming() && map.hasCustomMapRatio()) {
mapActivity.changeZoom(2, System.currentTimeMillis());
} else {
mapActivity.changeZoom(1, System.currentTimeMillis());
}
}
}
public void doZoomOut() {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
mapActivity.changeZoom(-1, System.currentTimeMillis());
}
}
private void updateZoomButtonsVisibility(int menuState) {
View zoomButtonsView = this.zoomButtonsView;
if (zoomButtonsView != null) {
if (menuState == MenuState.HEADER_ONLY) {
if (zoomButtonsView.getVisibility() != View.VISIBLE) {
zoomButtonsView.setVisibility(View.VISIBLE);
}
} else {
if (zoomButtonsView.getVisibility() == View.VISIBLE) {
zoomButtonsView.setVisibility(View.INVISIBLE);
}
}
}
}
private void updateAppearanceIcon() { private void updateAppearanceIcon() {
Drawable icon = getTrackIcon(app, trackDrawInfo.getWidth(), trackDrawInfo.isShowArrows(), trackDrawInfo.getColor()); Drawable icon = getTrackIcon(app, trackDrawInfo.getWidth(), trackDrawInfo.isShowArrows(), trackDrawInfo.getColor());
appearanceIcon.setImageDrawable(icon); appearanceIcon.setImageDrawable(icon);
@ -535,7 +403,7 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card
cancelButton.setOnClickListener(new View.OnClickListener() { cancelButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
discardChanges(); discardSplitChanges();
FragmentActivity activity = getActivity(); FragmentActivity activity = getActivity();
if (activity != null) { if (activity != null) {
activity.onBackPressed(); activity.onBackPressed();
@ -570,15 +438,21 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card
gpxFile.setShowArrows(trackDrawInfo.isShowArrows()); gpxFile.setShowArrows(trackDrawInfo.isShowArrows());
gpxFile.setShowStartFinish(trackDrawInfo.isShowStartFinish()); gpxFile.setShowStartFinish(trackDrawInfo.isShowStartFinish());
app.getSelectedGpxHelper().updateSelectedGpxFile(selectedGpxFile); if (gpxFile.showCurrentTrack) {
app.getSettings().CURRENT_TRACK_COLOR.set(trackDrawInfo.getColor());
gpxDataItem = new GpxDataItem(new File(gpxFile.path), gpxFile); } else {
app.getGpxDbHelper().add(gpxDataItem); if (gpxDataItem != null) {
saveGpx(gpxFile); gpxDataItem = new GpxDataItem(new File(gpxFile.path), gpxFile);
app.getGpxDbHelper().add(gpxDataItem);
}
app.getSelectedGpxHelper().updateSelectedGpxFile(selectedGpxFile);
saveGpx(gpxFile);
}
} }
private void discardChanges() { private void discardSplitChanges() {
if (gpxDataItem.getSplitType() != trackDrawInfo.getSplitType() || gpxDataItem.getSplitInterval() != trackDrawInfo.getSplitInterval()) { if (gpxDataItem != null && (gpxDataItem.getSplitType() != trackDrawInfo.getSplitType()
|| gpxDataItem.getSplitInterval() != trackDrawInfo.getSplitInterval())) {
int timeSplit = (int) gpxDataItem.getSplitInterval(); int timeSplit = (int) gpxDataItem.getSplitInterval();
double distanceSplit = gpxDataItem.getSplitInterval(); double distanceSplit = gpxDataItem.getSplitInterval();
@ -640,9 +514,11 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card
ViewGroup cardsContainer = getCardsContainer(); ViewGroup cardsContainer = getCardsContainer();
cardsContainer.removeAllViews(); cardsContainer.removeAllViews();
splitIntervalCard = new SplitIntervalCard(mapActivity, trackDrawInfo); if (!selectedGpxFile.isShowCurrentTrack()) {
splitIntervalCard.setListener(this); splitIntervalCard = new SplitIntervalCard(mapActivity, trackDrawInfo);
cardsContainer.addView(splitIntervalCard.build(mapActivity)); splitIntervalCard.setListener(this);
cardsContainer.addView(splitIntervalCard.build(mapActivity));
}
DirectionArrowsCard directionArrowsCard = new DirectionArrowsCard(mapActivity, trackDrawInfo); DirectionArrowsCard directionArrowsCard = new DirectionArrowsCard(mapActivity, trackDrawInfo);
directionArrowsCard.setListener(this); directionArrowsCard.setListener(this);

View file

@ -7,9 +7,11 @@ import androidx.annotation.NonNull;
import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING;
import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME;
public class TrackDrawInfo { public class TrackDrawInfo {
public static final String TRACK_FILE_PATH = "track_file_path";
private static final String TRACK_WIDTH = "track_width"; private static final String TRACK_WIDTH = "track_width";
private static final String TRACK_GRADIENT_SCALE_TYPE = "track_gradient_scale_type"; private static final String TRACK_GRADIENT_SCALE_TYPE = "track_gradient_scale_type";
private static final String TRACK_COLOR = "track_color"; private static final String TRACK_COLOR = "track_color";
@ -27,13 +29,18 @@ public class TrackDrawInfo {
private double splitInterval; private double splitInterval;
private boolean joinSegments; private boolean joinSegments;
private boolean showArrows; private boolean showArrows;
private boolean showStartFinish; private boolean showStartFinish = true;
private boolean currentRecording;
public TrackDrawInfo() {
public TrackDrawInfo(boolean currentRecording) {
this.currentRecording = currentRecording;
} }
public TrackDrawInfo(GpxDataItem gpxDataItem) { public TrackDrawInfo(Bundle bundle) {
readBundle(bundle);
}
public TrackDrawInfo(GpxDataItem gpxDataItem, boolean currentRecording) {
filePath = gpxDataItem.getFile().getPath(); filePath = gpxDataItem.getFile().getPath();
width = gpxDataItem.getWidth(); width = gpxDataItem.getWidth();
gradientScaleType = gpxDataItem.getGradientScaleType(); gradientScaleType = gpxDataItem.getGradientScaleType();
@ -43,6 +50,7 @@ public class TrackDrawInfo {
joinSegments = gpxDataItem.isJoinSegments(); joinSegments = gpxDataItem.isJoinSegments();
showArrows = gpxDataItem.isShowArrows(); showArrows = gpxDataItem.isShowArrows();
showStartFinish = gpxDataItem.isShowStartFinish(); showStartFinish = gpxDataItem.isShowStartFinish();
this.currentRecording = currentRecording;
} }
public String getFilePath() { public String getFilePath() {
@ -105,8 +113,12 @@ public class TrackDrawInfo {
return showStartFinish; return showStartFinish;
} }
protected void readBundle(@NonNull Bundle bundle) { public boolean isCurrentRecording() {
filePath = bundle.getString(TRACK_FILE_PATH); return currentRecording;
}
private void readBundle(@NonNull Bundle bundle) {
filePath = bundle.getString(TRACK_FILE_NAME);
width = bundle.getString(TRACK_WIDTH); width = bundle.getString(TRACK_WIDTH);
String gradientScaleTypeName = bundle.getString(TRACK_GRADIENT_SCALE_TYPE); String gradientScaleTypeName = bundle.getString(TRACK_GRADIENT_SCALE_TYPE);
if (!Algorithms.isEmpty(gradientScaleTypeName)) { if (!Algorithms.isEmpty(gradientScaleTypeName)) {
@ -118,10 +130,11 @@ public class TrackDrawInfo {
joinSegments = bundle.getBoolean(TRACK_JOIN_SEGMENTS); joinSegments = bundle.getBoolean(TRACK_JOIN_SEGMENTS);
showArrows = bundle.getBoolean(TRACK_SHOW_ARROWS); showArrows = bundle.getBoolean(TRACK_SHOW_ARROWS);
showStartFinish = bundle.getBoolean(TRACK_SHOW_START_FINISH); showStartFinish = bundle.getBoolean(TRACK_SHOW_START_FINISH);
currentRecording = bundle.getBoolean(CURRENT_RECORDING);
} }
protected void saveToBundle(@NonNull Bundle bundle) { protected void saveToBundle(@NonNull Bundle bundle) {
bundle.putString(TRACK_FILE_PATH, filePath); bundle.putString(TRACK_FILE_NAME, filePath);
bundle.putString(TRACK_WIDTH, width); bundle.putString(TRACK_WIDTH, width);
bundle.putString(TRACK_GRADIENT_SCALE_TYPE, gradientScaleType != null ? gradientScaleType.getTypeName() : ""); bundle.putString(TRACK_GRADIENT_SCALE_TYPE, gradientScaleType != null ? gradientScaleType.getTypeName() : "");
bundle.putInt(TRACK_COLOR, color); bundle.putInt(TRACK_COLOR, color);
@ -130,5 +143,6 @@ public class TrackDrawInfo {
bundle.putBoolean(TRACK_JOIN_SEGMENTS, joinSegments); bundle.putBoolean(TRACK_JOIN_SEGMENTS, joinSegments);
bundle.putBoolean(TRACK_SHOW_ARROWS, showArrows); bundle.putBoolean(TRACK_SHOW_ARROWS, showArrows);
bundle.putBoolean(TRACK_SHOW_START_FINISH, showStartFinish); bundle.putBoolean(TRACK_SHOW_START_FINISH, showStartFinish);
bundle.putBoolean(CURRENT_RECORDING, currentRecording);
} }
} }

View file

@ -1,11 +1,11 @@
package net.osmand.plus.views; package net.osmand.plus.views;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Paint.Align; import android.graphics.Paint.Align;
import android.graphics.Paint.Cap;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
import android.graphics.PointF; import android.graphics.PointF;
import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuff.Mode;
@ -50,6 +50,7 @@ import net.osmand.plus.mapcontextmenu.controllers.SelectedGpxMenuController.Sele
import net.osmand.plus.mapcontextmenu.other.TrackChartPoints; import net.osmand.plus.mapcontextmenu.other.TrackChartPoints;
import net.osmand.plus.render.OsmandRenderer; import net.osmand.plus.render.OsmandRenderer;
import net.osmand.plus.render.OsmandRenderer.RenderingContext; import net.osmand.plus.render.OsmandRenderer.RenderingContext;
import net.osmand.plus.render.RenderingIcons;
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference; import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
import net.osmand.plus.track.SaveGpxAsyncTask; import net.osmand.plus.track.SaveGpxAsyncTask;
import net.osmand.plus.track.TrackDrawInfo; import net.osmand.plus.track.TrackDrawInfo;
@ -78,6 +79,8 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
private static final Log log = PlatformUtil.getLog(GPXLayer.class); private static final Log log = PlatformUtil.getLog(GPXLayer.class);
private static final double TOUCH_RADIUS_MULTIPLIER = 1.5; private static final double TOUCH_RADIUS_MULTIPLIER = 1.5;
private static final double DIRECTION_ARROW_DISTANCE_MULTIPLIER = 10.0;
private static final float DIRECTION_ARROW_CIRCLE_MULTIPLIER = 1.5f;
private static final int DEFAULT_WIDTH_MULTIPLIER = 7; private static final int DEFAULT_WIDTH_MULTIPLIER = 7;
private static final int START_ZOOM = 7; private static final int START_ZOOM = 7;
@ -200,7 +203,11 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
grayColor = ContextCompat.getColor(view.getApplication(), R.color.color_favorite_gray); grayColor = ContextCompat.getColor(view.getApplication(), R.color.color_favorite_gray);
wayContext = new GeometryWayContext(view.getContext(), view.getDensity()); wayContext = new GeometryWayContext(view.getContext(), view.getDensity());
arrowBitmap = BitmapFactory.decodeResource(view.getApplication().getResources(), R.drawable.map_route_direction_arrow, null);
Paint paint = wayContext.getPaintIcon();
paint.setStrokeCap(Cap.ROUND);
arrowBitmap = RenderingIcons.getBitmapFromVectorDrawable(view.getContext(), R.drawable.mm_special_arrow_up);
} }
@Override @Override
@ -415,15 +422,21 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
} }
if (showArrows) { if (showArrows) {
QuadRect correctedQuadRect = getCorrectedQuadRect(tileBox.getLatLonBounds()); QuadRect correctedQuadRect = getCorrectedQuadRect(tileBox.getLatLonBounds());
String width = selectedGpxFile.getGpxFile().getWidth(currentTrackWidthPref.get());
int color = selectedGpxFile.getGpxFile().getColor(cachedColor); int color = selectedGpxFile.getGpxFile().getColor(cachedColor);
if (selectedGpxFile.isShowCurrentTrack()) { if (selectedGpxFile.isShowCurrentTrack()) {
color = currentTrackColor; color = currentTrackColor;
} }
if (hasTrackDrawInfoForSelectedGpx(selectedGpxFile)) { if (hasTrackDrawInfoForSelectedGpx(selectedGpxFile)) {
color = trackDrawInfo.getColor(); color = trackDrawInfo.getColor();
width = trackDrawInfo.getWidth();
}
Float trackWidth = cachedTrackWidth.get(width);
if (trackWidth == null) {
trackWidth = defaultTrackWidth;
} }
int contrastColor = UiUtilities.getContrastColor(view.getApplication(), color, false); int contrastColor = UiUtilities.getContrastColor(view.getApplication(), color, false);
GeometryWayStyle arrowsWayStyle = new GeometryArrowsWayStyle(wayContext, contrastColor); GeometryWayStyle arrowsWayStyle = new GeometryArrowsWayStyle(wayContext, arrowBitmap, contrastColor, color, trackWidth);
for (TrkSegment segment : selectedGpxFile.getPointsToDisplay()) { for (TrkSegment segment : selectedGpxFile.getPointsToDisplay()) {
List<Float> tx = new ArrayList<>(); List<Float> tx = new ArrayList<>();
List<Float> ty = new ArrayList<>(); List<Float> ty = new ArrayList<>();
@ -465,10 +478,10 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
int bottom = pixHeight + pixHeight / 4; int bottom = pixHeight + pixHeight / 4;
double zoomCoef = tb.getZoomAnimation() > 0 ? (Math.pow(2, tb.getZoomAnimation() + tb.getZoomFloatPart())) : 1f; double zoomCoef = tb.getZoomAnimation() > 0 ? (Math.pow(2, tb.getZoomAnimation() + tb.getZoomFloatPart())) : 1f;
double pxStep = arrowBitmap.getHeight() * 4f * zoomCoef; double pxStep = arrowBitmap.getHeight() * DIRECTION_ARROW_DISTANCE_MULTIPLIER * zoomCoef;
double dist = 0; double dist = 0;
List<PathPoint> arrows = new ArrayList<>(); List<ArrowPathPoint> arrows = new ArrayList<>();
for (int i = tx.size() - 2; i >= 0; i--) { for (int i = tx.size() - 2; i >= 0; i--) {
float px = tx.get(i); float px = tx.get(i);
float py = ty.get(i); float py = ty.get(i);
@ -490,7 +503,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
float iconx = (float) (px + pdx); float iconx = (float) (px + pdx);
float icony = (float) (py + pdy); float icony = (float) (py + pdy);
if (isIn(iconx, icony, left, top, right, bottom)) { if (isIn(iconx, icony, left, top, right, bottom)) {
arrows.add(new PathPoint(iconx, icony, angle, wayStyle)); arrows.add(new ArrowPathPoint(iconx, icony, angle, wayStyle));
} }
dist -= pxStep; dist -= pxStep;
percent -= pxStep / distSegment; percent -= pxStep / distSegment;
@ -502,13 +515,43 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
} }
} }
private static class ArrowPathPoint extends PathPoint {
ArrowPathPoint(float x, float y, double angle, GeometryWayStyle style) {
super(x, y, angle, style);
}
@Override
void draw(Canvas canvas, GeometryWayContext context) {
if (style instanceof GeometryArrowsWayStyle) {
GeometryArrowsWayStyle arrowsWayStyle = (GeometryArrowsWayStyle) style;
float arrowWidth = style.getPointBitmap().getWidth();
if (arrowWidth > arrowsWayStyle.getTrackWidth()) {
Paint paint = context.getPaintIcon();
paint.setColor(arrowsWayStyle.getTrackColor());
paint.setStrokeWidth(arrowWidth * DIRECTION_ARROW_CIRCLE_MULTIPLIER);
canvas.drawPoint(x, y, paint);
}
}
super.draw(canvas, context);
}
}
private static class GeometryArrowsWayStyle extends GeometryWayStyle { private static class GeometryArrowsWayStyle extends GeometryWayStyle {
protected Integer pointColor; private Bitmap arrowBitmap;
GeometryArrowsWayStyle(GeometryWayContext context, int pointColor) { protected int pointColor;
protected int trackColor;
protected float trackWidth;
GeometryArrowsWayStyle(GeometryWayContext context, Bitmap arrowBitmap, int arrowColor, int trackColor, float trackWidth) {
super(context); super(context);
this.pointColor = pointColor; this.arrowBitmap = arrowBitmap;
this.pointColor = arrowColor;
this.trackColor = trackColor;
this.trackWidth = trackWidth;
} }
@Override @Override
@ -524,13 +567,21 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
@Override @Override
public Bitmap getPointBitmap() { public Bitmap getPointBitmap() {
return getContext().getArrowBitmap(); return arrowBitmap;
} }
@Override @Override
public Integer getPointColor() { public Integer getPointColor() {
return pointColor; return pointColor;
} }
public int getTrackColor() {
return trackColor;
}
public float getTrackWidth() {
return trackWidth;
}
} }
private void drawSelectedFilesStartEndPoints(Canvas canvas, RotatedTileBox tileBox, List<SelectedGpxFile> selectedGPXFiles) { private void drawSelectedFilesStartEndPoints(Canvas canvas, RotatedTileBox tileBox, List<SelectedGpxFile> selectedGPXFiles) {
@ -546,13 +597,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
if (segment.points.size() >= 2) { if (segment.points.size() >= 2) {
WptPt start = segment.points.get(0); WptPt start = segment.points.get(0);
WptPt end = segment.points.get(segment.points.size() - 1); WptPt end = segment.points.get(segment.points.size() - 1);
drawStartEndPoints(canvas, tileBox, start, end);
if (start.equals(end)) {
drawPoint(canvas, tileBox, start, startAndFinishIcon);
} else {
drawPoint(canvas, tileBox, start, startPointIcon);
drawPoint(canvas, tileBox, end, finishPointIcon);
}
} }
} }
} }
@ -561,17 +606,29 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
} }
private boolean hasTrackDrawInfoForSelectedGpx(SelectedGpxFile selectedGpxFile) { private boolean hasTrackDrawInfoForSelectedGpx(SelectedGpxFile selectedGpxFile) {
return trackDrawInfo != null && trackDrawInfo.getFilePath().equals(selectedGpxFile.getGpxFile().path); return trackDrawInfo != null && (trackDrawInfo.isCurrentRecording() && selectedGpxFile.isShowCurrentTrack()
|| selectedGpxFile.getGpxFile().path.equals(trackDrawInfo.getFilePath()));
} }
private void drawPoint(Canvas canvas, RotatedTileBox tileBox, WptPt wptPt, Drawable icon) { private void drawStartEndPoints(Canvas canvas, RotatedTileBox tileBox, WptPt start, WptPt end) {
int pointX = (int) tileBox.getPixXFromLatLon(wptPt.lat, wptPt.lon); int startX = (int) tileBox.getPixXFromLatLon(start.lat, start.lon);
int pointY = (int) tileBox.getPixYFromLatLon(wptPt.lat, wptPt.lon); int startY = (int) tileBox.getPixYFromLatLon(start.lat, start.lon);
int endX = (int) tileBox.getPixXFromLatLon(end.lat, end.lon);
int endY = (int) tileBox.getPixYFromLatLon(end.lat, end.lon);
icon.setBounds(pointX - icon.getIntrinsicWidth() / 2, QuadRect startRect = calculateRect(startX, startY, startPointIcon.getIntrinsicWidth(), startPointIcon.getIntrinsicHeight());
pointY - icon.getIntrinsicHeight() / 2, QuadRect endRect = calculateRect(endX, endY, finishPointIcon.getIntrinsicWidth(), finishPointIcon.getIntrinsicHeight());
pointX + icon.getIntrinsicWidth() / 2,
pointY + icon.getIntrinsicHeight() / 2); if (QuadRect.intersects(startRect, endRect)) {
drawPoint(canvas, startRect, startAndFinishIcon);
} else {
drawPoint(canvas, startRect, startPointIcon);
drawPoint(canvas, endRect, finishPointIcon);
}
}
private void drawPoint(Canvas canvas, QuadRect rect, Drawable icon) {
icon.setBounds((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom);
icon.draw(canvas); icon.draw(canvas);
} }

View file

@ -68,6 +68,7 @@ import net.osmand.plus.settings.backend.OsmandSettings.LayerTransparencySeekbarM
import net.osmand.plus.views.corenative.NativeCoreContext; import net.osmand.plus.views.corenative.NativeCoreContext;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import gnu.trove.list.array.TIntArrayList; import gnu.trove.list.array.TIntArrayList;
@ -356,23 +357,8 @@ public class MapControlsLayer extends OsmandMapLayer {
private void initControls() { private void initControls() {
View backToLocation = mapActivity.findViewById(R.id.map_my_location_button); View backToLocation = mapActivity.findViewById(R.id.map_my_location_button);
backToLocationControl = createHudButton(backToLocation, R.drawable.ic_my_location, BACK_TO_LOC_HUD_ID) backToLocationControl = setupBackToLocationButton(backToLocation, BACK_TO_LOC_HUD_ID);
.setIconColorId(R.color.map_button_icon_color_light, R.color.map_button_icon_color_dark)
.setBg(R.drawable.btn_circle_blue);
controls.add(backToLocationControl);
backToLocation.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (OsmAndLocationProvider.isLocationPermissionAvailable(mapActivity)) {
mapActivity.getMapViewTrackingUtilities().backToLocationImpl();
} else {
ActivityCompat.requestPermissions(mapActivity,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
OsmAndLocationProvider.REQUEST_LOCATION_PERMISSION);
}
}
});
View backToMenuButton = mapActivity.findViewById(R.id.map_menu_button); View backToMenuButton = mapActivity.findViewById(R.id.map_menu_button);
final boolean dash = settings.SHOW_DASHBOARD_ON_MAP_SCREEN.get(); final boolean dash = settings.SHOW_DASHBOARD_ON_MAP_SCREEN.get();
@ -409,6 +395,28 @@ public class MapControlsLayer extends OsmandMapLayer {
}); });
} }
public MapHudButton setupBackToLocationButton(View backToLocation, String buttonId) {
MapHudButton backToLocationButton = createHudButton(backToLocation, R.drawable.ic_my_location, buttonId)
.setIconColorId(R.color.map_button_icon_color_light, R.color.map_button_icon_color_dark)
.setBg(R.drawable.btn_circle_blue);
backToLocation.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (OsmAndLocationProvider.isLocationPermissionAvailable(mapActivity)) {
mapActivity.getMapViewTrackingUtilities().backToLocationImpl();
} else {
ActivityCompat.requestPermissions(mapActivity,
new String[] {Manifest.permission.ACCESS_FINE_LOCATION},
OsmAndLocationProvider.REQUEST_LOCATION_PERMISSION);
}
}
});
controls.add(backToLocationButton);
return backToLocationButton;
}
public void doRoute(boolean hasTargets) { public void doRoute(boolean hasTargets) {
this.hasTargets = hasTargets; this.hasTargets = hasTargets;
onNavigationClick(); onNavigationClick();
@ -594,29 +602,21 @@ public class MapControlsLayer extends OsmandMapLayer {
} }
private void initZooms() { private void initZooms() {
final OsmandMapTileView view = mapActivity.getMapView(); OsmandMapTileView view = mapActivity.getMapView();
View.OnLongClickListener longClickListener = MapControlsLayer.getOnClickMagnifierListener(view);
View zoomInButton = mapActivity.findViewById(R.id.map_zoom_in_button); View zoomInButton = mapActivity.findViewById(R.id.map_zoom_in_button);
mapZoomIn = createHudButton(zoomInButton, R.drawable.ic_zoom_in, ZOOM_IN_HUD_ID).setRoundTransparent();
controls.add(mapZoomIn);
zoomInButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mapActivity.getContextMenu().zoomInPressed()) {
return;
}
if (view.isZooming()) {
mapActivity.changeZoom(2, System.currentTimeMillis());
} else {
mapActivity.changeZoom(1, System.currentTimeMillis());
}
lastZoom = System.currentTimeMillis();
}
});
final View.OnLongClickListener listener = MapControlsLayer.getOnClickMagnifierListener(view);
zoomInButton.setOnLongClickListener(listener);
View zoomOutButton = mapActivity.findViewById(R.id.map_zoom_out_button); View zoomOutButton = mapActivity.findViewById(R.id.map_zoom_out_button);
mapZoomOut = createHudButton(zoomOutButton, R.drawable.ic_zoom_out, ZOOM_OUT_HUD_ID).setRoundTransparent();
controls.add(mapZoomOut); mapZoomIn = setupZoomInButton(zoomInButton, longClickListener, ZOOM_IN_HUD_ID);
mapZoomOut = setupZoomOutButton(zoomOutButton, longClickListener, ZOOM_OUT_HUD_ID);
}
public MapHudButton setupZoomOutButton(View zoomOutButton, View.OnLongClickListener longClickListener, String buttonId) {
MapHudButton mapZoomOutButton = createHudButton(zoomOutButton, R.drawable.ic_zoom_out, buttonId);
mapZoomOutButton.setRoundTransparent();
zoomOutButton.setOnLongClickListener(longClickListener);
zoomOutButton.setOnClickListener(new View.OnClickListener() { zoomOutButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
@ -627,7 +627,44 @@ public class MapControlsLayer extends OsmandMapLayer {
lastZoom = System.currentTimeMillis(); lastZoom = System.currentTimeMillis();
} }
}); });
zoomOutButton.setOnLongClickListener(listener); controls.add(mapZoomOutButton);
return mapZoomOutButton;
}
public MapHudButton setupZoomInButton(View zoomInButton, View.OnLongClickListener longClickListener, String buttonId) {
MapHudButton mapZoomInButton = createHudButton(zoomInButton, R.drawable.ic_zoom_in, buttonId);
mapZoomInButton.setRoundTransparent();
zoomInButton.setOnLongClickListener(longClickListener);
zoomInButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mapActivity.getContextMenu().zoomInPressed()) {
return;
}
if (mapActivity.getMapView().isZooming()) {
mapActivity.changeZoom(2, System.currentTimeMillis());
} else {
mapActivity.changeZoom(1, System.currentTimeMillis());
}
lastZoom = System.currentTimeMillis();
}
});
controls.add(mapZoomInButton);
return mapZoomInButton;
}
public void removeHudButtons(List<String> buttonIds) {
List<MapHudButton> hudButtons = new ArrayList<>(controls);
for (Iterator<MapHudButton> iterator = hudButtons.iterator(); iterator.hasNext(); ) {
MapHudButton mapHudButton = iterator.next();
if (buttonIds.contains(mapHudButton.id)) {
iterator.remove();
}
}
controls = hudButtons;
} }
public void showMapControlsIfHidden() { public void showMapControlsIfHidden() {
@ -771,14 +808,12 @@ public class MapControlsLayer extends OsmandMapLayer {
return AndroidUiHelper.isOrientationPortrait(mapActivity); return AndroidUiHelper.isOrientationPortrait(mapActivity);
} }
@SuppressWarnings("deprecation")
private void updateControls(@NonNull RotatedTileBox tileBox, DrawSettings drawSettings) { private void updateControls(@NonNull RotatedTileBox tileBox, DrawSettings drawSettings) {
boolean isNight = drawSettings != null && drawSettings.isNightMode(); boolean isNight = drawSettings != null && drawSettings.isNightMode();
boolean portrait = isPotrait(); boolean portrait = isPotrait();
// int shadw = isNight ? mapActivity.getResources().getColor(R.color.widgettext_shadow_night) : // int shadw = isNight ? mapActivity.getResources().getColor(R.color.widgettext_shadow_night) :
// mapActivity.getResources().getColor(R.color.widgettext_shadow_day); // mapActivity.getResources().getColor(R.color.widgettext_shadow_day);
int textColor = isNight ? mapActivity.getResources().getColor(R.color.widgettext_night) : int textColor = ContextCompat.getColor(mapActivity, isNight ? R.color.widgettext_night : R.color.widgettext_day);
mapActivity.getResources().getColor(R.color.widgettext_day);
// TODOnightMode // TODOnightMode
// updatextColor(textColor, shadw, rulerControl, zoomControls, mapMenuControls); // updatextColor(textColor, shadw, rulerControl, zoomControls, mapMenuControls);
// default buttons // default buttons
@ -796,7 +831,7 @@ public class MapControlsLayer extends OsmandMapLayer {
boolean showRouteCalculationControls = routePlanningMode || boolean showRouteCalculationControls = routePlanningMode ||
((app.accessibilityEnabled() || (System.currentTimeMillis() - touchEvent < TIMEOUT_TO_SHOW_BUTTONS)) && routeFollowingMode); ((app.accessibilityEnabled() || (System.currentTimeMillis() - touchEvent < TIMEOUT_TO_SHOW_BUTTONS)) && routeFollowingMode);
boolean routeDialogOpened = mapRouteInfoMenu.isVisible() || (showRouteCalculationControls && mapRouteInfoMenu.needShowMenu()); boolean routeDialogOpened = mapRouteInfoMenu.isVisible() || (showRouteCalculationControls && mapRouteInfoMenu.needShowMenu());
updateMyLocation(rh, routeDialogOpened || contextMenuOpened); updateMyLocationVisibility(backToLocationControl, rh, routeDialogOpened || contextMenuOpened);
boolean showButtons = (showRouteCalculationControls || !routeFollowingMode) boolean showButtons = (showRouteCalculationControls || !routeFollowingMode)
&& !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode() && !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode()
&& !isInPlanRouteMode() && !contextMenuOpened && !isInChoosingRoutesMode() && !isInPlanRouteMode() && !contextMenuOpened && !isInChoosingRoutesMode()
@ -854,6 +889,9 @@ public class MapControlsLayer extends OsmandMapLayer {
} }
for (MapHudButton mc : controls) { for (MapHudButton mc : controls) {
if (mc.id.startsWith(BACK_TO_LOC_HUD_ID)) {
updateMyLocation(mc);
}
mc.update(mapActivity.getMyApplication(), isNight); mc.update(mapActivity.getMyApplication(), isNight);
} }
} }
@ -893,8 +931,7 @@ public class MapControlsLayer extends OsmandMapLayer {
return new CompassDrawable(originalDrawable); return new CompassDrawable(originalDrawable);
} }
private void updateMyLocation(RoutingHelper rh, boolean dialogOpened) { private void updateMyLocation(MapHudButton backToLocationControl) {
boolean portrait = isPotrait();
Location lastKnownLocation = mapActivity.getMyApplication().getLocationProvider().getLastKnownLocation(); Location lastKnownLocation = mapActivity.getMyApplication().getLocationProvider().getLastKnownLocation();
boolean enabled = lastKnownLocation != null; boolean enabled = lastKnownLocation != null;
boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation(); boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation();
@ -912,14 +949,18 @@ public class MapControlsLayer extends OsmandMapLayer {
backToLocationControl.setBg(R.drawable.btn_circle_blue); backToLocationControl.setBg(R.drawable.btn_circle_blue);
backToLocationControl.iv.setContentDescription(mapActivity.getString(R.string.map_widget_back_to_loc)); backToLocationControl.iv.setContentDescription(mapActivity.getString(R.string.map_widget_back_to_loc));
} }
boolean visible = !(tracked && rh.isFollowingMode());
backToLocationControl.updateVisibility(visible && !dialogOpened && !isInPlanRouteMode()
&& !isInTrackAppearanceMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait));
if (app.accessibilityEnabled()) { if (app.accessibilityEnabled()) {
boolean visible = backToLocationControl.iv.getVisibility() == View.VISIBLE;
backToLocationControl.iv.setClickable(enabled && visible); backToLocationControl.iv.setClickable(enabled && visible);
} }
} }
public void updateMyLocationVisibility(MapHudButton backToLocationControl, RoutingHelper rh, boolean dialogOpened) {
boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation();
boolean visible = !(tracked && rh.isFollowingMode());
backToLocationControl.updateVisibility(visible && !dialogOpened && !isInPlanRouteMode()
&& !isInTrackAppearanceMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !isPotrait()));
}
public boolean onSingleTap(PointF point, RotatedTileBox tileBox) { public boolean onSingleTap(PointF point, RotatedTileBox tileBox) {
return mapRouteInfoMenu.onSingleTap(point, tileBox); return mapRouteInfoMenu.onSingleTap(point, tileBox);
@ -991,31 +1032,31 @@ public class MapControlsLayer extends OsmandMapLayer {
transparencySetting = null; transparencySetting = null;
} }
private class MapHudButton { public class MapHudButton {
View iv;
int bgDark;
int bgLight;
int resId;
int resLightId;
int resDarkId;
int resClrLight = R.color.map_button_icon_color_light;
int resClrDark = R.color.map_button_icon_color_dark;
String id;
boolean flipIconForRtl;
boolean nightMode = false; private View iv;
boolean f = true; private int bgDark;
boolean compass; private int bgLight;
boolean compassOutside; private int resId;
boolean forceHideCompass; private int resLightId;
ViewPropertyAnimatorCompat hideAnimator; private int resDarkId;
private int resClrLight = R.color.map_button_icon_color_light;
private int resClrDark = R.color.map_button_icon_color_dark;
private String id;
private boolean flipIconForRtl;
private boolean nightMode = false;
private boolean f = true;
private boolean compass;
private boolean compassOutside;
private boolean forceHideCompass;
private ViewPropertyAnimatorCompat hideAnimator;
public MapHudButton setRoundTransparent() { public MapHudButton setRoundTransparent() {
setBg(R.drawable.btn_circle_trans, R.drawable.btn_circle_night); setBg(R.drawable.btn_circle_trans, R.drawable.btn_circle_night);
return this; return this;
} }
public MapHudButton setBg(int dayBg, int nightBg) { public MapHudButton setBg(int dayBg, int nightBg) {
if (bgDark == nightBg && dayBg == bgLight) { if (bgDark == nightBg && dayBg == bgLight) {
return this; return this;

View file

@ -13,13 +13,13 @@ import androidx.core.content.ContextCompat;
import net.osmand.data.RotatedTileBox; import net.osmand.data.RotatedTileBox;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.mapcontextmenu.other.TrackChartPoints; import net.osmand.plus.mapcontextmenu.other.TrackChartPoints;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.views.mapwidgets.LanesControl;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.CompassRulerControlWidgetState;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopCoordinatesView; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopCoordinatesView;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopTextView; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopTextView;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController;
@ -28,15 +28,18 @@ import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarView;
import net.osmand.plus.views.mapwidgets.MapMarkersWidgetsFactory; import net.osmand.plus.views.mapwidgets.MapMarkersWidgetsFactory;
import net.osmand.plus.views.mapwidgets.MapWidgetRegistry; import net.osmand.plus.views.mapwidgets.MapWidgetRegistry;
import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.MapWidgetRegInfo; import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.MapWidgetRegInfo;
import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WidgetState;
import net.osmand.plus.views.mapwidgets.NextTurnInfoWidget;
import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory; import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory;
import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory.AlarmWidget; import net.osmand.plus.views.mapwidgets.widgets.AlarmWidget;
import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory.BearingWidgetState; import net.osmand.plus.views.mapwidgets.widgets.NextTurnWidget;
import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory.LanesControl; import net.osmand.plus.views.mapwidgets.widgets.RulerWidget;
import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory.RulerWidget; import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget;
import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory.TimeControlWidgetState; import net.osmand.plus.views.mapwidgets.widgetstates.BearingWidgetState;
import net.osmand.plus.views.mapwidgets.TextInfoWidget; import net.osmand.plus.views.mapwidgets.widgetstates.CompassRulerWidgetState;
import net.osmand.plus.views.mapwidgets.widgetstates.TimeWidgetState;
import net.osmand.plus.views.mapwidgets.widgetstates.WidgetState;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_ALTITUDE; import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_ALTITUDE;
import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_BATTERY; import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_BATTERY;
@ -58,18 +61,20 @@ import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_SPEED;
import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_TIME; import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_TIME;
public class MapInfoLayer extends OsmandMapLayer { public class MapInfoLayer extends OsmandMapLayer {
private final MapActivity map; private final MapActivity map;
private final RouteLayer routeLayer; private final RouteLayer routeLayer;
private OsmandMapTileView view; private OsmandMapTileView view;
// groups // groups
private LinearLayout rightStack; private LinearLayout rightStack;
private LinearLayout leftStack; private LinearLayout leftStack;
private ImageButton expand; private ImageButton expand;
private View mapRulerLayout;
private static boolean expanded = false; private static boolean expanded = false;
private LanesControl lanesControl; private LanesControl lanesControl;
private AlarmWidget alarmControl; private AlarmWidget alarmControl;
private RulerWidget rulerControl; private List<RulerWidget> rulerWidgets;
private MapWidgetRegistry mapInfoControls; private MapWidgetRegistry mapInfoControls;
private OsmandSettings settings; private OsmandSettings settings;
@ -96,9 +101,11 @@ public class MapInfoLayer extends OsmandMapLayer {
public void initLayer(final OsmandMapTileView view) { public void initLayer(final OsmandMapTileView view) {
this.view = view; this.view = view;
mapInfoControls = map.getMapLayers().getMapWidgetRegistry() ; mapInfoControls = map.getMapLayers().getMapWidgetRegistry() ;
leftStack = (LinearLayout) map.findViewById(R.id.map_left_widgets_panel); leftStack = map.findViewById(R.id.map_left_widgets_panel);
rightStack = (LinearLayout) map.findViewById(R.id.map_right_widgets_panel); rightStack = map.findViewById(R.id.map_right_widgets_panel);
expand = (ImageButton) map.findViewById(R.id.map_collapse_button); expand = map.findViewById(R.id.map_collapse_button);
mapRulerLayout = map.findViewById(R.id.map_ruler_layout);
// update and create controls // update and create controls
registerAllControls(); registerAllControls();
map.getMyApplication().getAidlApi().registerWidgetControls(map); map.getMyApplication().getAidlApi().registerWidgetControls(map);
@ -159,11 +166,12 @@ public class MapInfoLayer extends OsmandMapLayer {
} }
public void registerAllControls(){ public void registerAllControls(){
rulerWidgets = new ArrayList<>();
RouteInfoWidgetsFactory ric = new RouteInfoWidgetsFactory(); RouteInfoWidgetsFactory ric = new RouteInfoWidgetsFactory();
MapInfoWidgetsFactory mic = new MapInfoWidgetsFactory(); MapInfoWidgetsFactory mic = new MapInfoWidgetsFactory();
MapMarkersWidgetsFactory mwf = map.getMapLayers().getMapMarkersLayer().getWidgetsFactory(); MapMarkersWidgetsFactory mwf = map.getMapLayers().getMapMarkersLayer().getWidgetsFactory();
OsmandApplication app = view.getApplication(); OsmandApplication app = view.getApplication();
lanesControl = ric.createLanesControl(map, view); lanesControl = RouteInfoWidgetsFactory.createLanesControl(map, view);
TextState ts = calculateTextState(); TextState ts = calculateTextState();
streetNameView = new TopTextView(map.getMyApplication(), map); streetNameView = new TopTextView(map.getMyApplication(), map);
@ -175,20 +183,19 @@ public class MapInfoLayer extends OsmandMapLayer {
topToolbarView = new TopToolbarView(map); topToolbarView = new TopToolbarView(map);
updateTopToolbar(false); updateTopToolbar(false);
alarmControl = ric.createAlarmInfoControl(app, map); alarmControl = RouteInfoWidgetsFactory.createAlarmInfoControl(app, map);
alarmControl.setVisibility(false); alarmControl.setVisibility(false);
rulerControl = ric.createRulerControl(app, map); setupRulerWidget(mapRulerLayout);
rulerControl.setVisibility(false);
// register left stack // register left stack
registerSideWidget(null, R.drawable.ic_action_compass, R.string.map_widget_compass, WIDGET_COMPASS, true, 4); registerSideWidget(null, R.drawable.ic_action_compass, R.string.map_widget_compass, WIDGET_COMPASS, true, 4);
NextTurnInfoWidget bigInfoControl = ric.createNextInfoControl(map, app, false); NextTurnWidget bigInfoControl = ric.createNextInfoControl(map, app, false);
registerSideWidget(bigInfoControl, R.drawable.ic_action_next_turn, R.string.map_widget_next_turn, WIDGET_NEXT_TURN, true, 5); registerSideWidget(bigInfoControl, R.drawable.ic_action_next_turn, R.string.map_widget_next_turn, WIDGET_NEXT_TURN, true, 5);
NextTurnInfoWidget smallInfoControl = ric.createNextInfoControl(map, app, true); NextTurnWidget smallInfoControl = ric.createNextInfoControl(map, app, true);
registerSideWidget(smallInfoControl, R.drawable.ic_action_next_turn, R.string.map_widget_next_turn_small, WIDGET_NEXT_TURN_SMALL, true, 6); registerSideWidget(smallInfoControl, R.drawable.ic_action_next_turn, R.string.map_widget_next_turn_small, WIDGET_NEXT_TURN_SMALL, true, 6);
NextTurnInfoWidget nextNextInfoControl = ric.createNextNextInfoControl(map, app, true); NextTurnWidget nextNextInfoControl = ric.createNextNextInfoControl(map, app, true);
registerSideWidget(nextNextInfoControl, R.drawable.ic_action_next_turn, R.string.map_widget_next_next_turn, WIDGET_NEXT_NEXT_TURN,true, 7); registerSideWidget(nextNextInfoControl, R.drawable.ic_action_next_turn, R.string.map_widget_next_next_turn, WIDGET_NEXT_NEXT_TURN,true, 7);
// register right stack // register right stack
@ -196,11 +203,11 @@ public class MapInfoLayer extends OsmandMapLayer {
TextInfoWidget intermediateDist = ric.createIntermediateDistanceControl(map); TextInfoWidget intermediateDist = ric.createIntermediateDistanceControl(map);
registerSideWidget(intermediateDist, R.drawable.ic_action_intermediate, R.string.map_widget_intermediate_distance, WIDGET_INTERMEDIATE_DISTANCE, false, 13); registerSideWidget(intermediateDist, R.drawable.ic_action_intermediate, R.string.map_widget_intermediate_distance, WIDGET_INTERMEDIATE_DISTANCE, false, 13);
TextInfoWidget intermediateTime = ric.createTimeControl(map, true); TextInfoWidget intermediateTime = ric.createTimeControl(map, true);
registerSideWidget(intermediateTime, new TimeControlWidgetState(app, true), WIDGET_INTERMEDIATE_TIME, false, 14); registerSideWidget(intermediateTime, new TimeWidgetState(app, true), WIDGET_INTERMEDIATE_TIME, false, 14);
TextInfoWidget dist = ric.createDistanceControl(map); TextInfoWidget dist = ric.createDistanceControl(map);
registerSideWidget(dist, R.drawable.ic_action_target, R.string.map_widget_distance, WIDGET_DISTANCE, false, 15); registerSideWidget(dist, R.drawable.ic_action_target, R.string.map_widget_distance, WIDGET_DISTANCE, false, 15);
TextInfoWidget time = ric.createTimeControl(map, false); TextInfoWidget time = ric.createTimeControl(map, false);
registerSideWidget(time, new TimeControlWidgetState(app, false), WIDGET_TIME, false, 16); registerSideWidget(time, new TimeWidgetState(app, false), WIDGET_TIME, false, 16);
TextInfoWidget marker = mwf.createMapMarkerControl(map, true); TextInfoWidget marker = mwf.createMapMarkerControl(map, true);
@ -224,7 +231,7 @@ public class MapInfoLayer extends OsmandMapLayer {
TextInfoWidget battery = ric.createBatteryControl(map); TextInfoWidget battery = ric.createBatteryControl(map);
registerSideWidget(battery, R.drawable.ic_action_battery, R.string.map_widget_battery, WIDGET_BATTERY, false, 42); registerSideWidget(battery, R.drawable.ic_action_battery, R.string.map_widget_battery, WIDGET_BATTERY, false, 42);
TextInfoWidget ruler = mic.createRulerControl(map); TextInfoWidget ruler = mic.createRulerControl(map);
registerSideWidget(ruler, new CompassRulerControlWidgetState(app), WIDGET_RULER, false, 43); registerSideWidget(ruler, new CompassRulerWidgetState(app), WIDGET_RULER, false, 43);
} }
public void recreateControls() { public void recreateControls() {
@ -236,7 +243,7 @@ public class MapInfoLayer extends OsmandMapLayer {
mapInfoControls.populateStackControl(rightStack, settings.getApplicationMode(), false, expanded); mapInfoControls.populateStackControl(rightStack, settings.getApplicationMode(), false, expanded);
rightStack.requestLayout(); rightStack.requestLayout();
expand.setVisibility(mapInfoControls.hasCollapsibles(settings.getApplicationMode())? expand.setVisibility(mapInfoControls.hasCollapsibles(settings.getApplicationMode())?
View.VISIBLE : View.GONE); View.VISIBLE : View.GONE);
Drawable expandIcon = map.getMyApplication().getUIUtilities().getMapIcon(expanded ? R.drawable.ic_action_arrow_up : Drawable expandIcon = map.getMyApplication().getUIUtilities().getMapIcon(expanded ? R.drawable.ic_action_arrow_up :
R.drawable.ic_action_arrow_down, true); R.drawable.ic_action_arrow_down, true);
@ -252,15 +259,34 @@ public class MapInfoLayer extends OsmandMapLayer {
}); });
} }
public RulerWidget setupRulerWidget(View mapRulerView) {
RulerWidget rulerWidget = RouteInfoWidgetsFactory.createRulerControl(map, mapRulerView);
rulerWidget.setVisibility(false);
TextState ts = calculateTextState();
boolean nightMode = drawSettings != null && drawSettings.isNightMode();
rulerWidget.updateTextSize(nightMode, ts.textColor, ts.textShadowColor, (int) (2 * view.getDensity()));
rulerWidgets.add(rulerWidget);
return rulerWidget;
}
public void removeRulerWidgets(List<RulerWidget> rulers) {
List<RulerWidget> widgetList = new ArrayList<>(rulerWidgets);
widgetList.removeAll(rulers);
rulerWidgets = widgetList;
}
public void setTrackChartPoints(TrackChartPoints trackChartPoints) { public void setTrackChartPoints(TrackChartPoints trackChartPoints) {
routeLayer.setTrackChartPoints(trackChartPoints); routeLayer.setTrackChartPoints(trackChartPoints);
} }
private static class TextState { private static class TextState {
boolean textBold ; boolean textBold;
boolean night; boolean night;
int textColor ; int textColor;
int textShadowColor ; int textShadowColor;
int boxTop; int boxTop;
int rightRes; int rightRes;
int leftRes; int leftRes;
@ -269,7 +295,6 @@ public class MapInfoLayer extends OsmandMapLayer {
int textShadowRadius; int textShadowRadius;
} }
private int themeId = -1; private int themeId = -1;
public void updateColorShadowsOfText() { public void updateColorShadowsOfText() {
boolean transparent = view.getSettings().TRANSPARENT_MAP_THEME.get(); boolean transparent = view.getSettings().TRANSPARENT_MAP_THEME.get();
@ -290,12 +315,15 @@ public class MapInfoLayer extends OsmandMapLayer {
updateTopCoordinates(nightMode, ts); updateTopCoordinates(nightMode, ts);
updateTopToolbar(nightMode); updateTopToolbar(nightMode);
lanesControl.updateTextSize(nightMode, ts.textColor, ts.textShadowColor, ts.textBold, ts.textShadowRadius / 2); lanesControl.updateTextSize(nightMode, ts.textColor, ts.textShadowColor, ts.textBold, ts.textShadowRadius / 2);
rulerControl.updateTextSize(nightMode, ts.textColor, ts.textShadowColor, (int) (2 * view.getDensity()));
int padding = expand.getPaddingLeft(); int padding = expand.getPaddingLeft();
expand.setBackgroundResource(ts.expand); expand.setBackgroundResource(ts.expand);
expand.setPadding(padding, padding, padding, padding); expand.setPadding(padding, padding, padding, padding);
rightStack.invalidate(); rightStack.invalidate();
leftStack.invalidate(); leftStack.invalidate();
for (RulerWidget rulerWidget : rulerWidgets) {
rulerWidget.updateTextSize(nightMode, ts.textColor, ts.textShadowColor, (int) (2 * view.getDensity()));
}
} }
} }
@ -371,9 +399,11 @@ public class MapInfoLayer extends OsmandMapLayer {
topToolbarView.updateInfo(); topToolbarView.updateInfo();
topCoordinatesView.updateInfo(); topCoordinatesView.updateInfo();
alarmControl.updateInfo(drawSettings); alarmControl.updateInfo(drawSettings);
rulerControl.updateInfo(tileBox, drawSettings);
lanesControl.updateInfo(drawSettings); lanesControl.updateInfo(drawSettings);
for (RulerWidget rulerWidget : rulerWidgets) {
rulerWidget.updateInfo(tileBox, drawSettings);
}
} }
@Override @Override

View file

@ -0,0 +1,139 @@
package net.osmand.plus.views.mapwidgets;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import net.osmand.Location;
import net.osmand.binary.RouteDataObject;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmAndLocationProvider;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.MapViewTrackingUtilities;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.routepreparationmenu.MapRouteInfoMenu;
import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.views.OsmandMapLayer;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget;
import net.osmand.router.RouteResultPreparation;
import java.util.Arrays;
public class LanesControl {
private MapViewTrackingUtilities trackingUtilities;
private OsmAndLocationProvider locationProvider;
private MapRouteInfoMenu mapRouteInfoMenu;
private RoutingHelper rh;
private OsmandSettings settings;
private ImageView lanesView;
private TextView lanesText;
private TextView lanesShadowText;
private OsmandApplication app;
private int dist;
private LanesDrawable lanesDrawable;
private View centerInfo;
private int shadowRadius;
public LanesControl(MapActivity mapActivity, OsmandMapTileView view) {
lanesView = mapActivity.findViewById(R.id.map_lanes);
lanesText = mapActivity.findViewById(R.id.map_lanes_dist_text);
lanesShadowText = mapActivity.findViewById(R.id.map_lanes_dist_text_shadow);
centerInfo = mapActivity.findViewById(R.id.map_center_info);
lanesDrawable = new LanesDrawable(mapActivity, mapActivity.getMapView().getScaleCoefficient());
lanesView.setImageDrawable(lanesDrawable);
trackingUtilities = mapActivity.getMapViewTrackingUtilities();
locationProvider = mapActivity.getMyApplication().getLocationProvider();
settings = mapActivity.getMyApplication().getSettings();
mapRouteInfoMenu = mapActivity.getMapRouteInfoMenu();
rh = mapActivity.getMyApplication().getRoutingHelper();
app = mapActivity.getMyApplication();
}
public void updateTextSize(boolean isNight, int textColor, int textShadowColor, boolean textBold, int shadowRadius) {
this.shadowRadius = shadowRadius;
TextInfoWidget.updateTextColor(lanesText, lanesShadowText, textColor, textShadowColor, textBold, shadowRadius);
}
public boolean updateInfo(OsmandMapLayer.DrawSettings drawSettings) {
boolean visible = false;
int locimminent = -1;
int[] loclanes = null;
int dist = 0;
// TurnType primary = null;
if ((rh == null || !rh.isFollowingMode() || rh.isDeviatedFromRoute() || (rh.getCurrentGPXRoute() != null && !rh.isCurrentGPXRouteV2()))
&& trackingUtilities.isMapLinkedToLocation() && settings.SHOW_LANES.get()) {
RouteDataObject ro = locationProvider.getLastKnownRouteSegment();
Location lp = locationProvider.getLastKnownLocation();
if (ro != null) {
float degree = lp == null || !lp.hasBearing() ? 0 : lp.getBearing();
loclanes = RouteResultPreparation.parseTurnLanes(ro, degree / 180 * Math.PI);
if (loclanes == null) {
loclanes = RouteResultPreparation.parseLanes(ro, degree / 180 * Math.PI);
}
}
} else if (rh != null && rh.isRouteCalculated()) {
if (rh.isFollowingMode() && settings.SHOW_LANES.get()) {
RouteCalculationResult.NextDirectionInfo r = rh.getNextRouteDirectionInfo(new RouteCalculationResult.NextDirectionInfo(), false);
if (r != null && r.directionInfo != null && r.directionInfo.getTurnType() != null) {
loclanes = r.directionInfo.getTurnType().getLanes();
// primary = r.directionInfo.getTurnType();
locimminent = r.imminent;
// Do not show too far
if ((r.distanceTo > 800 && r.directionInfo.getTurnType().isSkipToSpeak()) || r.distanceTo > 1200) {
loclanes = null;
}
dist = r.distanceTo;
}
} else {
int di = MapRouteInfoMenu.getDirectionInfo();
if (di >= 0 && mapRouteInfoMenu.isVisible()
&& di < rh.getRouteDirections().size()) {
RouteDirectionInfo next = rh.getRouteDirections().get(di);
if (next != null) {
loclanes = next.getTurnType().getLanes();
// primary = next.getTurnType();
}
} else {
loclanes = null;
}
}
}
visible = loclanes != null && loclanes.length > 0 && !MapRouteInfoMenu.chooseRoutesVisible && !MapRouteInfoMenu.waypointsVisible;
if (visible) {
if (!Arrays.equals(lanesDrawable.lanes, loclanes) ||
(locimminent == 0) != lanesDrawable.imminent) {
lanesDrawable.imminent = locimminent == 0;
lanesDrawable.lanes = loclanes;
lanesDrawable.updateBounds();
lanesView.setImageDrawable(null);
lanesView.setImageDrawable(lanesDrawable);
lanesView.requestLayout();
lanesView.invalidate();
}
if (RouteInfoWidgetsFactory.distChanged(dist, this.dist)) {
this.dist = dist;
if (dist == 0) {
lanesShadowText.setText("");
lanesText.setText("");
} else {
lanesShadowText.setText(OsmAndFormatter.getFormattedDistance(dist, app));
lanesText.setText(OsmAndFormatter.getFormattedDistance(dist, app));
}
lanesShadowText.invalidate();
lanesText.invalidate();
}
}
AndroidUiHelper.updateVisibility(lanesShadowText, visible && shadowRadius > 0);
AndroidUiHelper.updateVisibility(lanesText, visible);
AndroidUiHelper.updateVisibility(lanesView, visible);
AndroidUiHelper.updateVisibility(centerInfo, visible);
return true;
}
}

View file

@ -0,0 +1,300 @@
package net.osmand.plus.views.mapwidgets;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.views.TurnPathHelper;
import net.osmand.router.TurnType;
import java.util.ArrayList;
import java.util.List;
public class LanesDrawable extends Drawable {
public int[] lanes = null;
boolean imminent = false;
public boolean isTurnByTurn = false;
public boolean isNightMode = false;
private Context ctx;
private Paint paintBlack;
private Paint paintRouteDirection;
private Paint paintSecondTurn;
private float scaleCoefficient;
private int height;
private int width;
private float delta;
private float laneHalfSize;
private static final float miniCoeff = 2f;
private final boolean leftSide;
private int imgMinDelta;
private int imgMargin;
public LanesDrawable(MapActivity ctx, float scaleCoefficent) {
this.ctx = ctx;
OsmandSettings settings = ctx.getMyApplication().getSettings();
leftSide = settings.DRIVING_REGION.get().leftHandDriving;
imgMinDelta = ctx.getResources().getDimensionPixelSize(R.dimen.widget_turn_lane_min_delta);
imgMargin = ctx.getResources().getDimensionPixelSize(R.dimen.widget_turn_lane_margin);
laneHalfSize = ctx.getResources().getDimensionPixelSize(R.dimen.widget_turn_lane_size) / 2;
this.scaleCoefficient = scaleCoefficent;
paintBlack = new Paint(Paint.ANTI_ALIAS_FLAG);
paintBlack.setStyle(Paint.Style.STROKE);
paintBlack.setColor(Color.BLACK);
paintBlack.setStrokeWidth(scaleCoefficent);
paintRouteDirection = new Paint(Paint.ANTI_ALIAS_FLAG);
paintRouteDirection.setStyle(Paint.Style.FILL);
paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow));
paintSecondTurn = new Paint(Paint.ANTI_ALIAS_FLAG);
paintSecondTurn.setStyle(Paint.Style.FILL);
paintSecondTurn.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant));
}
public void updateBounds() {
float w = 0;
float h = 0;
float delta = imgMinDelta;
float coef = scaleCoefficient / miniCoeff;
if (lanes != null) {
List<RectF> boundsList = new ArrayList<>(lanes.length);
for (int i = 0; i < lanes.length; i++) {
int turnType = TurnType.getPrimaryTurn(lanes[i]);
int secondTurnType = TurnType.getSecondaryTurn(lanes[i]);
int thirdTurnType = TurnType.getTertiaryTurn(lanes[i]);
RectF imgBounds = new RectF();
if (thirdTurnType > 0) {
Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType,
secondTurnType, thirdTurnType, TurnPathHelper.THIRD_TURN, coef, leftSide, true);
if (p != null) {
RectF b = new RectF();
p.computeBounds(b, true);
if (!b.isEmpty()) {
if (imgBounds.isEmpty()) {
imgBounds.set(b);
} else {
imgBounds.union(b);
}
}
}
}
if (secondTurnType > 0) {
Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType,
secondTurnType, thirdTurnType, TurnPathHelper.SECOND_TURN, coef, leftSide, true);
if (p != null) {
RectF b = new RectF();
p.computeBounds(b, true);
if (!b.isEmpty()) {
if (imgBounds.isEmpty()) {
imgBounds.set(b);
} else {
imgBounds.union(b);
}
}
}
}
Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType,
secondTurnType, thirdTurnType, TurnPathHelper.FIRST_TURN, coef, leftSide, true);
if (p != null) {
RectF b = new RectF();
p.computeBounds(b, true);
if (!b.isEmpty()) {
if (imgBounds.isEmpty()) {
imgBounds.set(b);
} else {
imgBounds.union(b);
}
}
}
if (imgBounds.right > 0) {
boundsList.add(imgBounds);
float imageHeight = imgBounds.bottom;
if (imageHeight > h)
h = imageHeight;
}
}
if (boundsList.size() > 1) {
for (int i = 1; i < boundsList.size(); i++) {
RectF b1 = boundsList.get(i - 1);
RectF b2 = boundsList.get(i);
float d = b1.right + imgMargin * 2 - b2.left;
if (delta < d)
delta = d;
}
RectF b1 = boundsList.get(0);
RectF b2 = boundsList.get(boundsList.size() - 1);
w = -b1.left + (boundsList.size() - 1) * delta + b2.right;
} else if (boundsList.size() > 0) {
RectF b1 = boundsList.get(0);
w = b1.width();
}
if (w > 0) {
w += 4;
}
if (h > 0) {
h += 4;
}
}
this.width = (int) w;
this.height = (int) h;
this.delta = delta;
}
@Override
public int getIntrinsicHeight() {
return height;
}
@Override
public int getIntrinsicWidth() {
return width;
}
@Override
public void draw(@NonNull Canvas canvas) {
// setup default color
//canvas.drawColor(0, PorterDuff.Mode.CLEAR);
//to change color immediately when needed
if (lanes != null && lanes.length > 0) {
float coef = scaleCoefficient / miniCoeff;
canvas.save();
// canvas.translate((int) (16 * scaleCoefficient), 0);
for (int i = 0; i < lanes.length; i++) {
if ((lanes[i] & 1) == 1) {
if (isTurnByTurn) {
paintRouteDirection.setColor(isNightMode ? ctx.getResources().getColor(R.color.active_color_primary_dark) :
ctx.getResources().getColor(R.color.active_color_primary_light));
} else {
paintRouteDirection.setColor(imminent ? ctx.getResources().getColor(R.color.nav_arrow_imminent) :
ctx.getResources().getColor(R.color.nav_arrow));
}
} else {
paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant));
}
int turnType = TurnType.getPrimaryTurn(lanes[i]);
int secondTurnType = TurnType.getSecondaryTurn(lanes[i]);
int thirdTurnType = TurnType.getTertiaryTurn(lanes[i]);
RectF imgBounds = new RectF();
Path thirdTurnPath = null;
Path secondTurnPath = null;
Path firstTurnPath = null;
if (thirdTurnType > 0) {
Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType,
secondTurnType, thirdTurnType, TurnPathHelper.THIRD_TURN, coef, leftSide, true);
if (p != null) {
RectF b = new RectF();
p.computeBounds(b, true);
if (!b.isEmpty()) {
if (imgBounds.isEmpty()) {
imgBounds.set(b);
} else {
imgBounds.union(b);
}
thirdTurnPath = p;
}
}
}
if (secondTurnType > 0) {
Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType,
secondTurnType, thirdTurnType, TurnPathHelper.SECOND_TURN, coef, leftSide, true);
if (p != null) {
RectF b = new RectF();
p.computeBounds(b, true);
if (!b.isEmpty()) {
if (imgBounds.isEmpty()) {
imgBounds.set(b);
} else {
imgBounds.union(b);
}
secondTurnPath = p;
}
}
}
Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType,
secondTurnType, thirdTurnType, TurnPathHelper.FIRST_TURN, coef, leftSide, true);
if (p != null) {
RectF b = new RectF();
p.computeBounds(b, true);
if (!b.isEmpty()) {
if (imgBounds.isEmpty()) {
imgBounds.set(b);
} else {
imgBounds.union(b);
}
firstTurnPath = p;
}
}
if (firstTurnPath != null || secondTurnPath != null || thirdTurnPath != null) {
if (i == 0) {
imgBounds.set(imgBounds.left - 2, imgBounds.top, imgBounds.right + 2, imgBounds.bottom);
canvas.translate(-imgBounds.left, 0);
} else {
canvas.translate(-laneHalfSize, 0);
}
// 1st pass
if (thirdTurnPath != null) {
//canvas.drawPath(thirdTurnPath, paintSecondTurn);
canvas.drawPath(thirdTurnPath, paintBlack);
}
if (secondTurnPath != null) {
//canvas.drawPath(secondTurnPath, paintSecondTurn);
canvas.drawPath(secondTurnPath, paintBlack);
}
if (firstTurnPath != null) {
//canvas.drawPath(firstTurnPath, paintRouteDirection);
canvas.drawPath(firstTurnPath, paintBlack);
}
// 2nd pass
if (thirdTurnPath != null) {
canvas.drawPath(thirdTurnPath, paintSecondTurn);
}
if (secondTurnPath != null) {
canvas.drawPath(secondTurnPath, paintSecondTurn);
}
if (firstTurnPath != null) {
canvas.drawPath(firstTurnPath, paintRouteDirection);
}
canvas.translate(laneHalfSize + delta, 0);
}
}
canvas.restore();
}
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(ColorFilter cf) {
}
@Override
public int getOpacity() {
return 0;
}
}

View file

@ -68,8 +68,7 @@ import net.osmand.plus.settings.backend.OsmandSettings.RulerMode;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.RulerControlLayer; import net.osmand.plus.views.RulerControlLayer;
import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WidgetState; import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget;
import net.osmand.plus.views.mapwidgets.NextTurnInfoWidget.TurnDrawable;
import net.osmand.render.RenderingRuleSearchRequest; import net.osmand.render.RenderingRuleSearchRequest;
import net.osmand.render.RenderingRulesStorage; import net.osmand.render.RenderingRulesStorage;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
@ -160,54 +159,6 @@ public class MapInfoWidgetsFactory {
return gpsInfoControl; return gpsInfoControl;
} }
public static class CompassRulerControlWidgetState extends WidgetState {
public static final int COMPASS_CONTROL_WIDGET_STATE_SHOW = R.id.compass_ruler_control_widget_state_show;
public static final int COMPASS_CONTROL_WIDGET_STATE_HIDE = R.id.compass_ruler_control_widget_state_hide;
private final OsmandSettings.OsmandPreference<Boolean> showCompass;
public CompassRulerControlWidgetState(OsmandApplication ctx) {
super(ctx);
showCompass = ctx.getSettings().SHOW_COMPASS_CONTROL_RULER;
}
@Override
public int getMenuTitleId() {
return R.string.map_widget_ruler_control;
}
@Override
public int getMenuIconId() {
return R.drawable.ic_action_ruler_circle;
}
@Override
public int getMenuItemId() {
return showCompass.get() ? COMPASS_CONTROL_WIDGET_STATE_SHOW : COMPASS_CONTROL_WIDGET_STATE_HIDE;
}
@Override
public int[] getMenuTitleIds() {
return new int[]{R.string.show_compass_ruler, R.string.hide_compass_ruler};
}
@Override
public int[] getMenuIconIds() {
return new int[]{R.drawable.ic_action_compass_widget, R.drawable.ic_action_compass_widget_hide};
}
@Override
public int[] getMenuItemIds() {
return new int[]{COMPASS_CONTROL_WIDGET_STATE_SHOW, COMPASS_CONTROL_WIDGET_STATE_HIDE};
}
@Override
public void changeState(int stateId) {
showCompass.set(stateId == COMPASS_CONTROL_WIDGET_STATE_SHOW);
}
}
public TextInfoWidget createRulerControl(final MapActivity map) { public TextInfoWidget createRulerControl(final MapActivity map) {
final String title = ""; final String title = "";
final TextInfoWidget rulerControl = new TextInfoWidget(map) { final TextInfoWidget rulerControl = new TextInfoWidget(map) {
@ -936,7 +887,7 @@ public class MapInfoWidgetsFactory {
private boolean showMarker; private boolean showMarker;
public TopTextView(OsmandApplication app, MapActivity map) { public TopTextView(OsmandApplication app, MapActivity map) {
turnDrawable = new NextTurnInfoWidget.TurnDrawable(map, true); turnDrawable = new TurnDrawable(map, true);
topBar = map.findViewById(R.id.map_top_bar); topBar = map.findViewById(R.id.map_top_bar);
addressText = (TextView) map.findViewById(R.id.map_address_text); addressText = (TextView) map.findViewById(R.id.map_address_text);
addressTextShadow = (TextView) map.findViewById(R.id.map_address_text_shadow); addressTextShadow = (TextView) map.findViewById(R.id.map_address_text_shadow);

View file

@ -20,6 +20,7 @@ import net.osmand.plus.views.AnimateDraggingMapThread;
import net.osmand.plus.views.DirectionDrawable; import net.osmand.plus.views.DirectionDrawable;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;

View file

@ -27,6 +27,8 @@ import net.osmand.plus.quickaction.QuickActionListFragment;
import net.osmand.plus.views.MapInfoLayer; import net.osmand.plus.views.MapInfoLayer;
import net.osmand.plus.views.MapQuickActionLayer; import net.osmand.plus.views.MapQuickActionLayer;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget;
import net.osmand.plus.views.mapwidgets.widgetstates.WidgetState;
import net.osmand.plus.widgets.IconPopupMenu; import net.osmand.plus.widgets.IconPopupMenu;
import java.util.Collections; import java.util.Collections;
@ -362,7 +364,7 @@ public class MapWidgetRegistry {
cm.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.coordinates_widget, map) cm.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.coordinates_widget, map)
.setIcon(R.drawable.ic_action_coordinates_widget) .setIcon(R.drawable.ic_action_coordinates_widget)
.setSelected(settings.SHOW_COORDINATES_WIDGET.get()) .setSelected(settings.SHOW_COORDINATES_WIDGET.get())
.setListener(new ApearanceItemClickListener(settings.SHOW_COORDINATES_WIDGET, map)) .setListener(new AppearanceItemClickListener(settings.SHOW_COORDINATES_WIDGET, map))
.setLayout(R.layout.list_item_icon_and_switch).createItem()); .setLayout(R.layout.list_item_icon_and_switch).createItem());
cm.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.map_markers, map) cm.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.map_markers, map)
.setDescription(settings.MAP_MARKERS_MODE.get().toHumanString(map)) .setDescription(settings.MAP_MARKERS_MODE.get().toHumanString(map))
@ -408,14 +410,13 @@ public class MapWidgetRegistry {
@StringRes int stringId, OsmandPreference<Boolean> pref) { @StringRes int stringId, OsmandPreference<Boolean> pref) {
cm.addItem(new ContextMenuItem.ItemBuilder().setTitleId(stringId, map) cm.addItem(new ContextMenuItem.ItemBuilder().setTitleId(stringId, map)
.setSelected(pref.get()) .setSelected(pref.get())
.setListener(new ApearanceItemClickListener(pref, map)).createItem()); .setListener(new AppearanceItemClickListener(pref, map)).createItem());
} }
public static boolean distChanged(int oldDist, int dist) { public static boolean distChanged(int oldDist, int dist) {
return !(oldDist != 0 && oldDist - dist < 100 && Math.abs(((float) dist - oldDist) / oldDist) < 0.01); return !(oldDist != 0 && oldDist - dist < 100 && Math.abs(((float) dist - oldDist) / oldDist) < 0.01);
} }
public void addControls(MapActivity map, ContextMenuAdapter cm, ApplicationMode mode) { public void addControls(MapActivity map, ContextMenuAdapter cm, ApplicationMode mode) {
addQuickActionControl(map, cm, mode); addQuickActionControl(map, cm, mode);
// Right panel // Right panel
@ -819,49 +820,23 @@ public class MapWidgetRegistry {
return cm; return cm;
} }
class ApearanceItemClickListener implements ContextMenuAdapter.ItemClickListener { static class AppearanceItemClickListener implements ContextMenuAdapter.ItemClickListener {
private MapActivity map;
private MapActivity mapActivity;
private OsmandPreference<Boolean> pref; private OsmandPreference<Boolean> pref;
public ApearanceItemClickListener(OsmandPreference<Boolean> pref, MapActivity map) { public AppearanceItemClickListener(OsmandPreference<Boolean> pref, MapActivity mapActivity) {
this.pref = pref; this.pref = pref;
this.map = map; this.mapActivity = mapActivity;
} }
@Override @Override
public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> a, public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> a,
int itemId, int pos, boolean isChecked, int[] viewCoordinates) { int itemId, int pos, boolean isChecked, int[] viewCoordinates) {
pref.set(!pref.get()); pref.set(!pref.get());
map.updateApplicationModeSettings(); mapActivity.updateApplicationModeSettings();
a.notifyDataSetChanged(); a.notifyDataSetChanged();
return false; return false;
} }
} }
}
public static abstract class WidgetState {
private OsmandApplication ctx;
public OsmandApplication getCtx() {
return ctx;
}
public WidgetState(OsmandApplication ctx) {
this.ctx = ctx;
}
public abstract int getMenuTitleId();
public abstract int getMenuIconId();
public abstract int getMenuItemId();
public abstract int[] getMenuTitleIds();
public abstract int[] getMenuIconIds();
public abstract int[] getMenuItemIds();
public abstract void changeState(int stateId);
}
}

View file

@ -1,236 +0,0 @@
package net.osmand.plus.views.mapwidgets;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.TextPaint;
import androidx.annotation.ColorRes;
import androidx.annotation.NonNull;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.TurnPathHelper;
import net.osmand.router.TurnType;
public class NextTurnInfoWidget extends TextInfoWidget {
protected boolean horisontalMini;
protected int deviatedPath = 0;
protected int nextTurnDistance = 0;
private TurnDrawable turnDrawable;
private OsmandApplication app;
public NextTurnInfoWidget(Activity activity, OsmandApplication app, boolean horisontalMini) {
super(activity);
this.app = app;
this.horisontalMini = horisontalMini;
turnDrawable = new TurnDrawable(activity, horisontalMini);
if(horisontalMini) {
setImageDrawable(turnDrawable, false);
setTopImageDrawable(null, null);
} else {
setImageDrawable(null, true);
setTopImageDrawable(turnDrawable, "");
}
}
public TurnType getTurnType() {
return turnDrawable.turnType;
}
public void setTurnType(TurnType turnType) {
boolean vis = updateVisibility(turnType != null);
if (turnDrawable.setTurnType(turnType) || vis) {
turnDrawable.setTextPaint(topTextView.getPaint());
if(horisontalMini) {
setImageDrawable(turnDrawable, false);
} else {
setTopImageDrawable(turnDrawable, "");
// setTopImageDrawable(turnDrawable, turnType == null || turnType.getExitOut() == 0 ? "" :
// turnType.getExitOut() + "");
}
}
}
public void setTurnImminent(int turnImminent, boolean deviatedFromRoute) {
if(turnDrawable.turnImminent != turnImminent || turnDrawable.deviatedFromRoute != deviatedFromRoute) {
turnDrawable.setTurnImminent(turnImminent, deviatedFromRoute);
}
}
public void setDeviatePath(int deviatePath) {
if (RouteInfoWidgetsFactory.distChanged(deviatePath, this.deviatedPath)) {
this.deviatedPath = deviatePath;
updateDistance();
}
}
public void setTurnDistance(int nextTurnDistance) {
if (RouteInfoWidgetsFactory.distChanged(nextTurnDistance, this.nextTurnDistance)) {
this.nextTurnDistance = nextTurnDistance;
updateDistance();
}
}
private void updateDistance() {
int deviatePath = turnDrawable.deviatedFromRoute ? deviatedPath : nextTurnDistance;
String ds = OsmAndFormatter.getFormattedDistance(deviatePath, app);
if (ds != null) {
TurnType turnType = getTurnType();
RoutingHelper routingHelper = app.getRoutingHelper();
if ((turnType != null) && (routingHelper != null)) {
setContentDescription(ds + " " + routingHelper.getRoute().toString(turnType, app, false));
} else {
setContentDescription(ds);
}
}
int ls = ds.lastIndexOf(' ');
if (ls == -1) {
setTextNoUpdateVisibility(ds, null);
} else {
setTextNoUpdateVisibility(ds.substring(0, ls), ds.substring(ls + 1));
}
}
@Override
public boolean updateInfo(DrawSettings drawSettings) {
return false;
}
public static class TurnDrawable extends Drawable {
protected Paint paintBlack;
protected Paint paintRouteDirection;
protected Path pathForTurn = new Path();
protected Path pathForTurnOutlay = new Path();
protected TurnType turnType = null;
protected int turnImminent;
protected boolean deviatedFromRoute;
private Context ctx;
private boolean mini;
private PointF centerText;
private TextPaint textPaint;
private int clr;
public TurnDrawable(Context ctx, boolean mini) {
this.ctx = ctx;
this.mini = mini;
centerText = new PointF();
paintBlack = new Paint();
paintBlack.setStyle(Style.STROKE);
paintBlack.setColor(Color.BLACK);
paintBlack.setAntiAlias(true);
paintBlack.setStrokeWidth(2.5f);
paintRouteDirection = new Paint();
paintRouteDirection.setStyle(Style.FILL);
paintRouteDirection.setAntiAlias(true);
setColor(R.color.nav_arrow);
}
@ColorRes
public void setColor(int clr) {
if(clr != this.clr) {
this.clr = clr;
paintRouteDirection.setColor(ctx.getResources().getColor(clr));
}
}
@Override
protected void onBoundsChange(Rect bounds) {
Matrix m = new Matrix();
float scaleX = bounds.width() / 72f;
float scaleY = bounds.height() / 72f;
m.setScale(scaleX, scaleY);
pathForTurn.transform(m, pathForTurn);
centerText.x = scaleX * centerText.x;
centerText.y = scaleY * centerText.y;
pathForTurnOutlay.transform(m, pathForTurnOutlay);
}
public void setTurnImminent(int turnImminent, boolean deviatedFromRoute) {
//if user deviates from route that we should draw grey arrow
this.turnImminent = turnImminent;
this.deviatedFromRoute = deviatedFromRoute;
if (deviatedFromRoute){
paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant));
} else if (turnImminent > 0) {
paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow));
} else if (turnImminent == 0) {
paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_imminent));
} else {
paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant));
}
invalidateSelf();
}
@Override
public void draw(@NonNull Canvas canvas) {
/// small indent
// canvas.translate(0, 3 * scaleCoefficient);
canvas.drawPath(pathForTurnOutlay, paintBlack);
canvas.drawPath(pathForTurn, paintRouteDirection);
canvas.drawPath(pathForTurn, paintBlack);
if(textPaint != null ) {
if (turnType != null && !mini && turnType.getExitOut() > 0) {
canvas.drawText(turnType.getExitOut() + "", centerText.x,
centerText.y - (textPaint.descent() + textPaint.ascent()) / 2, textPaint);
}
}
}
public void setTextPaint(TextPaint textPaint) {
this.textPaint = textPaint;
this.textPaint.setTextAlign(Align.CENTER);
}
@Override
public void setAlpha(int alpha) {
paintRouteDirection.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter cf) {
paintRouteDirection.setColorFilter(cf);
}
@Override
public int getOpacity() {
return 0;
}
public boolean setTurnType(TurnType turnType) {
if(turnType != this.turnType) {
this.turnType = turnType;
TurnPathHelper.calcTurnPath(pathForTurn, pathForTurnOutlay, turnType, null,
centerText, mini, false, true, false);
onBoundsChange(getBounds());
return true;
}
return false;
}
}
}

View file

@ -0,0 +1,146 @@
package net.osmand.plus.views.mapwidgets;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.TextPaint;
import androidx.annotation.ColorRes;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import net.osmand.plus.R;
import net.osmand.plus.views.TurnPathHelper;
import net.osmand.router.TurnType;
public class TurnDrawable extends Drawable {
protected Paint paintBlack;
protected Paint paintRouteDirection;
protected Path pathForTurn = new Path();
protected Path pathForTurnOutlay = new Path();
protected TurnType turnType = null;
protected int turnImminent;
protected boolean deviatedFromRoute;
private Context ctx;
private boolean mini;
private PointF centerText;
private TextPaint textPaint;
private int clr;
public TurnDrawable(Context ctx, boolean mini) {
this.ctx = ctx;
this.mini = mini;
centerText = new PointF();
paintBlack = new Paint();
paintBlack.setStyle(Paint.Style.STROKE);
paintBlack.setColor(Color.BLACK);
paintBlack.setAntiAlias(true);
paintBlack.setStrokeWidth(2.5f);
paintRouteDirection = new Paint();
paintRouteDirection.setStyle(Paint.Style.FILL);
paintRouteDirection.setAntiAlias(true);
setColor(R.color.nav_arrow);
}
public void setColor(@ColorRes int clr) {
if (clr != this.clr) {
this.clr = clr;
paintRouteDirection.setColor(ContextCompat.getColor(ctx, clr));
}
}
@Override
protected void onBoundsChange(Rect bounds) {
Matrix m = new Matrix();
float scaleX = bounds.width() / 72f;
float scaleY = bounds.height() / 72f;
m.setScale(scaleX, scaleY);
pathForTurn.transform(m, pathForTurn);
centerText.x = scaleX * centerText.x;
centerText.y = scaleY * centerText.y;
pathForTurnOutlay.transform(m, pathForTurnOutlay);
}
public int getTurnImminent() {
return turnImminent;
}
public boolean isDeviatedFromRoute() {
return deviatedFromRoute;
}
public void setTurnImminent(int turnImminent, boolean deviatedFromRoute) {
//if user deviates from route that we should draw grey arrow
this.turnImminent = turnImminent;
this.deviatedFromRoute = deviatedFromRoute;
if (deviatedFromRoute) {
paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant));
} else if (turnImminent > 0) {
paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow));
} else if (turnImminent == 0) {
paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_imminent));
} else {
paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant));
}
invalidateSelf();
}
@Override
public void draw(@NonNull Canvas canvas) {
/// small indent
// canvas.translate(0, 3 * scaleCoefficient);
canvas.drawPath(pathForTurnOutlay, paintBlack);
canvas.drawPath(pathForTurn, paintRouteDirection);
canvas.drawPath(pathForTurn, paintBlack);
if (textPaint != null) {
if (turnType != null && !mini && turnType.getExitOut() > 0) {
canvas.drawText(turnType.getExitOut() + "", centerText.x,
centerText.y - (textPaint.descent() + textPaint.ascent()) / 2, textPaint);
}
}
}
public void setTextPaint(TextPaint textPaint) {
this.textPaint = textPaint;
this.textPaint.setTextAlign(Paint.Align.CENTER);
}
@Override
public void setAlpha(int alpha) {
paintRouteDirection.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter cf) {
paintRouteDirection.setColorFilter(cf);
}
@Override
public int getOpacity() {
return 0;
}
public TurnType getTurnType() {
return turnType;
}
public boolean setTurnType(TurnType turnType) {
if (turnType != this.turnType) {
this.turnType = turnType;
TurnPathHelper.calcTurnPath(pathForTurn, pathForTurnOutlay, turnType, null,
centerText, mini, false, true, false);
onBoundsChange(getBounds());
return true;
}
return false;
}
}

View file

@ -0,0 +1,193 @@
package net.osmand.plus.views.mapwidgets.widgets;
import android.content.res.Resources;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.core.content.ContextCompat;
import net.osmand.Location;
import net.osmand.binary.RouteDataObject;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmAndLocationProvider;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.MapViewTrackingUtilities;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.WaypointHelper;
import net.osmand.plus.routing.AlarmInfo;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.views.OsmandMapLayer;
import net.osmand.util.Algorithms;
import static android.util.TypedValue.COMPLEX_UNIT_PX;
public class AlarmWidget {
private View layout;
private ImageView icon;
private TextView widgetText;
private TextView widgetBottomText;
private OsmandSettings settings;
private RoutingHelper routingHelper;
private MapViewTrackingUtilities trackingUtilities;
private OsmAndLocationProvider locationProvider;
private WaypointHelper wh;
private int imgId;
private String cachedText;
private String cachedBottomText;
private OsmandSettings.DrivingRegion cachedRegion;
public AlarmWidget(final OsmandApplication app, MapActivity ma) {
layout = ma.findViewById(R.id.map_alarm_warning);
icon = ma.findViewById(R.id.map_alarm_warning_icon);
widgetText = ma.findViewById(R.id.map_alarm_warning_text);
widgetBottomText = ma.findViewById(R.id.map_alarm_warning_text_bottom);
settings = app.getSettings();
routingHelper = ma.getRoutingHelper();
trackingUtilities = ma.getMapViewTrackingUtilities();
locationProvider = app.getLocationProvider();
wh = app.getWaypointHelper();
}
public boolean updateInfo(OsmandMapLayer.DrawSettings drawSettings) {
boolean showRoutingAlarms = settings.SHOW_ROUTING_ALARMS.get();
boolean trafficWarnings = settings.SHOW_TRAFFIC_WARNINGS.get();
boolean cams = settings.SHOW_CAMERAS.get();
boolean peds = settings.SHOW_PEDESTRIAN.get();
boolean tunnels = settings.SHOW_TUNNELS.get();
boolean browseMap = settings.APPLICATION_MODE.get() == ApplicationMode.DEFAULT;
boolean visible = false;
if ((routingHelper.isFollowingMode() || trackingUtilities.isMapLinkedToLocation() && !browseMap)
&& showRoutingAlarms && (trafficWarnings || cams)) {
AlarmInfo alarm;
if (routingHelper.isFollowingMode() && !routingHelper.isDeviatedFromRoute() && (routingHelper.getCurrentGPXRoute() == null || routingHelper.isCurrentGPXRouteV2())) {
alarm = wh.getMostImportantAlarm(settings.SPEED_SYSTEM.get(), cams);
} else {
RouteDataObject ro = locationProvider.getLastKnownRouteSegment();
Location loc = locationProvider.getLastKnownLocation();
if (ro != null && loc != null) {
alarm = wh.calculateMostImportantAlarm(ro, loc, settings.METRIC_SYSTEM.get(),
settings.SPEED_SYSTEM.get(), cams);
} else {
alarm = null;
}
}
if (alarm != null) {
int locimgId = R.drawable.warnings_limit;
String text = "";
String bottomText = "";
OsmandSettings.DrivingRegion region = settings.DRIVING_REGION.get();
boolean americanType = region.isAmericanTypeSigns();
boolean isCanadianRegion = region == OsmandSettings.DrivingRegion.CANADA;
if (alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_LIMIT) {
if (isCanadianRegion) {
locimgId = R.drawable.warnings_speed_limit_ca;
bottomText = settings.SPEED_SYSTEM.get().toShortString(settings.getContext());
} else if (americanType) {
locimgId = R.drawable.warnings_speed_limit_us;
//else case is done by drawing red ring
}
text = alarm.getIntValue() + "";
} else if (alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_CAMERA) {
locimgId = R.drawable.warnings_speed_camera;
} else if (alarm.getType() == AlarmInfo.AlarmInfoType.BORDER_CONTROL) {
locimgId = R.drawable.warnings_border_control;
} else if (alarm.getType() == AlarmInfo.AlarmInfoType.HAZARD) {
if (americanType) {
locimgId = R.drawable.warnings_hazard_us;
} else {
locimgId = R.drawable.warnings_hazard;
}
} else if (alarm.getType() == AlarmInfo.AlarmInfoType.TOLL_BOOTH) {
//image done by drawing red ring
text = "$";
} else if (alarm.getType() == AlarmInfo.AlarmInfoType.TRAFFIC_CALMING) {
if (americanType) {
locimgId = R.drawable.warnings_traffic_calming_us;
} else {
locimgId = R.drawable.warnings_traffic_calming;
}
} else if (alarm.getType() == AlarmInfo.AlarmInfoType.STOP) {
locimgId = R.drawable.warnings_stop;
} else if (alarm.getType() == AlarmInfo.AlarmInfoType.RAILWAY) {
if (americanType) {
locimgId = R.drawable.warnings_railways_us;
} else {
locimgId = R.drawable.warnings_railways;
}
} else if (alarm.getType() == AlarmInfo.AlarmInfoType.PEDESTRIAN) {
if (americanType) {
locimgId = R.drawable.warnings_pedestrian_us;
} else {
locimgId = R.drawable.warnings_pedestrian;
}
} else if (alarm.getType() == AlarmInfo.AlarmInfoType.TUNNEL) {
if (americanType) {
locimgId = R.drawable.warnings_tunnel_us;
} else {
locimgId = R.drawable.warnings_tunnel;
}
bottomText = OsmAndFormatter.getFormattedAlarmInfoDistance(settings.getContext(), alarm.getFloatValue());
} else {
text = null;
bottomText = null;
}
visible = (text != null && text.length() > 0) || (locimgId != 0);
if (visible) {
if (alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_CAMERA) {
visible = cams;
} else if (alarm.getType() == AlarmInfo.AlarmInfoType.PEDESTRIAN) {
visible = peds;
} else if (alarm.getType() == AlarmInfo.AlarmInfoType.TUNNEL) {
visible = tunnels;
} else {
visible = trafficWarnings;
}
}
if (visible) {
if (locimgId != imgId) {
imgId = locimgId;
icon.setImageResource(locimgId);
}
Resources res = layout.getContext().getResources();
if (!Algorithms.objectEquals(text, cachedText) || cachedRegion != region) {
cachedText = text;
widgetText.setText(cachedText);
if (alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_LIMIT && americanType && !isCanadianRegion) {
int topPadding = res.getDimensionPixelSize(R.dimen.map_alarm_text_top_padding);
widgetText.setPadding(0, topPadding, 0, 0);
} else {
widgetText.setPadding(0, 0, 0, 0);
}
}
if (!Algorithms.objectEquals(bottomText, cachedBottomText) || cachedRegion != region) {
cachedBottomText = bottomText;
widgetBottomText.setText(cachedBottomText);
cachedRegion = region;
if (alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_LIMIT && isCanadianRegion) {
int bottomPadding = res.getDimensionPixelSize(R.dimen.map_button_margin);
widgetBottomText.setPadding(0, 0, 0, bottomPadding);
widgetBottomText.setTextSize(COMPLEX_UNIT_PX, res.getDimensionPixelSize(R.dimen.map_alarm_bottom_si_text_size));
} else {
widgetBottomText.setPadding(0, 0, 0, 0);
widgetBottomText.setTextSize(COMPLEX_UNIT_PX, res.getDimensionPixelSize(R.dimen.map_alarm_bottom_text_size));
}
widgetBottomText.setTextColor(ContextCompat.getColor(layout.getContext(),
americanType ? R.color.color_black : R.color.color_white));
}
}
}
}
AndroidUiHelper.updateVisibility(layout, visible);
return true;
}
public void setVisibility(boolean visibility) {
AndroidUiHelper.updateVisibility(layout, visibility);
}
}

View file

@ -0,0 +1,83 @@
package net.osmand.plus.views.mapwidgets.widgets;
import android.view.View;
import net.osmand.Location;
import net.osmand.data.LatLon;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.views.AnimateDraggingMapThread;
import net.osmand.plus.views.OsmandMapLayer;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory;
public abstract class DistanceToPointWidget extends TextInfoWidget {
private final OsmandMapTileView view;
private float[] calculations = new float[1];
private int cachedMeters;
public DistanceToPointWidget(MapActivity ma, int res, int resNight) {
super(ma);
this.view = ma.getMapView();
if (res != 0 && resNight != 0) {
setIcons(res, resNight);
}
setText(null, null);
setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
click(view);
}
});
}
protected void click(final OsmandMapTileView view) {
AnimateDraggingMapThread thread = view.getAnimatedDraggingThread();
LatLon pointToNavigate = getPointToNavigate();
if (pointToNavigate != null) {
int fZoom = Math.max(view.getZoom(), 15);
thread.startMoving(pointToNavigate.getLatitude(), pointToNavigate.getLongitude(), fZoom, true);
}
}
@Override
public boolean updateInfo(OsmandMapLayer.DrawSettings drawSettings) {
int d = getDistance();
if (isUpdateNeeded() || RouteInfoWidgetsFactory.distChanged(cachedMeters, d)) {
cachedMeters = d;
if (cachedMeters <= 20) {
cachedMeters = 0;
setText(null, null);
} else {
String ds = OsmAndFormatter.getFormattedDistance(cachedMeters, view.getApplication());
int ls = ds.lastIndexOf(' ');
if (ls == -1) {
setText(ds, null);
} else {
setText(ds.substring(0, ls), ds.substring(ls + 1));
}
}
return true;
}
return false;
}
@Override
public boolean isMetricSystemDepended() {
return true;
}
public abstract LatLon getPointToNavigate();
public int getDistance() {
int d = 0;
LatLon l = getPointToNavigate();
if (l != null) {
Location.distanceBetween(view.getLatitude(), view.getLongitude(), l.getLatitude(), l.getLongitude(), calculations);
d = (int) calculations[0];
}
return d;
}
}

View file

@ -0,0 +1,100 @@
package net.osmand.plus.views.mapwidgets.widgets;
import android.app.Activity;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory;
import net.osmand.plus.views.mapwidgets.TurnDrawable;
import net.osmand.router.TurnType;
public class NextTurnWidget extends TextInfoWidget {
protected boolean horizontalMini;
protected int deviatedPath = 0;
protected int nextTurnDistance = 0;
private TurnDrawable turnDrawable;
private OsmandApplication app;
public NextTurnWidget(Activity activity, OsmandApplication app, boolean horizontalMini) {
super(activity);
this.app = app;
this.horizontalMini = horizontalMini;
turnDrawable = new TurnDrawable(activity, horizontalMini);
if (horizontalMini) {
setImageDrawable(turnDrawable, false);
setTopImageDrawable(null, null);
} else {
setImageDrawable(null, true);
setTopImageDrawable(turnDrawable, "");
}
}
public TurnType getTurnType() {
return turnDrawable.getTurnType();
}
public void setTurnType(TurnType turnType) {
boolean vis = updateVisibility(turnType != null);
if (turnDrawable.setTurnType(turnType) || vis) {
turnDrawable.setTextPaint(topTextView.getPaint());
if (horizontalMini) {
setImageDrawable(turnDrawable, false);
} else {
setTopImageDrawable(turnDrawable, "");
// setTopImageDrawable(turnDrawable, turnType == null || turnType.getExitOut() == 0 ? "" :
// turnType.getExitOut() + "");
}
}
}
public void setTurnImminent(int turnImminent, boolean deviatedFromRoute) {
if (turnDrawable.getTurnImminent() != turnImminent || turnDrawable.isDeviatedFromRoute() != deviatedFromRoute) {
turnDrawable.setTurnImminent(turnImminent, deviatedFromRoute);
}
}
public void setDeviatePath(int deviatePath) {
if (RouteInfoWidgetsFactory.distChanged(deviatePath, this.deviatedPath)) {
this.deviatedPath = deviatePath;
updateDistance();
}
}
public void setTurnDistance(int nextTurnDistance) {
if (RouteInfoWidgetsFactory.distChanged(nextTurnDistance, this.nextTurnDistance)) {
this.nextTurnDistance = nextTurnDistance;
updateDistance();
}
}
private void updateDistance() {
int deviatePath = turnDrawable.isDeviatedFromRoute() ? deviatedPath : nextTurnDistance;
String ds = OsmAndFormatter.getFormattedDistance(deviatePath, app);
TurnType turnType = getTurnType();
RoutingHelper routingHelper = app.getRoutingHelper();
if ((turnType != null) && (routingHelper != null)) {
setContentDescription(ds + " " + RouteCalculationResult.toString(turnType, app, false));
} else {
setContentDescription(ds);
}
int ls = ds.lastIndexOf(' ');
if (ls == -1) {
setTextNoUpdateVisibility(ds, null);
} else {
setTextNoUpdateVisibility(ds.substring(0, ls), ds.substring(ls + 1));
}
}
@Override
public boolean updateInfo(DrawSettings drawSettings) {
return false;
}
}

View file

@ -0,0 +1,83 @@
package net.osmand.plus.views.mapwidgets.widgets;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import net.osmand.data.RotatedTileBox;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.OsmandMapTileView;
public class RulerWidget {
private MapActivity mapActivity;
private OsmandPreference<Float> mapDensity;
private View layout;
private ImageView icon;
private TextView text;
private TextView textShadow;
private String cacheRulerText;
private int maxWidth;
private int cacheRulerZoom;
private float cacheMapDensity;
private double cacheRulerTileX;
private double cacheRulerTileY;
public RulerWidget(MapActivity mapActivity, View view) {
this.mapActivity = mapActivity;
layout = view.findViewById(R.id.map_ruler_layout);
icon = view.findViewById(R.id.map_ruler_image);
text = view.findViewById(R.id.map_ruler_text);
textShadow = view.findViewById(R.id.map_ruler_text_shadow);
maxWidth = view.getResources().getDimensionPixelSize(R.dimen.map_ruler_width);
mapDensity = mapActivity.getMyApplication().getSettings().MAP_DENSITY;
cacheMapDensity = mapDensity.get();
}
public void updateTextSize(boolean isNight, int textColor, int textShadowColor, int shadowRadius) {
TextInfoWidget.updateTextColor(text, textShadow, textColor, textShadowColor, false, shadowRadius);
icon.setBackgroundResource(isNight ? R.drawable.ruler_night : R.drawable.ruler);
}
public boolean updateInfo(RotatedTileBox tb, DrawSettings nightMode) {
boolean visible = true;
OsmandMapTileView view = mapActivity.getMapView();
// update cache
if (view.isZooming()) {
visible = false;
} else if (!tb.isZoomAnimated() && (tb.getZoom() != cacheRulerZoom || Math.abs(tb.getCenterTileX() - cacheRulerTileX) > 1 || Math
.abs(tb.getCenterTileY() - cacheRulerTileY) > 1 || mapDensity.get() != cacheMapDensity) &&
tb.getPixWidth() > 0 && maxWidth > 0) {
cacheRulerZoom = tb.getZoom();
cacheRulerTileX = tb.getCenterTileX();
cacheRulerTileY = tb.getCenterTileY();
cacheMapDensity = mapDensity.get();
double pixDensity = tb.getPixDensity();
double roundedDist = OsmAndFormatter.calculateRoundedDist(maxWidth /
pixDensity, view.getApplication());
int cacheRulerDistPix = (int) (pixDensity * roundedDist);
cacheRulerText = OsmAndFormatter.getFormattedDistance((float) roundedDist, view.getApplication(), false);
textShadow.setText(cacheRulerText);
text.setText(cacheRulerText);
ViewGroup.LayoutParams lp = layout.getLayoutParams();
lp.width = cacheRulerDistPix;
layout.setLayoutParams(lp);
layout.requestLayout();
}
AndroidUiHelper.updateVisibility(layout, visible);
return true;
}
public void setVisibility(boolean visibility) {
AndroidUiHelper.updateVisibility(layout, visibility);
}
}

View file

@ -1,4 +1,4 @@
package net.osmand.plus.views.mapwidgets; package net.osmand.plus.views.mapwidgets.widgets;
import android.app.Activity; import android.app.Activity;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
@ -19,7 +19,9 @@ import net.osmand.plus.R;
import net.osmand.plus.UiUtilities; import net.osmand.plus.UiUtilities;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
public class TextInfoWidget { public class TextInfoWidget {
private OsmandApplication app;
private String contentTitle; private String contentTitle;
private View view; private View view;
@ -31,7 +33,6 @@ public class TextInfoWidget {
private ImageView topImageView; private ImageView topImageView;
protected TextView topTextView; protected TextView topTextView;
private boolean explicitlyVisible; private boolean explicitlyVisible;
private OsmandApplication app;
private int dayIcon; private int dayIcon;
private int nightIcon; private int nightIcon;
@ -44,35 +45,34 @@ public class TextInfoWidget {
public TextInfoWidget(Activity activity) { public TextInfoWidget(Activity activity) {
app = (OsmandApplication) activity.getApplication(); app = (OsmandApplication) activity.getApplication();
view = UiUtilities.getInflater(activity, isNight).inflate(R.layout.map_hud_widget, null); view = UiUtilities.getInflater(activity, isNight).inflate(R.layout.map_hud_widget, null);
bottomLayout = (ViewGroup) view.findViewById(R.id.widget_bottom_layout); bottomLayout = view.findViewById(R.id.widget_bottom_layout);
topImageView = (ImageView) view.findViewById(R.id.widget_top_icon); topImageView = view.findViewById(R.id.widget_top_icon);
topTextView = (TextView) view.findViewById(R.id.widget_top_icon_text); topTextView = view.findViewById(R.id.widget_top_icon_text);
imageView = (ImageView) view.findViewById(R.id.widget_icon); imageView = view.findViewById(R.id.widget_icon);
textView = (TextView) view.findViewById(R.id.widget_text); textView = view.findViewById(R.id.widget_text);
textViewShadow = (TextView) view.findViewById(R.id.widget_text_shadow); textViewShadow = view.findViewById(R.id.widget_text_shadow);
smallTextViewShadow = (TextView) view.findViewById(R.id.widget_text_small_shadow); smallTextViewShadow = view.findViewById(R.id.widget_text_small_shadow);
smallTextView = (TextView) view.findViewById(R.id.widget_text_small); smallTextView = view.findViewById(R.id.widget_text_small);
} }
public OsmandApplication getOsmandApplication() { public OsmandApplication getApplication() {
return app; return app;
} }
public View getView() { public View getView() {
return view; return view;
} }
public void setImageDrawable(Drawable imageDrawable) { public void setImageDrawable(Drawable imageDrawable) {
setImageDrawable(imageDrawable, false); setImageDrawable(imageDrawable, false);
} }
public void setImageDrawable(int res) { public void setImageDrawable(int res) {
setImageDrawable(app.getUIUtilities().getIcon(res, 0), false); setImageDrawable(app.getUIUtilities().getIcon(res, 0), false);
} }
public void setImageDrawable(Drawable imageDrawable, boolean gone) { public void setImageDrawable(Drawable imageDrawable, boolean gone) {
if(imageDrawable != null) { if (imageDrawable != null) {
imageView.setImageDrawable(imageDrawable); imageView.setImageDrawable(imageDrawable);
Object anim = imageView.getDrawable(); Object anim = imageView.getDrawable();
if (anim instanceof AnimationDrawable) { if (anim instanceof AnimationDrawable) {
@ -84,9 +84,9 @@ public class TextInfoWidget {
} }
imageView.invalidate(); imageView.invalidate();
} }
public void setTopImageDrawable(Drawable imageDrawable, String topText) { public void setTopImageDrawable(Drawable imageDrawable, String topText) {
if(imageDrawable != null) { if (imageDrawable != null) {
topImageView.setImageDrawable(imageDrawable); topImageView.setImageDrawable(imageDrawable);
topImageView.setVisibility(View.VISIBLE); topImageView.setVisibility(View.VISIBLE);
LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) bottomLayout.getLayoutParams(); LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) bottomLayout.getLayoutParams();
@ -96,17 +96,17 @@ public class TextInfoWidget {
topTextView.setVisibility(View.VISIBLE); topTextView.setVisibility(View.VISIBLE);
topTextView.setText(topText == null ? "" : topText); topTextView.setText(topText == null ? "" : topText);
} else { } else {
topImageView.setVisibility(View.GONE ); topImageView.setVisibility(View.GONE);
topTextView.setVisibility(View.GONE ); topTextView.setVisibility(View.GONE);
LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) bottomLayout.getLayoutParams(); LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) bottomLayout.getLayoutParams();
lp.gravity = Gravity.NO_GRAVITY; lp.gravity = Gravity.NO_GRAVITY;
bottomLayout.setLayoutParams(lp); bottomLayout.setLayoutParams(lp);
} }
topTextView.invalidate(); topTextView.invalidate();
topImageView.invalidate(); topImageView.invalidate();
} }
public boolean setIcons(int widgetDayIcon, int widgetNightIcon) { public boolean setIcons(int widgetDayIcon, int widgetNightIcon) {
if (dayIcon != widgetDayIcon || nightIcon != widgetNightIcon) { if (dayIcon != widgetDayIcon || nightIcon != widgetNightIcon) {
dayIcon = widgetDayIcon; dayIcon = widgetDayIcon;
@ -134,7 +134,7 @@ public class TextInfoWidget {
public void setContentDescription(CharSequence text) { public void setContentDescription(CharSequence text) {
view.setContentDescription(combine(contentTitle, text)); view.setContentDescription(combine(contentTitle, text));
} }
public void setContentTitle(int messageId) { public void setContentTitle(int messageId) {
setContentTitle(view.getContext().getString(messageId)); setContentTitle(view.getContext().getString(messageId));
} }
@ -143,7 +143,7 @@ public class TextInfoWidget {
contentTitle = text; contentTitle = text;
setContentDescription(combine(textView.getText(), smallTextView.getText())); setContentDescription(combine(textView.getText(), smallTextView.getText()));
} }
public void setText(String text, String subtext) { public void setText(String text, String subtext) {
setTextNoUpdateVisibility(text, subtext); setTextNoUpdateVisibility(text, subtext);
updateVisibility(text != null); updateVisibility(text != null);
@ -154,14 +154,14 @@ public class TextInfoWidget {
// if(this.text != null && this.text.length() > 7) { // if(this.text != null && this.text.length() > 7) {
// this.text = this.text.substring(0, 6) +".."; // this.text = this.text.substring(0, 6) +"..";
// } // }
if(text == null) { if (text == null) {
textView.setText(""); textView.setText("");
textViewShadow.setText(""); textViewShadow.setText("");
} else { } else {
textView.setText(text); textView.setText(text);
textViewShadow.setText(text); textViewShadow.setText(text);
} }
if(subtext == null) { if (subtext == null) {
smallTextView.setText(""); smallTextView.setText("");
smallTextViewShadow.setText(""); smallTextViewShadow.setText("");
} else { } else {
@ -169,7 +169,7 @@ public class TextInfoWidget {
smallTextViewShadow.setText(subtext); smallTextViewShadow.setText(subtext);
} }
} }
protected boolean updateVisibility(boolean visible) { protected boolean updateVisibility(boolean visible) {
if (visible != (view.getVisibility() == View.VISIBLE)) { if (visible != (view.getVisibility() == View.VISIBLE)) {
if (visible) { if (visible) {
@ -184,7 +184,7 @@ public class TextInfoWidget {
} }
return false; return false;
} }
public boolean isVisible() { public boolean isVisible() {
return view.getVisibility() == View.VISIBLE && view.getParent() != null; return view.getVisibility() == View.VISIBLE && view.getParent() != null;
} }
@ -223,15 +223,15 @@ public class TextInfoWidget {
public void setExplicitlyVisible(boolean explicitlyVisible) { public void setExplicitlyVisible(boolean explicitlyVisible) {
this.explicitlyVisible = explicitlyVisible; this.explicitlyVisible = explicitlyVisible;
} }
public boolean isExplicitlyVisible() { public boolean isExplicitlyVisible() {
return explicitlyVisible; return explicitlyVisible;
} }
public void updateIconMode(boolean night) { public void updateIconMode(boolean night) {
isNight = night; isNight = night;
if(dayIcon != 0) { if (dayIcon != 0) {
setImageDrawable(!night? dayIcon : nightIcon); setImageDrawable(!night ? dayIcon : nightIcon);
} }
} }
@ -240,10 +240,10 @@ public class TextInfoWidget {
updateTextColor(textView, textViewShadow, textColor, textShadowColor, bold, rad); updateTextColor(textView, textViewShadow, textColor, textShadowColor, bold, rad);
updateTextColor(topTextView, null, textColor, textShadowColor, bold, rad); updateTextColor(topTextView, null, textColor, textShadowColor, bold, rad);
} }
public static void updateTextColor(TextView tv, TextView shadow, int textColor, int textShadowColor, boolean textBold, int rad) { public static void updateTextColor(TextView tv, TextView shadow, int textColor, int textShadowColor, boolean textBold, int rad) {
if(shadow != null) { if (shadow != null) {
if(rad > 0) { if (rad > 0) {
shadow.setVisibility(View.VISIBLE); shadow.setVisibility(View.VISIBLE);
shadow.setTypeface(Typeface.DEFAULT, textBold ? Typeface.BOLD : Typeface.NORMAL); shadow.setTypeface(Typeface.DEFAULT, textBold ? Typeface.BOLD : Typeface.NORMAL);
shadow.getPaint().setStrokeWidth(rad); shadow.getPaint().setStrokeWidth(rad);
@ -258,4 +258,4 @@ public class TextInfoWidget {
tv.setTextColor(textColor); tv.setTextColor(textColor);
tv.setTypeface(Typeface.DEFAULT, textBold ? Typeface.BOLD : Typeface.NORMAL); tv.setTypeface(Typeface.DEFAULT, textBold ? Typeface.BOLD : Typeface.NORMAL);
} }
} }

View file

@ -0,0 +1,53 @@
package net.osmand.plus.views.mapwidgets.widgetstates;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.settings.backend.OsmandSettings;
public class BearingWidgetState extends WidgetState {
public static final int BEARING_WIDGET_STATE_RELATIVE_BEARING = R.id.bearing_widget_state_relative_bearing;
public static final int BEARING_WIDGET_STATE_MAGNETIC_BEARING = R.id.bearing_widget_state_magnetic_bearing;
private final OsmandSettings.OsmandPreference<Boolean> showRelativeBearing;
public BearingWidgetState(OsmandApplication ctx) {
super(ctx);
showRelativeBearing = ctx.getSettings().SHOW_RELATIVE_BEARING_OTHERWISE_REGULAR_BEARING;
}
@Override
public int getMenuTitleId() {
return showRelativeBearing.get() ? R.string.map_widget_bearing : R.string.map_widget_magnetic_bearing;
}
@Override
public int getMenuIconId() {
return showRelativeBearing.get() ? R.drawable.ic_action_relative_bearing : R.drawable.ic_action_bearing;
}
@Override
public int getMenuItemId() {
return showRelativeBearing.get() ? BEARING_WIDGET_STATE_RELATIVE_BEARING : BEARING_WIDGET_STATE_MAGNETIC_BEARING;
}
@Override
public int[] getMenuTitleIds() {
return new int[] {R.string.map_widget_magnetic_bearing, R.string.map_widget_bearing};
}
@Override
public int[] getMenuIconIds() {
return new int[] {R.drawable.ic_action_bearing, R.drawable.ic_action_relative_bearing};
}
@Override
public int[] getMenuItemIds() {
return new int[] {BEARING_WIDGET_STATE_MAGNETIC_BEARING, BEARING_WIDGET_STATE_RELATIVE_BEARING};
}
@Override
public void changeState(int stateId) {
showRelativeBearing.set(stateId == BEARING_WIDGET_STATE_RELATIVE_BEARING);
}
}

View file

@ -0,0 +1,53 @@
package net.osmand.plus.views.mapwidgets.widgetstates;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference;
public class CompassRulerWidgetState extends WidgetState {
public static final int COMPASS_CONTROL_WIDGET_STATE_SHOW = R.id.compass_ruler_control_widget_state_show;
public static final int COMPASS_CONTROL_WIDGET_STATE_HIDE = R.id.compass_ruler_control_widget_state_hide;
private final OsmandPreference<Boolean> showCompass;
public CompassRulerWidgetState(OsmandApplication app) {
super(app);
showCompass = app.getSettings().SHOW_COMPASS_CONTROL_RULER;
}
@Override
public int getMenuTitleId() {
return R.string.map_widget_ruler_control;
}
@Override
public int getMenuIconId() {
return R.drawable.ic_action_ruler_circle;
}
@Override
public int getMenuItemId() {
return showCompass.get() ? COMPASS_CONTROL_WIDGET_STATE_SHOW : COMPASS_CONTROL_WIDGET_STATE_HIDE;
}
@Override
public int[] getMenuTitleIds() {
return new int[] {R.string.show_compass_ruler, R.string.hide_compass_ruler};
}
@Override
public int[] getMenuIconIds() {
return new int[] {R.drawable.ic_action_compass_widget, R.drawable.ic_action_compass_widget_hide};
}
@Override
public int[] getMenuItemIds() {
return new int[] {COMPASS_CONTROL_WIDGET_STATE_SHOW, COMPASS_CONTROL_WIDGET_STATE_HIDE};
}
@Override
public void changeState(int stateId) {
showCompass.set(stateId == COMPASS_CONTROL_WIDGET_STATE_SHOW);
}
}

View file

@ -0,0 +1,71 @@
package net.osmand.plus.views.mapwidgets.widgetstates;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference;
public class TimeWidgetState extends WidgetState {
public static final int TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME = R.id.time_control_widget_state_arrival_time;
public static final int TIME_CONTROL_WIDGET_STATE_TIME_TO_GO = R.id.time_control_widget_state_time_to_go;
private final OsmandPreference<Boolean> showArrival;
private final boolean intermediate;
public TimeWidgetState(OsmandApplication app, boolean intermediate) {
super(app);
this.intermediate = intermediate;
if (intermediate) {
showArrival = app.getSettings().SHOW_INTERMEDIATE_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME;
} else {
showArrival = app.getSettings().SHOW_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME;
}
}
@Override
public int getMenuTitleId() {
if (intermediate) {
return showArrival.get() ? R.string.access_intermediate_arrival_time : R.string.map_widget_intermediate_time;
}
return showArrival.get() ? R.string.access_arrival_time : R.string.map_widget_time;
}
@Override
public int getMenuIconId() {
if (intermediate) {
return R.drawable.ic_action_intermediate_destination_time;
}
return showArrival.get() ? R.drawable.ic_action_time : R.drawable.ic_action_time_to_distance;
}
@Override
public int getMenuItemId() {
return showArrival.get() ? TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME : TIME_CONTROL_WIDGET_STATE_TIME_TO_GO;
}
@Override
public int[] getMenuTitleIds() {
if (intermediate) {
return new int[] {R.string.access_intermediate_arrival_time, R.string.map_widget_intermediate_time};
}
return new int[] {R.string.access_arrival_time, R.string.map_widget_time};
}
@Override
public int[] getMenuIconIds() {
if (intermediate) {
return new int[] {R.drawable.ic_action_intermediate_destination_time, R.drawable.ic_action_intermediate_destination_time};
}
return new int[] {R.drawable.ic_action_time, R.drawable.ic_action_time_to_distance};
}
@Override
public int[] getMenuItemIds() {
return new int[] {TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME, TIME_CONTROL_WIDGET_STATE_TIME_TO_GO};
}
@Override
public void changeState(int stateId) {
showArrival.set(stateId == TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME);
}
}

View file

@ -0,0 +1,30 @@
package net.osmand.plus.views.mapwidgets.widgetstates;
import net.osmand.plus.OsmandApplication;
public abstract class WidgetState {
private OsmandApplication ctx;
public OsmandApplication getCtx() {
return ctx;
}
public WidgetState(OsmandApplication ctx) {
this.ctx = ctx;
}
public abstract int getMenuTitleId();
public abstract int getMenuIconId();
public abstract int getMenuItemId();
public abstract int[] getMenuTitleIds();
public abstract int[] getMenuIconIds();
public abstract int[] getMenuItemIds();
public abstract void changeState(int stateId);
}