From d453b1e6fc7df967e0b22ee0486aebf270e8f6cb Mon Sep 17 00:00:00 2001 From: Chumva Date: Thu, 12 Dec 2019 14:05:56 +0200 Subject: [PATCH] Reorder app modes initial commit --- .../layout/edit_profiles_list_fragment.xml | 72 +++++++++ OsmAnd/res/values/strings.xml | 1 + OsmAnd/res/xml/settings_main_screen.xml | 1 + .../src/net/osmand/plus/ApplicationMode.java | 68 +++++++-- .../osmand/plus/profiles/ProfilesAdapter.java | 137 ++++++++++++++++++ .../ProfilesItemTouchHelperCallback.java | 57 ++++++++ .../plus/settings/EditProfilesFragment.java | 120 +++++++++++++++ 7 files changed, 442 insertions(+), 14 deletions(-) create mode 100644 OsmAnd/res/layout/edit_profiles_list_fragment.xml create mode 100644 OsmAnd/src/net/osmand/plus/profiles/ProfilesAdapter.java create mode 100644 OsmAnd/src/net/osmand/plus/profiles/ProfilesItemTouchHelperCallback.java create mode 100644 OsmAnd/src/net/osmand/plus/settings/EditProfilesFragment.java diff --git a/OsmAnd/res/layout/edit_profiles_list_fragment.xml b/OsmAnd/res/layout/edit_profiles_list_fragment.xml new file mode 100644 index 0000000000..53d992555a --- /dev/null +++ b/OsmAnd/res/layout/edit_profiles_list_fragment.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 8ee63b8ae0..b3a650da0e 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,7 @@ Thx - Hardy --> + Edit profiles Navigation type affects the rules for route calculations. %1$s • %2$s %1$s, %2$s diff --git a/OsmAnd/res/xml/settings_main_screen.xml b/OsmAnd/res/xml/settings_main_screen.xml index 93739098bf..46c9009625 100644 --- a/OsmAnd/res/xml/settings_main_screen.xml +++ b/OsmAnd/res/xml/settings_main_screen.xml @@ -58,6 +58,7 @@ android:layout="@layout/preference_button" android:persistent="false" android:title="@string/reorder_profiles" + app:fragment="net.osmand.plus.settings.EditProfilesFragment" tools:icon="@drawable/ic_action_edit_dark" /> comparator = new Comparator() { + @Override + public int compare(ApplicationMode o1, ApplicationMode o2) { + return (o1.order < o2.order) ? -1 : ((o1.order == o2.order) ? 0 : 1); + } + }; + Collections.sort(values, comparator); + Collections.sort(customValues, comparator); + Collections.sort(defaultValues, comparator); + Collections.sort(cachedFilteredValues, comparator); + } + public static ApplicationModeBuilder fromJson(OsmandApplication app, String json) { Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); ApplicationModeBean mb = gson.fromJson(json, ApplicationModeBean.class); @@ -677,6 +705,7 @@ public class ApplicationMode { applicationMode.iconColor = modeBean.iconColor; applicationMode.routingProfile = modeBean.routingProfile; applicationMode.routeService = modeBean.routeService; + applicationMode.order = modeBean.order; } } } @@ -689,15 +718,29 @@ public class ApplicationMode { if (!Algorithms.isEmpty(customProfiles)) { for (ApplicationModeBean m : customProfiles) { - ApplicationModeBuilder b = createCustomMode(valueOfStringKey(m.parent, CAR), - m.userProfileName, m.stringKey); - b.setRouteService(m.routeService).setRoutingProfile(m.routingProfile); - b.icon(app, m.iconName); - b.setColor(m.iconColor); - b.customReg(); + ApplicationMode parentMode = valueOfStringKey(m.parent, CAR); + createCustomMode(parentMode, m.userProfileName, m.stringKey) + .setRouteService(m.routeService) + .setRoutingProfile(m.routingProfile) + .icon(app, m.iconName) + .setColor(m.iconColor) + .setOrder(m.order) + .customReg(); } } + } + public static void saveAppModesToSettings(OsmandSettings settings) { + Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); + + List defaultModeBeans = createApplicationModeBeans(defaultValues); + List customModeBeans = createApplicationModeBeans(customValues); + + String defaultProfiles = gson.toJson(defaultModeBeans); + String customProfiles = gson.toJson(customModeBeans); + + settings.DEFAULT_APP_PROFILES.set(defaultProfiles); + settings.CUSTOM_APP_PROFILES.set(customProfiles); } private static void saveAppModesToSettings(OsmandSettings settings, boolean saveCustomModes) { @@ -724,6 +767,7 @@ public class ApplicationMode { mb.stringKey = mode.stringKey; mb.routeService = mode.routeService; mb.routingProfile = mode.routingProfile; + mb.order = mode.order; modeBeans.add(mb); } @@ -740,6 +784,7 @@ public class ApplicationMode { mode.routingProfile = builder.applicationMode.routingProfile; mode.routeService = builder.applicationMode.routeService; mode.iconColor = builder.applicationMode.iconColor; + mode.order = builder.applicationMode.order; } else { mode = builder.customReg(); initRegVisibility(); @@ -807,12 +852,7 @@ public class ApplicationMode { } public int getColor(boolean nightMode) { - if (nightMode) { - return nightColor; - } else { - return dayColor; - } + return nightMode ? nightColor : dayColor; } - } - + } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/profiles/ProfilesAdapter.java b/OsmAnd/src/net/osmand/plus/profiles/ProfilesAdapter.java new file mode 100644 index 0000000000..9cac42f24b --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/profiles/ProfilesAdapter.java @@ -0,0 +1,137 @@ +package net.osmand.plus.profiles; + +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.support.v4.content.ContextCompat; +import android.support.v4.view.MotionEventCompat; +import android.support.v7.widget.RecyclerView; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; + +import net.osmand.AndroidUtils; +import net.osmand.plus.ApplicationMode; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.settings.BaseSettingsFragment; + +import java.util.Collections; +import java.util.List; + +public class ProfilesAdapter extends AbstractProfileMenuAdapter + implements ProfilesItemTouchHelperCallback.ItemTouchHelperAdapter { + + private OsmandApplication app; + private List applicationModes; + private ProfilesAdapterListener listener; + + private boolean nightMode; + + public ProfilesAdapter(MapActivity mapActivity, List applicationModes) { + setHasStableIds(true); + app = mapActivity.getMyApplication(); + this.applicationModes = applicationModes; + nightMode = !mapActivity.getMyApplication().getSettings().isLightContent(); + } + + public void setAdapterListener(ProfilesAdapterListener listener) { + this.listener = listener; + } + + @NonNull + @Override + public SelectProfileViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View itemView = UiUtilities.getInflater(viewGroup.getContext(), nightMode).inflate(R.layout.profile_list_item, null); + itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + listener.onItemClick(view); + } + }); + return new SelectProfileViewHolder(itemView); + } + + @Override + public void onBindViewHolder(final SelectProfileViewHolder holder, final int pos) { + ApplicationMode mode = applicationModes.get(pos); + + holder.icon.setVisibility(View.VISIBLE); + holder.descr.setVisibility(View.VISIBLE); + holder.switcher.setVisibility(View.GONE); + holder.menuIcon.setVisibility(View.VISIBLE); + + holder.title.setText(mode.toHumanString(app)); + holder.descr.setText(BaseSettingsFragment.getAppModeDescription(app, mode)); + + //set up cell color + int profileColorResId = mode.getIconColorInfo().getColor(nightMode); + int colorNoAlpha = ContextCompat.getColor(app, profileColorResId); + Drawable drawable = UiUtilities.getColoredSelectableDrawable(app, colorNoAlpha, 0.3f); + + AndroidUtils.setBackground(holder.profileOptions, drawable); + + updateViewHolder(holder, mode); + + holder.menuIcon.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent event) { + if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) { + listener.onDragStarted(holder); + } + return false; + } + }); + } + + @Override + public int getItemCount() { + return applicationModes.size(); + } + + @Override + public boolean onItemMove(int from, int to) { + Collections.swap(applicationModes, from, to); + notifyItemMoved(from, to); + return true; + } + + @Override + public long getItemId(int position) { + return applicationModes.get(position).hashCode(); + } + + @Override + public void onItemDismiss(RecyclerView.ViewHolder holder) { + listener.onDragOrSwipeEnded(holder); + } + + private void updateViewHolder(SelectProfileViewHolder holder, ApplicationMode mode) { + int iconRes = mode.getIconRes(); + if (iconRes == 0 || iconRes == -1) { + iconRes = R.drawable.ic_action_world_globe; + } + int selectedIconColorRes = mode.getIconColorInfo().getColor(nightMode); + holder.icon.setImageDrawable(app.getUIUtilities().getIcon(iconRes, selectedIconColorRes)); + } + + public ApplicationMode getItem(int position) { + return applicationModes.get(position); + } + + class SelectProfileViewHolder extends ProfileAbstractViewHolder { + SelectProfileViewHolder(View itemView) { + super(itemView); + } + } + + public interface ProfilesAdapterListener { + + void onItemClick(View view); + + void onDragStarted(RecyclerView.ViewHolder holder); + + void onDragOrSwipeEnded(RecyclerView.ViewHolder holder); + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/profiles/ProfilesItemTouchHelperCallback.java b/OsmAnd/src/net/osmand/plus/profiles/ProfilesItemTouchHelperCallback.java new file mode 100644 index 0000000000..bfbb075c8e --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/profiles/ProfilesItemTouchHelperCallback.java @@ -0,0 +1,57 @@ +package net.osmand.plus.profiles; + +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.helper.ItemTouchHelper; + +public class ProfilesItemTouchHelperCallback extends ItemTouchHelper.Callback { + + private ProfilesItemTouchHelperCallback.ItemTouchHelperAdapter adapter; + + public ProfilesItemTouchHelperCallback(ProfilesItemTouchHelperCallback.ItemTouchHelperAdapter adapter) { + this.adapter = adapter; + } + + @Override + public boolean isLongPressDragEnabled() { + return false; + } + + @Override + public boolean isItemViewSwipeEnabled() { + return false; + } + + @Override + public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { + + } + + @Override + public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; + return makeMovementFlags(dragFlags, 0); + } + + @Override + public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) { + int from = source.getAdapterPosition(); + int to = target.getAdapterPosition(); + if (from == RecyclerView.NO_POSITION || to == RecyclerView.NO_POSITION) { + return false; + } + return adapter.onItemMove(from, to); + } + + @Override + public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + super.clearView(recyclerView, viewHolder); + adapter.onItemDismiss(viewHolder); + } + + interface ItemTouchHelperAdapter { + + boolean onItemMove(int from, int to); + + void onItemDismiss(RecyclerView.ViewHolder holder); + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/EditProfilesFragment.java b/OsmAnd/src/net/osmand/plus/settings/EditProfilesFragment.java new file mode 100644 index 0000000000..b1c8d0b598 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/EditProfilesFragment.java @@ -0,0 +1,120 @@ +package net.osmand.plus.settings; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.FragmentActivity; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.helper.ItemTouchHelper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageButton; +import android.widget.TextView; + +import net.osmand.AndroidUtils; +import net.osmand.plus.ApplicationMode; +import net.osmand.plus.OsmandSettings; +import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.base.BaseOsmAndFragment; +import net.osmand.plus.profiles.ProfilesAdapter; +import net.osmand.plus.profiles.ProfilesItemTouchHelperCallback; + +import java.util.ArrayList; +import java.util.List; + +public class EditProfilesFragment extends BaseOsmAndFragment { + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + MapActivity mapActivity = (MapActivity) getActivity(); + View mainView = inflater.inflate(R.layout.edit_profiles_list_fragment, container, false); + AndroidUtils.addStatusBarPadding21v(getContext(), mainView); + + ImageButton closeButton = mainView.findViewById(R.id.close_button); + closeButton.setImageResource(R.drawable.ic_action_remove_dark); + closeButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FragmentActivity fragmentActivity = getActivity(); + if (fragmentActivity != null) { + fragmentActivity.onBackPressed(); + } + } + }); + + TextView toolbarTitle = mainView.findViewById(R.id.toolbar_title); + toolbarTitle.setText(R.string.edit_profiles); + + RecyclerView recyclerView = mainView.findViewById(R.id.profiles_list); + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + + final List applicationModes = new ArrayList<>(ApplicationMode.allPossibleValues()); + final ProfilesAdapter adapter = new ProfilesAdapter(mapActivity, applicationModes); + final ItemTouchHelper touchHelper = new ItemTouchHelper(new ProfilesItemTouchHelperCallback(adapter)); + + touchHelper.attachToRecyclerView(recyclerView); + adapter.setAdapterListener(new ProfilesAdapter.ProfilesAdapterListener() { + + private int fromPosition; + private int toPosition; + + @Override + public void onItemClick(View view) { + + } + + @Override + public void onDragStarted(RecyclerView.ViewHolder holder) { + fromPosition = holder.getAdapterPosition(); + touchHelper.startDrag(holder); + } + + @Override + public void onDragOrSwipeEnded(RecyclerView.ViewHolder holder) { + toPosition = holder.getAdapterPosition(); + if (toPosition >= 0 && fromPosition >= 0 && toPosition != fromPosition) { + adapter.notifyDataSetChanged(); + } + } + }); + + recyclerView.setAdapter(adapter); + + View cancelButton = mainView.findViewById(R.id.cancel_button); + UiUtilities.setupDialogButton(false, cancelButton, UiUtilities.DialogButtonType.SECONDARY, R.string.shared_string_cancel); + cancelButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FragmentActivity fragmentActivity = getActivity(); + if (fragmentActivity != null) { + fragmentActivity.onBackPressed(); + } + } + }); + + View applyButton = mainView.findViewById(R.id.apply_button); + UiUtilities.setupDialogButton(false, applyButton, UiUtilities.DialogButtonType.PRIMARY, R.string.shared_string_apply); + applyButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MapActivity mapActivity = (MapActivity) getActivity(); + if (mapActivity != null) { + OsmandSettings settings = mapActivity.getMyApplication().getSettings(); + for (int i = 0; i < applicationModes.size(); i++) { + ApplicationMode mode = applicationModes.get(i); + mode.setOrder(i); + } + ApplicationMode.reorderAppModes(); + ApplicationMode.saveAppModesToSettings(settings); + mapActivity.onBackPressed(); + } + } + }); + + return mainView; + } +} \ No newline at end of file