From 51e63c99bd5f541e2e1b93bd83d3c8b1cca33e84 Mon Sep 17 00:00:00 2001 From: Dmitry Yunitsky Date: Wed, 27 Apr 2016 18:07:13 +0300 Subject: [PATCH 1/7] [android] Localized street in UI. --- .../mapswithme/maps/editor/StreetAdapter.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/android/src/com/mapswithme/maps/editor/StreetAdapter.java b/android/src/com/mapswithme/maps/editor/StreetAdapter.java index cd31cff64d..a3891fb9e7 100644 --- a/android/src/com/mapswithme/maps/editor/StreetAdapter.java +++ b/android/src/com/mapswithme/maps/editor/StreetAdapter.java @@ -120,19 +120,19 @@ public class StreetAdapter extends RecyclerView.Adapter Date: Tue, 21 Jun 2016 20:40:13 +0300 Subject: [PATCH 2/7] Language selection. --- .../jni/com/mapswithme/core/jni_helper.hpp | 22 ++++++++++++++----- .../jni/com/mapswithme/maps/editor/Editor.cpp | 17 +++++++++----- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/android/jni/com/mapswithme/core/jni_helper.hpp b/android/jni/com/mapswithme/core/jni_helper.hpp index 8384784437..7e26c3b292 100644 --- a/android/jni/com/mapswithme/core/jni_helper.hpp +++ b/android/jni/com/mapswithme/core/jni_helper.hpp @@ -9,6 +9,8 @@ #include "std/string.hpp" #include "std/shared_ptr.hpp" +#include "base/logging.hpp" + extern jclass g_mapObjectClazz; extern jclass g_bookmarkClazz; @@ -51,20 +53,28 @@ jobject GetNewParcelablePointD(JNIEnv * env, m2::PointD const & point); jobject GetNewPoint(JNIEnv * env, m2::PointD const & point); jobject GetNewPoint(JNIEnv * env, m2::PointI const & point); -template -jobjectArray ToJavaArray(JNIEnv * env, jclass clazz, vector const & src, TToJavaFn && toJavaFn) +template +jobjectArray ToJavaArray(JNIEnv * env, jclass clazz, TIt begin, TIt end, size_t const size, TToJavaFn && toJavaFn) { - size_t const size = src.size(); jobjectArray jArray = env->NewObjectArray((jint) size, clazz, 0); - for (size_t i = 0; i < size; i++) + size_t i = 0; + for (auto it = begin; it != end; ++it) { - TScopedLocalRef jItem(env, toJavaFn(env, src[i])); + TScopedLocalRef jItem(env, toJavaFn(env, *it)); env->SetObjectArrayElement(jArray, i, jItem.get()); + ++i; } return jArray; } + +template +jobjectArray ToJavaArray(JNIEnv * env, jclass clazz, TContainer const & src, TToJavaFn && toJavaFn) +{ + return ToJavaArray(env, clazz, begin(src), end(src), src.size(), move(toJavaFn)); +} + jobjectArray ToJavaStringArray(JNIEnv * env, vector const & src); void DumpDalvikReferenceTables(); -} +} // namespace jni diff --git a/android/jni/com/mapswithme/maps/editor/Editor.cpp b/android/jni/com/mapswithme/maps/editor/Editor.cpp index b572988e2b..a9a91c9ac3 100644 --- a/android/jni/com/mapswithme/maps/editor/Editor.cpp +++ b/android/jni/com/mapswithme/maps/editor/Editor.cpp @@ -3,6 +3,8 @@ #include "com/mapswithme/core/jni_helper.hpp" #include "com/mapswithme/maps/Framework.hpp" +#include "coding/multilang_utf8_string.hpp" + #include "base/assert.hpp" #include "base/logging.hpp" #include "base/string_utils.hpp" @@ -344,13 +346,18 @@ Java_com_mapswithme_maps_editor_Editor_nativeGetNearbyStreets(JNIEnv * env, jcla JNIEXPORT jobjectArray JNICALL Java_com_mapswithme_maps_editor_Editor_nativeGetSupportedLanguages(JNIEnv * env, jclass clazz) { - // TODO (yunikkk) implement + using TLang = StringUtf8Multilang::Lang; //public Language(@NonNull String code, @NonNull String name) -// static jclass const langClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/editor/data/Language"); -// static jmethodID const langCtor = jni::GetConstructorID(env, langClass, "(Ljava/lang/String;Ljava/lang/String;)V"); + static jclass const langClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/editor/data/Language"); + static jmethodID const langCtor = jni::GetConstructorID(env, langClass, "(Ljava/lang/String;Ljava/lang/String;)V"); -// return jni::ToJavaArray(env, langClass, g_editableMapObject.GetBuildingLevels(), ); - return nullptr; + return jni::ToJavaArray(env, langClass, StringUtf8Multilang::GetSupportedLanguages(), + [](JNIEnv * env, TLang const & lang) + { + jni::TScopedLocalRef const code(env, jni::ToJavaString(env, lang.m_code)); + jni::TScopedLocalRef const name(env, jni::ToJavaString(env, lang.m_name)); + return env->NewObject(langClass, langCtor, code.get(), name.get()); + }); } JNIEXPORT jstring JNICALL From 57f6d206925fe777796d72c81ea975ecedbd6eff Mon Sep 17 00:00:00 2001 From: Sergey Magidovich Date: Mon, 27 Jun 2016 15:56:54 +0300 Subject: [PATCH 3/7] Add convenient constructor for LocalizedNames. Add method. --- .../jni/com/mapswithme/maps/editor/Editor.cpp | 8 ++++++ .../com/mapswithme/maps/editor/Editor.java | 1 + indexer/editable_map_object.cpp | 25 ++++++++++++++++--- indexer/editable_map_object.hpp | 4 +++ .../Classes/Editor/MWMEditorViewController.mm | 3 +-- 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/android/jni/com/mapswithme/maps/editor/Editor.cpp b/android/jni/com/mapswithme/maps/editor/Editor.cpp index a9a91c9ac3..8b7c349cce 100644 --- a/android/jni/com/mapswithme/maps/editor/Editor.cpp +++ b/android/jni/com/mapswithme/maps/editor/Editor.cpp @@ -590,4 +590,12 @@ Java_com_mapswithme_maps_editor_Editor_nativeIsMapObjectUploaded(JNIEnv * env, j { return osm::Editor::Instance().IsFeatureUploaded(g_editableMapObject.GetID().m_mwmId, g_editableMapObject.GetID().m_index); } + +// static nativeMakeLocalizedName(String langCode, String name); +JNIEXPORT jobject JNICALL +Java_com_mapswithme_maps_editor_Editor_nativeMakeLocalizedName(JNIEnv * env, jclass clazz, jstring code, jstring name) +{ + osm::LocalizedName localizedName(jni::ToNativeString(env, code), jni::ToNativeString(env, name)); + return ToJavaName(env, localizedName); +} } // extern "C" diff --git a/android/src/com/mapswithme/maps/editor/Editor.java b/android/src/com/mapswithme/maps/editor/Editor.java index 2812281bd8..3bd5321189 100644 --- a/android/src/com/mapswithme/maps/editor/Editor.java +++ b/android/src/com/mapswithme/maps/editor/Editor.java @@ -105,6 +105,7 @@ public final class Editor public static native void nativeSetDefaultName(String name); public static native @NonNull LocalizedName[] nativeGetLocalizedNames(); public static native void nativeSetLocalizedNames(@NonNull LocalizedName[] names); + public static native LocalizedName nativeMakeLocalizedName(String langCode, String name); public static native Language[] nativeGetSupportedLanguages(); public static native LocalizedStreet nativeGetStreet(); diff --git a/indexer/editable_map_object.cpp b/indexer/editable_map_object.cpp index 83700838fc..8bc08aebaa 100644 --- a/indexer/editable_map_object.cpp +++ b/indexer/editable_map_object.cpp @@ -11,6 +11,26 @@ namespace osm { +// LocalizedName ----------------------------------------------------------------------------------- + +LocalizedName::LocalizedName(int8_t const code, string const & name) + : m_code(code) + , m_lang(StringUtf8Multilang::GetLangByCode(code)) + , m_langName(StringUtf8Multilang::GetLangNameByCode(code)) + , m_name(name) +{ +} + +LocalizedName::LocalizedName(string const & langCode, string const & name) + : m_code(StringUtf8Multilang::GetLangIndex(langCode)) + , m_lang(StringUtf8Multilang::GetLangByCode(m_code)) + , m_langName(StringUtf8Multilang::GetLangNameByCode(m_code)) + , m_name(name) +{ +} + +// EditableMapObject ------------------------------------------------------------------------------- + // static int8_t const EditableMapObject::kMaximumLevelsEditableByUsers = 25; @@ -34,8 +54,7 @@ vector EditableMapObject::GetLocalizedNames() const vector result; m_name.ForEach([&result](int8_t code, string const & name) -> bool { - result.push_back({code, StringUtf8Multilang::GetLangByCode(code), - StringUtf8Multilang::GetLangNameByCode(code), name}); + result.push_back({code, name}); return true; }); return result; @@ -212,7 +231,7 @@ bool EditableMapObject::ValidateBuildingLevels(string const & buildingLevels) // static bool EditableMapObject::ValidateHouseNumber(string const & houseNumber) { - // TODO(mgsergio): Make a better validation, use real samples for example. + // TODO(mgsergio): Use LooksLikeHouseNumber! if (houseNumber.empty()) return true; diff --git a/indexer/editable_map_object.hpp b/indexer/editable_map_object.hpp index 64ee930028..35bee85fa2 100644 --- a/indexer/editable_map_object.hpp +++ b/indexer/editable_map_object.hpp @@ -35,6 +35,10 @@ struct EditableProperties struct LocalizedName { + LocalizedName() = default; + LocalizedName(int8_t code, string const & name); + LocalizedName(string const & langCode, string const & name); + // m_code, m_lang and m_langName are defined in StringUtf8Multilang. int8_t const m_code; // Non-owning pointers to internal static char const * array. diff --git a/iphone/Maps/Classes/Editor/MWMEditorViewController.mm b/iphone/Maps/Classes/Editor/MWMEditorViewController.mm index 7ed80e8b24..4d74b97ac5 100644 --- a/iphone/Maps/Classes/Editor/MWMEditorViewController.mm +++ b/iphone/Maps/Classes/Editor/MWMEditorViewController.mm @@ -90,8 +90,7 @@ vector getAdditionalLocalizedNames(osm::EditableMapObject co emo.GetName().ForEach([&result](int8_t code, string const & name) -> bool { if (code != StringUtf8Multilang::kDefaultCode) - result.push_back({code, StringUtf8Multilang::GetLangByCode(code), - StringUtf8Multilang::GetLangNameByCode(code), name}); + result.push_back({code, name}); return true; }); return result; From 9f1e419f825cab84b140ec70ce08744cc6d76c07 Mon Sep 17 00:00:00 2001 From: Sergey Magidovich Date: Mon, 27 Jun 2016 16:11:43 +0300 Subject: [PATCH 4/7] Add localized names. --- android/3rd_party/BottomSheet/build.gradle | 2 +- android/UnitTests/build.gradle | 2 +- android/build.gradle | 2 +- .../maps/editor/EditorFragment.java | 82 +++++++++++++++---- .../maps/editor/EditorHostFragment.java | 63 +++++++++++++- .../maps/editor/LanguagesFragment.java | 32 +++++++- .../maps/editor/MultilanguageAdapter.java | 60 ++++++-------- 7 files changed, 179 insertions(+), 64 deletions(-) diff --git a/android/3rd_party/BottomSheet/build.gradle b/android/3rd_party/BottomSheet/build.gradle index f93a7a5d96..70f45ba9ad 100644 --- a/android/3rd_party/BottomSheet/build.gradle +++ b/android/3rd_party/BottomSheet/build.gradle @@ -4,7 +4,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' + classpath 'com.android.tools.build:gradle:2.1.2' } } diff --git a/android/UnitTests/build.gradle b/android/UnitTests/build.gradle index e30a3877d5..cbd1b88ad0 100644 --- a/android/UnitTests/build.gradle +++ b/android/UnitTests/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' + classpath 'com.android.tools.build:gradle:2.1.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/android/build.gradle b/android/build.gradle index e5ca7b798e..6e87bac5fe 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' + classpath 'com.android.tools.build:gradle:2.1.2' classpath 'io.fabric.tools:gradle:1.+' } } diff --git a/android/src/com/mapswithme/maps/editor/EditorFragment.java b/android/src/com/mapswithme/maps/editor/EditorFragment.java index fcd3d5a837..7791b4a7f4 100644 --- a/android/src/com/mapswithme/maps/editor/EditorFragment.java +++ b/android/src/com/mapswithme/maps/editor/EditorFragment.java @@ -17,6 +17,7 @@ import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; @@ -44,8 +45,8 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe private EditText mName; private RecyclerView mLocalizedNames; - private final RecyclerView.AdapterDataObserver mLocalizedNamesObserver = new RecyclerView.AdapterDataObserver() - { + + private final RecyclerView.AdapterDataObserver mLocalizedNamesObserver = new RecyclerView.AdapterDataObserver() { @Override public void onChanged() { @@ -76,6 +77,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe refreshLocalizedNames(); } }; + private MultilanguageAdapter mLocalizedNamesAdapter; private TextView mLocalizedShow; private boolean mIsLocalizedShown; @@ -195,6 +197,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe refreshOpeningTime(); refreshEditableFields(); refreshResetButton(); + refreshLocalizedNames(); } @Override @@ -204,6 +207,17 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe setEdits(); } + private void writeNames() + { + LinearLayoutManager lm = (LinearLayoutManager) mLocalizedNames.getLayoutManager(); + for (int i = 0; i < mLocalizedNamesAdapter.getItemCount(); ++i) + { + View nameItem = lm.findViewByPosition(i); + EditText name = (EditText) nameItem.findViewById(R.id.input); + mParent.setLocalizedNameTo(name.getText().toString(), i + 1); // +1 Skip default name. + } + } + boolean setEdits() { if (!validateFields()) @@ -218,7 +232,9 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe Editor.nativeSetEmail(mEmail.getText().toString()); Editor.nativeSetHasWifi(mWifi.isChecked()); Editor.nativeSetOperator(mOperator.getText().toString()); - // TODO set localizated names + + writeNames(); + Editor.nativeSetLocalizedNames(mParent.getLocalizedNamesAsArray()); return true; } @@ -324,29 +340,63 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe } } + private void initLocalizedNameView(final View view) + { + mLocalizedNames = (RecyclerView) view.findViewById(R.id.recycler); + mLocalizedNames.setLayoutManager(new LinearLayoutManager(getActivity())); + mLocalizedNamesAdapter = new MultilanguageAdapter(mParent); + mLocalizedNames.setAdapter(mLocalizedNamesAdapter); + mLocalizedNamesAdapter.registerAdapterDataObserver(mLocalizedNamesObserver); + refreshLocalizedNames(); + + final Bundle args = getArguments(); + if (args.containsKey(EditorHostFragment.kLastLocalizedNameIndex)) + { + showLocalizedNames(true); + UiUtils.waitLayout(mLocalizedNames, new ViewTreeObserver.OnGlobalLayoutListener() + { + @Override + public void onGlobalLayout() + { + LinearLayoutManager lm = (LinearLayoutManager) mLocalizedNames.getLayoutManager(); + int position = args.getInt(EditorHostFragment.kLastLocalizedNameIndex); + + View nameItem = mLocalizedNames.getLayoutManager().findViewByPosition(position); + + int cvNameTop = view.findViewById(R.id.cv__name).getTop(); + int nameItemTop = nameItem.getTop(); + + view.scrollTo(0, cvNameTop + nameItemTop); + + // TODO(mgsergio): Uncomment if focus and keyboard are required. + // TODO(mgsergio): Keyboard doesn't want to hide. Only pressing back button works. + // View nameItemInput = nameItem.findViewById(R.id.input); + // nameItemInput.requestFocus(); + // InputUtils.showKeyboard(nameItemInput); + } + }); + } + else + { + showLocalizedNames(false); + } + } + private void initViews(View view) { final View categoryBlock = view.findViewById(R.id.category); categoryBlock.setOnClickListener(this); // TODO show icon and fill it when core will implement that - UiUtils.hide(categoryBlock.findViewById(R.id.icon)); + // UiUtils.hide(categoryBlock.findViewById(R.id.icon)); mCategory = (TextView) categoryBlock.findViewById(R.id.name); mCardName = view.findViewById(R.id.cv__name); mCardAddress = view.findViewById(R.id.cv__address); mCardMetadata = view.findViewById(R.id.cv__metadata); mName = findInput(mCardName); - // TODO uncomment and finish localized name - // view.findViewById(R.id.add_langs).setOnClickListener(this); - UiUtils.hide(view.findViewById(R.id.add_langs)); + view.findViewById(R.id.add_langs).setOnClickListener(this); mLocalizedShow = (TextView) view.findViewById(R.id.show_langs); mLocalizedShow.setOnClickListener(this); - mLocalizedNames = (RecyclerView) view.findViewById(R.id.recycler); - mLocalizedNames.setLayoutManager(new LinearLayoutManager(getActivity())); - mLocalizedNamesAdapter = new MultilanguageAdapter(Editor.nativeGetLocalizedNames()); - mLocalizedNames.setAdapter(mLocalizedNamesAdapter); - mLocalizedNamesAdapter.registerAdapterDataObserver(mLocalizedNamesObserver); - refreshLocalizedNames(); - showLocalizedNames(false); + initLocalizedNameView(view); // Address view.findViewById(R.id.block_street).setOnClickListener(this); @@ -462,9 +512,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe private void refreshLocalizedNames() { - // TODO uncomment and finish localized names - // UiUtils.showIf(mLocalizedNamesAdapter.getItemCount() > 0, mLocalizedShow); - UiUtils.hide(mLocalizedNames, mLocalizedShow); + UiUtils.showIf(mLocalizedNamesAdapter.getItemCount() > 0, mLocalizedShow); } private void showLocalizedNames(boolean show) diff --git a/android/src/com/mapswithme/maps/editor/EditorHostFragment.java b/android/src/com/mapswithme/maps/editor/EditorHostFragment.java index f253b55c25..d8c8fd815b 100644 --- a/android/src/com/mapswithme/maps/editor/EditorHostFragment.java +++ b/android/src/com/mapswithme/maps/editor/EditorHostFragment.java @@ -16,6 +16,8 @@ import com.mapswithme.maps.MwmActivity; import com.mapswithme.maps.R; import com.mapswithme.maps.base.BaseMwmToolbarFragment; import com.mapswithme.maps.base.OnBackPressListener; +import com.mapswithme.maps.editor.data.Language; +import com.mapswithme.maps.editor.data.LocalizedName; import com.mapswithme.maps.editor.data.LocalizedStreet; import com.mapswithme.maps.widget.SearchToolbarController; import com.mapswithme.maps.widget.ToolbarController; @@ -24,10 +26,15 @@ import com.mapswithme.util.UiUtils; import com.mapswithme.util.Utils; import com.mapswithme.util.statistics.Statistics; +import java.util.ArrayList; +import java.util.Arrays; + public class EditorHostFragment extends BaseMwmToolbarFragment - implements OnBackPressListener, View.OnClickListener + implements OnBackPressListener, View.OnClickListener, LanguagesFragment.Listener { private boolean mIsNewObject; + final static String kExistingLocalizedNames = "ExistingLocalizedNames"; + final static String kLastLocalizedNameIndex = "LastLocalizedNameIndex"; enum Mode { @@ -40,6 +47,35 @@ public class EditorHostFragment extends BaseMwmToolbarFragment private Mode mMode; + /// A list of localized names added by a user and those that were in metadata. + private ArrayList mLocalizedNames; + + /// Used in MultilanguageAdapter to show, select and remove items. + ArrayList getLocalizedNames() + { + return mLocalizedNames; + } + + public LocalizedName[] getLocalizedNamesAsArray() + { + return mLocalizedNames.toArray(new LocalizedName[mLocalizedNames.size()]); + } + + void setLocalizedNames(LocalizedName[] names) + { + mLocalizedNames = new ArrayList(Arrays.asList(names)); + } + + void setLocalizedNameTo(String name, int index) + { + mLocalizedNames.get(index).name = name; + } + + void addLocalizedName(LocalizedName name) + { + mLocalizedNames.add(name); + } + @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) @@ -65,6 +101,7 @@ public class EditorHostFragment extends BaseMwmToolbarFragment mIsNewObject = getArguments().getBoolean(EditorActivity.EXTRA_NEW_OBJECT, false); mToolbarController.setTitle(getTitle()); + setLocalizedNames(Editor.nativeGetLocalizedNames()); editMapObject(); } @@ -104,11 +141,19 @@ public class EditorHostFragment extends BaseMwmToolbarFragment } protected void editMapObject() + { + editMapObject(false /* focusToLastLocalizedName */); + } + + protected void editMapObject(boolean focusToLastLocalizedName) { mMode = Mode.MAP_OBJECT; ((SearchToolbarController) mToolbarController).showControls(false); mToolbarController.setTitle(getTitle()); - final Fragment editorFragment = Fragment.instantiate(getActivity(), EditorFragment.class.getName()); + Bundle args = new Bundle(); + if (focusToLastLocalizedName) + args.putInt(kLastLocalizedNameIndex, mLocalizedNames.size() - 2); // -1 for zero-based and one more -1 for ignoring default name. + final Fragment editorFragment = Fragment.instantiate(getActivity(), EditorFragment.class.getName(), args); getChildFragmentManager().beginTransaction() .replace(R.id.fragment_container, editorFragment, EditorFragment.class.getName()) .commit(); @@ -133,7 +178,12 @@ public class EditorHostFragment extends BaseMwmToolbarFragment protected void addLocalizedLanguage() { - editWithFragment(Mode.LANGUAGE, R.string.choose_language, null, LanguagesFragment.class, false); + Bundle args = new Bundle(); + String[] languages = new String[mLocalizedNames.size()]; + for (int i = 0; i < mLocalizedNames.size(); ++i) + languages[i] = mLocalizedNames.get(i).lang; + args.putStringArray(kExistingLocalizedNames, languages); + editWithFragment(Mode.LANGUAGE, R.string.choose_language, args, LanguagesFragment.class, false); } private void editWithFragment(Mode newMode, @StringRes int toolbarTitle, @Nullable Bundle args, Class fragmentClass, boolean showSearch) @@ -249,4 +299,11 @@ public class EditorHostFragment extends BaseMwmToolbarFragment { return mIsNewObject; } + + @Override + public void onLanguageSelected(Language lang) + { + addLocalizedName(Editor.nativeMakeLocalizedName(lang.code, "")); + editMapObject(true /* focusToLastLocalizedName */); + } } diff --git a/android/src/com/mapswithme/maps/editor/LanguagesFragment.java b/android/src/com/mapswithme/maps/editor/LanguagesFragment.java index 6a981f908b..c7b77ed663 100644 --- a/android/src/com/mapswithme/maps/editor/LanguagesFragment.java +++ b/android/src/com/mapswithme/maps/editor/LanguagesFragment.java @@ -1,10 +1,18 @@ package com.mapswithme.maps.editor; +import android.os.Bundle; import android.support.v7.widget.RecyclerView; import com.mapswithme.maps.base.BaseMwmRecyclerFragment; import com.mapswithme.maps.editor.data.Language; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashSet; + +import static java.util.Collections.sort; + public class LanguagesFragment extends BaseMwmRecyclerFragment { public interface Listener @@ -15,14 +23,30 @@ public class LanguagesFragment extends BaseMwmRecyclerFragment @Override protected RecyclerView.Adapter createAdapter() { - return new LanguagesAdapter(this, Editor.nativeGetSupportedLanguages()); + Bundle args = getArguments(); + HashSet existingLanguages = new HashSet<>(Arrays.asList(args.getStringArray(EditorHostFragment.kExistingLocalizedNames))); + + ArrayList languages = new ArrayList<>(); + for (Language lang : Editor.nativeGetSupportedLanguages()) + { + if (existingLanguages.contains(lang.code)) + continue; + languages.add(lang); + } + + sort(languages, new Comparator() { + @Override + public int compare(Language lhs, Language rhs) { + return lhs.name.compareTo(rhs.name); + } + }); + + return new LanguagesAdapter(this, languages.toArray(new Language[languages.size()])); } protected void onLanguageSelected(Language language) { - if (getActivity() instanceof Listener) - ((Listener) getActivity()).onLanguageSelected(language); - else if (getParentFragment() instanceof Listener) + if (getParentFragment() instanceof Listener) ((Listener) getParentFragment()).onLanguageSelected(language); } } diff --git a/android/src/com/mapswithme/maps/editor/MultilanguageAdapter.java b/android/src/com/mapswithme/maps/editor/MultilanguageAdapter.java index 72f5c692d4..46815455e8 100644 --- a/android/src/com/mapswithme/maps/editor/MultilanguageAdapter.java +++ b/android/src/com/mapswithme/maps/editor/MultilanguageAdapter.java @@ -1,9 +1,6 @@ package com.mapswithme.maps.editor; -import android.support.v7.util.SortedList; import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.util.SortedListAdapterCallback; -import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -11,47 +8,33 @@ import android.widget.EditText; import com.mapswithme.maps.R; import com.mapswithme.maps.editor.data.LocalizedName; +import com.mapswithme.util.UiUtils; + +import java.util.ArrayList; public class MultilanguageAdapter extends RecyclerView.Adapter { - private SortedList mNames; + private ArrayList mNames; + private EditorHostFragment mHostFragment; - MultilanguageAdapter(LocalizedName[] names) + // TODO(mgsergio): Refactor: don't pass the whole EditorHostFragment. + MultilanguageAdapter(EditorHostFragment hostFragment) { - mNames = new SortedList<>(LocalizedName.class, - new SortedListAdapterCallback(this) - { - @Override - public int compare(LocalizedName o1, LocalizedName o2) - { - return o1.lang.compareTo(o2.lang); - } + mHostFragment = hostFragment; + mNames = new ArrayList<>(); + ArrayList names = mHostFragment.getLocalizedNames(); - @Override - public boolean areContentsTheSame(LocalizedName oldItem, LocalizedName newItem) - { - return TextUtils.equals(oldItem.name, newItem.name); - } - - @Override - public boolean areItemsTheSame(LocalizedName item1, LocalizedName item2) - { - return item1.code == item2.code; - } - }, - names.length); - - // skip default name - for (int i = 1; i < names.length; i++) - mNames.add(names[i]); + // Skip default name. + for (int i = 1; i < names.size(); i++) + mNames.add(names.get(i)); } - public void setNames(SortedList names) + public void setNames(ArrayList names) { mNames = names; } - public SortedList getNames() + public ArrayList getNames() { return mNames; } @@ -60,6 +43,8 @@ public class MultilanguageAdapter extends RecyclerView.Adapter Date: Fri, 1 Jul 2016 15:43:18 +0300 Subject: [PATCH 5/7] Remove useless resources. --- android/res/drawable-ldpi/ic_leadreboard.png | Bin 185 -> 0 bytes android/res/drawable-ldpi/ic_more.png | Bin 108 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 android/res/drawable-ldpi/ic_leadreboard.png delete mode 100644 android/res/drawable-ldpi/ic_more.png diff --git a/android/res/drawable-ldpi/ic_leadreboard.png b/android/res/drawable-ldpi/ic_leadreboard.png deleted file mode 100644 index 477f80abef891347e8c302085b5fe84da12e226d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 185 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+0wn(&ce?|m8a!PbLo_BPCpfTsI(P`QFe@@9 z9J#>R;`T%IrXdUSLfI+DPcQJjk(J-3$Cg;Kx@qD9!5eps*bGBl4?5IxNSs-~x-45_ z#s|$usS_BT()oFrl4%E0?RrD*95^;Do+7(8A5T-G@yGywoV$30a5 diff --git a/android/res/drawable-ldpi/ic_more.png b/android/res/drawable-ldpi/ic_more.png deleted file mode 100644 index fde57e5936918537de946a0d1891e442923059e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108 zcmeAS@N?(olHy`uVBq!ia0vp^%s|Y;!2%K~KmQO&8GE`ohHzZZJ#8q;peS(U!pBW~ z{Jg7$#1$S~{;)#Ncb3YnOB**X%AMQ&Y2}O={;4ab|9Qji^Tepac-k`spmqjNS3j3^ HP6w From 34a15422377ad46a98923bf701f1cdf796c34651 Mon Sep 17 00:00:00 2001 From: Sergey Magidovich Date: Fri, 1 Jul 2016 16:05:13 +0300 Subject: [PATCH 6/7] Fix scrolling. --- android/src/com/mapswithme/maps/editor/EditorFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/android/src/com/mapswithme/maps/editor/EditorFragment.java b/android/src/com/mapswithme/maps/editor/EditorFragment.java index 7791b4a7f4..a1723e5cc0 100644 --- a/android/src/com/mapswithme/maps/editor/EditorFragment.java +++ b/android/src/com/mapswithme/maps/editor/EditorFragment.java @@ -343,6 +343,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe private void initLocalizedNameView(final View view) { mLocalizedNames = (RecyclerView) view.findViewById(R.id.recycler); + mLocalizedNames.setNestedScrollingEnabled(false); mLocalizedNames.setLayoutManager(new LinearLayoutManager(getActivity())); mLocalizedNamesAdapter = new MultilanguageAdapter(mParent); mLocalizedNames.setAdapter(mLocalizedNamesAdapter); From dd673c23b9dec33e25ca27c5cc8082c49555af15 Mon Sep 17 00:00:00 2001 From: Sergey Magidovich Date: Fri, 1 Jul 2016 21:48:13 +0300 Subject: [PATCH 7/7] Code review. --- .../jni/com/mapswithme/core/jni_helper.hpp | 4 +- .../maps/editor/EditorFragment.java | 72 ++++++++----------- .../maps/editor/EditorHostFragment.java | 47 +++++++----- .../maps/editor/LanguagesFragment.java | 18 +++-- .../maps/editor/MultilanguageAdapter.java | 36 +++++----- .../mapswithme/maps/editor/StreetAdapter.java | 22 +++--- .../maps/editor/data/LocalizedName.java | 3 + indexer/editable_map_object.hpp | 1 - 8 files changed, 102 insertions(+), 101 deletions(-) diff --git a/android/jni/com/mapswithme/core/jni_helper.hpp b/android/jni/com/mapswithme/core/jni_helper.hpp index 7e26c3b292..6ac621c37c 100644 --- a/android/jni/com/mapswithme/core/jni_helper.hpp +++ b/android/jni/com/mapswithme/core/jni_helper.hpp @@ -9,8 +9,6 @@ #include "std/string.hpp" #include "std/shared_ptr.hpp" -#include "base/logging.hpp" - extern jclass g_mapObjectClazz; extern jclass g_bookmarkClazz; @@ -71,7 +69,7 @@ jobjectArray ToJavaArray(JNIEnv * env, jclass clazz, TIt begin, TIt end, size_t template jobjectArray ToJavaArray(JNIEnv * env, jclass clazz, TContainer const & src, TToJavaFn && toJavaFn) { - return ToJavaArray(env, clazz, begin(src), end(src), src.size(), move(toJavaFn)); + return ToJavaArray(env, clazz, begin(src), end(src), src.size(), forward(toJavaFn)); } jobjectArray ToJavaStringArray(JNIEnv * env, vector const & src); diff --git a/android/src/com/mapswithme/maps/editor/EditorFragment.java b/android/src/com/mapswithme/maps/editor/EditorFragment.java index a1723e5cc0..8335e8f5c5 100644 --- a/android/src/com/mapswithme/maps/editor/EditorFragment.java +++ b/android/src/com/mapswithme/maps/editor/EditorFragment.java @@ -38,6 +38,8 @@ import org.solovyev.android.views.llm.LinearLayoutManager; public class EditorFragment extends BaseMwmFragment implements View.OnClickListener, EditTextDialogFragment.OnTextSaveListener { + final static String LAST_LOCALIZED_NAME_INDEX = "LastLocalizedNameIndex"; + private TextView mCategory; private View mCardName; private View mCardAddress; @@ -46,7 +48,8 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe private RecyclerView mLocalizedNames; - private final RecyclerView.AdapterDataObserver mLocalizedNamesObserver = new RecyclerView.AdapterDataObserver() { + private final RecyclerView.AdapterDataObserver mLocalizedNamesObserver = new RecyclerView.AdapterDataObserver() + { @Override public void onChanged() { @@ -207,17 +210,6 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe setEdits(); } - private void writeNames() - { - LinearLayoutManager lm = (LinearLayoutManager) mLocalizedNames.getLayoutManager(); - for (int i = 0; i < mLocalizedNamesAdapter.getItemCount(); ++i) - { - View nameItem = lm.findViewByPosition(i); - EditText name = (EditText) nameItem.findViewById(R.id.input); - mParent.setLocalizedNameTo(name.getText().toString(), i + 1); // +1 Skip default name. - } - } - boolean setEdits() { if (!validateFields()) @@ -232,8 +224,6 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe Editor.nativeSetEmail(mEmail.getText().toString()); Editor.nativeSetHasWifi(mWifi.isChecked()); Editor.nativeSetOperator(mOperator.getText().toString()); - - writeNames(); Editor.nativeSetLocalizedNames(mParent.getLocalizedNamesAsArray()); return true; @@ -351,36 +341,34 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe refreshLocalizedNames(); final Bundle args = getArguments(); - if (args.containsKey(EditorHostFragment.kLastLocalizedNameIndex)) - { - showLocalizedNames(true); - UiUtils.waitLayout(mLocalizedNames, new ViewTreeObserver.OnGlobalLayoutListener() - { - @Override - public void onGlobalLayout() - { - LinearLayoutManager lm = (LinearLayoutManager) mLocalizedNames.getLayoutManager(); - int position = args.getInt(EditorHostFragment.kLastLocalizedNameIndex); - - View nameItem = mLocalizedNames.getLayoutManager().findViewByPosition(position); - - int cvNameTop = view.findViewById(R.id.cv__name).getTop(); - int nameItemTop = nameItem.getTop(); - - view.scrollTo(0, cvNameTop + nameItemTop); - - // TODO(mgsergio): Uncomment if focus and keyboard are required. - // TODO(mgsergio): Keyboard doesn't want to hide. Only pressing back button works. - // View nameItemInput = nameItem.findViewById(R.id.input); - // nameItemInput.requestFocus(); - // InputUtils.showKeyboard(nameItemInput); - } - }); - } - else + if (args == null || !args.containsKey(LAST_LOCALIZED_NAME_INDEX)) { showLocalizedNames(false); + return; } + showLocalizedNames(true); + UiUtils.waitLayout(mLocalizedNames, new ViewTreeObserver.OnGlobalLayoutListener() + { + @Override + public void onGlobalLayout() + { + LinearLayoutManager lm = (LinearLayoutManager) mLocalizedNames.getLayoutManager(); + int position = args.getInt(LAST_LOCALIZED_NAME_INDEX); + + View nameItem = lm.findViewByPosition(position); + + int cvNameTop = view.findViewById(R.id.cv__name).getTop(); + int nameItemTop = nameItem.getTop(); + + view.scrollTo(0, cvNameTop + nameItemTop); + + // TODO(mgsergio): Uncomment if focus and keyboard are required. + // TODO(mgsergio): Keyboard doesn't want to hide. Only pressing back button works. + // View nameItemInput = nameItem.findViewById(R.id.input); + // nameItemInput.requestFocus(); + // InputUtils.showKeyboard(nameItemInput); + } + }); } private void initViews(View view) @@ -388,7 +376,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe final View categoryBlock = view.findViewById(R.id.category); categoryBlock.setOnClickListener(this); // TODO show icon and fill it when core will implement that - // UiUtils.hide(categoryBlock.findViewById(R.id.icon)); + UiUtils.hide(categoryBlock.findViewById(R.id.icon)); mCategory = (TextView) categoryBlock.findViewById(R.id.name); mCardName = view.findViewById(R.id.cv__name); mCardAddress = view.findViewById(R.id.cv__address); diff --git a/android/src/com/mapswithme/maps/editor/EditorHostFragment.java b/android/src/com/mapswithme/maps/editor/EditorHostFragment.java index d8c8fd815b..116d900d61 100644 --- a/android/src/com/mapswithme/maps/editor/EditorHostFragment.java +++ b/android/src/com/mapswithme/maps/editor/EditorHostFragment.java @@ -27,14 +27,12 @@ import com.mapswithme.util.Utils; import com.mapswithme.util.statistics.Statistics; import java.util.ArrayList; -import java.util.Arrays; +import java.util.List; public class EditorHostFragment extends BaseMwmToolbarFragment implements OnBackPressListener, View.OnClickListener, LanguagesFragment.Listener { private boolean mIsNewObject; - final static String kExistingLocalizedNames = "ExistingLocalizedNames"; - final static String kLastLocalizedNameIndex = "LastLocalizedNameIndex"; enum Mode { @@ -47,33 +45,46 @@ public class EditorHostFragment extends BaseMwmToolbarFragment private Mode mMode; - /// A list of localized names added by a user and those that were in metadata. - private ArrayList mLocalizedNames; + /** + * A list of localized names added by a user and those that were in metadata. + */ + private static final List sLocalizedNames = new ArrayList<>(); - /// Used in MultilanguageAdapter to show, select and remove items. - ArrayList getLocalizedNames() + /** + * Used in MultilanguageAdapter to show, select and remove items. + */ + List getLocalizedNames() { - return mLocalizedNames; + return sLocalizedNames; } public LocalizedName[] getLocalizedNamesAsArray() { - return mLocalizedNames.toArray(new LocalizedName[mLocalizedNames.size()]); + return sLocalizedNames.toArray(new LocalizedName[sLocalizedNames.size()]); } void setLocalizedNames(LocalizedName[] names) { - mLocalizedNames = new ArrayList(Arrays.asList(names)); + sLocalizedNames.clear(); + for (LocalizedName name : names) + { + if (name.code == LocalizedName.DEFAULT_LANG_CODE) + continue; + sLocalizedNames.add(name); + } } - void setLocalizedNameTo(String name, int index) + /** + * Sets .name of an index item to name. + */ + void setName(String name, int index) { - mLocalizedNames.get(index).name = name; + sLocalizedNames.get(index).name = name; } void addLocalizedName(LocalizedName name) { - mLocalizedNames.add(name); + sLocalizedNames.add(name); } @Nullable @@ -152,7 +163,7 @@ public class EditorHostFragment extends BaseMwmToolbarFragment mToolbarController.setTitle(getTitle()); Bundle args = new Bundle(); if (focusToLastLocalizedName) - args.putInt(kLastLocalizedNameIndex, mLocalizedNames.size() - 2); // -1 for zero-based and one more -1 for ignoring default name. + args.putInt(EditorFragment.LAST_LOCALIZED_NAME_INDEX, sLocalizedNames.size() - 1); final Fragment editorFragment = Fragment.instantiate(getActivity(), EditorFragment.class.getName(), args); getChildFragmentManager().beginTransaction() .replace(R.id.fragment_container, editorFragment, EditorFragment.class.getName()) @@ -179,10 +190,10 @@ public class EditorHostFragment extends BaseMwmToolbarFragment protected void addLocalizedLanguage() { Bundle args = new Bundle(); - String[] languages = new String[mLocalizedNames.size()]; - for (int i = 0; i < mLocalizedNames.size(); ++i) - languages[i] = mLocalizedNames.get(i).lang; - args.putStringArray(kExistingLocalizedNames, languages); + ArrayList languages = new ArrayList<>(sLocalizedNames.size()); + for (LocalizedName name : sLocalizedNames) + languages.add(name.lang); + args.putStringArrayList(LanguagesFragment.EXISTING_LOCALIZED_NAMES, languages); editWithFragment(Mode.LANGUAGE, R.string.choose_language, args, LanguagesFragment.class, false); } diff --git a/android/src/com/mapswithme/maps/editor/LanguagesFragment.java b/android/src/com/mapswithme/maps/editor/LanguagesFragment.java index c7b77ed663..d1e8952a23 100644 --- a/android/src/com/mapswithme/maps/editor/LanguagesFragment.java +++ b/android/src/com/mapswithme/maps/editor/LanguagesFragment.java @@ -8,13 +8,17 @@ import com.mapswithme.maps.editor.data.Language; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Comparator; import java.util.HashSet; +import java.util.List; +import java.util.Set; -import static java.util.Collections.sort; public class LanguagesFragment extends BaseMwmRecyclerFragment { + final static String EXISTING_LOCALIZED_NAMES = "ExistingLocalizedNames"; + public interface Listener { void onLanguageSelected(Language language); @@ -24,17 +28,17 @@ public class LanguagesFragment extends BaseMwmRecyclerFragment protected RecyclerView.Adapter createAdapter() { Bundle args = getArguments(); - HashSet existingLanguages = new HashSet<>(Arrays.asList(args.getStringArray(EditorHostFragment.kExistingLocalizedNames))); + Set existingLanguages = new HashSet<>(args.getStringArrayList(EXISTING_LOCALIZED_NAMES)); - ArrayList languages = new ArrayList<>(); + List languages = new ArrayList<>(); for (Language lang : Editor.nativeGetSupportedLanguages()) { - if (existingLanguages.contains(lang.code)) - continue; - languages.add(lang); + if (!existingLanguages.contains(lang.code)) + languages.add(lang); } - sort(languages, new Comparator() { + Collections.sort(languages, new Comparator() + { @Override public int compare(Language lhs, Language rhs) { return lhs.name.compareTo(rhs.name); diff --git a/android/src/com/mapswithme/maps/editor/MultilanguageAdapter.java b/android/src/com/mapswithme/maps/editor/MultilanguageAdapter.java index 46815455e8..4fc1eca797 100644 --- a/android/src/com/mapswithme/maps/editor/MultilanguageAdapter.java +++ b/android/src/com/mapswithme/maps/editor/MultilanguageAdapter.java @@ -8,35 +8,21 @@ import android.widget.EditText; import com.mapswithme.maps.R; import com.mapswithme.maps.editor.data.LocalizedName; +import com.mapswithme.util.StringUtils; import com.mapswithme.util.UiUtils; -import java.util.ArrayList; +import java.util.List; public class MultilanguageAdapter extends RecyclerView.Adapter { - private ArrayList mNames; + private final List mNames; private EditorHostFragment mHostFragment; // TODO(mgsergio): Refactor: don't pass the whole EditorHostFragment. MultilanguageAdapter(EditorHostFragment hostFragment) { mHostFragment = hostFragment; - mNames = new ArrayList<>(); - ArrayList names = mHostFragment.getLocalizedNames(); - - // Skip default name. - for (int i = 1; i < names.size(); i++) - mNames.add(names.get(i)); - } - - public void setNames(ArrayList names) - { - mNames = names; - } - - public ArrayList getNames() - { - return mNames; + mNames = hostFragment.getLocalizedNames(); } @Override @@ -57,7 +43,10 @@ public class MultilanguageAdapter extends RecyclerView.Adapter